Merge branch 'master' of git.freeswitch.org:freeswitch
This commit is contained in:
commit
1d993d3aa2
|
@ -8,36 +8,65 @@
|
|||
.deps
|
||||
.\#*
|
||||
\#*
|
||||
.version
|
||||
AUTHORS
|
||||
COPYING
|
||||
ChangeLog
|
||||
Makefile
|
||||
Makefile.in
|
||||
NEWS
|
||||
README
|
||||
/Debug/
|
||||
/Release/
|
||||
/All/
|
||||
/bin/
|
||||
*.user
|
||||
*.suo
|
||||
*.ncb
|
||||
*.pdb
|
||||
*.map
|
||||
*.lib
|
||||
*.obj
|
||||
*.idb
|
||||
*.res
|
||||
*.exp
|
||||
*.exe
|
||||
*.manifest
|
||||
*.dep
|
||||
*.dll
|
||||
/BuildLog.htm
|
||||
/Path
|
||||
/w32/Library/lastversion
|
||||
/w32/Library/tmpVersion.Bat
|
||||
!/w32/Console/FreeSwitchConsole.vcproj.user
|
||||
!/w32/Setup/inno_setup/vcredist_x64.exe
|
||||
!/w32/Setup/inno_setup/vcredist_x86.exe
|
||||
/.version
|
||||
/AUTHORS
|
||||
/COPYING
|
||||
/ChangeLog
|
||||
/Makefile
|
||||
/Makefile.in
|
||||
/NEWS
|
||||
/README
|
||||
aclocal.m4
|
||||
build/Makefile
|
||||
build/Makefile.in
|
||||
build/config/compile
|
||||
build/config/config.guess
|
||||
build/config/depcomp
|
||||
build/config/install-sh
|
||||
build/config/ltmain.sh
|
||||
build/config/missing
|
||||
build/freeswitch.pc
|
||||
build/getlib.sh
|
||||
build/getsounds.sh
|
||||
build/modmake.rules
|
||||
autom4te.cache
|
||||
/build/Makefile
|
||||
/build/Makefile.in
|
||||
/build/config/compile
|
||||
/build/config/config.guess
|
||||
/build/config/depcomp
|
||||
/build/config/install-sh
|
||||
/build/config/ltmain.sh
|
||||
/build/config/missing
|
||||
/build/freeswitch.pc
|
||||
/build/getlib.sh
|
||||
/build/getsounds.sh
|
||||
/build/modmake.rules
|
||||
config.cache
|
||||
config.log
|
||||
config.status
|
||||
configure
|
||||
freeswitch
|
||||
fs_cli
|
||||
fs_ivrd
|
||||
libtool
|
||||
modules.conf
|
||||
quiet_libtool
|
||||
scripts/fsxs
|
||||
scripts/gentls_cert
|
||||
a.out.dSYM
|
||||
/configure
|
||||
configure.lineno
|
||||
/freeswitch
|
||||
/fs_cli
|
||||
/fs_ivrd
|
||||
/libtool
|
||||
/modules.conf
|
||||
/quiet_libtool
|
||||
/scripts/fsxs
|
||||
/scripts/gentls_cert
|
||||
/a.out.dSYM
|
||||
/freeswitch-sounds-*
|
||||
|
|
57
Makefile.am
57
Makefile.am
|
@ -349,7 +349,21 @@ src/include/switch_version.h: src/include/switch_version.h.in .version $(libfree
|
|||
cat src/include/switch_version.h.in > src/include/switch_version.h ; \
|
||||
touch .version ; \
|
||||
else \
|
||||
version=`svnversion . -n || echo hacked` ; \
|
||||
if [ -d .git ] ; then \
|
||||
version=`git log --format="%h %ci" -1 HEAD | head -1 || echo hacked` ; \
|
||||
if [ "x$$version" == "xhacked" ] ; then \
|
||||
version="hacked-`date -u +%Y%m%dT%H%M%SZ`" ; \
|
||||
else \
|
||||
version="git-$$version" ; \
|
||||
fi ;\
|
||||
else \
|
||||
version=`svnversion . -n || echo hacked` ; \
|
||||
if [ "x$$version" == "xhacked" ] ; then \
|
||||
version="hacked-`date -u +%Y%m%dT%H%M%SZ`" ; \
|
||||
else \
|
||||
version="svn-$$version" ; \
|
||||
fi ;\
|
||||
fi ; \
|
||||
oldversion=`cat .version 2>/dev/null || echo "0"` ; \
|
||||
if test "$$oldversion" != "$$version" || test $$force = 1 ; then \
|
||||
cat src/include/switch_version.h.in | sed "s/@SWITCH_VERSION_REVISION@/$$version/g" > src/include/switch_version.h ; \
|
||||
|
@ -437,23 +451,30 @@ install-data-local:
|
|||
test -d $(DESTDIR)$(sysconfdir) || $(MAKE) samples-conf
|
||||
test -d $(DESTDIR)$(htdocsdir) || $(MAKE) samples-htdocs
|
||||
|
||||
is-svn:
|
||||
@if [ ! -d .svn ] ; then \
|
||||
is-scm:
|
||||
@if [ ! -d .svn -a ! -d .git ] ; then \
|
||||
echo ; echo ; \
|
||||
echo "**************************************************************************************************" ; \
|
||||
echo "You can not update a release tarball or without a svn working copy, please checkout fresh from svn" ; \
|
||||
echo "**************************************************************************************************" ; \
|
||||
echo "*****************************************************************************************************" ; \
|
||||
echo "You can not update a release tarball or without a git or svn working copy please clone our git tree: " ; \
|
||||
echo "git clone git://git.freeswitch.org/freeswitch.git " ; \
|
||||
echo "or check out our read only svn mirror: " ; \
|
||||
echo "svn checkout http://svn.freeswitch.org/svn/freeswitch/trunk " ; \
|
||||
echo "*****************************************************************************************************" ; \
|
||||
echo ; echo ; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
update: is-svn
|
||||
update: is-scm
|
||||
@if test -d .svn ; then \
|
||||
test ! -f .version || rm -f .version ; \
|
||||
echo Updating... ; \
|
||||
svn update ; \
|
||||
elif test -d .git ; then \
|
||||
test ! -f .version || rm -f .version ; \
|
||||
echo "Pulling updates..." ; \
|
||||
git pull ; \
|
||||
else \
|
||||
echo "This source directory is not an svn working copy" ; \
|
||||
echo "This source directory is not a git tree or svn working copy" ; \
|
||||
fi
|
||||
|
||||
.nodepends:
|
||||
|
@ -483,18 +504,18 @@ core_install: install_core
|
|||
|
||||
everything: install
|
||||
|
||||
up: is-svn clean
|
||||
svn update
|
||||
up: is-scm clean
|
||||
$(MAKE) update
|
||||
$(MAKE) -j core
|
||||
$(MAKE) -j modules
|
||||
$(MAKE) install
|
||||
|
||||
sync: is-svn
|
||||
svn update
|
||||
sync: is-scm
|
||||
$(MAKE) update
|
||||
$(MAKE) install
|
||||
|
||||
speedy-sync: is-svn
|
||||
svn update
|
||||
speedy-sync: is-scm
|
||||
$(MAKE) update
|
||||
$(MAKE) -j install
|
||||
|
||||
libs/openzap/Makefile:
|
||||
|
@ -570,15 +591,15 @@ cluecon:
|
|||
@echo
|
||||
@echo http://www.cluecon.com
|
||||
@sleep 5
|
||||
current: cluecon is-svn update-clean
|
||||
svn update
|
||||
current: cluecon update-clean is-scm
|
||||
$(MAKE) update
|
||||
$(MAKE) all
|
||||
$(MAKE) install
|
||||
|
||||
installall: current
|
||||
|
||||
speedy-current: is-svn update-clean
|
||||
svn update
|
||||
speedy-current: update-clean is-scm
|
||||
$(MAKE) update
|
||||
$(MAKE) speedy-sure
|
||||
$(MAKE) install
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
cd src/mod/languages/mod_lua
|
||||
make swigclean
|
||||
make mod_lua_wrap.cpp
|
||||
make lua_wrap
|
||||
cd ../../../..
|
||||
|
||||
cd src/mod/languages/mod_perl
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
|
||||
# Must change all of the below together
|
||||
# For a release, set revision for that tagged release as well and uncomment
|
||||
AC_INIT([freeswitch], [1.0.trunk], BUG-REPORT-ADDRESS)
|
||||
AC_INIT([freeswitch], [1.0.head], BUG-REPORT-ADDRESS)
|
||||
AC_SUBST(SWITCH_VERSION_MAJOR, [1])
|
||||
AC_SUBST(SWITCH_VERSION_MINOR, [0])
|
||||
AC_SUBST(SWITCH_VERSION_MICRO, [trunk])
|
||||
#AC_SUBST(SWITCH_VERSION_REVISION, [svn-revision-here])
|
||||
AC_SUBST(SWITCH_VERSION_MICRO, [head])
|
||||
#AC_SUBST(SWITCH_VERSION_REVISION, [])
|
||||
|
||||
AC_CONFIG_FILES([src/include/switch_version.h.in:src/include/switch_version.h.template])
|
||||
AC_CONFIG_FILES([.version:.version.in])
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
*~
|
||||
*.o
|
||||
*.so
|
||||
*.lo
|
||||
*.a
|
||||
*.la
|
||||
.libs
|
||||
.deps
|
||||
.\#*
|
||||
\#*
|
||||
/Debug/
|
||||
/Release/
|
||||
/All/
|
||||
/bin/
|
||||
*.user
|
||||
*.suo
|
||||
*.ncb
|
||||
*.pdb
|
||||
*.map
|
||||
*.lib
|
||||
*.obj
|
||||
*.idb
|
||||
*.res
|
||||
*.exp
|
||||
*.exe
|
||||
*.manifest
|
||||
*.dep
|
||||
*.dll
|
||||
Makefile
|
||||
fscomm
|
||||
fscomm.exe
|
||||
fscomm.app
|
|
@ -31,7 +31,9 @@ SOURCES += main.cpp \
|
|||
preferences/prefsofia.cpp \
|
||||
preferences/accountdialog.cpp \
|
||||
preferences/prefaccounts.cpp \
|
||||
account.cpp
|
||||
account.cpp \
|
||||
widgets/codecwidget.cpp \
|
||||
channel.cpp
|
||||
HEADERS += mainwindow.h \
|
||||
fshost.h \
|
||||
call.h \
|
||||
|
@ -41,9 +43,12 @@ HEADERS += mainwindow.h \
|
|||
preferences/prefsofia.h \
|
||||
preferences/accountdialog.h \
|
||||
preferences/prefaccounts.h \
|
||||
account.h
|
||||
account.h \
|
||||
widgets/codecwidget.h \
|
||||
channel.h
|
||||
FORMS += mainwindow.ui \
|
||||
preferences/prefdialog.ui \
|
||||
preferences/accountdialog.ui
|
||||
preferences/accountdialog.ui \
|
||||
widgets/codecwidget.ui
|
||||
RESOURCES += resources.qrc
|
||||
OTHER_FILES += conf/freeswitch.xml
|
||||
|
|
|
@ -33,16 +33,7 @@
|
|||
|
||||
Call::Call()
|
||||
{
|
||||
}
|
||||
|
||||
Call::Call(int call_id, QString cid_name, QString cid_number, fscomm_call_direction_t direction, QString uuid) :
|
||||
_call_id(call_id),
|
||||
_cid_name(cid_name),
|
||||
_cid_number(cid_number),
|
||||
_direction(direction),
|
||||
_uuid (uuid)
|
||||
{
|
||||
_isActive = false;
|
||||
_answeredEpoch = 0;
|
||||
}
|
||||
|
||||
switch_status_t Call::toggleRecord(bool startRecord)
|
||||
|
@ -56,14 +47,14 @@ switch_status_t Call::toggleRecord(bool startRecord)
|
|||
_recording_filename = QString("%1/.fscomm/recordings/%2_%3.wav").arg(
|
||||
conf_dir.absolutePath(),
|
||||
QDateTime::currentDateTime().toString("yyyyMMddhhmmss"),
|
||||
_cid_number);
|
||||
status = g_FSHost.sendCmd("uuid_record", QString("%1 start %2").arg(_uuid, _recording_filename).toAscii().data(),&result);
|
||||
getCidNumber());
|
||||
status = g_FSHost.sendCmd("uuid_record", QString("%1 start %2").arg(getUuid(), _recording_filename).toAscii().data(),&result);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Stopping call recording on call [%s]\n",
|
||||
_uuid.toAscii().data());
|
||||
status = g_FSHost.sendCmd("uuid_record", QString("%1 stop %2").arg(_uuid, _recording_filename).toAscii().data(),&result);
|
||||
getUuid().toAscii().data());
|
||||
status = g_FSHost.sendCmd("uuid_record", QString("%1 stop %2").arg(getUuid(), _recording_filename).toAscii().data(),&result);
|
||||
}
|
||||
|
||||
return status;
|
||||
|
@ -74,13 +65,30 @@ void Call::sendDTMF(QString digit)
|
|||
QString result;
|
||||
QString dtmf_string = QString("dtmf %1").arg(digit);
|
||||
if (g_FSHost.sendCmd("pa", dtmf_string.toAscii(), &result) == SWITCH_STATUS_FALSE) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not send DTMF digit %s on call[%s]", digit.toAscii().data(), _uuid.toAscii().data());
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not send DTMF digit %s on call[%s]", digit.toAscii().data(), getUuid().toAscii().data());
|
||||
QMessageBox::critical(0, QWidget::tr("DTMF Error"), QWidget::tr("There was an error sending DTMF, please report this bug."), QMessageBox::Ok);
|
||||
}
|
||||
}
|
||||
|
||||
QTime Call::getCurrentStateTime()
|
||||
{
|
||||
int now = QDateTime::fromTime_t(_answered_epoch).secsTo(QDateTime::currentDateTime());
|
||||
qulonglong time = 0;
|
||||
|
||||
if (_state == FSCOMM_CALL_STATE_ANSWERED)
|
||||
{
|
||||
time = _answeredEpoch;
|
||||
}
|
||||
else if(_state == FSCOMM_CALL_STATE_RINGING)
|
||||
{
|
||||
if (_direction == FSCOMM_CALL_DIRECTION_INBOUND)
|
||||
{
|
||||
/* TODO: DOESNT WORK - How do I get what time it started to ring? */
|
||||
_channel.data()->getProgressEpoch() == 0 ? time = _channel.data()->getProgressMediaEpoch() : time = _channel.data()->getProgressEpoch();
|
||||
}
|
||||
else
|
||||
_otherLegChannel.data()->getProgressEpoch() == 0 ? time = _otherLegChannel.data()->getProgressMediaEpoch() : time = _otherLegChannel.data()->getProgressEpoch();
|
||||
}
|
||||
|
||||
int now = QDateTime::fromTime_t(time).secsTo(QDateTime::currentDateTime());
|
||||
return QTime::fromString(QString::number(now), "s");
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <QtCore>
|
||||
#include <QString>
|
||||
#include <switch.h>
|
||||
#include "channel.h"
|
||||
|
||||
typedef enum {
|
||||
FSCOMM_CALL_STATE_RINGING = 0,
|
||||
|
@ -48,12 +49,20 @@ typedef enum {
|
|||
class Call {
|
||||
public:
|
||||
Call();
|
||||
Call(int call_id, QString cid_name, QString cid_number, fscomm_call_direction_t direction, QString uuid);
|
||||
QString getCidName(void) { return _cid_name; }
|
||||
QString getCidNumber(void) { return _cid_number; }
|
||||
int getCallID(void) { return _call_id; }
|
||||
QString getUUID(void) { return _uuid; }
|
||||
void setbUUID(QString uuid) { _buuid = uuid; }
|
||||
/* Needs rework */
|
||||
QString getCidName(void) { return _channel.data()->getCidName(); }
|
||||
QString getCidNumber(void) { return _channel.data()->getCidNumber(); }
|
||||
QString getDestinationNumber(void) { return _otherLegChannel.data()->getDestinationNumber(); }
|
||||
|
||||
void setChannel(QSharedPointer<Channel> channel) { _channel = channel; }
|
||||
QSharedPointer<Channel> getChannel() { return _channel; }
|
||||
void setOtherLegChannel(QSharedPointer<Channel> channel) { _otherLegChannel = channel; }
|
||||
QSharedPointer<Channel> getOtherLegChannel() { return _otherLegChannel; }
|
||||
|
||||
QString getUuid(void) { return _channel.data()->getUuid(); }
|
||||
QString getOtherLegUuid(void) { return _otherLegChannel.data()->getUuid(); }
|
||||
void setCallDirection(fscomm_call_direction_t dir) { _direction = dir; }
|
||||
int getCallID(void) { return _channel.data()->getPaCallId(); }
|
||||
fscomm_call_direction_t getDirection() { return _direction; }
|
||||
fscomm_call_state_t getState() { return _state; }
|
||||
void setState(fscomm_call_state_t state) { _state = state; }
|
||||
|
@ -63,21 +72,20 @@ public:
|
|||
bool isActive() { return _isActive == true; }
|
||||
switch_status_t toggleRecord(bool);
|
||||
void sendDTMF(QString digit);
|
||||
void setAnsweredEpoch(qulonglong time) { _answered_epoch = time/1000000; }
|
||||
void setAnsweredEpoch(qulonglong time) { _answeredEpoch = time/1000000; }
|
||||
QTime getCurrentStateTime();
|
||||
|
||||
private:
|
||||
int _call_id;
|
||||
QString _cid_name;
|
||||
QString _cid_number;
|
||||
QSharedPointer<Channel> _channel; /* This should be our portaudio channel */
|
||||
QSharedPointer<Channel> _otherLegChannel;
|
||||
|
||||
QString _cause;
|
||||
fscomm_call_direction_t _direction;
|
||||
QString _uuid;
|
||||
QString _buuid;
|
||||
|
||||
bool _isActive;
|
||||
QString _recording_filename;
|
||||
fscomm_call_state_t _state;
|
||||
qulonglong _answered_epoch;
|
||||
qulonglong _answeredEpoch;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(Call)
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
#include "channel.h"
|
||||
|
||||
Channel::Channel(QString uuid):
|
||||
_uuid(uuid)
|
||||
{
|
||||
_progressEpoch = 0;
|
||||
_progressMediaEpoch = 0;
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
#ifndef CHANNEL_H
|
||||
#define CHANNEL_H
|
||||
|
||||
#include <QtCore>
|
||||
|
||||
class Channel
|
||||
{
|
||||
public:
|
||||
Channel() {}
|
||||
Channel(QString uuid);
|
||||
QString getUuid() { return _uuid; }
|
||||
void setCidName(QString cidName) { _cidName = cidName; }
|
||||
QString getCidName() { return _cidName; }
|
||||
void setCidNumber(QString cidNumber) { _cidNumber = cidNumber; }
|
||||
QString getCidNumber() { return _cidNumber; }
|
||||
void setDestinatinonNumber(QString destinationNumber) { _destinationNumber = destinationNumber; }
|
||||
QString getDestinationNumber() { return _destinationNumber; }
|
||||
|
||||
int getPaCallId() { return _paCallId; }
|
||||
void setPaCallId(int paCallId) { _paCallId = paCallId;}
|
||||
|
||||
void setProgressEpoch(qulonglong time) { _progressEpoch = time/1000000; }
|
||||
qulonglong getProgressEpoch() { return _progressEpoch; }
|
||||
void setProgressMediaEpoch(qulonglong time) { _progressMediaEpoch = time/1000000; }
|
||||
qulonglong getProgressMediaEpoch() { return _progressMediaEpoch; }
|
||||
|
||||
private:
|
||||
QString _uuid;
|
||||
QString _cidName;
|
||||
QString _cidNumber;
|
||||
QString _destinationNumber;
|
||||
int _paCallId;
|
||||
qulonglong _progressEpoch;
|
||||
qulonglong _progressMediaEpoch;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(Channel)
|
||||
|
||||
#endif // CHANNEL_H
|
|
@ -89,6 +89,7 @@
|
|||
<load module="mod_ilbc"/>
|
||||
<load module="mod_speex"/>
|
||||
<load module="mod_celt"/>
|
||||
<load module="mod_silk"/>
|
||||
<load module="mod_siren"/>
|
||||
<load module="mod_sndfile"/>
|
||||
<load module="mod_tone_stream"/>
|
||||
|
|
|
@ -43,9 +43,10 @@ FSHost::FSHost(QObject *parent) :
|
|||
switch_core_set_globals();
|
||||
|
||||
qRegisterMetaType<QSharedPointer<Call> >("QSharedPointer<Call>");
|
||||
qRegisterMetaType<QSharedPointer<Call> >("QSharedPointer<Channel>");
|
||||
qRegisterMetaType<QSharedPointer<Account> >("QSharedPointer<Account>");
|
||||
|
||||
connect(this, SIGNAL(loadedModule(QString,QString,QString)), this, SLOT(minimalModuleLoaded(QString,QString,QString)));
|
||||
connect(this, SIGNAL(loadedModule(QString,QString)), this, SLOT(minimalModuleLoaded(QString,QString)));
|
||||
|
||||
}
|
||||
|
||||
|
@ -167,261 +168,170 @@ void FSHost::run(void)
|
|||
}
|
||||
}
|
||||
|
||||
switch_status_t FSHost::processAlegEvent(switch_event_t * event, QString uuid)
|
||||
void FSHost::generalEventHandler(QSharedPointer<switch_event_t>event)
|
||||
{
|
||||
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
||||
QSharedPointer<Call> call = _active_calls.value(uuid);
|
||||
QString uuid = switch_event_get_header_nil(event.data(), "Unique-ID");
|
||||
|
||||
if (call.isNull())
|
||||
{
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "We don't have a call object for A leg on event %s.\n", switch_event_name(event->event_id));
|
||||
qDebug() << _active_calls.keys();
|
||||
printEventHeaders(event);
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
/* Inbound call */
|
||||
if (call.data()->getDirection() == FSCOMM_CALL_DIRECTION_INBOUND)
|
||||
{
|
||||
switch(event->event_id) {
|
||||
case SWITCH_EVENT_CHANNEL_ANSWER:
|
||||
{
|
||||
QString answeredEpoch = switch_event_get_header_nil(event, "Caller-Channel-Answered-Time");
|
||||
call.data()->setAnsweredEpoch(answeredEpoch.toLong());
|
||||
call.data()->setbUUID(switch_event_get_header_nil(event, "Other-Leg-Unique-ID"));
|
||||
_bleg_uuids.insert(switch_event_get_header_nil(event, "Other-Leg-Unique-ID"), uuid);
|
||||
call.data()->setState(FSCOMM_CALL_STATE_ANSWERED);
|
||||
emit answered(call);
|
||||
break;
|
||||
}
|
||||
case SWITCH_EVENT_CHANNEL_HANGUP_COMPLETE:
|
||||
{
|
||||
emit hungup(_active_calls.take(uuid));
|
||||
break;
|
||||
}
|
||||
case SWITCH_EVENT_CHANNEL_STATE:
|
||||
{
|
||||
qDebug() << QString("CHANNEL_STATE Answer-State: %1 | Channel-State: %2 | %3 | %4\n").arg(switch_event_get_header_nil(event, "Answer-State"),switch_event_get_header_nil(event, "Channel-State"), uuid.toAscii().constData(), switch_event_get_header_nil(event, "Other-Leg-Unique-ID"));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Outbound call */
|
||||
else
|
||||
{
|
||||
switch(event->event_id)
|
||||
switch(event.data()->event_id) {
|
||||
case SWITCH_EVENT_CHANNEL_CREATE: /*1A - 17B*/
|
||||
{
|
||||
case SWITCH_EVENT_CHANNEL_BRIDGE:
|
||||
{
|
||||
_active_calls.value(uuid).data()->setbUUID(switch_event_get_header_nil(event, "Other-Leg-Unique-ID"));
|
||||
_bleg_uuids.insert(switch_event_get_header_nil(event, "Other-Leg-Unique-ID"), uuid);
|
||||
break;
|
||||
}
|
||||
case SWITCH_EVENT_CHANNEL_HANGUP_COMPLETE:
|
||||
{
|
||||
if (call.data()->getState() == FSCOMM_CALL_STATE_TRYING)
|
||||
{
|
||||
QString cause = switch_event_get_header_nil(event, "Hangup-Cause");
|
||||
call.data()->setState(FSCOMM_CALL_STATE_FAILED);
|
||||
call.data()->setCause(cause);
|
||||
emit callFailed(call);
|
||||
_active_calls.take(uuid);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
qDebug() << QString("A leg: %1(%2)\n").arg(switch_event_name(event->event_id), switch_event_get_header_nil(event, "Event-Subclass"));
|
||||
eventChannelCreate(event, uuid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
switch_status_t FSHost::processBlegEvent(switch_event_t * event, QString buuid)
|
||||
{
|
||||
QString uuid = _bleg_uuids.value(buuid);
|
||||
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
||||
QSharedPointer<Call> call = _active_calls.value(uuid);
|
||||
|
||||
if (call.isNull())
|
||||
{
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "We don't have a call object for B leg on event %s.\n", switch_event_name(event->event_id));
|
||||
qDebug() << _active_calls.keys();
|
||||
printEventHeaders(event);
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
/* Inbound call */
|
||||
if (call.data()->getDirection() == FSCOMM_CALL_DIRECTION_INBOUND)
|
||||
{
|
||||
qDebug() << " Inbound call";
|
||||
}
|
||||
/* Outbound call */
|
||||
else
|
||||
{
|
||||
switch(event->event_id)
|
||||
case SWITCH_EVENT_CHANNEL_ANSWER: /*2A - 31B*/
|
||||
{
|
||||
case SWITCH_EVENT_CHANNEL_ANSWER:
|
||||
{
|
||||
/* When do we get here? */
|
||||
QString answeredEpoch = switch_event_get_header_nil(event, "Caller-Channel-Answered-Time");
|
||||
call.data()->setAnsweredEpoch(answeredEpoch.toULongLong());
|
||||
emit answered(call);
|
||||
break;
|
||||
}
|
||||
case SWITCH_EVENT_CHANNEL_HANGUP_COMPLETE:
|
||||
{
|
||||
_active_calls.take(uuid);
|
||||
emit hungup(call);
|
||||
_bleg_uuids.take(buuid);
|
||||
break;
|
||||
}
|
||||
case SWITCH_EVENT_CHANNEL_STATE:
|
||||
{
|
||||
if (QString(switch_event_get_header_nil(event, "Answer-State")) == "early")
|
||||
{
|
||||
call.data()->setState(FSCOMM_CALL_STATE_RINGING);
|
||||
emit ringing(call);
|
||||
}
|
||||
else if (QString(switch_event_get_header_nil(event, "Answer-State")) == "answered")
|
||||
{
|
||||
call.data()->setState(FSCOMM_CALL_STATE_ANSWERED);
|
||||
emit answered(call);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
qDebug() << QString("B leg: %1(%2)\n").arg(switch_event_name(event->event_id), switch_event_get_header_nil(event, "Event-Subclass"));
|
||||
eventChannelAnswer(event, uuid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
void FSHost::generalEventHandler(switch_event_t *event)
|
||||
{
|
||||
/*printEventHeaders(event);*/
|
||||
QString uuid = switch_event_get_header_nil(event, "Unique-ID");
|
||||
|
||||
if (_bleg_uuids.contains(uuid))
|
||||
{
|
||||
if (processBlegEvent(event, uuid) == SWITCH_STATUS_SUCCESS)
|
||||
case SWITCH_EVENT_CODEC:/*3/4A - 24/25B*/
|
||||
{
|
||||
return;
|
||||
eventCodec(event, uuid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (_active_calls.contains(uuid))
|
||||
{
|
||||
if (processAlegEvent(event, uuid) == SWITCH_STATUS_SUCCESS)
|
||||
case SWITCH_EVENT_CHANNEL_STATE:/*6/7/8/37/44/46A - 20/21/22/28/38/40/42B*/
|
||||
{
|
||||
return;
|
||||
eventChannelState(event, uuid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* This is how we identify new calls, inbound and outbound */
|
||||
switch(event->event_id) {
|
||||
case SWITCH_EVENT_CUSTOM:
|
||||
case SWITCH_EVENT_CHANNEL_EXECUTE:/*9/11/13/15A*/
|
||||
{
|
||||
if (strcmp(event->subclass_name, "portaudio::ringing") == 0 && !_active_calls.contains(uuid))
|
||||
eventChannelExecute(event, uuid);
|
||||
break;
|
||||
}
|
||||
case SWITCH_EVENT_CHANNEL_EXECUTE_COMPLETE:/*10/12/14/16/35A*/
|
||||
{
|
||||
eventChannelExecuteComplete(event, uuid);
|
||||
break;
|
||||
}
|
||||
case SWITCH_EVENT_CHANNEL_OUTGOING:/*18B*/
|
||||
{
|
||||
eventChannelOutgoing(event, uuid);
|
||||
break;
|
||||
}
|
||||
case SWITCH_EVENT_CHANNEL_ORIGINATE:/*19B*/
|
||||
{
|
||||
eventChannelOriginate(event, uuid);
|
||||
break;
|
||||
}
|
||||
case SWITCH_EVENT_CALL_UPDATE:/*23/29/30B*/
|
||||
{
|
||||
eventCallUpdate(event, uuid);
|
||||
break;
|
||||
}
|
||||
case SWITCH_EVENT_CHANNEL_PROGRESS:
|
||||
{
|
||||
eventChannelProgress(event, uuid);
|
||||
break;
|
||||
}
|
||||
case SWITCH_EVENT_CHANNEL_PROGRESS_MEDIA:/*26B*/
|
||||
{
|
||||
eventChannelProgressMedia(event, uuid);
|
||||
break;
|
||||
}
|
||||
case SWITCH_EVENT_CHANNEL_BRIDGE:/*27A*/
|
||||
{
|
||||
eventChannelBridge(event, uuid);
|
||||
break;
|
||||
}
|
||||
/*32?*/
|
||||
/*case SWITCH_EVENT_RECV_INFO:
|
||||
{
|
||||
eventRecvInfo(event, uuid);
|
||||
break;
|
||||
}*/
|
||||
case SWITCH_EVENT_CHANNEL_HANGUP:/*36A-33B*/
|
||||
{
|
||||
eventChannelHangup(event, uuid);
|
||||
break;
|
||||
}
|
||||
case SWITCH_EVENT_CHANNEL_UNBRIDGE:/*34A*/
|
||||
{
|
||||
eventChannelUnbridge(event, uuid);
|
||||
break;
|
||||
}
|
||||
case SWITCH_EVENT_CHANNEL_HANGUP_COMPLETE:/*39/43B*/
|
||||
{
|
||||
eventChannelHangupComplete(event, uuid);
|
||||
break;
|
||||
}
|
||||
case SWITCH_EVENT_CHANNEL_DESTROY:/*45A-41B*/
|
||||
{
|
||||
eventChannelDestroy(event, uuid);
|
||||
break;
|
||||
}
|
||||
case SWITCH_EVENT_CUSTOM:/*5A*/
|
||||
{
|
||||
if (strcmp(event.data()->subclass_name, "sofia::gateway_state") == 0)
|
||||
{
|
||||
Call *callPtr = new Call(atoi(switch_event_get_header_nil(event, "call_id")),
|
||||
switch_event_get_header_nil(event, "Caller-Caller-ID-Name"),
|
||||
switch_event_get_header_nil(event, "Caller-Caller-ID-Number"),
|
||||
FSCOMM_CALL_DIRECTION_INBOUND,
|
||||
uuid);
|
||||
QSharedPointer<Call> call(callPtr);
|
||||
_active_calls.insert(uuid, call);
|
||||
call.data()->setState(FSCOMM_CALL_STATE_RINGING);
|
||||
emit ringing(call);
|
||||
}
|
||||
else if (strcmp(event->subclass_name, "portaudio::makecall") == 0)
|
||||
{
|
||||
Call *callPtr = new Call(atoi(switch_event_get_header_nil(event, "call_id")),NULL,
|
||||
switch_event_get_header_nil(event, "Caller-Destination-Number"),
|
||||
FSCOMM_CALL_DIRECTION_OUTBOUND,
|
||||
uuid);
|
||||
QSharedPointer<Call> call(callPtr);
|
||||
_active_calls.insert(uuid, call);
|
||||
call.data()->setState(FSCOMM_CALL_STATE_TRYING);
|
||||
emit newOutgoingCall(call);
|
||||
}
|
||||
else if (strcmp(event->subclass_name, "sofia::gateway_state") == 0)
|
||||
{
|
||||
QString state = switch_event_get_header_nil(event, "State");
|
||||
QString gw = switch_event_get_header_nil(event, "Gateway");
|
||||
QString state = switch_event_get_header_nil(event.data(), "State");
|
||||
QString gw = switch_event_get_header_nil(event.data(), "Gateway");
|
||||
QSharedPointer<Account> acc = _accounts.value(gw);
|
||||
if (acc.isNull())
|
||||
return;
|
||||
|
||||
if (state == "TRYING") {
|
||||
acc.data()->setStatusPhrase(switch_event_get_header_nil(event, "Phrase"));
|
||||
acc.data()->setStatusPhrase(switch_event_get_header_nil(event.data(), "Phrase"));
|
||||
acc.data()->setState(FSCOMM_GW_STATE_TRYING);
|
||||
emit accountStateChange(acc);
|
||||
} else if (state == "REGISTER") {
|
||||
acc.data()->setStatusPhrase(switch_event_get_header_nil(event, "Phrase"));
|
||||
acc.data()->setStatusPhrase(switch_event_get_header_nil(event.data(), "Phrase"));
|
||||
acc.data()->setState(FSCOMM_GW_STATE_REGISTER);
|
||||
emit accountStateChange(acc);
|
||||
} else if (state == "REGED") {
|
||||
acc.data()->setStatusPhrase(switch_event_get_header_nil(event, "Phrase"));
|
||||
acc.data()->setStatusPhrase(switch_event_get_header_nil(event.data(), "Phrase"));
|
||||
acc.data()->setState(FSCOMM_GW_STATE_REGED);
|
||||
emit accountStateChange(acc);
|
||||
} else if (state == "UNREGED") {
|
||||
acc.data()->setStatusPhrase(switch_event_get_header_nil(event, "Phrase"));
|
||||
acc.data()->setStatusPhrase(switch_event_get_header_nil(event.data(), "Phrase"));
|
||||
acc.data()->setState(FSCOMM_GW_STATE_UNREGED);
|
||||
emit accountStateChange(acc);
|
||||
} else if (state == "UNREGISTER") {
|
||||
acc.data()->setStatusPhrase(switch_event_get_header_nil(event, "Phrase"));
|
||||
acc.data()->setStatusPhrase(switch_event_get_header_nil(event.data(), "Phrase"));
|
||||
acc.data()->setState(FSCOMM_GW_STATE_UNREGISTER);
|
||||
emit accountStateChange(acc);
|
||||
} else if (state =="FAILED") {
|
||||
acc.data()->setStatusPhrase(switch_event_get_header_nil(event, "Phrase"));
|
||||
acc.data()->setStatusPhrase(switch_event_get_header_nil(event.data(), "Phrase"));
|
||||
acc.data()->setState(FSCOMM_GW_STATE_FAILED);
|
||||
emit accountStateChange(acc);
|
||||
} else if (state == "FAIL_WAIT") {
|
||||
acc.data()->setState(FSCOMM_GW_STATE_FAIL_WAIT);
|
||||
emit accountStateChange(acc);
|
||||
} else if (state == "EXPIRED") {
|
||||
acc.data()->setStatusPhrase(switch_event_get_header_nil(event, "Phrase"));
|
||||
acc.data()->setStatusPhrase(switch_event_get_header_nil(event.data(), "Phrase"));
|
||||
acc.data()->setState(FSCOMM_GW_STATE_EXPIRED);
|
||||
emit accountStateChange(acc);
|
||||
} else if (state == "NOREG") {
|
||||
acc.data()->setStatusPhrase(switch_event_get_header_nil(event, "Phrase"));
|
||||
acc.data()->setStatusPhrase(switch_event_get_header_nil(event.data(), "Phrase"));
|
||||
acc.data()->setState(FSCOMM_GW_STATE_NOREG);
|
||||
emit accountStateChange(acc);
|
||||
}
|
||||
}
|
||||
else if (strcmp(event->subclass_name, "sofia::gateway_add") == 0)
|
||||
else if (strcmp(event.data()->subclass_name, "sofia::gateway_add") == 0)
|
||||
{
|
||||
QString gw = switch_event_get_header_nil(event, "Gateway");
|
||||
QString gw = switch_event_get_header_nil(event.data(), "Gateway");
|
||||
Account * accPtr = new Account(gw);
|
||||
QSharedPointer<Account> acc = QSharedPointer<Account>(accPtr);
|
||||
acc.data()->setState(FSCOMM_GW_STATE_NOAVAIL);
|
||||
_accounts.insert(gw, acc);
|
||||
emit newAccount(acc);
|
||||
}
|
||||
else if (strcmp(event->subclass_name, "sofia::gateway_delete") == 0)
|
||||
else if (strcmp(event.data()->subclass_name, "sofia::gateway_delete") == 0)
|
||||
{
|
||||
QSharedPointer<Account> acc = _accounts.take(switch_event_get_header_nil(event, "Gateway"));
|
||||
QSharedPointer<Account> acc = _accounts.take(switch_event_get_header_nil(event.data(), "Gateway"));
|
||||
if (!acc.isNull())
|
||||
emit delAccount(acc);
|
||||
}
|
||||
else
|
||||
{
|
||||
printEventHeaders(event);
|
||||
//printEventHeaders(event);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SWITCH_EVENT_MODULE_LOAD:
|
||||
{
|
||||
QString modType = switch_event_get_header_nil(event, "type");
|
||||
QString modName = switch_event_get_header_nil(event, "name");
|
||||
QString modKey = switch_event_get_header_nil(event, "key");
|
||||
emit loadedModule(modType, modName, modKey);
|
||||
QString modType = switch_event_get_header_nil(event.data(), "type");
|
||||
QString modKey = switch_event_get_header_nil(event.data(), "key");
|
||||
emit loadedModule(modType, modKey);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -429,7 +339,107 @@ void FSHost::generalEventHandler(switch_event_t *event)
|
|||
}
|
||||
}
|
||||
|
||||
void FSHost::minimalModuleLoaded(QString modType, QString modName, QString modKey)
|
||||
void FSHost::eventChannelCreate(QSharedPointer<switch_event_t>event, QString uuid)
|
||||
{
|
||||
Channel *channelPtr = new Channel(uuid);
|
||||
QSharedPointer<Channel>channel(channelPtr);
|
||||
_channels.insert(uuid, channel);
|
||||
}
|
||||
void FSHost::eventChannelAnswer(QSharedPointer<switch_event_t>event, QString uuid)
|
||||
{
|
||||
_channels.value(uuid).data()->setDestinatinonNumber(switch_event_get_header_nil(event.data(), "Caller-Destination-Number"));
|
||||
if (_active_calls.contains(uuid))
|
||||
{
|
||||
_active_calls.value(uuid).data()->setAnsweredEpoch(QString(switch_event_get_header_nil(event.data(), "Caller-Channel-Answered-Time")).toULongLong());
|
||||
_active_calls.value(uuid).data()->setState(FSCOMM_CALL_STATE_ANSWERED);
|
||||
emit answered(_active_calls.value(uuid));
|
||||
}
|
||||
}
|
||||
void FSHost::eventChannelState(QSharedPointer<switch_event_t>event, QString uuid)
|
||||
{}
|
||||
void FSHost::eventChannelExecute(QSharedPointer<switch_event_t>event, QString uuid)
|
||||
{}
|
||||
void FSHost::eventChannelExecuteComplete(QSharedPointer<switch_event_t>event, QString uuid)
|
||||
{
|
||||
_channels.value(uuid).data()->setPaCallId(atoi(switch_event_get_header_nil(event.data(), "variable_pa_call_id")));
|
||||
}
|
||||
void FSHost::eventChannelOutgoing(QSharedPointer<switch_event_t>event, QString uuid)
|
||||
{
|
||||
/* Checks if this is an inbound or outbound call */
|
||||
/** Outbound call */
|
||||
if ( strcmp(switch_event_get_header_nil(event.data(), "Caller-Source"), "mod_portaudio") == 0 )
|
||||
{
|
||||
Call *callPtr = new Call();
|
||||
|
||||
callPtr->setCallDirection(FSCOMM_CALL_DIRECTION_OUTBOUND);
|
||||
callPtr->setChannel(_channels.value(uuid));
|
||||
callPtr->setOtherLegChannel(_channels.value(switch_event_get_header_nil(event.data(), "Other-Leg-Unique-ID")));
|
||||
QSharedPointer<Call> call(callPtr);
|
||||
_active_calls.insert(uuid, call);
|
||||
call.data()->setState(FSCOMM_CALL_STATE_TRYING);
|
||||
emit newOutgoingCall(call);
|
||||
}
|
||||
/** Inbound call */
|
||||
else
|
||||
{
|
||||
Call *callPtr = new Call();
|
||||
|
||||
callPtr->setCallDirection(FSCOMM_CALL_DIRECTION_INBOUND);
|
||||
callPtr->setChannel(_channels.value(switch_event_get_header_nil(event.data(), "Other-Leg-Unique-ID")));
|
||||
callPtr->setOtherLegChannel(_channels.value(uuid));
|
||||
QSharedPointer<Call> call(callPtr);
|
||||
_active_calls.insert(switch_event_get_header_nil(event.data(), "Other-Leg-Unique-ID"), call);
|
||||
call.data()->setState(FSCOMM_CALL_STATE_RINGING);
|
||||
emit ringing(call);
|
||||
}
|
||||
}
|
||||
void FSHost::eventChannelOriginate(QSharedPointer<switch_event_t>event, QString uuid)
|
||||
{}
|
||||
void FSHost::eventChannelProgress(QSharedPointer<switch_event_t>event, QString uuid)
|
||||
{}
|
||||
void FSHost::eventChannelProgressMedia(QSharedPointer<switch_event_t>event, QString uuid)
|
||||
{
|
||||
_channels.value(uuid).data()->setProgressEpoch(QString(switch_event_get_header_nil(event.data(), "Caller-Channel-Progress-Time")).toULongLong());
|
||||
if (_active_calls.contains(uuid))
|
||||
{
|
||||
_active_calls.value(uuid).data()->setState(FSCOMM_CALL_STATE_RINGING);
|
||||
emit ringing(_active_calls.value(uuid));
|
||||
}
|
||||
}
|
||||
void FSHost::eventChannelBridge(QSharedPointer<switch_event_t>event, QString uuid)
|
||||
{
|
||||
QString time;
|
||||
time = switch_event_get_header_nil(event.data(), "Caller-Channel-Progress-Time");
|
||||
if (time.toULongLong() > 0) _channels.value(uuid).data()->setProgressEpoch(time.toULongLong());
|
||||
time = switch_event_get_header_nil(event.data(), "Caller-Channel-Progress-Media-Time");
|
||||
if (time.toULongLong() > 0) _channels.value(uuid).data()->setProgressMediaEpoch(time.toULongLong());
|
||||
}
|
||||
void FSHost::eventChannelHangup(QSharedPointer<switch_event_t>event, QString uuid)
|
||||
{
|
||||
if (_active_calls.contains(uuid))
|
||||
{
|
||||
emit hungup(_active_calls.take(uuid));
|
||||
}
|
||||
}
|
||||
void FSHost::eventChannelUnbridge(QSharedPointer<switch_event_t>event, QString uuid)
|
||||
{}
|
||||
void FSHost::eventChannelHangupComplete(QSharedPointer<switch_event_t>event, QString uuid)
|
||||
{}
|
||||
void FSHost::eventChannelDestroy(QSharedPointer<switch_event_t>event, QString uuid)
|
||||
{
|
||||
_channels.take(uuid);
|
||||
}
|
||||
void FSHost::eventCodec(QSharedPointer<switch_event_t>event, QString uuid)
|
||||
{
|
||||
_channels.value(uuid).data()->setCidName(switch_event_get_header_nil(event.data(), "Caller-Caller-ID-Name"));
|
||||
_channels.value(uuid).data()->setCidNumber(switch_event_get_header_nil(event.data(), "Caller-Caller-ID-Number"));
|
||||
}
|
||||
void FSHost::eventCallUpdate(QSharedPointer<switch_event_t>event, QString uuid)
|
||||
{}
|
||||
void FSHost::eventRecvInfo(QSharedPointer<switch_event_t>event, QString uuid)
|
||||
{}
|
||||
|
||||
void FSHost::minimalModuleLoaded(QString modType, QString modKey)
|
||||
{
|
||||
if (modType == "endpoint")
|
||||
{
|
||||
|
@ -501,11 +511,11 @@ QSharedPointer<Call> FSHost::getCurrentActiveCall()
|
|||
return QSharedPointer<Call>();
|
||||
}
|
||||
|
||||
void FSHost::printEventHeaders(switch_event_t *event)
|
||||
void FSHost::printEventHeaders(QSharedPointer<switch_event_t>event)
|
||||
{
|
||||
switch_event_header_t *hp;
|
||||
qDebug() << QString("Received event: %1(%2)\n").arg(switch_event_name(event->event_id), switch_event_get_header_nil(event, "Event-Subclass"));
|
||||
for (hp = event->headers; hp; hp = hp->next) {
|
||||
qDebug() << QString("Received event: %1(%2)").arg(switch_event_name(event.data()->event_id), switch_event_get_header_nil(event.data(), "Event-Subclass"));
|
||||
for (hp = event.data()->headers; hp; hp = hp->next) {
|
||||
qDebug() << hp->name << "=" << hp->value;
|
||||
}
|
||||
qDebug() << "\n\n";
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include <QSharedPointer>
|
||||
#include <switch.h>
|
||||
#include "call.h"
|
||||
#include "channel.h"
|
||||
#include "account.h"
|
||||
|
||||
class FSHost : public QThread
|
||||
|
@ -43,7 +44,7 @@ Q_OBJECT
|
|||
public:
|
||||
explicit FSHost(QObject *parent = 0);
|
||||
switch_status_t sendCmd(const char *cmd, const char *args, QString *res);
|
||||
void generalEventHandler(switch_event_t *event);
|
||||
void generalEventHandler(QSharedPointer<switch_event_t>event);
|
||||
QSharedPointer<Call> getCallByUUID(QString uuid) { return _active_calls.value(uuid); }
|
||||
QSharedPointer<Call> getCurrentActiveCall();
|
||||
QList<QSharedPointer<Account> > getAccounts() { return _accounts.values(); }
|
||||
|
@ -57,15 +58,20 @@ protected:
|
|||
void run(void);
|
||||
|
||||
signals:
|
||||
/* Status signals */
|
||||
void coreLoadingError(QString);
|
||||
void loadingModules(QString, int, QColor);
|
||||
void loadedModule(QString, QString, QString);
|
||||
void loadedModule(QString, QString);
|
||||
void ready(void);
|
||||
|
||||
/* Call signals */
|
||||
void ringing(QSharedPointer<Call>);
|
||||
void answered(QSharedPointer<Call>);
|
||||
void newOutgoingCall(QSharedPointer<Call>);
|
||||
void callFailed(QSharedPointer<Call>);
|
||||
void hungup(QSharedPointer<Call>);
|
||||
|
||||
/* Account signals */
|
||||
void accountStateChange(QSharedPointer<Account>);
|
||||
void newAccount(QSharedPointer<Account>);
|
||||
void delAccount(QSharedPointer<Account>);
|
||||
|
@ -73,16 +79,39 @@ signals:
|
|||
private slots:
|
||||
/* We need to wait for the gateway deletion before reloading it */
|
||||
void accountReloadSlot(QSharedPointer<Account>);
|
||||
void minimalModuleLoaded(QString, QString, QString);
|
||||
void minimalModuleLoaded(QString, QString);
|
||||
|
||||
private:
|
||||
switch_status_t processBlegEvent(switch_event_t *, QString);
|
||||
switch_status_t processAlegEvent(switch_event_t *, QString);
|
||||
/* Helper methods */
|
||||
void createFolders();
|
||||
void printEventHeaders(switch_event_t *event);
|
||||
void printEventHeaders(QSharedPointer<switch_event_t>event);
|
||||
|
||||
/*FSM State handlers*/
|
||||
/** Channel Related*/
|
||||
void eventChannelCreate(QSharedPointer<switch_event_t> event, QString uuid);
|
||||
void eventChannelAnswer(QSharedPointer<switch_event_t> event, QString uuid);
|
||||
void eventChannelState(QSharedPointer<switch_event_t>event, QString uuid);
|
||||
void eventChannelExecute(QSharedPointer<switch_event_t>event, QString uuid);
|
||||
void eventChannelExecuteComplete(QSharedPointer<switch_event_t>event, QString uuid);
|
||||
void eventChannelOutgoing(QSharedPointer<switch_event_t>event, QString uuid);
|
||||
void eventChannelOriginate(QSharedPointer<switch_event_t>event, QString uuid);
|
||||
void eventChannelProgress(QSharedPointer<switch_event_t>event, QString uuid);
|
||||
void eventChannelProgressMedia(QSharedPointer<switch_event_t>event, QString uuid);
|
||||
void eventChannelBridge(QSharedPointer<switch_event_t>event, QString uuid);
|
||||
void eventChannelHangup(QSharedPointer<switch_event_t>event, QString uuid);
|
||||
void eventChannelUnbridge(QSharedPointer<switch_event_t>event, QString uuid);
|
||||
void eventChannelHangupComplete(QSharedPointer<switch_event_t>event, QString uuid);
|
||||
void eventChannelDestroy(QSharedPointer<switch_event_t>event, QString uuid);
|
||||
|
||||
/** Others*/
|
||||
void eventCodec(QSharedPointer<switch_event_t>event, QString uuid);
|
||||
void eventCallUpdate(QSharedPointer<switch_event_t>event, QString uuid);
|
||||
void eventRecvInfo(QSharedPointer<switch_event_t>event, QString uuid);
|
||||
|
||||
/* Structures to keep track of things */
|
||||
QHash<QString, QSharedPointer<Call> > _active_calls;
|
||||
QHash<QString, QSharedPointer<Account> > _accounts;
|
||||
QHash<QString, QString> _bleg_uuids;
|
||||
QHash<QString, QSharedPointer<Channel> > _channels;
|
||||
QList<QString> _reloading_Accounts;
|
||||
QList<QString> _loadedModules;
|
||||
};
|
||||
|
@ -97,9 +126,9 @@ static void eventHandlerCallback(switch_event_t *event)
|
|||
{
|
||||
switch_event_t *clone = NULL;
|
||||
if (switch_event_dup(&clone, event) == SWITCH_STATUS_SUCCESS) {
|
||||
g_FSHost.generalEventHandler(clone);
|
||||
QSharedPointer<switch_event_t> e(clone);
|
||||
g_FSHost.generalEventHandler(e);
|
||||
}
|
||||
switch_safe_free(clone);
|
||||
}
|
||||
|
||||
#endif // FSHOST_H
|
||||
|
|
|
@ -133,7 +133,7 @@ void MainWindow::updateCallTimers()
|
|||
QSharedPointer<Call> call = g_FSHost.getCallByUUID(item->data(Qt::UserRole).toString());
|
||||
QTime time = call.data()->getCurrentStateTime();
|
||||
item->setText(time.toString("hh:mm:ss"));
|
||||
item->setTextAlignment(Qt::AlignRight);
|
||||
item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -267,7 +267,6 @@ void MainWindow::makeCall()
|
|||
switch_core_set_variable("fscomm_caller_id_name", cidName.toAscii().data());
|
||||
switch_core_set_variable("fscomm_caller_id_num", cidNum.toAscii().data());
|
||||
|
||||
qDebug() << "Name:" << cidName << "Num:" << cidNum;
|
||||
}
|
||||
|
||||
if (ok && !dialstring.isEmpty())
|
||||
|
@ -357,26 +356,26 @@ void MainWindow::recordCall(bool pressed)
|
|||
tr("<p>Could not get active call to start/stop recording."
|
||||
"<p>Please report this bug."),
|
||||
QMessageBox::Ok);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not record call [%s].\n", call.data()->getUUID().toAscii().data());
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not record call [%s].\n", call.data()->getUuid().toAscii().data());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::newOutgoingCall(QSharedPointer<Call> call)
|
||||
{
|
||||
ui->textEdit->setText(QString("Calling %1 (%2)").arg(call.data()->getCidName(), call.data()->getCidNumber()));
|
||||
ui->textEdit->setText(QString("Calling %1").arg(call.data()->getDestinationNumber()));
|
||||
|
||||
ui->tableCalls->setRowCount(ui->tableCalls->rowCount()+1);
|
||||
QTableWidgetItem *item0 = new QTableWidgetItem(QString("%1 (%2)").arg(call.data()->getCidName(), call.data()->getCidNumber()));
|
||||
item0->setData(Qt::UserRole, call.data()->getUUID());
|
||||
QTableWidgetItem *item0 = new QTableWidgetItem(QString("%1").arg(call.data()->getDestinationNumber()));
|
||||
item0->setData(Qt::UserRole, call.data()->getUuid());
|
||||
ui->tableCalls->setItem(ui->tableCalls->rowCount()-1,0,item0);
|
||||
|
||||
QTableWidgetItem *item1 = new QTableWidgetItem(tr("Dialing..."));
|
||||
item1->setData(Qt::UserRole, call.data()->getUUID());
|
||||
item1->setData(Qt::UserRole, call.data()->getUuid());
|
||||
ui->tableCalls->setItem(ui->tableCalls->rowCount()-1,1,item1);
|
||||
|
||||
QTableWidgetItem *item2 = new QTableWidgetItem("00:00:00");
|
||||
item2->setData(Qt::UserRole, call.data()->getUUID());
|
||||
item2->setData(Qt::UserRole, call.data()->getUuid());
|
||||
ui->tableCalls->setItem(ui->tableCalls->rowCount()-1,2,item2);
|
||||
|
||||
ui->tableCalls->resizeColumnsToContents();
|
||||
|
@ -393,27 +392,33 @@ void MainWindow::ringing(QSharedPointer<Call> call)
|
|||
for (int i=0; i<ui->tableCalls->rowCount(); i++)
|
||||
{
|
||||
QTableWidgetItem *item = ui->tableCalls->item(i, 1);
|
||||
if (item->data(Qt::UserRole).toString() == call.data()->getUUID())
|
||||
if (item->data(Qt::UserRole).toString() == call.data()->getUuid())
|
||||
{
|
||||
item->setText(tr("Ringing"));
|
||||
ui->textEdit->setText(QString("Call from %1 (%2)").arg(call.data()->getCidName(), call.data()->getCidNumber()));
|
||||
if (call.data()->getDirection() == FSCOMM_CALL_DIRECTION_INBOUND)
|
||||
ui->textEdit->setText(QString("Call from %1 (%2)").arg(call.data()->getCidName(), call.data()->getCidNumber()));
|
||||
else
|
||||
ui->textEdit->setText(QString("Call to %1 is ringing.").arg(call.data()->getDestinationNumber()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ui->textEdit->setText(QString("Call from %1 (%2)").arg(call.data()->getCidName(), call.data()->getCidNumber()));
|
||||
if (call.data()->getDirection() == FSCOMM_CALL_DIRECTION_INBOUND)
|
||||
ui->textEdit->setText(QString("Call from %1 (%2)").arg(call.data()->getCidName(), call.data()->getCidNumber()));
|
||||
else
|
||||
ui->textEdit->setText(QString("Call to %1 is ringing.").arg(call.data()->getDestinationNumber()));
|
||||
|
||||
ui->tableCalls->setRowCount(ui->tableCalls->rowCount()+1);
|
||||
QTableWidgetItem *item0 = new QTableWidgetItem(QString("%1 (%2)").arg(call.data()->getCidName(), call.data()->getCidNumber()));
|
||||
item0->setData(Qt::UserRole, call.data()->getUUID());
|
||||
item0->setData(Qt::UserRole, call.data()->getUuid());
|
||||
ui->tableCalls->setItem(ui->tableCalls->rowCount()-1,0,item0);
|
||||
|
||||
QTableWidgetItem *item1 = new QTableWidgetItem(tr("Ringing"));
|
||||
item1->setData(Qt::UserRole, call.data()->getUUID());
|
||||
item1->setData(Qt::UserRole, call.data()->getUuid());
|
||||
ui->tableCalls->setItem(ui->tableCalls->rowCount()-1,1,item1);
|
||||
|
||||
QTableWidgetItem *item2 = new QTableWidgetItem("00:00:00");
|
||||
item2->setData(Qt::UserRole, call.data()->getUUID());
|
||||
item2->setData(Qt::UserRole, call.data()->getUuid());
|
||||
ui->tableCalls->setItem(ui->tableCalls->rowCount()-1,2,item2);
|
||||
|
||||
ui->tableCalls->resizeColumnsToContents();
|
||||
|
@ -429,7 +434,7 @@ void MainWindow::answered(QSharedPointer<Call> call)
|
|||
for (int i=0; i<ui->tableCalls->rowCount(); i++)
|
||||
{
|
||||
QTableWidgetItem *item = ui->tableCalls->item(i, 1);
|
||||
if (item->data(Qt::UserRole).toString() == call.data()->getUUID())
|
||||
if (item->data(Qt::UserRole).toString() == call.data()->getUuid())
|
||||
{
|
||||
item->setText(tr("Answered"));
|
||||
ui->tableCalls->resizeColumnsToContents();
|
||||
|
@ -463,7 +468,7 @@ void MainWindow::callFailed(QSharedPointer<Call> call)
|
|||
for (int i=0; i<ui->tableCalls->rowCount(); i++)
|
||||
{
|
||||
QTableWidgetItem *item = ui->tableCalls->item(i, 1);
|
||||
if (item->data(Qt::UserRole).toString() == call.data()->getUUID())
|
||||
if (item->data(Qt::UserRole).toString() == call.data()->getUuid())
|
||||
{
|
||||
ui->tableCalls->removeRow(i);
|
||||
ui->tableCalls->resizeColumnsToContents();
|
||||
|
@ -505,7 +510,7 @@ void MainWindow::hungup(QSharedPointer<Call> call)
|
|||
for (int i=0; i<ui->tableCalls->rowCount(); i++)
|
||||
{
|
||||
QTableWidgetItem *item = ui->tableCalls->item(i, 1);
|
||||
if (item->data(Qt::UserRole).toString() == call.data()->getUUID())
|
||||
if (item->data(Qt::UserRole).toString() == call.data()->getUuid())
|
||||
{
|
||||
ui->tableCalls->removeRow(i);
|
||||
ui->tableCalls->resizeColumnsToContents();
|
||||
|
@ -515,7 +520,14 @@ void MainWindow::hungup(QSharedPointer<Call> call)
|
|||
}
|
||||
}
|
||||
call.data()->setActive(false);
|
||||
ui->textEdit->setText(tr("Call with %1 (%2) hungup.").arg(call.data()->getCidName(), call.data()->getCidNumber()));
|
||||
if (call.data()->getDirection() == FSCOMM_CALL_DIRECTION_INBOUND)
|
||||
{
|
||||
ui->textEdit->setText(tr("Call with %1 (%2) hungup.").arg(call.data()->getCidName(), call.data()->getCidNumber()));
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->textEdit->setText(tr("Call with %1 hungup.").arg(call.data()->getDestinationNumber()));
|
||||
}
|
||||
/* TODO: Will cause problems if 2 calls are received at the same time */
|
||||
ui->recoredCallBtn->setEnabled(false);
|
||||
ui->recoredCallBtn->setChecked(false);
|
||||
|
|
|
@ -201,7 +201,7 @@
|
|||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>2</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab">
|
||||
<attribute name="title">
|
||||
|
@ -490,28 +490,17 @@
|
|||
<string>Codecs</string>
|
||||
</attribute>
|
||||
<layout class="QFormLayout" name="formLayout_7">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_21">
|
||||
<property name="text">
|
||||
<string>codec-prefs</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="sofiaCodecPrefsEdit">
|
||||
<property name="text">
|
||||
<string>CELT@48000h,G7221@32000h,G7221@16000h,G722,PCMU,PCMA,GSM</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_30">
|
||||
<property name="text">
|
||||
<string>inbound-codec-negotiation</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="sofiaInboundCodecNegotiationCombo">
|
||||
<item>
|
||||
<property name="text">
|
||||
|
@ -525,15 +514,15 @@
|
|||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_42">
|
||||
<property name="text">
|
||||
<string>Codecs</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QListWidget" name="listAvailableCodecs"/>
|
||||
<item row="1" column="1">
|
||||
<widget class="CodecWidget" name="sofiaProfileCodecWidget" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
@ -1028,6 +1017,14 @@
|
|||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>CodecWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>widgets/codecwidget.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../resources.qrc"/>
|
||||
</resources>
|
||||
|
|
|
@ -42,7 +42,7 @@ void PrefSofia::readConfig()
|
|||
_ui->sofiaSipPortSpin->setValue(settings.value("sip-port").toInt());
|
||||
_ui->sofiaDialplanEdit->setText(settings.value("dialplan").toString());
|
||||
_ui->sofiaDtmfDurationSpin->setValue(settings.value("dtmf-duration").toInt());
|
||||
_ui->sofiaCodecPrefsEdit->setText(settings.value("codec-prefs").toString());
|
||||
_ui->sofiaProfileCodecWidget->setCodecString(settings.value("codec-prefs").toString());
|
||||
_ui->sofiaUseRtpTimerCombo->setCurrentIndex(_ui->sofiaUseRtpTimerCombo->findText(settings.value("use-rtp-timer").toString()));
|
||||
_ui->sofiaRtpTimerNameEdit->setText(settings.value("rtp-timer-name").toString());
|
||||
_ui->sofiaRtpIpEdit->setText(settings.value("rtp-ip").toString());
|
||||
|
@ -68,15 +68,6 @@ void PrefSofia::readConfig()
|
|||
settings.endGroup();
|
||||
settings.endGroup();
|
||||
|
||||
/* This is here to show the proper codec config! */
|
||||
const switch_codec_implementation_t *codecs[SWITCH_MAX_CODECS];
|
||||
uint32_t num_codecs = switch_loadable_module_get_codecs(codecs, sizeof(codecs) / sizeof(codecs[0]));
|
||||
uint32_t x;
|
||||
|
||||
for (x = 0; x < num_codecs; x++) {
|
||||
_ui->listAvailableCodecs->addItem(codecs[x]->iananame);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void PrefSofia::writeConfig()
|
||||
|
@ -110,7 +101,7 @@ void PrefSofia::writeConfig()
|
|||
settings.setValue("sip-port", _ui->sofiaSipPortSpin->value());
|
||||
settings.setValue("dialplan", _ui->sofiaDialplanEdit->text());
|
||||
settings.setValue("dtmf-duration", _ui->sofiaDtmfDurationSpin->value());
|
||||
settings.setValue("codec-prefs", _ui->sofiaCodecPrefsEdit->text());
|
||||
settings.setValue("codec-prefs", _ui->sofiaProfileCodecWidget->getCodecString());
|
||||
settings.setValue("use-rtp-timer", _ui->sofiaUseRtpTimerCombo->currentText());
|
||||
settings.setValue("rtp-timer-name", _ui->sofiaRtpTimerNameEdit->text());
|
||||
settings.setValue("rtp-ip", _ui->sofiaRtpIpEdit->text());
|
||||
|
|
|
@ -0,0 +1,148 @@
|
|||
#include "codecwidget.h"
|
||||
#include "ui_codecwidget.h"
|
||||
#include "fshost.h"
|
||||
|
||||
CodecWidget::CodecWidget(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::CodecWidget)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
connect(ui->btnEnable, SIGNAL(clicked()), this, SLOT(enableCodecs()));
|
||||
connect(ui->btnDisable, SIGNAL(clicked()), this, SLOT(disableCodecs()));
|
||||
connect(ui->btnUp, SIGNAL(clicked()), this, SLOT(moveUp()));
|
||||
connect(ui->btnDown, SIGNAL(clicked()), this, SLOT(moveDown()));
|
||||
readCodecs();
|
||||
}
|
||||
|
||||
CodecWidget::~CodecWidget()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void CodecWidget::moveUp()
|
||||
{
|
||||
QList<QListWidgetItem *>items = ui->listEnabledCodecs->selectedItems();
|
||||
foreach(QListWidgetItem *item, items)
|
||||
{
|
||||
int row = ui->listEnabledCodecs->row(item);
|
||||
if (row != 0)
|
||||
ui->listEnabledCodecs->insertItem(row-1, ui->listEnabledCodecs->takeItem(row));
|
||||
}
|
||||
}
|
||||
|
||||
void CodecWidget::moveDown()
|
||||
{
|
||||
QList<QListWidgetItem *>items = ui->listEnabledCodecs->selectedItems();
|
||||
foreach(QListWidgetItem *item, items)
|
||||
{
|
||||
int row = ui->listEnabledCodecs->row(item);
|
||||
if (row != ui->listEnabledCodecs->count())
|
||||
ui->listEnabledCodecs->insertItem(row+1, ui->listEnabledCodecs->takeItem(row));
|
||||
}
|
||||
}
|
||||
|
||||
void CodecWidget::enableCodecs()
|
||||
{
|
||||
QList<QListWidgetItem *>items = ui->listAvailCodecs->selectedItems();
|
||||
foreach(QListWidgetItem *item, items)
|
||||
{
|
||||
ui->listEnabledCodecs->insertItem(0,item->text());
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
|
||||
void CodecWidget::disableCodecs()
|
||||
{
|
||||
QList<QListWidgetItem *>items = ui->listEnabledCodecs->selectedItems();
|
||||
foreach(QListWidgetItem *item, items)
|
||||
{
|
||||
ui->listAvailCodecs->insertItem(0,item->text());
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
|
||||
void CodecWidget::changeEvent(QEvent *e)
|
||||
{
|
||||
QWidget::changeEvent(e);
|
||||
switch (e->type()) {
|
||||
case QEvent::LanguageChange:
|
||||
ui->retranslateUi(this);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CodecWidget::readCodecs(void)
|
||||
{
|
||||
/* This is here to show the proper codec config! */
|
||||
const switch_codec_implementation_t *codecs[SWITCH_MAX_CODECS];
|
||||
uint32_t num_codecs = switch_loadable_module_get_codecs(codecs, sizeof(codecs) / sizeof(codecs[0]));
|
||||
uint32_t x;
|
||||
|
||||
for (x = 0; x < num_codecs; x++) {
|
||||
|
||||
/* Codecs we cannot enable/disable or dont want to */
|
||||
if (QString(codecs[x]->iananame) == "PROXY" ||
|
||||
QString(codecs[x]->iananame) == "PROXY-VID")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
QList<QHash<QString, QString> > implList;
|
||||
QHash<QString, QString> implPair;
|
||||
implPair.insert(QString::number(codecs[x]->samples_per_second), QString::number(codecs[x]->microseconds_per_packet/1000));
|
||||
implList.append(implPair);
|
||||
|
||||
/* Iterate over the other implementations */
|
||||
switch_codec_implementation_t *curr = codecs[x]->next;
|
||||
while (curr != NULL)
|
||||
{
|
||||
QHash<QString, QString> implPair;
|
||||
implPair.insert(QString::number(curr->samples_per_second), QString::number(curr->microseconds_per_packet/1000));
|
||||
implList.append(implPair);
|
||||
curr = curr->next;
|
||||
}
|
||||
_listCodecs.insert(codecs[x]->iananame, implList);
|
||||
ui->listAvailCodecs->insertItem(0, codecs[x]->iananame);
|
||||
}
|
||||
ui->listAvailCodecs->sortItems(Qt::AscendingOrder);
|
||||
}
|
||||
|
||||
QString CodecWidget::getCodecString()
|
||||
{
|
||||
QString codecList;
|
||||
for(int i = 0; i<ui->listEnabledCodecs->count(); i++)
|
||||
{
|
||||
QString codecName = ui->listEnabledCodecs->item(i)->text();
|
||||
if (!_listCodecs.contains(codecName))
|
||||
QMessageBox::warning(this, tr("Error"), tr("Codec %1 does not exist as loaded codec, therefore will not be used.").arg(codecName), QMessageBox::Ok);
|
||||
codecList += codecName;
|
||||
if (i!= ui->listEnabledCodecs->count()-1)
|
||||
codecList += ",";
|
||||
}
|
||||
return codecList;
|
||||
}
|
||||
|
||||
void CodecWidget::setCodecString(QString codecList)
|
||||
{
|
||||
QStringList rawEnCodecs;
|
||||
QStringList split = codecList.split(",");
|
||||
foreach(QString s, split)
|
||||
{
|
||||
QStringList cs = s.split("@");
|
||||
if (!rawEnCodecs.contains(cs[0]))
|
||||
{
|
||||
ui->listEnabledCodecs->insertItem(ui->listEnabledCodecs->count(), cs[0]);
|
||||
rawEnCodecs.append(cs[0]);
|
||||
}
|
||||
}
|
||||
|
||||
foreach(QString c, rawEnCodecs)
|
||||
{
|
||||
foreach(QListWidgetItem *i, ui->listAvailCodecs->findItems(c, Qt::MatchExactly))
|
||||
{
|
||||
delete i;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
#ifndef CODECWIDGET_H
|
||||
#define CODECWIDGET_H
|
||||
|
||||
#include <QtGui>
|
||||
|
||||
namespace Ui {
|
||||
class CodecWidget;
|
||||
}
|
||||
|
||||
class CodecWidget : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
CodecWidget(QWidget *parent = 0);
|
||||
~CodecWidget();
|
||||
QString getCodecString();
|
||||
void setCodecString(QString);
|
||||
|
||||
protected:
|
||||
void changeEvent(QEvent *e);
|
||||
|
||||
private slots:
|
||||
void enableCodecs();
|
||||
void disableCodecs();
|
||||
void moveUp();
|
||||
void moveDown();
|
||||
|
||||
private:
|
||||
void readCodecs(void);
|
||||
Ui::CodecWidget *ui;
|
||||
QHash<QString, QList<QHash<QString, QString> > > _listCodecs;
|
||||
};
|
||||
|
||||
#endif // CODECWIDGET_H
|
|
@ -0,0 +1,157 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>CodecWidget</class>
|
||||
<widget class="QWidget" name="CodecWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>612</width>
|
||||
<height>235</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Available Codecs</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListWidget" name="listAvailCodecs">
|
||||
<property name="dragEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="dragDropMode">
|
||||
<enum>QAbstractItemView::DragDrop</enum>
|
||||
</property>
|
||||
<property name="defaultDropAction">
|
||||
<enum>Qt::MoveAction</enum>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QToolButton" name="btnEnable">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="arrowType">
|
||||
<enum>Qt::RightArrow</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="btnDisable">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="arrowType">
|
||||
<enum>Qt::LeftArrow</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Enabled Codecs</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListWidget" name="listEnabledCodecs">
|
||||
<property name="dragEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="dragDropMode">
|
||||
<enum>QAbstractItemView::DragDrop</enum>
|
||||
</property>
|
||||
<property name="defaultDropAction">
|
||||
<enum>Qt::MoveAction</enum>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QToolButton" name="btnUp">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="arrowType">
|
||||
<enum>Qt::UpArrow</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="btnAdv">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="btnDown">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="arrowType">
|
||||
<enum>Qt::DownArrow</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
File diff suppressed because it is too large
Load Diff
|
@ -72,7 +72,8 @@ $(SRC)/libteletone_detect.c \
|
|||
$(SRC)/libteletone_generate.c \
|
||||
$(SRC)/ftdm_buffer.c \
|
||||
$(SRC)/ftdm_threadmutex.c \
|
||||
$(SRC)/ftdm_dso.c
|
||||
$(SRC)/ftdm_dso.c \
|
||||
$(SRC)/ftdm_cpu_monitor.c
|
||||
|
||||
library_include_HEADERS = \
|
||||
$(SRC)/include/fsk.h \
|
||||
|
@ -90,7 +91,8 @@ $(SRC)/include/ftdm_buffer.h \
|
|||
$(SRC)/include/ftdm_config.h \
|
||||
$(SRC)/include/ftdm_threadmutex.h \
|
||||
$(SRC)/include/ftdm_dso.h \
|
||||
$(SRC)/include/ftdm_types.h
|
||||
$(SRC)/include/ftdm_types.h \
|
||||
$(SRC)/include/ftdm_cpu_monitor.h
|
||||
|
||||
lib_LTLIBRARIES = libfreetdm.la
|
||||
libfreetdm_la_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS)
|
||||
|
@ -105,7 +107,7 @@ core-install: install-libLTLIBRARIES
|
|||
#
|
||||
# tools & test programs
|
||||
#
|
||||
noinst_PROGRAMS = testtones detect_tones detect_dtmf testisdn testpri testr2 testanalog testapp testcid
|
||||
noinst_PROGRAMS = testtones detect_tones detect_dtmf testpri testr2 testanalog testapp testcid #testisdn
|
||||
if HAVE_SCTP
|
||||
noinst_PROGRAMS += testboost
|
||||
endif
|
||||
|
@ -131,9 +133,9 @@ detect_dtmf_SOURCES = $(SRC)/detect_dtmf.c
|
|||
detect_dtmf_LDADD = libfreetdm.la
|
||||
detect_dtmf_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS)
|
||||
|
||||
testisdn_SOURCES = $(SRC)/testisdn.c
|
||||
testisdn_LDADD = libfreetdm.la
|
||||
testisdn_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS)
|
||||
#testisdn_SOURCES = $(SRC)/testisdn.c
|
||||
#testisdn_LDADD = libfreetdm.la
|
||||
#testisdn_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS)
|
||||
|
||||
testpri_SOURCES = $(SRC)/testpri.c
|
||||
testpri_LDADD = libfreetdm.la
|
||||
|
@ -160,7 +162,7 @@ testanalog_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS)
|
|||
#
|
||||
# ftmod modules
|
||||
#
|
||||
mod_LTLIBRARIES = ftmod_zt.la ftmod_skel.la ftmod_isdn.la ftmod_analog.la ftmod_analog_em.la
|
||||
mod_LTLIBRARIES = ftmod_zt.la ftmod_skel.la ftmod_analog.la ftmod_analog_em.la #ftmod_isdn.la
|
||||
|
||||
|
||||
if HAVE_SCTP
|
||||
|
@ -196,32 +198,32 @@ ftmod_wanpipe_la_LDFLAGS = -module -avoid-version -lsangoma
|
|||
ftmod_wanpipe_la_LIBADD = $(MYLIB)
|
||||
endif
|
||||
|
||||
ftmod_isdn_la_SOURCES = \
|
||||
$(SRC)/isdn/EuroISDNStateNT.c \
|
||||
$(SRC)/isdn/EuroISDNStateTE.c \
|
||||
$(SRC)/isdn/mfifo.c \
|
||||
$(SRC)/isdn/Q921.c \
|
||||
$(SRC)/isdn/Q931api.c \
|
||||
$(SRC)/isdn/Q931.c \
|
||||
$(SRC)/isdn/Q931ie.c \
|
||||
$(SRC)/isdn/Q931mes.c \
|
||||
$(SRC)/isdn/Q931StateNT.c \
|
||||
$(SRC)/isdn/Q931StateTE.c \
|
||||
$(SRC)/isdn/nationalmes.c \
|
||||
$(SRC)/isdn/nationalStateNT.c \
|
||||
$(SRC)/isdn/nationalStateTE.c \
|
||||
$(SRC)/isdn/DMSmes.c \
|
||||
$(SRC)/isdn/DMSStateNT.c \
|
||||
$(SRC)/isdn/DMSStateTE.c \
|
||||
$(SRC)/isdn/5ESSmes.c \
|
||||
$(SRC)/isdn/5ESSStateNT.c \
|
||||
$(SRC)/isdn/5ESSStateTE.c \
|
||||
$(SRC)/isdn/Q932mes.c \
|
||||
$(SRC)/ftmod/ftmod_isdn/ftmod_isdn.c
|
||||
#ftmod_isdn_la_SOURCES = \
|
||||
#$(SRC)/isdn/EuroISDNStateNT.c \
|
||||
#$(SRC)/isdn/EuroISDNStateTE.c \
|
||||
#$(SRC)/isdn/mfifo.c \
|
||||
#$(SRC)/isdn/Q921.c \
|
||||
#$(SRC)/isdn/Q931api.c \
|
||||
#$(SRC)/isdn/Q931.c \
|
||||
#$(SRC)/isdn/Q931ie.c \
|
||||
#$(SRC)/isdn/Q931mes.c \
|
||||
#$(SRC)/isdn/Q931StateNT.c \
|
||||
#$(SRC)/isdn/Q931StateTE.c \
|
||||
#$(SRC)/isdn/nationalmes.c \
|
||||
#$(SRC)/isdn/nationalStateNT.c \
|
||||
#$(SRC)/isdn/nationalStateTE.c \
|
||||
#$(SRC)/isdn/DMSmes.c \
|
||||
#$(SRC)/isdn/DMSStateNT.c \
|
||||
#$(SRC)/isdn/DMSStateTE.c \
|
||||
#$(SRC)/isdn/5ESSmes.c \
|
||||
#$(SRC)/isdn/5ESSStateNT.c \
|
||||
#$(SRC)/isdn/5ESSStateTE.c \
|
||||
#$(SRC)/isdn/Q932mes.c \
|
||||
#$(SRC)/ftmod/ftmod_isdn/ftmod_isdn.c
|
||||
|
||||
ftmod_isdn_la_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS) -D_GNU_SOURCE
|
||||
ftmod_isdn_la_LDFLAGS = $(PCAP_LIB_FLAGS) -module -avoid-version
|
||||
ftmod_isdn_la_LIBADD = $(MYLIB)
|
||||
#ftmod_isdn_la_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS) -D_GNU_SOURCE
|
||||
#ftmod_isdn_la_LDFLAGS = $(PCAP_LIB_FLAGS) -module -avoid-version
|
||||
#ftmod_isdn_la_LIBADD = $(MYLIB)
|
||||
|
||||
ftmod_analog_la_SOURCES = $(SRC)/ftmod/ftmod_analog/ftmod_analog.c
|
||||
ftmod_analog_la_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS)
|
||||
|
|
|
@ -2767,6 +2767,8 @@ void dump_chan(ftdm_span_t *span, uint32_t chan_id, switch_stream_handle_t *stre
|
|||
"type: %s\n"
|
||||
"state: %s\n"
|
||||
"last_state: %s\n"
|
||||
"txgain: %3.2f\n"
|
||||
"rxgain: %3.2f\n"
|
||||
"cid_date: %s\n"
|
||||
"cid_name: %s\n"
|
||||
"cid_num: %s\n"
|
||||
|
@ -2782,6 +2784,8 @@ void dump_chan(ftdm_span_t *span, uint32_t chan_id, switch_stream_handle_t *stre
|
|||
ftdm_chan_type2str(span->channels[chan_id]->type),
|
||||
ftdm_channel_state2str(span->channels[chan_id]->state),
|
||||
ftdm_channel_state2str(span->channels[chan_id]->last_state),
|
||||
span->channels[chan_id]->txgain,
|
||||
span->channels[chan_id]->rxgain,
|
||||
span->channels[chan_id]->caller_data.cid_date,
|
||||
span->channels[chan_id]->caller_data.cid_name,
|
||||
span->channels[chan_id]->caller_data.cid_num.digits,
|
||||
|
@ -2808,6 +2812,8 @@ void dump_chan_xml(ftdm_span_t *span, uint32_t chan_id, switch_stream_handle_t *
|
|||
" <type>%s</type>\n"
|
||||
" <state>%s</state>\n"
|
||||
" <last-state>%s</last-state>\n"
|
||||
" <txgain>%3.2f</txgain>\n"
|
||||
" <rxgain>%3.2f</rxgain>\n"
|
||||
" <cid-date>%s</cid-date>\n"
|
||||
" <cid-name>%s</cid-name>\n"
|
||||
" <cid-num>%s</cid-num>\n"
|
||||
|
@ -2824,6 +2830,8 @@ void dump_chan_xml(ftdm_span_t *span, uint32_t chan_id, switch_stream_handle_t *
|
|||
ftdm_chan_type2str(span->channels[chan_id]->type),
|
||||
ftdm_channel_state2str(span->channels[chan_id]->state),
|
||||
ftdm_channel_state2str(span->channels[chan_id]->last_state),
|
||||
span->channels[chan_id]->txgain,
|
||||
span->channels[chan_id]->rxgain,
|
||||
span->channels[chan_id]->caller_data.cid_date,
|
||||
span->channels[chan_id]->caller_data.cid_name,
|
||||
span->channels[chan_id]->caller_data.cid_num.digits,
|
||||
|
@ -3142,6 +3150,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_freetdm_load)
|
|||
module_pool = pool;
|
||||
|
||||
ftdm_global_set_logger(ftdm_logger);
|
||||
|
||||
ftdm_cpu_monitor_disable();
|
||||
|
||||
if (ftdm_global_init() != FTDM_SUCCESS) {
|
||||
ftdm_log(FTDM_LOG_ERROR, "Error loading FreeTDM\n");
|
||||
|
|
|
@ -0,0 +1,271 @@
|
|||
/*
|
||||
* Copyright (c) 2010, Sangoma Technologies
|
||||
* Moises Silva <moy@sangoma.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the original author; nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Contributors:
|
||||
* David Yat Sin <dyatsin@sangoma.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
#define _WIN32_WINNT 0x0501 // To make GetSystemTimes visible in windows.h
|
||||
#include <windows.h>
|
||||
#else /* LINUX */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#include "freetdm.h"
|
||||
#include "ftdm_cpu_monitor.h"
|
||||
struct ftdm_cpu_monitor_stats
|
||||
{
|
||||
/* bool, just used to retrieve the values for the first time and not calculate the percentage of idle time */
|
||||
int valid_last_times;
|
||||
|
||||
/* last calculated percentage of idle time */
|
||||
double last_percentage_of_idle_time;
|
||||
|
||||
#ifdef __linux__
|
||||
/* all of these are the Linux jiffies last retrieved count */
|
||||
unsigned long long last_user_time;
|
||||
unsigned long long last_system_time;
|
||||
unsigned long long last_idle_time;
|
||||
|
||||
unsigned long long last_nice_time;
|
||||
unsigned long long last_irq_time;
|
||||
unsigned long long last_soft_irq_time;
|
||||
unsigned long long last_io_wait_time;
|
||||
unsigned long long last_steal_time;
|
||||
|
||||
/* /proc/stat file descriptor used to retrieve the counters */
|
||||
int procfd;
|
||||
int initd;
|
||||
#elif defined (WIN32) || defined (WIN64)
|
||||
__int64 i64LastUserTime;
|
||||
__int64 i64LastKernelTime;
|
||||
__int64 i64LastIdleTime;
|
||||
#else
|
||||
/* Unsupported */
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef __linux__
|
||||
static ftdm_status_t ftdm_cpu_read_stats(struct ftdm_cpu_monitor_stats *p,
|
||||
unsigned long long *user,
|
||||
unsigned long long *nice,
|
||||
unsigned long long *system,
|
||||
unsigned long long *idle,
|
||||
unsigned long long *iowait,
|
||||
unsigned long long *irq,
|
||||
unsigned long long *softirq,
|
||||
unsigned long long *steal)
|
||||
{
|
||||
// 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"
|
||||
static const char procfile[] = "/proc/stat";
|
||||
int rc = 0;
|
||||
int myerrno = 0;
|
||||
int elements = 0;
|
||||
const char *cpustr = NULL;
|
||||
char statbuff[1024];
|
||||
|
||||
if (!p->initd) {
|
||||
p->procfd = open(procfile, O_RDONLY, 0);
|
||||
if(p->procfd == -1) {
|
||||
ftdm_log(FTDM_LOG_ERROR, "Failed to open CPU statistics file %s: %s\n", procfile, strerror(myerrno));
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
p->initd = 1;
|
||||
} else {
|
||||
lseek(p->procfd, 0L, SEEK_SET);
|
||||
}
|
||||
|
||||
rc = read(p->procfd, statbuff, sizeof(statbuff) - 1);
|
||||
if (rc <= 0) {
|
||||
myerrno = errno;
|
||||
ftdm_log(FTDM_LOG_ERROR, "Failed to read CPU statistics file %s: %s\n", procfile, strerror(myerrno));
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
|
||||
cpustr = strstr(statbuff, "cpu ");
|
||||
if (!cpustr) {
|
||||
ftdm_log(FTDM_LOG_ERROR, "wrong format for Linux proc cpu statistics: missing cpu string\n");
|
||||
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;
|
||||
}
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
FT_DECLARE(ftdm_status_t) ftdm_cpu_get_system_idle_time (struct ftdm_cpu_monitor_stats *p, double *idle_percentage)
|
||||
{
|
||||
unsigned long long user, nice, system, idle, iowait, irq, softirq, steal;
|
||||
unsigned long long usertime, kerneltime, idletime, totaltime, halftime;
|
||||
|
||||
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");
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
|
||||
if (!p->valid_last_times) {
|
||||
// we dont strictly need to save all of them but I feel code is more clear if we do
|
||||
p->valid_last_times = 1;
|
||||
p->last_user_time = user;
|
||||
p->last_nice_time = nice;
|
||||
p->last_system_time = system;
|
||||
p->last_irq_time = irq;
|
||||
p->last_soft_irq_time = softirq;
|
||||
p->last_io_wait_time = iowait;
|
||||
p->last_steal_time = steal;
|
||||
p->last_idle_time = idle;
|
||||
p->last_percentage_of_idle_time = 100.0;
|
||||
*idle_percentage = p->last_percentage_of_idle_time;
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
usertime = (user - p->last_user_time) + (nice - p->last_nice_time);
|
||||
kerneltime = (system - p->last_system_time) + (irq - p->last_irq_time) + (softirq - p->last_soft_irq_time);
|
||||
kerneltime += (iowait - p->last_io_wait_time);
|
||||
kerneltime += (steal - p->last_steal_time);
|
||||
idletime = (idle - p->last_idle_time);
|
||||
|
||||
totaltime = usertime + kerneltime + idletime;
|
||||
|
||||
if (totaltime <= 0) {
|
||||
// this may happen if not enough time has elapsed and the jiffies counters are the same than the last time we checked
|
||||
// jiffies depend on timer interrupts which depend on the number of HZ compile time setting of the kernel
|
||||
// typical configs set HZ to 100 (that means, 100 jiffies updates per second, that is one each 10ms)
|
||||
// avoid an arithmetic exception and return the same values
|
||||
*idle_percentage = p->last_percentage_of_idle_time;
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
halftime = totaltime / 2UL;
|
||||
|
||||
p->last_percentage_of_idle_time = ((100 * idletime + halftime) / totaltime);
|
||||
*idle_percentage = p->last_percentage_of_idle_time;
|
||||
|
||||
p->last_user_time = user;
|
||||
p->last_nice_time = nice;
|
||||
p->last_system_time = system;
|
||||
p->last_irq_time = irq;
|
||||
p->last_soft_irq_time = softirq;
|
||||
p->last_io_wait_time = iowait;
|
||||
p->last_steal_time = steal;
|
||||
p->last_idle_time = idle;
|
||||
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
#elif defined (WIN32) || defined (WIN64)
|
||||
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;
|
||||
|
||||
if (!::GetSystemTimes(&idleTime, &kernelTime, &userTime)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
__int64 i64UserTime = (__int64)userTime.dwLowDateTime | ((__int64)userTime.dwHighDateTime << 32);
|
||||
|
||||
__int64 i64KernelTime = (__int64)kernelTime.dwLowDateTime | ((__int64)kernelTime.dwHighDateTime << 32);
|
||||
|
||||
__int64 i64IdleTime = (__int64)idleTime.dwLowDateTime | ((__int64)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;
|
||||
*idle_percentage = 100.0 * i64Idle / i64System;
|
||||
} else {
|
||||
*idle_percentage = 100.0;
|
||||
p->valid_last_times = 1;
|
||||
}
|
||||
|
||||
/* Remember current value for the next call */
|
||||
p->i64LastUserTime = i64UserTime;
|
||||
p->i64LastKernelTime = i64KernelTime;
|
||||
p->i64LastIdleTime = i64IdleTime;
|
||||
|
||||
/* Success */
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
#else
|
||||
/* Unsupported */
|
||||
FT_DECLARE(ftdm_status_t) ftdm_cpu_get_system_idle_time(struct ftdm_cpu_monitor_stats *p, double *idle_percentage)
|
||||
{
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
#endif
|
||||
|
||||
FT_DECLARE(struct ftdm_cpu_monitor_stats*) ftdm_new_cpu_monitor(void)
|
||||
{
|
||||
return calloc(1, sizeof(struct ftdm_cpu_monitor_stats));
|
||||
}
|
||||
|
||||
FT_DECLARE(void) ftdm_delete_cpu_monitor(struct ftdm_cpu_monitor_stats *p)
|
||||
{
|
||||
#ifdef __linux__
|
||||
close(p->procfd);
|
||||
#endif
|
||||
free(p);
|
||||
}
|
||||
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
* indent-tabs-mode:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
|
||||
*/
|
|
@ -48,6 +48,7 @@
|
|||
#ifdef FTDM_PIKA_SUPPORT
|
||||
#include "ftdm_pika.h"
|
||||
#endif
|
||||
#include "ftdm_cpu_monitor.h"
|
||||
|
||||
#define SPAN_PENDING_CHANS_QUEUE_SIZE 1000
|
||||
|
||||
|
@ -80,6 +81,16 @@ FT_DECLARE(ftdm_time_t) ftdm_current_time_in_ms(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
uint8_t running;
|
||||
uint8_t alarm;
|
||||
uint32_t interval;
|
||||
uint8_t alarm_action_flags;
|
||||
uint8_t set_alarm_threshold;
|
||||
uint8_t reset_alarm_threshold;
|
||||
ftdm_interrupt_t *interrupt;
|
||||
} cpu_monitor_t;
|
||||
|
||||
static struct {
|
||||
ftdm_hash_t *interface_hash;
|
||||
ftdm_hash_t *module_hash;
|
||||
|
@ -93,8 +104,16 @@ static struct {
|
|||
uint32_t running;
|
||||
ftdm_span_t *spans;
|
||||
ftdm_group_t *groups;
|
||||
cpu_monitor_t cpu_monitor;
|
||||
} globals;
|
||||
|
||||
static uint8_t ftdm_cpu_monitor_disabled = 0;
|
||||
|
||||
enum ftdm_enum_cpu_alarm_action_flags
|
||||
{
|
||||
FTDM_CPU_ALARM_ACTION_WARN = (1 << 0),
|
||||
FTDM_CPU_ALARM_ACTION_REJECT = (1 << 1)
|
||||
};
|
||||
|
||||
/* enum lookup funcs */
|
||||
FTDM_ENUM_NAMES(TONEMAP_NAMES, TONEMAP_STRINGS)
|
||||
|
@ -412,7 +431,9 @@ static ftdm_status_t ftdm_span_destroy(ftdm_span_t *span)
|
|||
}
|
||||
|
||||
/* destroy final basic resources of the span data structure */
|
||||
ftdm_queue_destroy(&span->pendingchans);
|
||||
if (span->pendingchans) {
|
||||
ftdm_queue_destroy(&span->pendingchans);
|
||||
}
|
||||
ftdm_mutex_unlock(span->mutex);
|
||||
ftdm_mutex_destroy(&span->mutex);
|
||||
ftdm_safe_free(span->signal_data);
|
||||
|
@ -518,9 +539,6 @@ FT_DECLARE(ftdm_status_t) ftdm_span_create(ftdm_io_interface_t *fio, ftdm_span_t
|
|||
status = ftdm_mutex_create(&new_span->mutex);
|
||||
ftdm_assert(status == FTDM_SUCCESS, "mutex creation failed\n");
|
||||
|
||||
status = ftdm_queue_create(&new_span->pendingchans, SPAN_PENDING_CHANS_QUEUE_SIZE);
|
||||
ftdm_assert(status == FTDM_SUCCESS, "span chans queue creation failed\n");
|
||||
|
||||
ftdm_set_flag(new_span, FTDM_SPAN_CONFIGURED);
|
||||
new_span->span_id = ++globals.span_index;
|
||||
new_span->fio = fio;
|
||||
|
@ -1163,7 +1181,9 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_set_state(ftdm_channel_t *ftdmchan, ftdm_
|
|||
|
||||
ftdm_mutex_lock(ftdmchan->span->mutex);
|
||||
ftdm_set_flag(ftdmchan->span, FTDM_SPAN_STATE_CHANGE);
|
||||
ftdm_queue_enqueue(ftdmchan->span->pendingchans, ftdmchan);
|
||||
if (ftdmchan->span->pendingchans) {
|
||||
ftdm_queue_enqueue(ftdmchan->span->pendingchans, ftdmchan);
|
||||
}
|
||||
ftdm_mutex_unlock(ftdmchan->span->mutex);
|
||||
|
||||
ftdmchan->last_state = ftdmchan->state;
|
||||
|
@ -1329,7 +1349,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_span(uint32_t span_id, ftdm_direc
|
|||
return FTDM_FAIL;
|
||||
}
|
||||
|
||||
if (span->channel_request && !span->suggest_chan_id) {
|
||||
if (span->channel_request && !ftdm_test_flag(span, FTDM_SPAN_SUGGEST_CHAN_ID)) {
|
||||
ftdm_set_caller_data(span, caller_data);
|
||||
return span->channel_request(span, 0, direction, caller_data, ftdmchan);
|
||||
}
|
||||
|
@ -1469,6 +1489,14 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_chan(ftdm_channel_t *ftdmchan)
|
|||
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", "Channel is alarmed\n");
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
|
||||
if (globals.cpu_monitor.alarm &&
|
||||
globals.cpu_monitor.alarm_action_flags & FTDM_CPU_ALARM_ACTION_REJECT) {
|
||||
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", "CPU usage alarm is on - refusing to open channel\n");
|
||||
ftdm_log(FTDM_LOG_WARNING, "CPU usage alarm is on - refusing to open channel\n");
|
||||
ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_SWITCH_CONGESTION;
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
|
||||
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_READY) || (status = ftdm_mutex_trylock(ftdmchan->mutex)) != FTDM_SUCCESS) {
|
||||
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "Channel is not ready or is in use %d %d", ftdm_test_flag(ftdmchan, FTDM_CHANNEL_READY), status);
|
||||
|
@ -2006,7 +2034,6 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_command(ftdm_channel_t *ftdmchan, ftdm_co
|
|||
}
|
||||
break;
|
||||
|
||||
/* FIXME: validate user gain values */
|
||||
case FTDM_COMMAND_SET_RX_GAIN:
|
||||
{
|
||||
ftdmchan->rxgain = FTDM_COMMAND_OBJ_FLOAT;
|
||||
|
@ -2798,6 +2825,24 @@ FT_DECLARE(char *) ftdm_api_execute(const char *type, const char *cmd)
|
|||
return rval;
|
||||
}
|
||||
|
||||
static void ftdm_set_channels_gains(ftdm_span_t *span, int currindex, float rxgain, float txgain)
|
||||
{
|
||||
unsigned chan_index = 0;
|
||||
|
||||
if (!span->chan_count) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (chan_index = currindex+1; chan_index <= span->chan_count; chan_index++) {
|
||||
if (!FTDM_IS_VOICE_CHANNEL(span->channels[chan_index])) {
|
||||
continue;
|
||||
}
|
||||
ftdm_channel_command(span->channels[chan_index], FTDM_COMMAND_SET_RX_GAIN, &rxgain);
|
||||
ftdm_channel_command(span->channels[chan_index], FTDM_COMMAND_SET_TX_GAIN, &txgain);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static ftdm_status_t ftdm_group_add_channels(const char* name, ftdm_span_t* span, int currindex);
|
||||
static ftdm_status_t load_config(void)
|
||||
|
@ -2814,6 +2859,8 @@ static ftdm_status_t load_config(void)
|
|||
char group_name[80] = "default";
|
||||
ftdm_io_interface_t *fio = NULL;
|
||||
ftdm_analog_start_type_t tmp;
|
||||
float rxgain = 0.0;
|
||||
float txgain = 0.0;
|
||||
ftdm_size_t len = 0;
|
||||
|
||||
if (!ftdm_config_open_file(&cfg, cfg_name)) {
|
||||
|
@ -2921,6 +2968,7 @@ static ftdm_status_t load_config(void)
|
|||
if (span->trunk_type == FTDM_TRUNK_FXO) {
|
||||
currindex = span->chan_count;
|
||||
configured += fio->configure_span(span, val, FTDM_CHAN_TYPE_FXO, name, number);
|
||||
ftdm_set_channels_gains(span, currindex, rxgain, txgain);
|
||||
ftdm_group_add_channels(group_name, span, currindex);
|
||||
} else {
|
||||
ftdm_log(FTDM_LOG_WARNING, "Cannot add FXO channels to an FXS trunk!\n");
|
||||
|
@ -2934,6 +2982,7 @@ static ftdm_status_t load_config(void)
|
|||
if (span->trunk_type == FTDM_TRUNK_FXS) {
|
||||
currindex = span->chan_count;
|
||||
configured += fio->configure_span(span, val, FTDM_CHAN_TYPE_FXS, name, number);
|
||||
ftdm_set_channels_gains(span, currindex, rxgain, txgain);
|
||||
ftdm_group_add_channels(group_name, span, currindex);
|
||||
} else {
|
||||
ftdm_log(FTDM_LOG_WARNING, "Cannot add FXS channels to an FXO trunk!\n");
|
||||
|
@ -2947,6 +2996,7 @@ static ftdm_status_t load_config(void)
|
|||
if (span->trunk_type == FTDM_TRUNK_EM) {
|
||||
currindex = span->chan_count;
|
||||
configured += fio->configure_span(span, val, FTDM_CHAN_TYPE_EM, name, number);
|
||||
ftdm_set_channels_gains(span, currindex, rxgain, txgain);
|
||||
ftdm_group_add_channels(group_name, span, currindex);
|
||||
} else {
|
||||
ftdm_log(FTDM_LOG_WARNING, "Cannot add EM channels to a non-EM trunk!\n");
|
||||
|
@ -2954,6 +3004,7 @@ static ftdm_status_t load_config(void)
|
|||
} else if (!strcasecmp(var, "b-channel")) {
|
||||
currindex = span->chan_count;
|
||||
configured += fio->configure_span(span, val, FTDM_CHAN_TYPE_B, name, number);
|
||||
ftdm_set_channels_gains(span, currindex, rxgain, txgain);
|
||||
ftdm_group_add_channels(group_name, span, currindex);
|
||||
} else if (!strcasecmp(var, "d-channel")) {
|
||||
if (d) {
|
||||
|
@ -2972,10 +3023,19 @@ static ftdm_status_t load_config(void)
|
|||
} else if (!strcasecmp(var, "cas-channel")) {
|
||||
currindex = span->chan_count;
|
||||
configured += fio->configure_span(span, val, FTDM_CHAN_TYPE_CAS, name, number);
|
||||
ftdm_set_channels_gains(span, currindex, rxgain, txgain);
|
||||
ftdm_group_add_channels(group_name, span, currindex);
|
||||
} else if (!strcasecmp(var, "dtmf_hangup")) {
|
||||
span->dtmf_hangup = ftdm_strdup(val);
|
||||
span->dtmf_hangup_len = strlen(val);
|
||||
} else if (!strcasecmp(var, "txgain")) {
|
||||
if (sscanf(val, "%f", &txgain) != 1) {
|
||||
ftdm_log(FTDM_LOG_ERROR, "invalid txgain: '%s'\n", val);
|
||||
}
|
||||
} else if (!strcasecmp(var, "rxgain")) {
|
||||
if (sscanf(val, "%f", &rxgain) != 1) {
|
||||
ftdm_log(FTDM_LOG_ERROR, "invalid rxgain: '%s'\n", val);
|
||||
}
|
||||
} else if (!strcasecmp(var, "group")) {
|
||||
len = strlen(val);
|
||||
if (len >= sizeof(group_name)) {
|
||||
|
@ -2987,6 +3047,44 @@ static ftdm_status_t load_config(void)
|
|||
} else {
|
||||
ftdm_log(FTDM_LOG_ERROR, "unknown span variable '%s'\n", var);
|
||||
}
|
||||
} else if (!strncasecmp(cfg.category, "general", 7)) {
|
||||
if (!strncasecmp(var, "cpu_monitoring_interval", sizeof("cpu_monitoring_interval")-1)) {
|
||||
if (atoi(val) > 0) {
|
||||
globals.cpu_monitor.interval = atoi(val);
|
||||
} else {
|
||||
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);
|
||||
} 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);
|
||||
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"
|
||||
", setting threshold to %d\n", globals.cpu_monitor.reset_alarm_threshold);
|
||||
}
|
||||
} else {
|
||||
ftdm_log(FTDM_LOG_ERROR, "Invalid cpu alarm reset threshold %s\n", val);
|
||||
}
|
||||
} else if (!strncasecmp(var, "cpu_alarm_action", sizeof("cpu_alarm_action")-1)) {
|
||||
char* p = val;
|
||||
do {
|
||||
if (!strncasecmp(p, "reject", sizeof("reject")-1)) {
|
||||
globals.cpu_monitor.alarm_action_flags |= FTDM_CPU_ALARM_ACTION_REJECT;
|
||||
} else if (!strncasecmp(p, "warn", sizeof("warn")-1)) {
|
||||
globals.cpu_monitor.alarm_action_flags |= FTDM_CPU_ALARM_ACTION_WARN;
|
||||
}
|
||||
p = strchr(p, ',');
|
||||
if (p) {
|
||||
while(*p++) if (*p != 0x20) break;
|
||||
}
|
||||
} while (p);
|
||||
}
|
||||
} else {
|
||||
ftdm_log(FTDM_LOG_ERROR, "unknown param [%s] '%s' / '%s'\n", cfg.category, var, val);
|
||||
}
|
||||
|
@ -3266,6 +3364,9 @@ FT_DECLARE(ftdm_status_t) ftdm_configure_span(const char *type, ftdm_span_t *spa
|
|||
va_list ap;
|
||||
va_start(ap, sig_cb);
|
||||
status = mod->sig_configure(span, sig_cb, ap);
|
||||
if (status == FTDM_SUCCESS && ftdm_test_flag(span, FTDM_SPAN_USE_CHAN_QUEUE)) {
|
||||
status = ftdm_queue_create(&span->pendingchans, SPAN_PENDING_CHANS_QUEUE_SIZE);
|
||||
}
|
||||
va_end(ap);
|
||||
} else {
|
||||
ftdm_log(FTDM_LOG_ERROR, "can't find '%s'\n", type);
|
||||
|
@ -3512,6 +3613,85 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t
|
|||
return status;
|
||||
}
|
||||
|
||||
static void *ftdm_cpu_monitor_run(ftdm_thread_t *me, void *obj)
|
||||
{
|
||||
cpu_monitor_t *monitor = (cpu_monitor_t *)obj;
|
||||
struct ftdm_cpu_monitor_stats *cpu_stats = ftdm_new_cpu_monitor();
|
||||
if (!cpu_stats) {
|
||||
return NULL;
|
||||
}
|
||||
monitor->running = 1;
|
||||
|
||||
while(ftdm_running()) {
|
||||
double time;
|
||||
if (ftdm_cpu_get_system_idle_time(cpu_stats, &time)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (monitor->alarm) {
|
||||
if ((int)time >= (100 - monitor->set_alarm_threshold)) {
|
||||
ftdm_log(FTDM_LOG_DEBUG, "CPU alarm OFF (idle:%d)\n", (int) time);
|
||||
monitor->alarm = 0;
|
||||
}
|
||||
if (monitor->alarm_action_flags & FTDM_CPU_ALARM_ACTION_WARN) {
|
||||
ftdm_log(FTDM_LOG_WARNING, "CPU alarm is ON (cpu usage:%d)\n", (int) (100-time));
|
||||
}
|
||||
} else {
|
||||
if ((int)time <= (100-monitor->reset_alarm_threshold)) {
|
||||
ftdm_log(FTDM_LOG_DEBUG, "CPU alarm ON (idle:%d)\n", (int) time);
|
||||
monitor->alarm = 1;
|
||||
}
|
||||
}
|
||||
ftdm_interrupt_wait(monitor->interrupt, monitor->interval);
|
||||
}
|
||||
|
||||
ftdm_delete_cpu_monitor(cpu_stats);
|
||||
monitor->running = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static ftdm_status_t ftdm_cpu_monitor_start(void)
|
||||
{
|
||||
if (ftdm_interrupt_create(&globals.cpu_monitor.interrupt, FTDM_INVALID_SOCKET) != FTDM_SUCCESS) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "Failed to create CPU monitor interrupt\n");
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
|
||||
if (ftdm_thread_create_detached(ftdm_cpu_monitor_run, &globals.cpu_monitor) != FTDM_SUCCESS) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "Failed to create cpu monitor thread!!\n");
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
static void ftdm_cpu_monitor_stop(void)
|
||||
{
|
||||
if (!globals.cpu_monitor.interrupt) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!globals.cpu_monitor.running) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ftdm_interrupt_signal(globals.cpu_monitor.interrupt) != FTDM_SUCCESS) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "Failed to interrupt the CPU monitor\n");
|
||||
return;
|
||||
}
|
||||
|
||||
while (globals.cpu_monitor.running) {
|
||||
ftdm_sleep(10);
|
||||
}
|
||||
|
||||
ftdm_interrupt_destroy(&globals.cpu_monitor.interrupt);
|
||||
}
|
||||
|
||||
FT_DECLARE(void) ftdm_cpu_monitor_disable(void)
|
||||
{
|
||||
ftdm_cpu_monitor_disabled = 1;
|
||||
}
|
||||
|
||||
|
||||
FT_DECLARE(ftdm_status_t) ftdm_global_init(void)
|
||||
{
|
||||
memset(&globals, 0, sizeof(globals));
|
||||
|
@ -3534,14 +3714,34 @@ FT_DECLARE(ftdm_status_t) ftdm_global_init(void)
|
|||
|
||||
FT_DECLARE(ftdm_status_t) ftdm_global_configuration(void)
|
||||
{
|
||||
int modcount = ftdm_load_modules();
|
||||
int modcount = 0;
|
||||
|
||||
if (!globals.running) {
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
|
||||
modcount = ftdm_load_modules();
|
||||
|
||||
ftdm_log(FTDM_LOG_NOTICE, "Modules configured: %d \n", modcount);
|
||||
|
||||
globals.cpu_monitor.interval = 1000;
|
||||
globals.cpu_monitor.alarm_action_flags = FTDM_CPU_ALARM_ACTION_WARN | FTDM_CPU_ALARM_ACTION_REJECT;
|
||||
globals.cpu_monitor.set_alarm_threshold = 80;
|
||||
globals.cpu_monitor.reset_alarm_threshold = 70;
|
||||
|
||||
if (load_config() != FTDM_SUCCESS) {
|
||||
globals.running = 0;
|
||||
ftdm_log(FTDM_LOG_ERROR, "FreeTDM global configuration failed!\n");
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
|
||||
if (!ftdm_cpu_monitor_disabled) {
|
||||
if (ftdm_cpu_monitor_start() != FTDM_SUCCESS) {
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -3559,6 +3759,8 @@ FT_DECLARE(ftdm_status_t) ftdm_global_destroy(void)
|
|||
|
||||
globals.running = 0;
|
||||
|
||||
ftdm_cpu_monitor_stop();
|
||||
|
||||
globals.span_index = 0;
|
||||
|
||||
ftdm_span_close_all();
|
||||
|
|
|
@ -2385,7 +2385,7 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_isdn_configure_span)
|
|||
|
||||
if ((isdn_data->opts & FTDM_ISDN_OPT_SUGGEST_CHANNEL)) {
|
||||
span->channel_request = isdn_channel_request;
|
||||
span->suggest_chan_id = 1;
|
||||
ftdm_set_flag(span, FTDM_SPAN_SUGGEST_CHAN_ID);
|
||||
}
|
||||
span->state_map = &isdn_state_map;
|
||||
|
||||
|
|
|
@ -1331,7 +1331,7 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_libpri_configure_span)
|
|||
|
||||
if ((isdn_data->opts & FTMOD_LIBPRI_OPT_SUGGEST_CHANNEL)) {
|
||||
span->channel_request = isdn_channel_request;
|
||||
span->suggest_chan_id = 1;
|
||||
ftdm_set_flag(span, FTDM_SPAN_SUGGEST_CHAN_ID);
|
||||
}
|
||||
|
||||
span->state_map = &isdn_state_map;
|
||||
|
|
|
@ -880,8 +880,8 @@ static __inline__ void advance_chan_states(ftdm_channel_t *ftdmchan);
|
|||
*/
|
||||
static void handle_call_start(ftdm_span_t *span, sangomabc_connection_t *mcon, sangomabc_event_t *event)
|
||||
{
|
||||
ftdm_channel_t *ftdmchan;
|
||||
|
||||
ftdm_channel_t *ftdmchan = NULL;
|
||||
int hangup_cause = FTDM_CAUSE_CALL_REJECTED;
|
||||
if (!(ftdmchan = find_ftdmchan(span, (sangomabc_short_event_t*)event, 0))) {
|
||||
if ((ftdmchan = find_ftdmchan(span, (sangomabc_short_event_t*)event, 1))) {
|
||||
int r;
|
||||
|
@ -896,7 +896,7 @@ static void handle_call_start(ftdm_span_t *span, sangomabc_connection_t *mcon, s
|
|||
|
||||
}
|
||||
ftdm_set_sflag(ftdmchan, SFLAG_SENT_FINAL_MSG);
|
||||
ftdmchan=NULL;
|
||||
ftdmchan = NULL;
|
||||
}
|
||||
ftdm_log(FTDM_LOG_CRIT, "START CANT FIND CHAN %d:%d\n", event->span+1,event->chan+1);
|
||||
goto error;
|
||||
|
@ -953,12 +953,13 @@ static void handle_call_start(ftdm_span_t *span, sangomabc_connection_t *mcon, s
|
|||
return;
|
||||
|
||||
error:
|
||||
hangup_cause = ftdmchan ? ftdmchan->caller_data.hangup_cause : FTDM_CAUSE_REQUESTED_CHAN_UNAVAIL;
|
||||
sangomabc_exec_command(mcon,
|
||||
event->span,
|
||||
event->chan,
|
||||
0,
|
||||
SIGBOOST_EVENT_CALL_START_NACK,
|
||||
0, 0);
|
||||
hangup_cause, 0);
|
||||
|
||||
}
|
||||
|
||||
|
@ -2239,7 +2240,8 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_boost_configure_span)
|
|||
span->get_span_sig_status = sangoma_boost_get_span_sig_status;
|
||||
span->set_span_sig_status = sangoma_boost_set_span_sig_status;
|
||||
span->state_map = &boost_state_map;
|
||||
span->suggest_chan_id = 0;
|
||||
ftdm_clear_flag(span, FTDM_SPAN_SUGGEST_CHAN_ID);
|
||||
ftdm_set_flag(span, FTDM_SPAN_USE_CHAN_QUEUE);
|
||||
if (sigmod_iface) {
|
||||
/* the core will do the hunting */
|
||||
span->channel_request = NULL;
|
||||
|
|
|
@ -654,7 +654,6 @@ struct ftdm_span {
|
|||
char *type;
|
||||
char *dtmf_hangup;
|
||||
size_t dtmf_hangup_len;
|
||||
int suggest_chan_id;
|
||||
ftdm_state_map_t *state_map;
|
||||
ftdm_caller_data_t default_caller_data;
|
||||
ftdm_queue_t *pendingchans;
|
||||
|
@ -825,6 +824,7 @@ FT_DECLARE(ftdm_status_t) ftdm_span_find_by_name(const char *name, ftdm_span_t *
|
|||
FT_DECLARE(char *) ftdm_api_execute(const char *type, const char *cmd);
|
||||
FT_DECLARE(int) ftdm_vasprintf(char **ret, const char *fmt, va_list ap);
|
||||
FT_DECLARE(ftdm_status_t) ftdm_channel_set_caller_data(ftdm_channel_t *ftdmchan, ftdm_caller_data_t *caller_data);
|
||||
FT_DECLARE(void) ftdm_cpu_monitor_disable(void);
|
||||
|
||||
FIO_CODEC_FUNCTION(fio_slin2ulaw);
|
||||
FIO_CODEC_FUNCTION(fio_ulaw2slin);
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright (c) 2010, Sangoma Technologies
|
||||
* Moises Silva <moy@sangoma.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the original author; nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* Contributors:
|
||||
* David Yat Sin <dyatsin@sangoma.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/*! \brief opaque cpu stats structure */
|
||||
struct ftdm_cpu_monitor_stats;
|
||||
|
||||
/*!
|
||||
* \brief create a new cpu monitor
|
||||
* \return profile timer structure previously created with new_profile_timer, NULL on error
|
||||
*/
|
||||
FT_DECLARE(struct ftdm_cpu_monitor_stats*) ftdm_new_cpu_monitor(void);
|
||||
|
||||
/*!
|
||||
* \brief Deletes cpu_monitor
|
||||
*/
|
||||
FT_DECLARE(void) ftdm_delete_cpu_monitor(struct ftdm_cpu_monitor_stats *p);
|
||||
|
||||
/*!
|
||||
* \brief provides the percentage of idle system time
|
||||
* \param p cpu_stats structure previously created with ftdm_new_cpu_monitor
|
||||
* \param pointer to store the percentage of idle time
|
||||
* \return -1 on error 0 for success
|
||||
*/
|
||||
FT_DECLARE(ftdm_status_t) ftdm_cpu_get_system_idle_time (struct ftdm_cpu_monitor_stats *p, double *idle_percentage);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
* indent-tabs-mode:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
|
||||
*/
|
|
@ -325,7 +325,9 @@ typedef enum {
|
|||
FTDM_SPAN_STATE_CHANGE = (1 << 2),
|
||||
FTDM_SPAN_SUSPENDED = (1 << 3),
|
||||
FTDM_SPAN_IN_THREAD = (1 << 4),
|
||||
FTDM_SPAN_STOP_THREAD = (1 << 5)
|
||||
FTDM_SPAN_STOP_THREAD = (1 << 5),
|
||||
FTDM_SPAN_USE_CHAN_QUEUE = (1 << 6),
|
||||
FTDM_SPAN_SUGGEST_CHAN_ID = (1 << 7),
|
||||
} ftdm_span_flag_t;
|
||||
|
||||
typedef enum {
|
||||
|
|
|
@ -100,13 +100,16 @@ if test "x${ax_cv_c_compiler_vendor}" = "xsun" ; then
|
|||
fi
|
||||
fi
|
||||
|
||||
SOFIA_PLAT_CFLAGS=
|
||||
# openbsd seems to not define NULL as a void pointer, I blame standards by committee for this.
|
||||
# This is a dirty hack, but shuts up all the warnings
|
||||
case "$host" in
|
||||
*-openbsd*) SOFIA_CFLAGS="$SOFIA_CFLAGS -DNULL='(void *) 0L'";;
|
||||
*-openbsd*) SOFIA_PLAT_CFLAGS="-DNULL='(void *) 0L'";;
|
||||
*) ;;
|
||||
esac
|
||||
|
||||
AC_SUBST(SOFIA_PLAT_CFLAGS, $SOFIA_PLAT_CFLAGS)
|
||||
|
||||
|
||||
### checks for header files
|
||||
### -----------------------
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# common Makefile targets for libsofia-sip-ua modules
|
||||
# ---------------------------------------------------
|
||||
|
||||
AM_CFLAGS = $(CWFLAG) $(SOFIA_CFLAGS) $(SOFIA_COVERAGE)
|
||||
AM_CFLAGS = $(CWFLAG) $(SOFIA_CFLAGS) $(SOFIA_COVERAGE) $(SOFIA_PLAT_CFLAGS)
|
||||
|
||||
# Use with --enable-ndebug
|
||||
if NDEBUG
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
sofiasrcdir = ${top_srcdir}/libsofia-sip-ua
|
||||
sofiabuilddir = ${top_builddir}/libsofia-sip-ua
|
||||
|
||||
AM_CFLAGS = $(CWFLAG) $(SOFIA_COVERAGE) $(SOFIA_CFLAGS) $(openssl_CFLAGS)
|
||||
AM_CFLAGS = $(CWFLAG) $(SOFIA_COVERAGE) $(SOFIA_CFLAGS) $(openssl_CFLAGS) $(SOFIA_PLAT_CFLAGS)
|
||||
|
||||
SOFIA_COVERAGE = $(COVERAGE_FLAGS)
|
||||
|
||||
|
|
|
@ -1,4 +1 @@
|
|||
.svn
|
||||
.gitignore
|
||||
.update
|
||||
configure.gnu
|
||||
|
|
|
@ -35,11 +35,12 @@ fi
|
|||
sed -e "s|\(AC_SUBST(SWITCH_VERSION_MAJOR, \[\).*\(\])\)|\1$major\2|" \
|
||||
-e "s|\(AC_SUBST(SWITCH_VERSION_MINOR, \[\).*\(\])\)|\1$minor\2|" \
|
||||
-e "s|\(AC_SUBST(SWITCH_VERSION_MICRO, \[\).*\(\])\)|\1$micro\2|" \
|
||||
-e "s|\(AC_SUBST(SWITCH_VERSION_REVISION, \[\).*\(\])\)|\1$rev\2|" \
|
||||
-e "s|\(AC_INIT(\[freeswitch\], \[\).*\(\], BUG-REPORT-ADDRESS)\)|\1$major.$minor.$micro\2|" \
|
||||
-i configure.in
|
||||
|
||||
if [ -n "$rev" ]; then
|
||||
sed -e "s|#\(AC_SUBST(SWITCH_VERSION_REVISION\)|\1|" \
|
||||
sed -e "s|\(AC_SUBST(SWITCH_VERSION_REVISION, \[\).*\(\])\)|\1$rev\2|" \
|
||||
-e "s|#\(AC_SUBST(SWITCH_VERSION_REVISION\)|\1|" \
|
||||
-i configure.in
|
||||
fi
|
||||
|
||||
|
@ -61,16 +62,17 @@ rm -f docs/COPYING
|
|||
rm -f docs/ChangeLog
|
||||
rm -rf .git
|
||||
cd ..
|
||||
tar -czvf $dst_name.tar.gz $dst_dir
|
||||
tar -cjvf $dst_name.tar.bz2 $dst_dir
|
||||
tar -cJvf $dst_name.tar.xz $dst_dir
|
||||
rm -rf $dst_dir
|
||||
tar -cvf $dst_name.tar $dst_dir
|
||||
gzip -9 -c $dst_name.tar > $dst_name.tar.gz || echo "gzip not available"
|
||||
bzip2 -z -k $dst_name.tar || echo "bzip2 not available"
|
||||
xz -z -9 -k $dst_name.tar || echo "xz / xz-utils not available"
|
||||
rm -rf $dst_name.tar $dst_dir
|
||||
|
||||
cat 1>&2 <<EOF
|
||||
----------------------------------------------------------------------
|
||||
The v$ver tag has been committed locally, but it will not be
|
||||
globally visible until you 'git push' this repository up to the server
|
||||
(I didn't do that for you).
|
||||
globally visible until you 'git push --tags' this repository up to the
|
||||
server (I didn't do that for you, as you might want to review first).
|
||||
----------------------------------------------------------------------
|
||||
EOF
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
Makefile
|
||||
Makefile.in
|
||||
include/stamp-h1
|
||||
include/switch_am_config.h
|
||||
include/switch_private.h
|
||||
include/switch_private.h.in
|
||||
include/switch_swigable_cpp.h
|
||||
include/switch_version.h
|
||||
include/switch_version.h.in
|
||||
/Makefile
|
||||
/Makefile.in
|
||||
/include/stamp-h1
|
||||
/include/switch_am_config.h
|
||||
/include/switch_private.h
|
||||
/include/switch_private.h.in
|
||||
/include/switch_swigable_cpp.h
|
||||
/include/switch_version.h
|
||||
/include/switch_version.h.in
|
||||
|
|
|
@ -1213,6 +1213,7 @@ SWITCH_DECLARE(switch_status_t) switch_mcast_join(switch_socket_t *sock, switch_
|
|||
*/
|
||||
SWITCH_DECLARE(switch_status_t) switch_mcast_hops(switch_socket_t *sock, uint8_t ttl);
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_mcast_loopback(switch_socket_t *sock, uint8_t opt);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
|
|
@ -245,6 +245,11 @@ SWITCH_DECLARE(const char *) switch_channel_get_variable_partner(switch_channel_
|
|||
#define switch_channel_set_variable(_channel, _var, _val) switch_channel_set_variable_var_check(_channel, _var, _val, SWITCH_TRUE)
|
||||
#define switch_channel_set_variable_partner(_channel, _var, _val) switch_channel_set_variable_partner_var_check(_channel, _var, _val, SWITCH_TRUE)
|
||||
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_channel_export_variable_var_check(switch_channel_t *channel, const char *varname, const char *value, switch_bool_t var_check, switch_bool_t nolocal);
|
||||
|
||||
#define switch_channel_export_variable(_channel, _varname, _value, _nolocal) switch_channel_export_variable_var_check(_channel, _varname, _value, SWITCH_TRUE, _nolocal)
|
||||
|
||||
/*!
|
||||
\brief Retrieve a variable from a given channel
|
||||
\param channel channel to retrieve variable from
|
||||
|
|
|
@ -1,52 +1,59 @@
|
|||
Makefile
|
||||
Makefile.in
|
||||
applications/mod_commands/Makefile
|
||||
applications/mod_conference/Makefile
|
||||
applications/mod_dptools/Makefile
|
||||
applications/mod_enum/Makefile
|
||||
applications/mod_enum/Makefile.in
|
||||
applications/mod_enum/mod_enum.log
|
||||
applications/mod_expr/Makefile
|
||||
applications/mod_expr/Makefile.in
|
||||
applications/mod_expr/mod_expr.log
|
||||
applications/mod_fifo/Makefile
|
||||
applications/mod_fsv/Makefile
|
||||
applications/mod_limit/Makefile
|
||||
applications/mod_stress/Makefile
|
||||
applications/mod_stress/Makefile.in
|
||||
applications/mod_t38gateway/Makefile
|
||||
applications/mod_t38gateway/Makefile.in
|
||||
applications/mod_valet_parking/Makefile
|
||||
applications/mod_voicemail/Makefile
|
||||
asr_tts/mod_unimrcp/Makefile
|
||||
asr_tts/mod_unimrcp/Makefile.in
|
||||
dialplans/mod_dialplan_asterisk/Makefile
|
||||
dialplans/mod_dialplan_xml/Makefile
|
||||
endpoints/mod_portaudio/Makefile
|
||||
endpoints/mod_portaudio/Makefile.in
|
||||
endpoints/mod_skinny/Makefile
|
||||
endpoints/mod_skinny/Makefile.in
|
||||
endpoints/mod_skypopen/Makefile
|
||||
endpoints/mod_skypopen/Makefile.in
|
||||
endpoints/mod_sofia/Makefile
|
||||
endpoints/mod_sofia/Makefile.in
|
||||
endpoints/mod_sofia/mod_sofia.log
|
||||
event_handlers/mod_erlang_event/Makefile
|
||||
event_handlers/mod_event_socket/Makefile
|
||||
formats/mod_native_file/Makefile
|
||||
formats/mod_portaudio_stream/Makefile
|
||||
formats/mod_portaudio_stream/Makefile.in
|
||||
formats/mod_tone_stream/Makefile
|
||||
languages/mod_java/Makefile
|
||||
languages/mod_lua/Makefile
|
||||
languages/mod_lua/Makefile.in
|
||||
languages/mod_lua/mod_lua.log
|
||||
languages/mod_python/Makefile
|
||||
languages/mod_spidermonkey/Makefile
|
||||
languages/mod_spidermonkey/Makefile.in
|
||||
languages/mod_spidermonkey/mod_spidermonkey.log
|
||||
loggers/mod_console/Makefile
|
||||
loggers/mod_logfile/Makefile
|
||||
loggers/mod_syslog/Makefile
|
||||
say/mod_say_en/Makefile
|
||||
say/mod_say_ru/Makefile
|
||||
/Makefile
|
||||
/Makefile.in
|
||||
/applications/mod_commands/Makefile
|
||||
/applications/mod_conference/Makefile
|
||||
/applications/mod_dptools/Makefile
|
||||
/applications/mod_enum/Makefile
|
||||
/applications/mod_enum/Makefile.in
|
||||
/applications/mod_enum/mod_enum.log
|
||||
/applications/mod_expr/Makefile
|
||||
/applications/mod_expr/Makefile.in
|
||||
/applications/mod_expr/mod_expr.log
|
||||
/applications/mod_fifo/Makefile
|
||||
/applications/mod_fsv/Makefile
|
||||
/applications/mod_limit/Makefile
|
||||
/applications/mod_stress/Makefile
|
||||
/applications/mod_stress/Makefile.in
|
||||
/applications/mod_t38gateway/Makefile
|
||||
/applications/mod_t38gateway/Makefile.in
|
||||
/applications/mod_valet_parking/Makefile
|
||||
/applications/mod_voicemail/Makefile
|
||||
/asr_tts/mod_unimrcp/Makefile
|
||||
/asr_tts/mod_unimrcp/Makefile.in
|
||||
/dialplans/mod_dialplan_asterisk/Makefile
|
||||
/dialplans/mod_dialplan_xml/Makefile
|
||||
/endpoints/mod_portaudio/Makefile
|
||||
/endpoints/mod_portaudio/Makefile.in
|
||||
/endpoints/mod_skinny/Makefile
|
||||
/endpoints/mod_skinny/Makefile.in
|
||||
/endpoints/mod_skypopen/Makefile
|
||||
/endpoints/mod_skypopen/Makefile.in
|
||||
/endpoints/mod_sofia/Makefile
|
||||
/endpoints/mod_sofia/Makefile.in
|
||||
/endpoints/mod_sofia/mod_sofia.log
|
||||
/event_handlers/mod_erlang_event/Makefile
|
||||
/event_handlers/mod_event_socket/Makefile
|
||||
/formats/mod_native_file/Makefile
|
||||
/formats/mod_portaudio_stream/Makefile
|
||||
/formats/mod_portaudio_stream/Makefile.in
|
||||
/formats/mod_tone_stream/Makefile
|
||||
/languages/mod_java/Makefile
|
||||
/languages/mod_lua/Makefile
|
||||
/languages/mod_lua/Makefile.in
|
||||
/languages/mod_lua/mod_lua.log
|
||||
/languages/mod_python/Makefile
|
||||
/languages/mod_spidermonkey/Makefile
|
||||
/languages/mod_spidermonkey/Makefile.in
|
||||
/languages/mod_spidermonkey/mod_spidermonkey.log
|
||||
/loggers/mod_console/Makefile
|
||||
/loggers/mod_logfile/Makefile
|
||||
/loggers/mod_syslog/Makefile
|
||||
/say/mod_say_en/Makefile
|
||||
/say/mod_say_ru/Makefile
|
||||
/applications/mod_stress/mod_stress.log
|
||||
/asr_tts/mod_unimrcp/mod_unimrcp.log
|
||||
/endpoints/mod_portaudio/mod_portaudio.log
|
||||
/endpoints/mod_skypopen/mod_skypopen.log
|
||||
/formats/mod_portaudio_stream/mod_portaudio_stream.log
|
||||
/languages/mod_java/freeswitch.jar
|
||||
/languages/mod_managed/freeswitch_wrap.cpp
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
*
|
||||
* Rupa Schomaker <rupa@rupa.com>
|
||||
*
|
||||
* mod_cidlookup.c -- API for querying cid->name services
|
||||
* mod_cidlookup.c -- API for querying cid->name services and local data
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Makefile
|
|
@ -2,13 +2,12 @@ include $(top_srcdir)/build/modmake.rulesam
|
|||
MODNAME=mod_enum
|
||||
|
||||
UDNS_DIR=$(switch_srcdir)/libs/udns
|
||||
AM_CFLAGS += -I$(UDNS_DIR) -DHAVE_POLL
|
||||
mod_enum_la_CFLAGS = -I$(UDNS_DIR) -DHAVE_POLL $(AM_CFLAGS)
|
||||
|
||||
mod_LTLIBRARIES = mod_enum.la
|
||||
mod_enum_la_SOURCES = mod_enum.c
|
||||
mod_enum_la_SOURCES += $(UDNS_DIR)/udns_dn.c $(UDNS_DIR)/udns_dntosp.c $(UDNS_DIR)/udns_parse.c $(UDNS_DIR)/udns_misc.c
|
||||
mod_enum_la_SOURCES += $(UDNS_DIR)/udns_rr_a.c $(UDNS_DIR)/udns_rr_ptr.c $(UDNS_DIR)/udns_rr_mx.c $(UDNS_DIR)/udns_rr_txt.c $(UDNS_DIR)/udns_bl.c
|
||||
mod_enum_la_SOURCES += $(UDNS_DIR)/udns_rr_srv.c $(UDNS_DIR)/udns_rr_naptr.c $(UDNS_DIR)/udns_codes.c $(UDNS_DIR)/udns_resolver.c
|
||||
mod_enum_la_CFLAGS = $(AM_CFLAGS)
|
||||
mod_enum_la_LIBADD = $(switch_builddir)/libfreeswitch.la
|
||||
mod_enum_la_LDFLAGS = -avoid-version -module -no-undefined -shared
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Makefile
|
|
@ -0,0 +1 @@
|
|||
Makefile
|
|
@ -0,0 +1 @@
|
|||
Makefile
|
|
@ -0,0 +1,2 @@
|
|||
!/gsmlib/gsmlib-*/aclocal.m4
|
||||
!/gsmlib/gsmlib-*/configure
|
|
@ -6,8 +6,7 @@ PALA=$(switch_builddir)/libs/portaudio/lib/libportaudio.la
|
|||
|
||||
mod_LTLIBRARIES = mod_portaudio.la
|
||||
mod_portaudio_la_SOURCES = mod_portaudio.c pablio.c pa_ringbuffer.c
|
||||
mod_portaudio_la_CFLAGS = $(AM_CFLAGS)
|
||||
mod_portaudio_la_CFLAGS += -I. -I$(PA_DIR)/include -D__EXTENSION__=1
|
||||
mod_portaudio_la_CFLAGS = -I. -I$(PA_DIR)/include -D__EXTENSION__=1 $(AM_CFLAGS)
|
||||
mod_portaudio_la_LIBADD = $(switch_builddir)/libfreeswitch.la $(PALA)
|
||||
mod_portaudio_la_LDFLAGS = -avoid-version -module -no-undefined -shared $(PA_LIBS)
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ include $(top_srcdir)/build/modmake.rulesam
|
|||
MODNAME=mod_skinny
|
||||
|
||||
mod_LTLIBRARIES = mod_skinny.la
|
||||
mod_skinny_la_SOURCES = mod_skinny.c skinny_protocol.c skinny_tables.c
|
||||
mod_skinny_la_CFLAGS = $(AM_CFLAGS) -DSKINNY_SVN_VERSION=\"`cat $(switch_builddir)/.version`\"
|
||||
mod_skinny_la_SOURCES = mod_skinny.c skinny_protocol.c skinny_tables.c skinny_api.c
|
||||
mod_skinny_la_CFLAGS = $(AM_CFLAGS)
|
||||
mod_skinny_la_LIBADD = $(switch_builddir)/libfreeswitch.la
|
||||
mod_skinny_la_LDFLAGS = -avoid-version -module -no-undefined -shared
|
||||
|
|
|
@ -49,7 +49,9 @@ sub send {
|
|||
$parsed_count++;
|
||||
}
|
||||
if($parsed_count != scalar(keys %{$self->{'data'}})) {
|
||||
printf "Incomplete message: %d out of %d\n", $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;
|
||||
}
|
||||
$self->{'socket'}->send_data($self->{'type'}, $raw);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -42,50 +42,54 @@
|
|||
#define SKINNY_EVENT_UNREGISTER "skinny::unregister"
|
||||
#define SKINNY_EVENT_EXPIRE "skinny::expire"
|
||||
#define SKINNY_EVENT_ALARM "skinny::alarm"
|
||||
#define SKINNY_EVENT_CALL_STATE "skinny::call_state"
|
||||
|
||||
struct skinny_globals {
|
||||
/* data */
|
||||
int calls;
|
||||
switch_mutex_t *calls_mutex;
|
||||
switch_hash_t *profile_hash;
|
||||
switch_event_node_t *heartbeat_node;
|
||||
int running;
|
||||
int running;
|
||||
switch_memory_pool_t *pool;
|
||||
switch_mutex_t *mutex;
|
||||
switch_hash_t *profile_hash;
|
||||
switch_event_node_t *heartbeat_node;
|
||||
switch_event_node_t *call_state_node;
|
||||
};
|
||||
typedef struct skinny_globals skinny_globals_t;
|
||||
|
||||
skinny_globals_t globals;
|
||||
|
||||
struct skinny_profile {
|
||||
/* prefs */
|
||||
char *name;
|
||||
char *domain;
|
||||
char *ip;
|
||||
unsigned int port;
|
||||
char *dialplan;
|
||||
char *context;
|
||||
uint32_t keep_alive;
|
||||
char date_format[6];
|
||||
int debug;
|
||||
/* db */
|
||||
char *dbname;
|
||||
char *odbc_dsn;
|
||||
char *odbc_user;
|
||||
char *odbc_pass;
|
||||
switch_odbc_handle_t *master_odbc;
|
||||
/* stats */
|
||||
uint32_t ib_calls;
|
||||
uint32_t ob_calls;
|
||||
uint32_t ib_failed_calls;
|
||||
uint32_t ob_failed_calls;
|
||||
/* listener */
|
||||
int listener_threads;
|
||||
switch_mutex_t *listener_mutex;
|
||||
switch_socket_t *sock;
|
||||
switch_mutex_t *sock_mutex;
|
||||
struct listener *listeners;
|
||||
uint8_t listener_ready;
|
||||
/* call id */
|
||||
uint32_t next_call_id;
|
||||
/* prefs */
|
||||
char *name;
|
||||
char *domain;
|
||||
char *ip;
|
||||
unsigned int port;
|
||||
char *dialplan;
|
||||
char *context;
|
||||
uint32_t keep_alive;
|
||||
char date_format[6];
|
||||
int debug;
|
||||
/* db */
|
||||
char *dbname;
|
||||
char *odbc_dsn;
|
||||
char *odbc_user;
|
||||
char *odbc_pass;
|
||||
switch_odbc_handle_t *master_odbc;
|
||||
switch_mutex_t *sql_mutex;
|
||||
/* stats */
|
||||
uint32_t ib_calls;
|
||||
uint32_t ob_calls;
|
||||
uint32_t ib_failed_calls;
|
||||
uint32_t ob_failed_calls;
|
||||
/* listener */
|
||||
int listener_threads;
|
||||
switch_mutex_t *listener_mutex;
|
||||
switch_socket_t *sock;
|
||||
switch_mutex_t *sock_mutex;
|
||||
struct listener *listeners;
|
||||
uint8_t listener_ready;
|
||||
/* call id */
|
||||
uint32_t next_call_id;
|
||||
/* others */
|
||||
switch_memory_pool_t *pool;
|
||||
};
|
||||
typedef struct skinny_profile skinny_profile_t;
|
||||
|
||||
|
@ -95,28 +99,26 @@ typedef struct skinny_profile skinny_profile_t;
|
|||
/*****************************************************************************/
|
||||
|
||||
typedef enum {
|
||||
LFLAG_RUNNING = (1 << 0),
|
||||
LFLAG_RUNNING = (1 << 0),
|
||||
} event_flag_t;
|
||||
|
||||
#define SKINNY_MAX_LINES 42
|
||||
struct listener {
|
||||
skinny_profile_t *profile;
|
||||
char device_name[16];
|
||||
uint32_t device_instance;
|
||||
switch_core_session_t *session[SKINNY_MAX_LINES];
|
||||
uint32_t line_state[SKINNY_MAX_LINES]; /* See enum skinny_key_set */
|
||||
skinny_profile_t *profile;
|
||||
char device_name[16];
|
||||
uint32_t device_instance;
|
||||
|
||||
switch_socket_t *sock;
|
||||
switch_memory_pool_t *pool;
|
||||
switch_thread_rwlock_t *rwlock;
|
||||
switch_sockaddr_t *sa;
|
||||
char remote_ip[50];
|
||||
switch_mutex_t *flag_mutex;
|
||||
uint32_t flags;
|
||||
switch_port_t remote_port;
|
||||
uint32_t id;
|
||||
time_t expire_time;
|
||||
struct listener *next;
|
||||
switch_socket_t *sock;
|
||||
switch_memory_pool_t *pool;
|
||||
switch_thread_rwlock_t *rwlock;
|
||||
switch_sockaddr_t *sa;
|
||||
char remote_ip[50];
|
||||
switch_mutex_t *flag_mutex;
|
||||
uint32_t flags;
|
||||
switch_port_t remote_port;
|
||||
uint32_t id;
|
||||
time_t expire_time;
|
||||
struct listener *next;
|
||||
};
|
||||
|
||||
typedef struct listener listener_t;
|
||||
|
@ -127,83 +129,92 @@ typedef switch_status_t (*skinny_listener_callback_func_t) (listener_t *listener
|
|||
/* CHANNEL TYPES */
|
||||
/*****************************************************************************/
|
||||
typedef enum {
|
||||
TFLAG_IO = (1 << 0),
|
||||
TFLAG_INBOUND = (1 << 1),
|
||||
TFLAG_OUTBOUND = (1 << 2),
|
||||
TFLAG_DTMF = (1 << 3),
|
||||
TFLAG_VOICE = (1 << 4),
|
||||
TFLAG_HANGUP = (1 << 5),
|
||||
TFLAG_LINEAR = (1 << 6),
|
||||
TFLAG_CODEC = (1 << 7),
|
||||
|
||||
TFLAG_READING = (1 << 9),
|
||||
TFLAG_WRITING = (1 << 10)
|
||||
TFLAG_IO = (1 << 0),
|
||||
TFLAG_INBOUND = (1 << 1),
|
||||
TFLAG_OUTBOUND = (1 << 2),
|
||||
TFLAG_DTMF = (1 << 3),
|
||||
TFLAG_VOICE = (1 << 4),
|
||||
TFLAG_HANGUP = (1 << 5),
|
||||
TFLAG_LINEAR = (1 << 6),
|
||||
TFLAG_CODEC = (1 << 7),
|
||||
|
||||
TFLAG_READING = (1 << 9),
|
||||
TFLAG_WRITING = (1 << 10)
|
||||
} TFLAGS;
|
||||
|
||||
typedef enum {
|
||||
GFLAG_MY_CODEC_PREFS = (1 << 0)
|
||||
GFLAG_MY_CODEC_PREFS = (1 << 0)
|
||||
} GFLAGS;
|
||||
|
||||
struct private_object {
|
||||
unsigned int flags;
|
||||
switch_frame_t read_frame;
|
||||
unsigned char databuf[SWITCH_RECOMMENDED_BUFFER_SIZE];
|
||||
switch_core_session_t *session;
|
||||
switch_caller_profile_t *caller_profile;
|
||||
switch_mutex_t *mutex;
|
||||
switch_mutex_t *flag_mutex;
|
||||
/* identification */
|
||||
struct listener *listener;
|
||||
uint32_t line;
|
||||
uint32_t call_id;
|
||||
uint32_t party_id;
|
||||
char *line_name;
|
||||
char *line_shortname;
|
||||
char *line_displayname;
|
||||
char dest[10];
|
||||
/* codec */
|
||||
char *iananame;
|
||||
switch_codec_t read_codec;
|
||||
switch_codec_t write_codec;
|
||||
switch_codec_implementation_t read_impl;
|
||||
switch_codec_implementation_t write_impl;
|
||||
unsigned long rm_rate;
|
||||
uint32_t codec_ms;
|
||||
char *rm_encoding;
|
||||
char *rm_fmtp;
|
||||
switch_payload_t agreed_pt;
|
||||
/* RTP */
|
||||
switch_rtp_t *rtp_session;
|
||||
char *local_sdp_audio_ip;
|
||||
switch_port_t local_sdp_audio_port;
|
||||
char *remote_sdp_audio_ip;
|
||||
switch_port_t remote_sdp_audio_port;
|
||||
unsigned int flags;
|
||||
switch_frame_t read_frame;
|
||||
unsigned char databuf[SWITCH_RECOMMENDED_BUFFER_SIZE];
|
||||
switch_core_session_t *session;
|
||||
switch_caller_profile_t *caller_profile;
|
||||
switch_mutex_t *mutex;
|
||||
switch_mutex_t *flag_mutex;
|
||||
/* identification */
|
||||
uint32_t call_id;
|
||||
uint32_t party_id;
|
||||
|
||||
skinny_profile_t *profile;
|
||||
|
||||
/* codec */
|
||||
char *iananame;
|
||||
switch_codec_t read_codec;
|
||||
switch_codec_t write_codec;
|
||||
switch_codec_implementation_t read_impl;
|
||||
switch_codec_implementation_t write_impl;
|
||||
unsigned long rm_rate;
|
||||
uint32_t codec_ms;
|
||||
char *rm_encoding;
|
||||
char *rm_fmtp;
|
||||
switch_payload_t agreed_pt;
|
||||
/* RTP */
|
||||
switch_rtp_t *rtp_session;
|
||||
char *local_sdp_audio_ip;
|
||||
switch_port_t local_sdp_audio_port;
|
||||
char *remote_sdp_audio_ip;
|
||||
switch_port_t remote_sdp_audio_port;
|
||||
};
|
||||
|
||||
typedef struct private_object private_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
/* PROFILES FUNCTIONS */
|
||||
/*****************************************************************************/
|
||||
skinny_profile_t *skinny_find_profile(const char *profile_name);
|
||||
switch_status_t skinny_profile_dump(const skinny_profile_t *profile, switch_stream_handle_t *stream);
|
||||
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);
|
||||
switch_core_session_t * skinny_profile_find_session(skinny_profile_t *profile, listener_t *listener, uint32_t *line_instance_p, uint32_t call_id);
|
||||
switch_status_t dump_device(skinny_profile_t *profile, const char *device_name, switch_stream_handle_t *stream);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* SQL FUNCTIONS */
|
||||
/*****************************************************************************/
|
||||
void skinny_execute_sql(skinny_profile_t *profile, char *sql, switch_mutex_t *mutex);
|
||||
switch_bool_t skinny_execute_sql_callback(skinny_profile_t *profile,
|
||||
switch_mutex_t *mutex, char *sql, switch_core_db_callback_func_t callback, void *pdata);
|
||||
switch_mutex_t *mutex, char *sql, switch_core_db_callback_func_t callback, void *pdata);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* LISTENER FUNCTIONS */
|
||||
/*****************************************************************************/
|
||||
uint8_t listener_is_ready(listener_t *listener);
|
||||
switch_status_t keepalive_listener(listener_t *listener, void *pvt);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* CHANNEL FUNCTIONS */
|
||||
/*****************************************************************************/
|
||||
uint32_t skinny_line_perform_set_state(listener_t *listener, const char *file, const char *func, int line, uint32_t instance, uint32_t state, uint32_t call_id);
|
||||
#define skinny_line_set_state(listener, instance, state, call_id) skinny_line_perform_set_state(listener, __FILE__, __SWITCH_FUNC__, __LINE__, instance, state, call_id)
|
||||
void skinny_line_perform_set_state(const char *file, const char *func, int line, listener_t *listener, uint32_t line_instance, uint32_t call_id, uint32_t call_state);
|
||||
#define skinny_line_set_state(listener, line_instance, call_id, call_state) skinny_line_perform_set_state(__FILE__, __SWITCH_FUNC__, __LINE__, listener, line_instance, call_id, call_state)
|
||||
|
||||
uint32_t skinny_line_get_state(listener_t *listener, uint32_t instance);
|
||||
uint32_t skinny_line_get_state(listener_t *listener, uint32_t line_instance, uint32_t call_id);
|
||||
|
||||
switch_status_t skinny_tech_set_codec(private_t *tech_pvt, int force);
|
||||
void tech_init(private_t *tech_pvt, switch_core_session_t *session, listener_t *listener, uint32_t line);
|
||||
void tech_init(private_t *tech_pvt, skinny_profile_t *profile, switch_core_session_t *session);
|
||||
switch_status_t channel_on_init(switch_core_session_t *session);
|
||||
switch_status_t channel_on_hangup(switch_core_session_t *session);
|
||||
switch_status_t channel_on_destroy(switch_core_session_t *session);
|
||||
|
@ -211,8 +222,8 @@ switch_status_t channel_on_routing(switch_core_session_t *session);
|
|||
switch_status_t channel_on_exchange_media(switch_core_session_t *session);
|
||||
switch_status_t channel_on_soft_execute(switch_core_session_t *session);
|
||||
switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event,
|
||||
switch_caller_profile_t *outbound_profile,
|
||||
switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags, switch_call_cause_t *cancel_cause);
|
||||
switch_caller_profile_t *outbound_profile,
|
||||
switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags, switch_call_cause_t *cancel_cause);
|
||||
switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id);
|
||||
switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id);
|
||||
switch_status_t channel_kill_channel(switch_core_session_t *session, int sig);
|
||||
|
@ -224,3 +235,14 @@ switch_endpoint_interface_t *skinny_get_endpoint_interface();
|
|||
|
||||
#endif /* _MOD_SKINNY_H */
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
* indent-tabs-mode:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
|
||||
*/
|
||||
|
||||
|
|
|
@ -0,0 +1,473 @@
|
|||
/*
|
||||
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
* Copyright (C) 2010, Mathieu Parent <math.parent@gmail.com>
|
||||
*
|
||||
* Version: MPL 1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mathieu Parent <math.parent@gmail.com>
|
||||
* Portions created by the Initial Developer are Copyright (C)
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Mathieu Parent <math.parent@gmail.com>
|
||||
*
|
||||
*
|
||||
* skinny_api.c -- Skinny Call Control Protocol (SCCP) Endpoint Module
|
||||
*
|
||||
*/
|
||||
|
||||
#include <switch.h>
|
||||
#include "mod_skinny.h"
|
||||
#include "skinny_protocol.h"
|
||||
#include "skinny_tables.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/* skinny_api_list_* */
|
||||
/*****************************************************************************/
|
||||
|
||||
static switch_status_t skinny_api_list_profiles(const char *line, const char *cursor, switch_console_callback_match_t **matches)
|
||||
{
|
||||
switch_console_callback_match_t *my_matches = NULL;
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
switch_hash_index_t *hi;
|
||||
void *val;
|
||||
skinny_profile_t *profile;
|
||||
|
||||
/* walk profiles */
|
||||
switch_mutex_lock(globals.mutex);
|
||||
for (hi = switch_hash_first(NULL, globals.profile_hash); hi; hi = switch_hash_next(hi)) {
|
||||
switch_hash_this(hi, NULL, NULL, &val);
|
||||
profile = (skinny_profile_t *) val;
|
||||
|
||||
switch_console_push_match(&my_matches, profile->name);
|
||||
}
|
||||
switch_mutex_unlock(globals.mutex);
|
||||
|
||||
if (my_matches) {
|
||||
*matches = my_matches;
|
||||
status = SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
struct match_helper {
|
||||
switch_console_callback_match_t *my_matches;
|
||||
};
|
||||
|
||||
static int skinny_api_list_devices_callback(void *pArg, int argc, char **argv, char **columnNames)
|
||||
{
|
||||
struct match_helper *h = (struct match_helper *) pArg;
|
||||
char *device_name = argv[0];
|
||||
|
||||
switch_console_push_match(&h->my_matches, device_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static switch_status_t skinny_api_list_devices(const char *line, const char *cursor, switch_console_callback_match_t **matches)
|
||||
{
|
||||
struct match_helper h = { 0 };
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
skinny_profile_t *profile = NULL;
|
||||
char *sql;
|
||||
|
||||
char *myline;
|
||||
char *argv[1024] = { 0 };
|
||||
int argc = 0;
|
||||
|
||||
if (!(myline = strdup(line))) {
|
||||
status = SWITCH_STATUS_MEMERR;
|
||||
return status;
|
||||
}
|
||||
if (!(argc = switch_separate_string(myline, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) || argc != 5) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if(!strcasecmp(argv[1], "profile")) {/* skinny profile <profile_name> ... */
|
||||
profile = skinny_find_profile(argv[2]);
|
||||
} else if(!strcasecmp(argv[2], "profile")) {/* skinny status profile <profile_name> ... */
|
||||
profile = skinny_find_profile(argv[3]);
|
||||
}
|
||||
|
||||
if(profile) {
|
||||
if ((sql = switch_mprintf("SELECT name FROM skinny_devices"))) {
|
||||
skinny_execute_sql_callback(profile, profile->sql_mutex, sql, skinny_api_list_devices_callback, &h);
|
||||
switch_safe_free(sql);
|
||||
}
|
||||
}
|
||||
|
||||
if (h.my_matches) {
|
||||
*matches = h.my_matches;
|
||||
status = SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static switch_status_t skinny_api_list_reset_types(const char *line, const char *cursor, switch_console_callback_match_t **matches)
|
||||
{
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
SKINNY_PUSH_DEVICE_RESET_TYPES
|
||||
return status;
|
||||
}
|
||||
|
||||
static switch_status_t skinny_api_list_stimuli(const char *line, const char *cursor, switch_console_callback_match_t **matches)
|
||||
{
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
SKINNY_PUSH_STIMULI
|
||||
return status;
|
||||
}
|
||||
|
||||
static switch_status_t skinny_api_list_ring_types(const char *line, const char *cursor, switch_console_callback_match_t **matches)
|
||||
{
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
SKINNY_PUSH_RING_TYPES
|
||||
return status;
|
||||
}
|
||||
|
||||
static switch_status_t skinny_api_list_ring_modes(const char *line, const char *cursor, switch_console_callback_match_t **matches)
|
||||
{
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
SKINNY_PUSH_RING_MODES
|
||||
return status;
|
||||
}
|
||||
|
||||
static switch_status_t skinny_api_list_stimulus_instances(const char *line, const char *cursor, switch_console_callback_match_t **matches)
|
||||
{
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
switch_console_callback_match_t *my_matches = NULL;
|
||||
|
||||
switch_console_push_match(&my_matches, "<stimulus_instance>");
|
||||
switch_console_push_match(&my_matches, "0");
|
||||
|
||||
if (my_matches) {
|
||||
*matches = my_matches;
|
||||
status = SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static switch_status_t skinny_api_list_stimulus_modes(const char *line, const char *cursor, switch_console_callback_match_t **matches)
|
||||
{
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
SKINNY_PUSH_LAMP_MODES
|
||||
return status;
|
||||
}
|
||||
|
||||
static switch_status_t skinny_api_list_speaker_modes(const char *line, const char *cursor, switch_console_callback_match_t **matches)
|
||||
{
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
SKINNY_PUSH_SPEAKER_MODES
|
||||
return status;
|
||||
}
|
||||
|
||||
static switch_status_t skinny_api_list_call_states(const char *line, const char *cursor, switch_console_callback_match_t **matches)
|
||||
{
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
SKINNY_PUSH_CALL_STATES
|
||||
return status;
|
||||
}
|
||||
|
||||
static switch_status_t skinny_api_list_line_instances(const char *line, const char *cursor, switch_console_callback_match_t **matches)
|
||||
{
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
switch_console_callback_match_t *my_matches = NULL;
|
||||
|
||||
/* TODO */
|
||||
switch_console_push_match(&my_matches, "1");
|
||||
switch_console_push_match(&my_matches, "<line_instance>");
|
||||
|
||||
if (my_matches) {
|
||||
*matches = my_matches;
|
||||
status = SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static switch_status_t skinny_api_list_call_ids(const char *line, const char *cursor, switch_console_callback_match_t **matches)
|
||||
{
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
switch_console_callback_match_t *my_matches = NULL;
|
||||
|
||||
/* TODO */
|
||||
switch_console_push_match(&my_matches, "1345");
|
||||
switch_console_push_match(&my_matches, "<call_id>");
|
||||
|
||||
if (my_matches) {
|
||||
*matches = my_matches;
|
||||
status = SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* skinny_api_cmd_* */
|
||||
/*****************************************************************************/
|
||||
static switch_status_t skinny_api_cmd_status_profile(const char *profile_name, switch_stream_handle_t *stream)
|
||||
{
|
||||
skinny_profile_t *profile;
|
||||
if ((profile = skinny_find_profile(profile_name))) {
|
||||
skinny_profile_dump(profile, stream);
|
||||
} else {
|
||||
stream->write_function(stream, "Profile not found!\n");
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t skinny_api_cmd_status_profile_device(const char *profile_name, const char *device_name, switch_stream_handle_t *stream)
|
||||
{
|
||||
skinny_profile_t *profile;
|
||||
if ((profile = skinny_find_profile(profile_name))) {
|
||||
dump_device(profile, device_name, stream);
|
||||
} else {
|
||||
stream->write_function(stream, "Profile not found!\n");
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t skinny_api_cmd_profile_device_send_ringer_message(const char *profile_name, const char *device_name, const char *ring_type, const char *ring_mode, switch_stream_handle_t *stream)
|
||||
{
|
||||
skinny_profile_t *profile;
|
||||
|
||||
if ((profile = skinny_find_profile(profile_name))) {
|
||||
listener_t *listener = NULL;
|
||||
skinny_profile_find_listener_by_device_name(profile, device_name, &listener);
|
||||
if(listener) {
|
||||
send_set_ringer(listener, skinny_str2ring_type(ring_type), skinny_str2ring_mode(ring_mode), 0, 0);
|
||||
} else {
|
||||
stream->write_function(stream, "Listener not found!\n");
|
||||
}
|
||||
} else {
|
||||
stream->write_function(stream, "Profile not found!\n");
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t skinny_api_cmd_profile_device_send_lamp_message(const char *profile_name, const char *device_name, const char *stimulus, const char *instance, const char *lamp_mode, switch_stream_handle_t *stream)
|
||||
{
|
||||
skinny_profile_t *profile;
|
||||
|
||||
if ((profile = skinny_find_profile(profile_name))) {
|
||||
listener_t *listener = NULL;
|
||||
skinny_profile_find_listener_by_device_name(profile, device_name, &listener);
|
||||
if(listener) {
|
||||
send_set_lamp(listener, skinny_str2button(stimulus), atoi(instance), skinny_str2lamp_mode(lamp_mode));
|
||||
} else {
|
||||
stream->write_function(stream, "Listener not found!\n");
|
||||
}
|
||||
} else {
|
||||
stream->write_function(stream, "Profile not found!\n");
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t skinny_api_cmd_profile_device_send_speaker_mode_message(const char *profile_name, const char *device_name, const char *speaker_mode, switch_stream_handle_t *stream)
|
||||
{
|
||||
skinny_profile_t *profile;
|
||||
|
||||
if ((profile = skinny_find_profile(profile_name))) {
|
||||
listener_t *listener = NULL;
|
||||
skinny_profile_find_listener_by_device_name(profile, device_name, &listener);
|
||||
if(listener) {
|
||||
send_set_speaker_mode(listener, skinny_str2speaker_mode(speaker_mode));
|
||||
} else {
|
||||
stream->write_function(stream, "Listener not found!\n");
|
||||
}
|
||||
} else {
|
||||
stream->write_function(stream, "Profile not found!\n");
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t skinny_api_cmd_profile_device_send_call_state_message(const char *profile_name, const char *device_name, const char *call_state, const char *line_instance, const char *call_id, switch_stream_handle_t *stream)
|
||||
{
|
||||
skinny_profile_t *profile;
|
||||
|
||||
if ((profile = skinny_find_profile(profile_name))) {
|
||||
listener_t *listener = NULL;
|
||||
skinny_profile_find_listener_by_device_name(profile, device_name, &listener);
|
||||
if(listener) {
|
||||
send_call_state(listener, skinny_str2call_state(call_state), atoi(line_instance), atoi(call_id));
|
||||
} else {
|
||||
stream->write_function(stream, "Listener not found!\n");
|
||||
}
|
||||
} else {
|
||||
stream->write_function(stream, "Profile not found!\n");
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t skinny_api_cmd_profile_device_send_reset_message(const char *profile_name, const char *device_name, const char *reset_type, switch_stream_handle_t *stream)
|
||||
{
|
||||
skinny_profile_t *profile;
|
||||
|
||||
if ((profile = skinny_find_profile(profile_name))) {
|
||||
listener_t *listener = NULL;
|
||||
skinny_profile_find_listener_by_device_name(profile, device_name, &listener);
|
||||
if(listener) {
|
||||
send_reset(listener, skinny_str2device_reset_type(reset_type));
|
||||
} else {
|
||||
stream->write_function(stream, "Listener not found!\n");
|
||||
}
|
||||
} else {
|
||||
stream->write_function(stream, "Profile not found!\n");
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* API */
|
||||
/*****************************************************************************/
|
||||
SWITCH_STANDARD_API(skinny_function)
|
||||
{
|
||||
char *argv[1024] = { 0 };
|
||||
int argc = 0;
|
||||
char *mycmd = NULL;
|
||||
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
||||
const char *usage_string = "USAGE:\n"
|
||||
"--------------------------------------------------------------------------------\n"
|
||||
"skinny help\n"
|
||||
"skinny status profile <profile_name>\n"
|
||||
"skinny status profile <profile_name> device <device_name>\n"
|
||||
"skinny profile <profile_name> device <device_name> send ResetMessage [DeviceReset|DeviceRestart]\n"
|
||||
"skinny profile <profile_name> device <device_name> send SetRingerMessage <ring_type> <ring_mode>\n"
|
||||
"skinny profile <profile_name> device <device_name> send SetLampMessage <stimulus> <instance> <lamp_mode>\n"
|
||||
"skinny profile <profile_name> device <device_name> send SetSpeakerModeMessage <speaker_mode>\n"
|
||||
"skinny profile <profile_name> device <device_name> send CallStateMessage <call_state> <line_instance> <call_id>\n"
|
||||
"--------------------------------------------------------------------------------\n";
|
||||
if (session) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
if (zstr(cmd)) {
|
||||
stream->write_function(stream, "%s", usage_string);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!(mycmd = strdup(cmd))) {
|
||||
status = SWITCH_STATUS_MEMERR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!(argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) || !argv[0]) {
|
||||
stream->write_function(stream, "%s", usage_string);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!strcasecmp(argv[0], "help")) {/* skinny help */
|
||||
stream->write_function(stream, "%s", usage_string);
|
||||
goto done;
|
||||
} else if (argc == 3 && !strcasecmp(argv[0], "status") && !strcasecmp(argv[1], "profile")) {
|
||||
/* skinny status profile <profile_name> */
|
||||
status = skinny_api_cmd_status_profile(argv[2], stream);
|
||||
} else if (argc == 5 && !strcasecmp(argv[0], "status") && !strcasecmp(argv[1], "profile") && !strcasecmp(argv[3], "device")) {
|
||||
/* skinny status profile <profile_name> device <device_name> */
|
||||
status = skinny_api_cmd_status_profile_device(argv[2], argv[4], stream);
|
||||
} else if (argc >= 6 && !strcasecmp(argv[0], "profile") && !strcasecmp(argv[2], "device") && !strcasecmp(argv[4], "send")) {
|
||||
/* skinny profile <profile_name> device <device_name> send ... */
|
||||
switch(skinny_str2message_type(argv[5])) {
|
||||
case SET_RINGER_MESSAGE:
|
||||
if(argc == 8) {
|
||||
/* SetRingerMessage <ring_type> <ring_mode> */
|
||||
status = skinny_api_cmd_profile_device_send_ringer_message(argv[1], argv[3], argv[6], argv[7], stream);
|
||||
}
|
||||
break;
|
||||
case SET_LAMP_MESSAGE:
|
||||
if (argc == 9) {
|
||||
/* SetLampMessage <stimulus> <instance> <lamp_mode> */
|
||||
status = skinny_api_cmd_profile_device_send_lamp_message(argv[1], argv[3], argv[6], argv[7], argv[8], stream);
|
||||
}
|
||||
break;
|
||||
case SET_SPEAKER_MODE_MESSAGE:
|
||||
if (argc == 7) {
|
||||
/* SetSpeakerModeMessage <speaker_mode> */
|
||||
status = skinny_api_cmd_profile_device_send_speaker_mode_message(argv[1], argv[3], argv[6], stream);
|
||||
}
|
||||
break;
|
||||
case CALL_STATE_MESSAGE:
|
||||
if (argc == 9) {
|
||||
/* CallStateMessage <call_state> <line_instance> <call_id> */
|
||||
status = skinny_api_cmd_profile_device_send_call_state_message(argv[1], argv[3], argv[6], argv[7], argv[8], stream);
|
||||
}
|
||||
break;
|
||||
case RESET_MESSAGE:
|
||||
if (argc == 7) {
|
||||
/* ResetMessage <reset_type> */
|
||||
status = skinny_api_cmd_profile_device_send_reset_message(argv[1], argv[3], argv[6], stream);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
stream->write_function(stream, "Unhandled message %s\n", argv[5]);
|
||||
}
|
||||
} else {
|
||||
stream->write_function(stream, "Unknown Command [%s]\n", argv[0]);
|
||||
}
|
||||
|
||||
done:
|
||||
switch_safe_free(mycmd);
|
||||
return status;
|
||||
}
|
||||
|
||||
switch_status_t skinny_api_register(switch_loadable_module_interface_t **module_interface)
|
||||
{
|
||||
switch_api_interface_t *api_interface;
|
||||
|
||||
SWITCH_ADD_API(api_interface, "skinny", "Skinny Controls", skinny_function, "<cmd> <args>");
|
||||
switch_console_set_complete("add skinny help");
|
||||
|
||||
switch_console_set_complete("add skinny status profile ::skinny::list_profiles");
|
||||
switch_console_set_complete("add skinny status profile ::skinny::list_profiles device ::skinny::list_devices");
|
||||
|
||||
switch_console_set_complete("add skinny profile ::skinny::list_profiles device ::skinny::list_devices send ResetMessage ::skinny::list_reset_types");
|
||||
switch_console_set_complete("add skinny profile ::skinny::list_profiles device ::skinny::list_devices send SetRingerMessage ::skinny::list_ring_types ::skinny::list_ring_modes");
|
||||
switch_console_set_complete("add skinny profile ::skinny::list_profiles device ::skinny::list_devices send SetLampMessage ::skinny::list_stimuli ::skinny::list_stimulus_instances ::skinny::list_stimulus_modes");
|
||||
switch_console_set_complete("add skinny profile ::skinny::list_profiles device ::skinny::list_devices send SetSpeakerModeMessage ::skinny::list_speaker_modes");
|
||||
switch_console_set_complete("add skinny profile ::skinny::list_profiles device ::skinny::list_devices send CallStateMessage ::skinny::list_call_states ::skinny::list_line_instances ::skinny::list_call_ids");
|
||||
|
||||
switch_console_add_complete_func("::skinny::list_profiles", skinny_api_list_profiles);
|
||||
switch_console_add_complete_func("::skinny::list_devices", skinny_api_list_devices);
|
||||
switch_console_add_complete_func("::skinny::list_reset_types", skinny_api_list_reset_types);
|
||||
switch_console_add_complete_func("::skinny::list_ring_types", skinny_api_list_ring_types);
|
||||
switch_console_add_complete_func("::skinny::list_ring_modes", skinny_api_list_ring_modes);
|
||||
switch_console_add_complete_func("::skinny::list_stimuli", skinny_api_list_stimuli);
|
||||
switch_console_add_complete_func("::skinny::list_stimulus_instances", skinny_api_list_stimulus_instances);
|
||||
switch_console_add_complete_func("::skinny::list_stimulus_modes", skinny_api_list_stimulus_modes);
|
||||
switch_console_add_complete_func("::skinny::list_speaker_modes", skinny_api_list_speaker_modes);
|
||||
switch_console_add_complete_func("::skinny::list_call_states", skinny_api_list_call_states);
|
||||
switch_console_add_complete_func("::skinny::list_line_instances", skinny_api_list_line_instances);
|
||||
switch_console_add_complete_func("::skinny::list_call_ids", skinny_api_list_call_ids);
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
* indent-tabs-mode:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
|
||||
*/
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
* Copyright (C) 2010, Mathieu Parent <math.parent@gmail.com>
|
||||
*
|
||||
* Version: MPL 1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mathieu Parent <math.parent@gmail.com>
|
||||
* Portions created by the Initial Developer are Copyright (C)
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Mathieu Parent <math.parent@gmail.com>
|
||||
*
|
||||
*
|
||||
* skinny_api.h -- Skinny Call Control Protocol (SCCP) Endpoint Module
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _SKINNY_API_H
|
||||
#define _SKINNY_API_H
|
||||
|
||||
switch_status_t skinny_api_register(switch_loadable_module_interface_t **module_interface);
|
||||
|
||||
#endif /* _SKINNY_API_H */
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
* indent-tabs-mode:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
|
||||
*/
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -35,157 +35,169 @@
|
|||
|
||||
/* Translation tables */
|
||||
struct skinny_table SKINNY_MESSAGE_TYPES[] = {
|
||||
{"KeepAliveMessage", KEEP_ALIVE_MESSAGE},
|
||||
{"RegisterMessage", REGISTER_MESSAGE},
|
||||
{"PortMessage", PORT_MESSAGE},
|
||||
{"KeypadButtonMessage", KEYPAD_BUTTON_MESSAGE},
|
||||
{"StimulusMessage", STIMULUS_MESSAGE},
|
||||
{"OffHookMessage", OFF_HOOK_MESSAGE},
|
||||
{"OnHookMessage", ON_HOOK_MESSAGE},
|
||||
{"SpeedDialStatReqMessage", SPEED_DIAL_STAT_REQ_MESSAGE},
|
||||
{"LineStatReqMessage", LINE_STAT_REQ_MESSAGE},
|
||||
{"ConfigStatReqMessage", CONFIG_STAT_REQ_MESSAGE},
|
||||
{"TimeDateReqMessage", TIME_DATE_REQ_MESSAGE},
|
||||
{"ButtonTemplateReqMessage", BUTTON_TEMPLATE_REQ_MESSAGE},
|
||||
{"CapabilitiesReqMessage", CAPABILITIES_RES_MESSAGE},
|
||||
{"AlarmMessage", ALARM_MESSAGE},
|
||||
{"OpenReceiveChannelAckMessage", OPEN_RECEIVE_CHANNEL_ACK_MESSAGE},
|
||||
{"SoftKeySetReqMessage", SOFT_KEY_SET_REQ_MESSAGE},
|
||||
{"SoftKeyEventMessage", SOFT_KEY_EVENT_MESSAGE},
|
||||
{"UnregisterMessage", UNREGISTER_MESSAGE},
|
||||
{"SoftKeyTemplateReqMessage", SOFT_KEY_TEMPLATE_REQ_MESSAGE},
|
||||
{"ServiceUrlStatReqMessage", SERVICE_URL_STAT_REQ_MESSAGE},
|
||||
{"FeatureStatReqMessage", FEATURE_STAT_REQ_MESSAGE},
|
||||
{"HeadsetStatusMessage", HEADSET_STATUS_MESSAGE},
|
||||
{"RegisterAvailableLinesMessage", REGISTER_AVAILABLE_LINES_MESSAGE},
|
||||
{"RegisterAckMessage", REGISTER_ACK_MESSAGE},
|
||||
{"StartToneMessage", START_TONE_MESSAGE},
|
||||
{"StopToneMessage", STOP_TONE_MESSAGE},
|
||||
{"SetRingerMessage", SET_RINGER_MESSAGE},
|
||||
{"SetLampMessage", SET_LAMP_MESSAGE},
|
||||
{"SetSpeakerModeMessage", SET_SPEAKER_MODE_MESSAGE},
|
||||
{"StartMediaTransmissionMessage", START_MEDIA_TRANSMISSION_MESSAGE},
|
||||
{"StopMediaTransmissionMessage", STOP_MEDIA_TRANSMISSION_MESSAGE},
|
||||
{"CallInfoMessage", CALL_INFO_MESSAGE},
|
||||
{"SpeedDialStatResMessage", SPEED_DIAL_STAT_RES_MESSAGE},
|
||||
{"LineStatResMessage", LINE_STAT_RES_MESSAGE},
|
||||
{"ConfigStatResMessage", CONFIG_STAT_RES_MESSAGE},
|
||||
{"DefineTimeDateMessage", DEFINE_TIME_DATE_MESSAGE},
|
||||
{"ButtonTemplateResMessage", BUTTON_TEMPLATE_RES_MESSAGE},
|
||||
{"CapabilitiesReqMessage", CAPABILITIES_REQ_MESSAGE},
|
||||
{"RegisterRejMessage", REGISTER_REJ_MESSAGE},
|
||||
{"ResetMessage", RESET_MESSAGE},
|
||||
{"KeepAliveAckMessage", KEEP_ALIVE_ACK_MESSAGE},
|
||||
{"OpenReceiveChannelMessage", OPEN_RECEIVE_CHANNEL_MESSAGE},
|
||||
{"OCloseReceiveChannelMessage", CLOSE_RECEIVE_CHANNEL_MESSAGE},
|
||||
{"SoftKeyTemplateResMessage", SOFT_KEY_TEMPLATE_RES_MESSAGE},
|
||||
{"SoftKeySetResMessage", SOFT_KEY_SET_RES_MESSAGE},
|
||||
{"SelectSoftKeysMessage", SELECT_SOFT_KEYS_MESSAGE},
|
||||
{"CallStateMessage", CALL_STATE_MESSAGE},
|
||||
{"DisplayPromptStatusMessage", DISPLAY_PROMPT_STATUS_MESSAGE},
|
||||
{"ClearPromptStatusMessage", CLEAR_PROMPT_STATUS_MESSAGE},
|
||||
{"ActivateCallPlaneMessage", ACTIVATE_CALL_PLANE_MESSAGE},
|
||||
{"UnregisterAckMessage", UNREGISTER_ACK_MESSAGE},
|
||||
{"DialedNumberMessage", DIALED_NUMBER_MESSAGE},
|
||||
{"FeatureResMessage", FEATURE_STAT_RES_MESSAGE},
|
||||
{"ServiceUrlStatMessage", SERVICE_URL_STAT_RES_MESSAGE},
|
||||
{NULL, 0}
|
||||
{"KeepAliveMessage", KEEP_ALIVE_MESSAGE},
|
||||
{"RegisterMessage", REGISTER_MESSAGE},
|
||||
{"PortMessage", PORT_MESSAGE},
|
||||
{"KeypadButtonMessage", KEYPAD_BUTTON_MESSAGE},
|
||||
{"StimulusMessage", STIMULUS_MESSAGE},
|
||||
{"OffHookMessage", OFF_HOOK_MESSAGE},
|
||||
{"OnHookMessage", ON_HOOK_MESSAGE},
|
||||
{"SpeedDialStatReqMessage", SPEED_DIAL_STAT_REQ_MESSAGE},
|
||||
{"LineStatReqMessage", LINE_STAT_REQ_MESSAGE},
|
||||
{"ConfigStatReqMessage", CONFIG_STAT_REQ_MESSAGE},
|
||||
{"TimeDateReqMessage", TIME_DATE_REQ_MESSAGE},
|
||||
{"ButtonTemplateReqMessage", BUTTON_TEMPLATE_REQ_MESSAGE},
|
||||
{"CapabilitiesReqMessage", CAPABILITIES_RES_MESSAGE},
|
||||
{"AlarmMessage", ALARM_MESSAGE},
|
||||
{"OpenReceiveChannelAckMessage", OPEN_RECEIVE_CHANNEL_ACK_MESSAGE},
|
||||
{"SoftKeySetReqMessage", SOFT_KEY_SET_REQ_MESSAGE},
|
||||
{"SoftKeyEventMessage", SOFT_KEY_EVENT_MESSAGE},
|
||||
{"UnregisterMessage", UNREGISTER_MESSAGE},
|
||||
{"SoftKeyTemplateReqMessage", SOFT_KEY_TEMPLATE_REQ_MESSAGE},
|
||||
{"ServiceUrlStatReqMessage", SERVICE_URL_STAT_REQ_MESSAGE},
|
||||
{"FeatureStatReqMessage", FEATURE_STAT_REQ_MESSAGE},
|
||||
{"HeadsetStatusMessage", HEADSET_STATUS_MESSAGE},
|
||||
{"RegisterAvailableLinesMessage", REGISTER_AVAILABLE_LINES_MESSAGE},
|
||||
{"RegisterAckMessage", REGISTER_ACK_MESSAGE},
|
||||
{"StartToneMessage", START_TONE_MESSAGE},
|
||||
{"StopToneMessage", STOP_TONE_MESSAGE},
|
||||
{"SetRingerMessage", SET_RINGER_MESSAGE},
|
||||
{"SetLampMessage", SET_LAMP_MESSAGE},
|
||||
{"SetSpeakerModeMessage", SET_SPEAKER_MODE_MESSAGE},
|
||||
{"StartMediaTransmissionMessage", START_MEDIA_TRANSMISSION_MESSAGE},
|
||||
{"StopMediaTransmissionMessage", STOP_MEDIA_TRANSMISSION_MESSAGE},
|
||||
{"CallInfoMessage", CALL_INFO_MESSAGE},
|
||||
{"SpeedDialStatResMessage", SPEED_DIAL_STAT_RES_MESSAGE},
|
||||
{"LineStatResMessage", LINE_STAT_RES_MESSAGE},
|
||||
{"ConfigStatResMessage", CONFIG_STAT_RES_MESSAGE},
|
||||
{"DefineTimeDateMessage", DEFINE_TIME_DATE_MESSAGE},
|
||||
{"ButtonTemplateResMessage", BUTTON_TEMPLATE_RES_MESSAGE},
|
||||
{"CapabilitiesReqMessage", CAPABILITIES_REQ_MESSAGE},
|
||||
{"RegisterRejectMessage", REGISTER_REJECT_MESSAGE},
|
||||
{"ResetMessage", RESET_MESSAGE},
|
||||
{"KeepAliveAckMessage", KEEP_ALIVE_ACK_MESSAGE},
|
||||
{"OpenReceiveChannelMessage", OPEN_RECEIVE_CHANNEL_MESSAGE},
|
||||
{"CloseReceiveChannelMessage", CLOSE_RECEIVE_CHANNEL_MESSAGE},
|
||||
{"SoftKeyTemplateResMessage", SOFT_KEY_TEMPLATE_RES_MESSAGE},
|
||||
{"SoftKeySetResMessage", SOFT_KEY_SET_RES_MESSAGE},
|
||||
{"SelectSoftKeysMessage", SELECT_SOFT_KEYS_MESSAGE},
|
||||
{"CallStateMessage", CALL_STATE_MESSAGE},
|
||||
{"DisplayPromptStatusMessage", DISPLAY_PROMPT_STATUS_MESSAGE},
|
||||
{"ClearPromptStatusMessage", CLEAR_PROMPT_STATUS_MESSAGE},
|
||||
{"ActivateCallPlaneMessage", ACTIVATE_CALL_PLANE_MESSAGE},
|
||||
{"UnregisterAckMessage", UNREGISTER_ACK_MESSAGE},
|
||||
{"DialedNumberMessage", DIALED_NUMBER_MESSAGE},
|
||||
{"FeatureResMessage", FEATURE_STAT_RES_MESSAGE},
|
||||
{"DisplayPriNotifyMessage", DISPLAY_PRI_NOTIFY_MESSAGE},
|
||||
{"ServiceUrlStatMessage", SERVICE_URL_STAT_RES_MESSAGE},
|
||||
{NULL, 0}
|
||||
};
|
||||
SKINNY_DECLARE_ID2STR(skinny_message_type2str, SKINNY_MESSAGE_TYPES, "UnknownMessage")
|
||||
SKINNY_DECLARE_STR2ID(skinny_str2message_type, SKINNY_MESSAGE_TYPES, -1)
|
||||
|
||||
struct skinny_table SKINNY_RING_TYPES[] = {
|
||||
{"RingOff", SKINNY_RING_OFF},
|
||||
{"RingInside", SKINNY_RING_INSIDE},
|
||||
{"RingOutside", SKINNY_RING_OUTSIDE},
|
||||
{"RingFeature", SKINNY_RING_FEATURE},
|
||||
{NULL, 0}
|
||||
{"RingOff", SKINNY_RING_OFF},
|
||||
{"RingInside", SKINNY_RING_INSIDE},
|
||||
{"RingOutside", SKINNY_RING_OUTSIDE},
|
||||
{"RingFeature", SKINNY_RING_FEATURE},
|
||||
{NULL, 0}
|
||||
};
|
||||
SKINNY_DECLARE_ID2STR(skinny_ring_type2str, SKINNY_RING_TYPES, "RingTypeUnknown")
|
||||
SKINNY_DECLARE_STR2ID(skinny_str2ring_type, SKINNY_RING_TYPES, -1)
|
||||
|
||||
struct skinny_table SKINNY_RING_MODES[] = {
|
||||
{"RingForever", SKINNY_RING_FOREVER},
|
||||
{"RingOnce", SKINNY_RING_ONCE},
|
||||
{NULL, 0}
|
||||
{"RingForever", SKINNY_RING_FOREVER},
|
||||
{"RingOnce", SKINNY_RING_ONCE},
|
||||
{NULL, 0}
|
||||
};
|
||||
SKINNY_DECLARE_ID2STR(skinny_ring_mode2str, SKINNY_RING_MODES, "RingModeUnknown")
|
||||
SKINNY_DECLARE_STR2ID(skinny_str2ring_mode, SKINNY_RING_MODES, -1)
|
||||
|
||||
struct skinny_table SKINNY_BUTTONS[] = {
|
||||
{"Unknown", SKINNY_BUTTON_UNKNOWN},
|
||||
{"LastNumberRedial", SKINNY_BUTTON_LAST_NUMBER_REDIAL},
|
||||
{"SpeedDial", SKINNY_BUTTON_SPEED_DIAL},
|
||||
{"Line", SKINNY_BUTTON_LINE},
|
||||
{"Voicemail", SKINNY_BUTTON_VOICEMAIL},
|
||||
{"Privacy", SKINNY_BUTTON_PRIVACY},
|
||||
{"ServiceUrl", SKINNY_BUTTON_SERVICE_URL},
|
||||
{"Undefined", SKINNY_BUTTON_UNDEFINED},
|
||||
{NULL, 0}
|
||||
{"Unknown", SKINNY_BUTTON_UNKNOWN},
|
||||
{"LastNumberRedial", SKINNY_BUTTON_LAST_NUMBER_REDIAL},
|
||||
{"SpeedDial", SKINNY_BUTTON_SPEED_DIAL},
|
||||
{"Line", SKINNY_BUTTON_LINE},
|
||||
{"Voicemail", SKINNY_BUTTON_VOICEMAIL},
|
||||
{"Privacy", SKINNY_BUTTON_PRIVACY},
|
||||
{"ServiceUrl", SKINNY_BUTTON_SERVICE_URL},
|
||||
{"Undefined", SKINNY_BUTTON_UNDEFINED},
|
||||
{NULL, 0}
|
||||
};
|
||||
SKINNY_DECLARE_ID2STR(skinny_button2str, SKINNY_BUTTONS, "Unknown")
|
||||
SKINNY_DECLARE_STR2ID(skinny_str2button, SKINNY_BUTTONS, -1)
|
||||
|
||||
struct skinny_table SKINNY_LAMP_MODES[] = {
|
||||
{"Off", SKINNY_LAMP_OFF},
|
||||
{"On", SKINNY_LAMP_ON},
|
||||
{"Wink", SKINNY_LAMP_WINK},
|
||||
{"Flash", SKINNY_LAMP_FLASH},
|
||||
{"Blink", SKINNY_LAMP_BLINK},
|
||||
{NULL, 0}
|
||||
{"Off", SKINNY_LAMP_OFF},
|
||||
{"On", SKINNY_LAMP_ON},
|
||||
{"Wink", SKINNY_LAMP_WINK},
|
||||
{"Flash", SKINNY_LAMP_FLASH},
|
||||
{"Blink", SKINNY_LAMP_BLINK},
|
||||
{NULL, 0}
|
||||
};
|
||||
SKINNY_DECLARE_ID2STR(skinny_lamp_mode2str, SKINNY_LAMP_MODES, "Unknown")
|
||||
SKINNY_DECLARE_STR2ID(skinny_str2lamp_mode, SKINNY_LAMP_MODES, -1)
|
||||
|
||||
struct skinny_table SKINNY_SPEAKER_MODES[] = {
|
||||
{"SpeakerOn", SKINNY_SPEAKER_ON},
|
||||
{"SpeakerOff", SKINNY_SPEAKER_OFF},
|
||||
{NULL, 0}
|
||||
{"SpeakerOn", SKINNY_SPEAKER_ON},
|
||||
{"SpeakerOff", SKINNY_SPEAKER_OFF},
|
||||
{NULL, 0}
|
||||
};
|
||||
SKINNY_DECLARE_ID2STR(skinny_speaker_mode2str, SKINNY_SPEAKER_MODES, "Unknown")
|
||||
SKINNY_DECLARE_STR2ID(skinny_str2speaker_mode, SKINNY_SPEAKER_MODES, -1)
|
||||
|
||||
struct skinny_table SKINNY_KEY_SETS[] = {
|
||||
{"KeySetOnHook", SKINNY_KEY_SET_ON_HOOK},
|
||||
{"KeySetConnected", SKINNY_KEY_SET_CONNECTED},
|
||||
{"KeySetOnHold", SKINNY_KEY_SET_ON_HOLD},
|
||||
{"KeySetRingIn", SKINNY_KEY_SET_RING_IN},
|
||||
{"KeySetOffHook", SKINNY_KEY_SET_OFF_HOOK},
|
||||
{"KeySetConnectedWithTransfer", SKINNY_KEY_SET_CONNECTED_WITH_TRANSFER},
|
||||
{"KeySetDigitsAfterDialingFirstDigit", SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT},
|
||||
{"KeySetConnectedWithConference", SKINNY_KEY_SET_CONNECTED_WITH_CONFERENCE},
|
||||
{"KeySetRingOut", SKINNY_KEY_SET_RING_OUT},
|
||||
{"KeySetOffHookWithFeatures", SKINNY_KEY_SET_OFF_HOOK_WITH_FEATURES},
|
||||
{NULL, 0}
|
||||
{"KeySetOnHook", SKINNY_KEY_SET_ON_HOOK},
|
||||
{"KeySetConnected", SKINNY_KEY_SET_CONNECTED},
|
||||
{"KeySetOnHold", SKINNY_KEY_SET_ON_HOLD},
|
||||
{"KeySetRingIn", SKINNY_KEY_SET_RING_IN},
|
||||
{"KeySetOffHook", SKINNY_KEY_SET_OFF_HOOK},
|
||||
{"KeySetConnectedWithTransfer", SKINNY_KEY_SET_CONNECTED_WITH_TRANSFER},
|
||||
{"KeySetDigitsAfterDialingFirstDigit", SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT},
|
||||
{"KeySetConnectedWithConference", SKINNY_KEY_SET_CONNECTED_WITH_CONFERENCE},
|
||||
{"KeySetRingOut", SKINNY_KEY_SET_RING_OUT},
|
||||
{"KeySetOffHookWithFeatures", SKINNY_KEY_SET_OFF_HOOK_WITH_FEATURES},
|
||||
{NULL, 0}
|
||||
};
|
||||
SKINNY_DECLARE_ID2STR(skinny_soft_key_set2str, SKINNY_KEY_SETS, "UNKNOWN_SOFT_KEY_SET")
|
||||
SKINNY_DECLARE_STR2ID(skinny_str2soft_key_set, SKINNY_KEY_SETS, -1)
|
||||
|
||||
struct skinny_table SKINNY_CALL_STATES[] = {
|
||||
{"OffHook", SKINNY_OFF_HOOK},
|
||||
{"OnHook", SKINNY_ON_HOOK},
|
||||
{"RingOut", SKINNY_RING_OUT},
|
||||
{"RingIn", SKINNY_RING_IN},
|
||||
{"Connected", SKINNY_CONNECTED},
|
||||
{"Busy", SKINNY_BUSY},
|
||||
{"Congestion", SKINNY_CONGESTION},
|
||||
{"Hold", SKINNY_HOLD},
|
||||
{"CallWaiting", SKINNY_CALL_WAITING},
|
||||
{"CallTransfer", SKINNY_CALL_TRANSFER},
|
||||
{"CallPark", SKINNY_CALL_PARK},
|
||||
{"Proceed", SKINNY_PROCEED},
|
||||
{"CallRemoteMultiline", SKINNY_CALL_REMOTE_MULTILINE},
|
||||
{"InvalidNumber", SKINNY_INVALID_NUMBER},
|
||||
{NULL, 0}
|
||||
{"OffHook", SKINNY_OFF_HOOK},
|
||||
{"OnHook", SKINNY_ON_HOOK},
|
||||
{"RingOut", SKINNY_RING_OUT},
|
||||
{"RingIn", SKINNY_RING_IN},
|
||||
{"Connected", SKINNY_CONNECTED},
|
||||
{"Busy", SKINNY_BUSY},
|
||||
{"LineInUse", SKINNY_LINE_IN_USE},
|
||||
{"Hold", SKINNY_HOLD},
|
||||
{"CallWaiting", SKINNY_CALL_WAITING},
|
||||
{"CallTransfer", SKINNY_CALL_TRANSFER},
|
||||
{"CallPark", SKINNY_CALL_PARK},
|
||||
{"Proceed", SKINNY_PROCEED},
|
||||
{"InUseRemotely", SKINNY_IN_USE_REMOTELY},
|
||||
{"InvalidNumber", SKINNY_INVALID_NUMBER},
|
||||
{NULL, 0}
|
||||
};
|
||||
SKINNY_DECLARE_ID2STR(skinny_call_state2str, SKINNY_CALL_STATES, "CallStateUnknown")
|
||||
SKINNY_DECLARE_STR2ID(skinny_str2call_state, SKINNY_CALL_STATES, -1)
|
||||
|
||||
struct skinny_table SKINNY_DEVICE_RESET_TYPES[] = {
|
||||
{"DeviceReset", SKINNY_DEVICE_RESET},
|
||||
{"DeviceRestart", SKINNY_DEVICE_RESTART},
|
||||
{NULL, 0}
|
||||
{"DeviceReset", SKINNY_DEVICE_RESET},
|
||||
{"DeviceRestart", SKINNY_DEVICE_RESTART},
|
||||
{NULL, 0}
|
||||
};
|
||||
SKINNY_DECLARE_ID2STR(skinny_device_reset_type2str, SKINNY_DEVICE_RESET_TYPES, "DeviceResetTypeUnknown")
|
||||
SKINNY_DECLARE_STR2ID(skinny_str2device_reset_type, SKINNY_DEVICE_RESET_TYPES, -1)
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
* indent-tabs-mode:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
|
||||
*/
|
||||
|
||||
|
|
|
@ -36,74 +36,74 @@
|
|||
/* SKINNY TABLES */
|
||||
/*****************************************************************************/
|
||||
struct skinny_table {
|
||||
const char *name;
|
||||
uint32_t id;
|
||||
const char *name;
|
||||
uint32_t id;
|
||||
};
|
||||
|
||||
#define SKINNY_DECLARE_ID2STR(func, TABLE, DEFAULT_STR) \
|
||||
const char *func(uint32_t id) \
|
||||
{ \
|
||||
const char *str = DEFAULT_STR; \
|
||||
\
|
||||
for (uint8_t x = 0; x < (sizeof(TABLE) / sizeof(struct skinny_table)) - 1; x++) {\
|
||||
if (TABLE[x].id == id) {\
|
||||
str = TABLE[x].name;\
|
||||
break;\
|
||||
}\
|
||||
}\
|
||||
\
|
||||
return str;\
|
||||
const char *str = DEFAULT_STR; \
|
||||
\
|
||||
for (uint8_t x = 0; x < (sizeof(TABLE) / sizeof(struct skinny_table)) - 1; x++) {\
|
||||
if (TABLE[x].id == id) {\
|
||||
str = TABLE[x].name;\
|
||||
break;\
|
||||
}\
|
||||
}\
|
||||
\
|
||||
return str;\
|
||||
}
|
||||
|
||||
#define SKINNY_DECLARE_STR2ID(func, TABLE, DEFAULT_ID) \
|
||||
uint32_t func(const char *str)\
|
||||
{\
|
||||
uint32_t id = DEFAULT_ID;\
|
||||
\
|
||||
if (*str > 47 && *str < 58) {\
|
||||
id = atoi(str);\
|
||||
} else {\
|
||||
for (uint8_t x = 0; x < (sizeof(TABLE) / sizeof(struct skinny_table)) - 1 && TABLE[x].name; x++) {\
|
||||
if (!strcasecmp(TABLE[x].name, str)) {\
|
||||
id = TABLE[x].id;\
|
||||
break;\
|
||||
}\
|
||||
}\
|
||||
}\
|
||||
return id;\
|
||||
uint32_t id = DEFAULT_ID;\
|
||||
\
|
||||
if (*str > 47 && *str < 58) {\
|
||||
id = atoi(str);\
|
||||
} else {\
|
||||
for (uint8_t x = 0; x < (sizeof(TABLE) / sizeof(struct skinny_table)) - 1 && TABLE[x].name; x++) {\
|
||||
if (!strcasecmp(TABLE[x].name, str)) {\
|
||||
id = TABLE[x].id;\
|
||||
break;\
|
||||
}\
|
||||
}\
|
||||
}\
|
||||
return id;\
|
||||
}
|
||||
|
||||
#define SKINNY_DECLARE_PUSH_MATCH(TABLE) \
|
||||
switch_console_callback_match_t *my_matches = NULL;\
|
||||
for (uint8_t x = 0; x < (sizeof(TABLE) / sizeof(struct skinny_table)) - 1; x++) {\
|
||||
switch_console_push_match(&my_matches, TABLE[x].name);\
|
||||
}\
|
||||
if (my_matches) {\
|
||||
*matches = my_matches;\
|
||||
status = SWITCH_STATUS_SUCCESS;\
|
||||
}
|
||||
|
||||
switch_console_callback_match_t *my_matches = NULL;\
|
||||
for (uint8_t x = 0; x < (sizeof(TABLE) / sizeof(struct skinny_table)) - 1; x++) {\
|
||||
switch_console_push_match(&my_matches, TABLE[x].name);\
|
||||
}\
|
||||
if (my_matches) {\
|
||||
*matches = my_matches;\
|
||||
status = SWITCH_STATUS_SUCCESS;\
|
||||
}
|
||||
|
||||
struct skinny_table SKINNY_MESSAGE_TYPES[55];
|
||||
|
||||
struct skinny_table SKINNY_MESSAGE_TYPES[56];
|
||||
const char *skinny_message_type2str(uint32_t id);
|
||||
uint32_t skinny_str2message_type(const char *str);
|
||||
#define SKINNY_PUSH_MESSAGE_TYPES SKINNY_DECLARE_PUSH_MATCH(SKINNY_MESSAGE_TYPES)
|
||||
|
||||
enum skinny_tone {
|
||||
SKINNY_TONE_SILENCE = 0x00,
|
||||
SKINNY_TONE_DIALTONE = 0x21,
|
||||
SKINNY_TONE_BUSYTONE = 0x23,
|
||||
SKINNY_TONE_ALERT = 0x24,
|
||||
SKINNY_TONE_REORDER = 0x25,
|
||||
SKINNY_TONE_CALLWAITTONE = 0x2D,
|
||||
SKINNY_TONE_NOTONE = 0x7F,
|
||||
SKINNY_TONE_SILENCE = 0x00,
|
||||
SKINNY_TONE_DIALTONE = 0x21,
|
||||
SKINNY_TONE_BUSYTONE = 0x23,
|
||||
SKINNY_TONE_ALERT = 0x24,
|
||||
SKINNY_TONE_REORDER = 0x25,
|
||||
SKINNY_TONE_CALLWAITTONE = 0x2D,
|
||||
SKINNY_TONE_NOTONE = 0x7F,
|
||||
};
|
||||
|
||||
enum skinny_ring_type {
|
||||
SKINNY_RING_OFF = 1,
|
||||
SKINNY_RING_INSIDE = 2,
|
||||
SKINNY_RING_OUTSIDE = 3,
|
||||
SKINNY_RING_FEATURE = 4
|
||||
SKINNY_RING_OFF = 1,
|
||||
SKINNY_RING_INSIDE = 2,
|
||||
SKINNY_RING_OUTSIDE = 3,
|
||||
SKINNY_RING_FEATURE = 4
|
||||
};
|
||||
struct skinny_table SKINNY_RING_TYPES[5];
|
||||
const char *skinny_ring_type2str(uint32_t id);
|
||||
|
@ -111,8 +111,8 @@ uint32_t skinny_str2ring_type(const char *str);
|
|||
#define SKINNY_PUSH_RING_TYPES SKINNY_DECLARE_PUSH_MATCH(SKINNY_RING_TYPES)
|
||||
|
||||
enum skinny_ring_mode {
|
||||
SKINNY_RING_FOREVER = 1,
|
||||
SKINNY_RING_ONCE = 2,
|
||||
SKINNY_RING_FOREVER = 1,
|
||||
SKINNY_RING_ONCE = 2,
|
||||
};
|
||||
struct skinny_table SKINNY_RING_MODES[3];
|
||||
const char *skinny_ring_mode2str(uint32_t id);
|
||||
|
@ -121,11 +121,11 @@ uint32_t skinny_str2ring_mode(const char *str);
|
|||
|
||||
|
||||
enum skinny_lamp_mode {
|
||||
SKINNY_LAMP_OFF = 1,
|
||||
SKINNY_LAMP_ON = 2,
|
||||
SKINNY_LAMP_WINK = 3,
|
||||
SKINNY_LAMP_FLASH = 4,
|
||||
SKINNY_LAMP_BLINK = 5,
|
||||
SKINNY_LAMP_OFF = 1,
|
||||
SKINNY_LAMP_ON = 2,
|
||||
SKINNY_LAMP_WINK = 3,
|
||||
SKINNY_LAMP_FLASH = 4,
|
||||
SKINNY_LAMP_BLINK = 5,
|
||||
};
|
||||
struct skinny_table SKINNY_LAMP_MODES[6];
|
||||
const char *skinny_lamp_mode2str(uint32_t id);
|
||||
|
@ -133,8 +133,8 @@ uint32_t skinny_str2lamp_mode(const char *str);
|
|||
#define SKINNY_PUSH_LAMP_MODES SKINNY_DECLARE_PUSH_MATCH(SKINNY_LAMP_MODES)
|
||||
|
||||
enum skinny_speaker_mode {
|
||||
SKINNY_SPEAKER_ON = 1,
|
||||
SKINNY_SPEAKER_OFF = 2,
|
||||
SKINNY_SPEAKER_ON = 1,
|
||||
SKINNY_SPEAKER_OFF = 2,
|
||||
};
|
||||
struct skinny_table SKINNY_SPEAKER_MODES[3];
|
||||
const char *skinny_speaker_mode2str(uint32_t id);
|
||||
|
@ -142,20 +142,20 @@ uint32_t skinny_str2speaker_mode(const char *str);
|
|||
#define SKINNY_PUSH_SPEAKER_MODES SKINNY_DECLARE_PUSH_MATCH(SKINNY_SPEAKER_MODES)
|
||||
|
||||
enum skinny_call_type {
|
||||
SKINNY_INBOUND_CALL = 1,
|
||||
SKINNY_OUTBOUND_CALL = 2,
|
||||
SKINNY_FORWARD_CALL = 3,
|
||||
SKINNY_INBOUND_CALL = 1,
|
||||
SKINNY_OUTBOUND_CALL = 2,
|
||||
SKINNY_FORWARD_CALL = 3,
|
||||
};
|
||||
|
||||
enum skinny_button_definition {
|
||||
SKINNY_BUTTON_UNKNOWN = 0x00,
|
||||
SKINNY_BUTTON_LAST_NUMBER_REDIAL = 0x01,
|
||||
SKINNY_BUTTON_SPEED_DIAL = 0x02,
|
||||
SKINNY_BUTTON_LINE = 0x09,
|
||||
SKINNY_BUTTON_VOICEMAIL = 0x0F,
|
||||
SKINNY_BUTTON_PRIVACY = 0x13,
|
||||
SKINNY_BUTTON_SERVICE_URL = 0x14,
|
||||
SKINNY_BUTTON_UNDEFINED = 0xFF,
|
||||
SKINNY_BUTTON_UNKNOWN = 0x00,
|
||||
SKINNY_BUTTON_LAST_NUMBER_REDIAL = 0x01,
|
||||
SKINNY_BUTTON_SPEED_DIAL = 0x02,
|
||||
SKINNY_BUTTON_LINE = 0x09,
|
||||
SKINNY_BUTTON_VOICEMAIL = 0x0F,
|
||||
SKINNY_BUTTON_PRIVACY = 0x13,
|
||||
SKINNY_BUTTON_SERVICE_URL = 0x14,
|
||||
SKINNY_BUTTON_UNDEFINED = 0xFF,
|
||||
};
|
||||
struct skinny_table SKINNY_BUTTONS[9];
|
||||
const char *skinny_button2str(uint32_t id);
|
||||
|
@ -163,39 +163,39 @@ uint32_t skinny_str2button(const char *str);
|
|||
#define SKINNY_PUSH_STIMULI SKINNY_DECLARE_PUSH_MATCH(SKINNY_BUTTONS)
|
||||
|
||||
enum skinny_soft_key_event {
|
||||
SOFTKEY_REDIAL = 0x01,
|
||||
SOFTKEY_NEWCALL = 0x02,
|
||||
SOFTKEY_HOLD = 0x03,
|
||||
SOFTKEY_TRANSFER = 0x04,
|
||||
SOFTKEY_CFWDALL = 0x05,
|
||||
SOFTKEY_CFWDBUSY = 0x06,
|
||||
SOFTKEY_CFWDNOANSWER = 0x07,
|
||||
SOFTKEY_BACKSPACE = 0x08,
|
||||
SOFTKEY_ENDCALL = 0x09,
|
||||
SOFTKEY_RESUME = 0x0A,
|
||||
SOFTKEY_ANSWER = 0x0B,
|
||||
SOFTKEY_INFO = 0x0C,
|
||||
SOFTKEY_CONFRM = 0x0D,
|
||||
SOFTKEY_PARK = 0x0E,
|
||||
SOFTKEY_JOIN = 0x0F,
|
||||
SOFTKEY_MEETMECONFRM = 0x10,
|
||||
SOFTKEY_CALLPICKUP = 0x11,
|
||||
SOFTKEY_GRPCALLPICKUP = 0x12,
|
||||
SOFTKEY_DND = 0x13,
|
||||
SOFTKEY_IDIVERT = 0x14,
|
||||
SOFTKEY_REDIAL = 0x01,
|
||||
SOFTKEY_NEWCALL = 0x02,
|
||||
SOFTKEY_HOLD = 0x03,
|
||||
SOFTKEY_TRANSFER = 0x04,
|
||||
SOFTKEY_CFWDALL = 0x05,
|
||||
SOFTKEY_CFWDBUSY = 0x06,
|
||||
SOFTKEY_CFWDNOANSWER = 0x07,
|
||||
SOFTKEY_BACKSPACE = 0x08,
|
||||
SOFTKEY_ENDCALL = 0x09,
|
||||
SOFTKEY_RESUME = 0x0A,
|
||||
SOFTKEY_ANSWER = 0x0B,
|
||||
SOFTKEY_INFO = 0x0C,
|
||||
SOFTKEY_CONFRM = 0x0D,
|
||||
SOFTKEY_PARK = 0x0E,
|
||||
SOFTKEY_JOIN = 0x0F,
|
||||
SOFTKEY_MEETMECONFRM = 0x10,
|
||||
SOFTKEY_CALLPICKUP = 0x11,
|
||||
SOFTKEY_GRPCALLPICKUP = 0x12,
|
||||
SOFTKEY_DND = 0x13,
|
||||
SOFTKEY_IDIVERT = 0x14,
|
||||
};
|
||||
|
||||
enum skinny_key_set {
|
||||
SKINNY_KEY_SET_ON_HOOK = 0,
|
||||
SKINNY_KEY_SET_CONNECTED = 1,
|
||||
SKINNY_KEY_SET_ON_HOLD = 2,
|
||||
SKINNY_KEY_SET_RING_IN = 3,
|
||||
SKINNY_KEY_SET_OFF_HOOK = 4,
|
||||
SKINNY_KEY_SET_CONNECTED_WITH_TRANSFER = 5,
|
||||
SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT = 6,
|
||||
SKINNY_KEY_SET_CONNECTED_WITH_CONFERENCE = 7,
|
||||
SKINNY_KEY_SET_RING_OUT = 8,
|
||||
SKINNY_KEY_SET_OFF_HOOK_WITH_FEATURES = 9,
|
||||
SKINNY_KEY_SET_ON_HOOK = 0,
|
||||
SKINNY_KEY_SET_CONNECTED = 1,
|
||||
SKINNY_KEY_SET_ON_HOLD = 2,
|
||||
SKINNY_KEY_SET_RING_IN = 3,
|
||||
SKINNY_KEY_SET_OFF_HOOK = 4,
|
||||
SKINNY_KEY_SET_CONNECTED_WITH_TRANSFER = 5,
|
||||
SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT = 6,
|
||||
SKINNY_KEY_SET_CONNECTED_WITH_CONFERENCE = 7,
|
||||
SKINNY_KEY_SET_RING_OUT = 8,
|
||||
SKINNY_KEY_SET_OFF_HOOK_WITH_FEATURES = 9,
|
||||
};
|
||||
struct skinny_table SKINNY_KEY_SETS[11];
|
||||
const char *skinny_soft_key_set2str(uint32_t id);
|
||||
|
@ -204,20 +204,20 @@ uint32_t skinny_str2soft_key_set(const char *str);
|
|||
|
||||
|
||||
enum skinny_call_state {
|
||||
SKINNY_OFF_HOOK = 1,
|
||||
SKINNY_ON_HOOK = 2,
|
||||
SKINNY_RING_OUT = 3,
|
||||
SKINNY_RING_IN = 4,
|
||||
SKINNY_CONNECTED = 5,
|
||||
SKINNY_BUSY = 6,
|
||||
SKINNY_CONGESTION = 7,
|
||||
SKINNY_HOLD = 8,
|
||||
SKINNY_CALL_WAITING = 9,
|
||||
SKINNY_CALL_TRANSFER = 10,
|
||||
SKINNY_CALL_PARK = 11,
|
||||
SKINNY_PROCEED = 12,
|
||||
SKINNY_CALL_REMOTE_MULTILINE = 13,
|
||||
SKINNY_INVALID_NUMBER = 14
|
||||
SKINNY_OFF_HOOK = 1,
|
||||
SKINNY_ON_HOOK = 2,
|
||||
SKINNY_RING_OUT = 3,
|
||||
SKINNY_RING_IN = 4,
|
||||
SKINNY_CONNECTED = 5,
|
||||
SKINNY_BUSY = 6,
|
||||
SKINNY_LINE_IN_USE = 7,
|
||||
SKINNY_HOLD = 8,
|
||||
SKINNY_CALL_WAITING = 9,
|
||||
SKINNY_CALL_TRANSFER = 10,
|
||||
SKINNY_CALL_PARK = 11,
|
||||
SKINNY_PROCEED = 12,
|
||||
SKINNY_IN_USE_REMOTELY = 13,
|
||||
SKINNY_INVALID_NUMBER = 14
|
||||
};
|
||||
struct skinny_table SKINNY_CALL_STATES[15];
|
||||
const char *skinny_call_state2str(uint32_t id);
|
||||
|
@ -235,3 +235,14 @@ uint32_t skinny_str2device_reset_type(const char *str);
|
|||
|
||||
#endif /* _SKINNY_TABLES_H */
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
* indent-tabs-mode:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
|
||||
*/
|
||||
|
||||
|
|
|
@ -11,12 +11,13 @@ BEGIN {
|
|||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Sys::Hostname;
|
||||
use Net::Skinny;
|
||||
use Net::Skinny::Protocol qw/:all/;
|
||||
use Net::Skinny::Message;
|
||||
|
||||
#Config
|
||||
my $skinny_server = '127.0.0.1';
|
||||
my $skinny_server = hostname;
|
||||
my $device_name = "SEP001120AABBCC";
|
||||
my $device_ip = 10+256*(11+256*(12+256*13)); # 10.11.12.13
|
||||
#======
|
||||
|
@ -70,6 +71,7 @@ $socket->receive_message(); # SoftKeyTemplateRes
|
|||
|
||||
$socket->send_message(SOFT_KEY_SET_REQ_MESSAGE);
|
||||
$socket->receive_message(); # SoftKeySetRes
|
||||
$socket->receive_message(); # SelectSoftKeys
|
||||
|
||||
$socket->send_message(
|
||||
LINE_STAT_REQ_MESSAGE,
|
||||
|
@ -82,8 +84,68 @@ $socket->send_message(
|
|||
count => 2
|
||||
);
|
||||
|
||||
while(1) {
|
||||
$socket->sleep(20);
|
||||
for(my $i = 0; $i < 1; $i++) {
|
||||
$socket->sleep(5);
|
||||
$socket->send_message(KEEP_ALIVE_MESSAGE);
|
||||
$socket->receive_message(); # keepaliveack
|
||||
}
|
||||
$socket->sleep(5);
|
||||
|
||||
#NewCall
|
||||
$socket->send_message(
|
||||
SOFT_KEY_EVENT_MESSAGE,
|
||||
event => 2, #NewCall
|
||||
line_instance => 2,
|
||||
call_id => 0
|
||||
);
|
||||
$socket->receive_message(); # SetRinger
|
||||
$socket->receive_message(); # SetSpeakerMode
|
||||
$socket->receive_message(); # SetLamp
|
||||
$socket->receive_message(); # SelectSoftKeys
|
||||
$socket->receive_message(); # DisplayPromptStatus
|
||||
$socket->receive_message(); # ActivateCallPlane
|
||||
$socket->receive_message(); # StartTone
|
||||
|
||||
$socket->sleep(5);
|
||||
|
||||
#VoiceMail
|
||||
$socket->send_message(
|
||||
STIMULUS_MESSAGE,
|
||||
instance_type => 0xf, #VoiceMail
|
||||
instance => 0,
|
||||
);
|
||||
$socket->receive_message(); #
|
||||
$socket->receive_message(); #
|
||||
$socket->receive_message(); #
|
||||
$socket->receive_message(); #
|
||||
$socket->receive_message(); #
|
||||
$socket->receive_message(); #
|
||||
$socket->receive_message(); #
|
||||
$socket->receive_message(); #
|
||||
$socket->receive_message(); #
|
||||
$socket->receive_message(); #
|
||||
|
||||
#
|
||||
$socket->send_message(
|
||||
OPEN_RECEIVE_CHANNEL_ACK_MESSAGE,
|
||||
status => 1,
|
||||
ip => $device_ip,
|
||||
port => 12,
|
||||
pass_thru_party_id => 0,
|
||||
);
|
||||
$socket->receive_message(); # StartMediaTransmission
|
||||
|
||||
$socket->sleep(20);
|
||||
|
||||
#EndCall
|
||||
$socket->send_message(
|
||||
SOFT_KEY_EVENT_MESSAGE,
|
||||
event => 0x09, #NewCall
|
||||
line_instance => 1,
|
||||
call_id => 0
|
||||
);
|
||||
|
||||
while(1) {
|
||||
$socket->receive_message();
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,6 @@ include $(top_srcdir)/build/modmake.rulesam
|
|||
MODNAME=mod_skypopen
|
||||
mod_LTLIBRARIES = mod_skypopen.la
|
||||
mod_skypopen_la_SOURCES = mod_skypopen.c skypopen_protocol.c
|
||||
mod_skypopen_la_CFLAGS = $(AM_CFLAGS) -DSKYPOPEN_SVN_VERSION=\"`cat $(switch_builddir)/.version`\" -I../../../../libs/spandsp/src -I../../../..//libs/tiff-3.8.2/libtiff
|
||||
mod_skypopen_la_CFLAGS = $(AM_CFLAGS) -DSKYPOPEN_SVN_VERSION=\"`git describe`\" -I../../../../libs/spandsp/src -I../../../..//libs/tiff-3.8.2/libtiff
|
||||
mod_skypopen_la_LIBADD = $(switch_builddir)/libfreeswitch.la
|
||||
mod_skypopen_la_LDFLAGS = -L../../../../libs/spandsp/src -avoid-version -module -no-undefined -shared -lX11 -lspandsp
|
||||
|
|
|
@ -52,7 +52,6 @@ static struct {
|
|||
char *bindings;
|
||||
uint32_t key_count;
|
||||
char hostname[80];
|
||||
uint64_t host_hash;
|
||||
switch_port_t port;
|
||||
switch_sockaddr_t *addr;
|
||||
switch_socket_t *udp_socket;
|
||||
|
@ -295,36 +294,35 @@ static void event_handler(switch_event_t *event)
|
|||
|
||||
switch_uuid_get(&uuid);
|
||||
switch_uuid_format(uuid_str, &uuid);
|
||||
len = strlen(packet) + sizeof(globals.host_hash) + SWITCH_UUID_FORMATTED_LENGTH + EVP_MAX_IV_LENGTH + strlen((char *) MAGIC);
|
||||
len = strlen(packet) + SWITCH_UUID_FORMATTED_LENGTH + EVP_MAX_IV_LENGTH + strlen((char *) MAGIC);
|
||||
#else
|
||||
len = strlen(packet) + sizeof(globals.host_hash) + strlen((char *) MAGIC);
|
||||
len = strlen(packet) + strlen((char *) MAGIC);
|
||||
#endif
|
||||
buf = malloc(len + 1);
|
||||
memset(buf, 0, len + 1);
|
||||
switch_assert(buf);
|
||||
memcpy(buf, &globals.host_hash, sizeof(globals.host_hash));
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
if (globals.psk) {
|
||||
switch_copy_string(buf + sizeof(globals.host_hash), uuid_str, SWITCH_UUID_FORMATTED_LENGTH);
|
||||
switch_copy_string(buf, uuid_str, SWITCH_UUID_FORMATTED_LENGTH);
|
||||
|
||||
EVP_CIPHER_CTX_init(&ctx);
|
||||
EVP_EncryptInit(&ctx, EVP_bf_cbc(), NULL, NULL);
|
||||
EVP_CIPHER_CTX_set_key_length(&ctx, strlen(globals.psk));
|
||||
EVP_EncryptInit(&ctx, NULL, (unsigned char *) globals.psk, (unsigned char *) uuid_str);
|
||||
EVP_EncryptUpdate(&ctx, (unsigned char *) buf + sizeof(globals.host_hash) + SWITCH_UUID_FORMATTED_LENGTH,
|
||||
EVP_EncryptUpdate(&ctx, (unsigned char *) buf + SWITCH_UUID_FORMATTED_LENGTH,
|
||||
&outlen, (unsigned char *) packet, (int) strlen(packet));
|
||||
EVP_EncryptUpdate(&ctx, (unsigned char *) buf + sizeof(globals.host_hash) + SWITCH_UUID_FORMATTED_LENGTH + outlen,
|
||||
EVP_EncryptUpdate(&ctx, (unsigned char *) buf + SWITCH_UUID_FORMATTED_LENGTH + outlen,
|
||||
&tmplen, (unsigned char *) MAGIC, (int) strlen((char *) MAGIC));
|
||||
outlen += tmplen;
|
||||
EVP_EncryptFinal(&ctx, (unsigned char *) buf + sizeof(globals.host_hash) + SWITCH_UUID_FORMATTED_LENGTH + outlen, &tmplen);
|
||||
EVP_EncryptFinal(&ctx, (unsigned char *) buf + SWITCH_UUID_FORMATTED_LENGTH + outlen, &tmplen);
|
||||
outlen += tmplen;
|
||||
len = (size_t) outlen + sizeof(globals.host_hash) + SWITCH_UUID_FORMATTED_LENGTH;
|
||||
*(buf + sizeof(globals.host_hash) + SWITCH_UUID_FORMATTED_LENGTH + outlen) = '\0';
|
||||
len = (size_t) outlen + SWITCH_UUID_FORMATTED_LENGTH;
|
||||
*(buf + SWITCH_UUID_FORMATTED_LENGTH + outlen) = '\0';
|
||||
} else {
|
||||
#endif
|
||||
switch_copy_string(buf + sizeof(globals.host_hash), packet, len - sizeof(globals.host_hash));
|
||||
switch_copy_string(buf + sizeof(globals.host_hash) + strlen(packet), (char *) MAGIC, strlen((char *) MAGIC) + 1);
|
||||
switch_copy_string(buf, packet, len);
|
||||
switch_copy_string(buf + strlen(packet), (char *) MAGIC, strlen((char *) MAGIC) + 1);
|
||||
#ifdef HAVE_OPENSSL
|
||||
}
|
||||
#endif
|
||||
|
@ -369,7 +367,6 @@ SWITCH_STANDARD_API(multicast_peers)
|
|||
SWITCH_MODULE_LOAD_FUNCTION(mod_event_multicast_load)
|
||||
{
|
||||
switch_api_interface_t *api_interface;
|
||||
switch_ssize_t hlen = -1;
|
||||
switch_status_t status = SWITCH_STATUS_GENERR;
|
||||
|
||||
memset(&globals, 0, sizeof(globals));
|
||||
|
@ -381,7 +378,6 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_event_multicast_load)
|
|||
switch_core_hash_init(&globals.peer_hash, module_pool);
|
||||
|
||||
gethostname(globals.hostname, sizeof(globals.hostname));
|
||||
globals.host_hash = switch_hashfunc_default(globals.hostname, &hlen);
|
||||
globals.key_count = 0;
|
||||
|
||||
if (load_config() != SWITCH_STATUS_SUCCESS) {
|
||||
|
@ -414,6 +410,11 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_event_multicast_load)
|
|||
switch_goto_status(SWITCH_STATUS_TERM, fail);
|
||||
}
|
||||
|
||||
if (switch_mcast_loopback(globals.udp_socket, 0) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to disable loopback\n");
|
||||
switch_goto_status(SWITCH_STATUS_TERM, fail);
|
||||
}
|
||||
|
||||
if (switch_socket_bind(globals.udp_socket, globals.addr) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Bind Error\n");
|
||||
switch_goto_status(SWITCH_STATUS_TERM, fail);
|
||||
|
@ -501,7 +502,6 @@ SWITCH_MODULE_RUNTIME_FUNCTION(mod_event_multicast_runtime)
|
|||
char *myaddr;
|
||||
size_t len = MULTICAST_BUFFSIZE;
|
||||
char *packet;
|
||||
uint64_t host_hash = 0;
|
||||
switch_status_t status;
|
||||
memset(buf, 0, len);
|
||||
|
||||
|
@ -520,12 +520,8 @@ SWITCH_MODULE_RUNTIME_FUNCTION(mod_event_multicast_runtime)
|
|||
}
|
||||
#endif
|
||||
|
||||
memcpy(&host_hash, buf, sizeof(host_hash));
|
||||
packet = buf + sizeof(host_hash);
|
||||
packet = buf;
|
||||
|
||||
if (host_hash == globals.host_hash) {
|
||||
continue;
|
||||
}
|
||||
#ifdef HAVE_OPENSSL
|
||||
if (globals.psk) {
|
||||
char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
|
||||
|
@ -533,7 +529,7 @@ SWITCH_MODULE_RUNTIME_FUNCTION(mod_event_multicast_runtime)
|
|||
int outl, tmplen;
|
||||
EVP_CIPHER_CTX ctx;
|
||||
|
||||
len -= sizeof(host_hash) + SWITCH_UUID_FORMATTED_LENGTH;
|
||||
len -= SWITCH_UUID_FORMATTED_LENGTH;
|
||||
|
||||
tmp = malloc(len);
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Makefile
|
|
@ -7,8 +7,7 @@ MODPA_DIR=$(switch_srcdir)/src/mod/endpoints/mod_portaudio
|
|||
|
||||
mod_LTLIBRARIES = mod_portaudio_stream.la
|
||||
mod_portaudio_stream_la_SOURCES = mod_portaudio_stream.c $(MODPA_DIR)/pablio.c $(MODPA_DIR)/pa_ringbuffer.c
|
||||
mod_portaudio_stream_la_CFLAGS = $(AM_CFLAGS)
|
||||
mod_portaudio_stream_la_CFLAGS += -I. -I$(PA_DIR)/include -D__EXTENSION__=1 -I$(MODPA_DIR)
|
||||
mod_portaudio_stream_la_CFLAGS = -I. -I$(PA_DIR)/include -D__EXTENSION__=1 -I$(MODPA_DIR) $(AM_CFLAGS)
|
||||
mod_portaudio_stream_la_LIBADD = $(switch_builddir)/libfreeswitch.la $(PALA)
|
||||
mod_portaudio_stream_la_LDFLAGS = -avoid-version -module -no-undefined -shared $(PA_LIBS)
|
||||
|
||||
|
|
|
@ -21403,6 +21403,26 @@ 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) {
|
||||
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);
|
||||
jresult = result;
|
||||
return jresult;
|
||||
}
|
||||
|
||||
|
||||
SWIGEXPORT char * SWIGSTDCALL CSharp_switch_channel_get_variable_dup(void * jarg1, char * jarg2, int jarg3) {
|
||||
char * jresult ;
|
||||
switch_channel_t *arg1 = (switch_channel_t *) 0 ;
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -2904,6 +2904,11 @@ 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);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static string switch_channel_get_variable_dup(SWIGTYPE_p_switch_channel channel, string varname, switch_bool_t dup) {
|
||||
string ret = freeswitchPINVOKE.switch_channel_get_variable_dup(SWIGTYPE_p_switch_channel.getCPtr(channel), varname, (int)dup);
|
||||
return ret;
|
||||
|
@ -10209,6 +10214,9 @@ class freeswitchPINVOKE {
|
|||
[DllImport("mod_managed", EntryPoint="CSharp_switch_channel_get_variable_partner")]
|
||||
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);
|
||||
|
||||
[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);
|
||||
|
||||
|
|
|
@ -768,6 +768,10 @@ SWITCH_DECLARE(switch_status_t) switch_mcast_hops(switch_socket_t *sock, uint8_t
|
|||
return apr_mcast_hops(sock, ttl);
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_mcast_loopback(switch_socket_t *sock, uint8_t opt)
|
||||
{
|
||||
return apr_mcast_loopback(sock, opt);
|
||||
}
|
||||
|
||||
/* socket functions */
|
||||
|
||||
|
|
|
@ -737,6 +737,37 @@ SWITCH_DECLARE(switch_status_t) switch_channel_set_profile_var(switch_channel_t
|
|||
return status;
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_channel_export_variable_var_check(switch_channel_t *channel, const char *varname, const char *value, switch_bool_t var_check, switch_bool_t nolocal)
|
||||
{
|
||||
const char *exports, *exports_varname = varname;
|
||||
switch_status_t status;
|
||||
|
||||
exports = switch_channel_get_variable(channel, SWITCH_EXPORT_VARS_VARIABLE);
|
||||
|
||||
if (nolocal) {
|
||||
exports_varname = switch_mprintf("nolocal:%s", varname);
|
||||
}
|
||||
|
||||
if ((status = switch_channel_set_variable_var_check(channel, exports_varname, value, var_check)) != SWITCH_STATUS_SUCCESS) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (varname && value) {
|
||||
if (exports) {
|
||||
switch_channel_set_variable_printf(channel, SWITCH_EXPORT_VARS_VARIABLE, "%s,%s", exports, exports_varname);
|
||||
} else {
|
||||
switch_channel_set_variable(channel, SWITCH_EXPORT_VARS_VARIABLE, exports_varname);
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
if (exports_varname != varname) {
|
||||
free((char*)exports_varname);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_channel_set_variable_var_check(switch_channel_t *channel,
|
||||
const char *varname, const char *value, switch_bool_t var_check)
|
||||
{
|
||||
|
|
|
@ -304,6 +304,7 @@ static int switch_console_process(char *xcmd)
|
|||
switch_stream_handle_t stream = { 0 };
|
||||
switch_status_t status;
|
||||
FILE *handle = switch_core_get_console();
|
||||
int r = 1;
|
||||
|
||||
SWITCH_STANDARD_STREAM(stream);
|
||||
switch_assert(stream.data);
|
||||
|
@ -316,6 +317,9 @@ static int switch_console_process(char *xcmd)
|
|||
fflush(handle);
|
||||
}
|
||||
} else {
|
||||
if (!strcasecmp(xcmd, "...") || !strcasecmp(xcmd, "shutdown")) {
|
||||
r = 0;
|
||||
}
|
||||
if (handle) {
|
||||
fprintf(handle, "Unknown Command: %s\n", xcmd);
|
||||
fflush(handle);
|
||||
|
@ -324,7 +328,7 @@ static int switch_console_process(char *xcmd)
|
|||
|
||||
switch_safe_free(stream.data);
|
||||
|
||||
return 1;
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -128,17 +128,20 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_get_partner(switch_core_sess
|
|||
}
|
||||
|
||||
|
||||
struct str_node {
|
||||
char *str;
|
||||
struct str_node *next;
|
||||
};
|
||||
|
||||
SWITCH_DECLARE(void) switch_core_session_hupall_matching_var(const char *var_name, const char *var_val, switch_call_cause_t cause)
|
||||
{
|
||||
switch_hash_index_t *hi;
|
||||
void *val;
|
||||
switch_core_session_t *session;
|
||||
switch_memory_pool_t *pool;
|
||||
switch_queue_t *queue;
|
||||
void *pop;
|
||||
struct str_node *head = NULL, *np;
|
||||
|
||||
switch_core_new_memory_pool(&pool);
|
||||
switch_queue_create(&queue, 250000, pool);
|
||||
|
||||
if (!var_val)
|
||||
return;
|
||||
|
@ -152,7 +155,10 @@ SWITCH_DECLARE(void) switch_core_session_hupall_matching_var(const char *var_nam
|
|||
if (switch_core_session_read_lock(session) == SWITCH_STATUS_SUCCESS) {
|
||||
if (switch_channel_up(session->channel) &&
|
||||
(this_val = switch_channel_get_variable(session->channel, var_name)) && (!strcmp(this_val, var_val))) {
|
||||
switch_queue_push(queue, switch_core_strdup(pool, session->uuid_str));
|
||||
np = switch_core_alloc(pool, sizeof(*np));
|
||||
np->str = switch_core_strdup(pool, session->uuid_str);
|
||||
np->next = head;
|
||||
head = np;
|
||||
}
|
||||
switch_core_session_rwunlock(session);
|
||||
}
|
||||
|
@ -160,10 +166,8 @@ SWITCH_DECLARE(void) switch_core_session_hupall_matching_var(const char *var_nam
|
|||
}
|
||||
switch_mutex_unlock(runtime.session_hash_mutex);
|
||||
|
||||
while (switch_queue_trypop(queue, &pop) == SWITCH_STATUS_SUCCESS && pop) {
|
||||
char *uuid = (char *) pop;
|
||||
|
||||
if ((session = switch_core_session_locate(uuid))) {
|
||||
for(np = head; np; np = np->next) {
|
||||
if ((session = switch_core_session_locate(np->str))) {
|
||||
switch_channel_hangup(session->channel, cause);
|
||||
switch_core_session_rwunlock(session);
|
||||
}
|
||||
|
@ -179,12 +183,10 @@ SWITCH_DECLARE(void) switch_core_session_hupall_endpoint(const switch_endpoint_i
|
|||
void *val;
|
||||
switch_core_session_t *session;
|
||||
switch_memory_pool_t *pool;
|
||||
switch_queue_t *queue;
|
||||
void *pop;
|
||||
|
||||
struct str_node *head = NULL, *np;
|
||||
|
||||
switch_core_new_memory_pool(&pool);
|
||||
switch_queue_create(&queue, 250000, pool);
|
||||
|
||||
|
||||
switch_mutex_lock(runtime.session_hash_mutex);
|
||||
for (hi = switch_hash_first(NULL, session_manager.session_table); hi; hi = switch_hash_next(hi)) {
|
||||
switch_hash_this(hi, NULL, NULL, &val);
|
||||
|
@ -192,7 +194,10 @@ SWITCH_DECLARE(void) switch_core_session_hupall_endpoint(const switch_endpoint_i
|
|||
session = (switch_core_session_t *) val;
|
||||
if (switch_core_session_read_lock(session) == SWITCH_STATUS_SUCCESS) {
|
||||
if (session->endpoint_interface == endpoint_interface) {
|
||||
switch_queue_push(queue, switch_core_strdup(pool, session->uuid_str));
|
||||
np = switch_core_alloc(pool, sizeof(*np));
|
||||
np->str = switch_core_strdup(pool, session->uuid_str);
|
||||
np->next = head;
|
||||
head = np;
|
||||
}
|
||||
switch_core_session_rwunlock(session);
|
||||
}
|
||||
|
@ -200,10 +205,8 @@ SWITCH_DECLARE(void) switch_core_session_hupall_endpoint(const switch_endpoint_i
|
|||
}
|
||||
switch_mutex_unlock(runtime.session_hash_mutex);
|
||||
|
||||
while (switch_queue_trypop(queue, &pop) == SWITCH_STATUS_SUCCESS && pop) {
|
||||
char *uuid = (char *) pop;
|
||||
|
||||
if ((session = switch_core_session_locate(uuid))) {
|
||||
for(np = head; np; np = np->next) {
|
||||
if ((session = switch_core_session_locate(np->str))) {
|
||||
switch_channel_hangup(session->channel, cause);
|
||||
switch_core_session_rwunlock(session);
|
||||
}
|
||||
|
@ -219,11 +222,10 @@ SWITCH_DECLARE(void) switch_core_session_hupall(switch_call_cause_t cause)
|
|||
void *val;
|
||||
switch_core_session_t *session;
|
||||
switch_memory_pool_t *pool;
|
||||
switch_queue_t *queue;
|
||||
void *pop;
|
||||
struct str_node *head = NULL, *np;
|
||||
|
||||
switch_core_new_memory_pool(&pool);
|
||||
switch_queue_create(&queue, 250000, pool);
|
||||
|
||||
|
||||
switch_mutex_lock(runtime.session_hash_mutex);
|
||||
for (hi = switch_hash_first(NULL, session_manager.session_table); hi; hi = switch_hash_next(hi)) {
|
||||
|
@ -231,17 +233,18 @@ SWITCH_DECLARE(void) switch_core_session_hupall(switch_call_cause_t cause)
|
|||
if (val) {
|
||||
session = (switch_core_session_t *) val;
|
||||
if (switch_core_session_read_lock(session) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_queue_push(queue, switch_core_strdup(pool, session->uuid_str));
|
||||
np = switch_core_alloc(pool, sizeof(*np));
|
||||
np->str = switch_core_strdup(pool, session->uuid_str);
|
||||
np->next = head;
|
||||
head = np;
|
||||
switch_core_session_rwunlock(session);
|
||||
}
|
||||
}
|
||||
}
|
||||
switch_mutex_unlock(runtime.session_hash_mutex);
|
||||
|
||||
while (switch_queue_trypop(queue, &pop) == SWITCH_STATUS_SUCCESS && pop) {
|
||||
char *uuid = (char *) pop;
|
||||
|
||||
if ((session = switch_core_session_locate(uuid))) {
|
||||
for(np = head; np; np = np->next) {
|
||||
if ((session = switch_core_session_locate(np->str))) {
|
||||
switch_channel_hangup(session->channel, cause);
|
||||
switch_core_session_rwunlock(session);
|
||||
}
|
||||
|
|
|
@ -633,6 +633,7 @@ SWITCH_MODULE_LOAD_FUNCTION(core_pcm_load)
|
|||
mod_g711_load(module_interface, pool);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
//return SWITCH_STATUS_NOUNLOAD;
|
||||
}
|
||||
|
||||
SWITCH_MODULE_SHUTDOWN_FUNCTION(core_pcm_shutdown)
|
||||
|
|
Loading…
Reference in New Issue