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

This commit is contained in:
Giovanni 2010-04-06 17:55:58 +02:00
commit 1d993d3aa2
90 changed files with 5353 additions and 3410 deletions

89
.gitignore vendored
View File

@ -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-*

View File

@ -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

View File

@ -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

View File

@ -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])

32
fscomm/.gitignore vendored Normal file
View File

@ -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

View File

@ -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

View File

@ -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");
}

View File

@ -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)

8
fscomm/channel.cpp Normal file
View File

@ -0,0 +1,8 @@
#include "channel.h"
Channel::Channel(QString uuid):
_uuid(uuid)
{
_progressEpoch = 0;
_progressMediaEpoch = 0;
}

39
fscomm/channel.h Normal file
View File

@ -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

View File

@ -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"/>

View File

@ -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";

View File

@ -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

View File

@ -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);

View File

@ -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>

View File

@ -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());

View File

@ -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;
}
}
}

View File

@ -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

View File

@ -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>

2065
libs/.gitignore vendored

File diff suppressed because it is too large Load Diff

View File

View File

View File

@ -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)

View File

@ -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");

View File

@ -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:
*/

View File

@ -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();

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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:
*/

View File

@ -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 {

View File

View File

View File

View File

View File

View File

@ -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
### -----------------------

View File

@ -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

View File

@ -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)

View File

0
libs/sqlite/notes/.empty Normal file
View File

View File

View File

@ -1,4 +1 @@
.svn
.gitignore
.update
configure.gnu

View File

@ -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

18
src/.gitignore vendored
View File

@ -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

View File

@ -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);
/** @} */

View File

@ -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

111
src/mod/.gitignore vendored
View File

@ -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

View File

@ -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
*
*/

View File

@ -0,0 +1 @@
Makefile

View File

@ -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

View File

@ -0,0 +1 @@
Makefile

View File

@ -0,0 +1 @@
Makefile

View File

@ -0,0 +1 @@
Makefile

View File

@ -0,0 +1,2 @@
!/gsmlib/gsmlib-*/aclocal.m4
!/gsmlib/gsmlib-*/configure

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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:
*/

View File

@ -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:
*/

View File

@ -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

View File

@ -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:
*/

View File

@ -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:
*/

View File

@ -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();
}

View File

@ -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

View File

@ -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);

View File

@ -0,0 +1 @@
Makefile

View File

@ -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)

View File

@ -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 ;

View File

@ -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);

0
src/mod/timers/.empty Normal file
View File

View File

@ -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 */

View File

@ -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)
{

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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)

0
web/etc/.empty Normal file
View File

0
web/planet/.empty Normal file
View File