diff --git a/.gitignore b/.gitignore index 0a14fb5228..41b0907f48 100644 --- a/.gitignore +++ b/.gitignore @@ -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-* diff --git a/Makefile.am b/Makefile.am index afb5673877..a9e4921344 100644 --- a/Makefile.am +++ b/Makefile.am @@ -349,7 +349,21 @@ src/include/switch_version.h: src/include/switch_version.h.in .version $(libfree cat src/include/switch_version.h.in > src/include/switch_version.h ; \ touch .version ; \ else \ - version=`svnversion . -n || echo hacked` ; \ + if [ -d .git ] ; then \ + version=`git log --format="%h %ci" -1 HEAD | head -1 || echo hacked` ; \ + if [ "x$$version" == "xhacked" ] ; then \ + version="hacked-`date -u +%Y%m%dT%H%M%SZ`" ; \ + else \ + version="git-$$version" ; \ + fi ;\ + else \ + version=`svnversion . -n || echo hacked` ; \ + if [ "x$$version" == "xhacked" ] ; then \ + version="hacked-`date -u +%Y%m%dT%H%M%SZ`" ; \ + else \ + version="svn-$$version" ; \ + fi ;\ + fi ; \ oldversion=`cat .version 2>/dev/null || echo "0"` ; \ if test "$$oldversion" != "$$version" || test $$force = 1 ; then \ cat src/include/switch_version.h.in | sed "s/@SWITCH_VERSION_REVISION@/$$version/g" > src/include/switch_version.h ; \ @@ -437,23 +451,30 @@ install-data-local: test -d $(DESTDIR)$(sysconfdir) || $(MAKE) samples-conf test -d $(DESTDIR)$(htdocsdir) || $(MAKE) samples-htdocs -is-svn: - @if [ ! -d .svn ] ; then \ +is-scm: + @if [ ! -d .svn -a ! -d .git ] ; then \ echo ; echo ; \ - echo "**************************************************************************************************" ; \ - echo "You can not update a release tarball or without a svn working copy, please checkout fresh from svn" ; \ - echo "**************************************************************************************************" ; \ + echo "*****************************************************************************************************" ; \ + echo "You can not update a release tarball or without a git or svn working copy please clone our git tree: " ; \ + echo "git clone git://git.freeswitch.org/freeswitch.git " ; \ + echo "or check out our read only svn mirror: " ; \ + echo "svn checkout http://svn.freeswitch.org/svn/freeswitch/trunk " ; \ + echo "*****************************************************************************************************" ; \ echo ; echo ; \ exit 1; \ fi -update: is-svn +update: is-scm @if test -d .svn ; then \ test ! -f .version || rm -f .version ; \ echo Updating... ; \ svn update ; \ + elif test -d .git ; then \ + test ! -f .version || rm -f .version ; \ + echo "Pulling updates..." ; \ + git pull ; \ else \ - echo "This source directory is not an svn working copy" ; \ + echo "This source directory is not a git tree or svn working copy" ; \ fi .nodepends: @@ -483,18 +504,18 @@ core_install: install_core everything: install -up: is-svn clean - svn update +up: is-scm clean + $(MAKE) update $(MAKE) -j core $(MAKE) -j modules $(MAKE) install -sync: is-svn - svn update +sync: is-scm + $(MAKE) update $(MAKE) install -speedy-sync: is-svn - svn update +speedy-sync: is-scm + $(MAKE) update $(MAKE) -j install libs/openzap/Makefile: @@ -570,15 +591,15 @@ cluecon: @echo @echo http://www.cluecon.com @sleep 5 -current: cluecon is-svn update-clean - svn update +current: cluecon update-clean is-scm + $(MAKE) update $(MAKE) all $(MAKE) install installall: current -speedy-current: is-svn update-clean - svn update +speedy-current: update-clean is-scm + $(MAKE) update $(MAKE) speedy-sure $(MAKE) install diff --git a/build/swigall.sh b/build/swigall.sh index ee7abf19cd..0525faf073 100755 --- a/build/swigall.sh +++ b/build/swigall.sh @@ -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 diff --git a/configure.in b/configure.in index de262a86db..16ba3e6999 100644 --- a/configure.in +++ b/configure.in @@ -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]) diff --git a/fscomm/.gitignore b/fscomm/.gitignore new file mode 100644 index 0000000000..f12ee46654 --- /dev/null +++ b/fscomm/.gitignore @@ -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 diff --git a/fscomm/FSComm.pro b/fscomm/FSComm.pro index 4bb59b669a..8542f54123 100644 --- a/fscomm/FSComm.pro +++ b/fscomm/FSComm.pro @@ -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 diff --git a/fscomm/call.cpp b/fscomm/call.cpp index 32bdaf894a..a13f01712e 100644 --- a/fscomm/call.cpp +++ b/fscomm/call.cpp @@ -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"); } diff --git a/fscomm/call.h b/fscomm/call.h index 4973c0484d..891bb17f54 100644 --- a/fscomm/call.h +++ b/fscomm/call.h @@ -32,6 +32,7 @@ #include #include #include +#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; } + QSharedPointer getChannel() { return _channel; } + void setOtherLegChannel(QSharedPointer channel) { _otherLegChannel = channel; } + QSharedPointer 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; /* This should be our portaudio channel */ + QSharedPointer _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) diff --git a/fscomm/channel.cpp b/fscomm/channel.cpp new file mode 100644 index 0000000000..ca056854c2 --- /dev/null +++ b/fscomm/channel.cpp @@ -0,0 +1,8 @@ +#include "channel.h" + +Channel::Channel(QString uuid): + _uuid(uuid) +{ + _progressEpoch = 0; + _progressMediaEpoch = 0; +} diff --git a/fscomm/channel.h b/fscomm/channel.h new file mode 100644 index 0000000000..b97126cda7 --- /dev/null +++ b/fscomm/channel.h @@ -0,0 +1,39 @@ +#ifndef CHANNEL_H +#define CHANNEL_H + +#include + +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 diff --git a/fscomm/conf/freeswitch.xml b/fscomm/conf/freeswitch.xml index 18e514546d..285940ad18 100644 --- a/fscomm/conf/freeswitch.xml +++ b/fscomm/conf/freeswitch.xml @@ -89,6 +89,7 @@ + diff --git a/fscomm/fshost.cpp b/fscomm/fshost.cpp index c5f5056c0d..3d7984fcdc 100644 --- a/fscomm/fshost.cpp +++ b/fscomm/fshost.cpp @@ -43,9 +43,10 @@ FSHost::FSHost(QObject *parent) : switch_core_set_globals(); qRegisterMetaType >("QSharedPointer"); + qRegisterMetaType >("QSharedPointer"); qRegisterMetaType >("QSharedPointer"); - 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(QSharedPointerevent) { - switch_status_t status = SWITCH_STATUS_SUCCESS; - QSharedPointer 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 = _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(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(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 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 acc = QSharedPointer(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 acc = _accounts.take(switch_event_get_header_nil(event, "Gateway")); + QSharedPointer 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(QSharedPointerevent, QString uuid) +{ + Channel *channelPtr = new Channel(uuid); + QSharedPointerchannel(channelPtr); + _channels.insert(uuid, channel); +} +void FSHost::eventChannelAnswer(QSharedPointerevent, 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(QSharedPointerevent, QString uuid) +{} +void FSHost::eventChannelExecute(QSharedPointerevent, QString uuid) +{} +void FSHost::eventChannelExecuteComplete(QSharedPointerevent, QString uuid) +{ + _channels.value(uuid).data()->setPaCallId(atoi(switch_event_get_header_nil(event.data(), "variable_pa_call_id"))); +} +void FSHost::eventChannelOutgoing(QSharedPointerevent, 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(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(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(QSharedPointerevent, QString uuid) +{} +void FSHost::eventChannelProgress(QSharedPointerevent, QString uuid) +{} +void FSHost::eventChannelProgressMedia(QSharedPointerevent, 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(QSharedPointerevent, 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(QSharedPointerevent, QString uuid) +{ + if (_active_calls.contains(uuid)) + { + emit hungup(_active_calls.take(uuid)); + } +} +void FSHost::eventChannelUnbridge(QSharedPointerevent, QString uuid) +{} +void FSHost::eventChannelHangupComplete(QSharedPointerevent, QString uuid) +{} +void FSHost::eventChannelDestroy(QSharedPointerevent, QString uuid) +{ + _channels.take(uuid); +} +void FSHost::eventCodec(QSharedPointerevent, 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(QSharedPointerevent, QString uuid) +{} +void FSHost::eventRecvInfo(QSharedPointerevent, QString uuid) +{} + +void FSHost::minimalModuleLoaded(QString modType, QString modKey) { if (modType == "endpoint") { @@ -501,11 +511,11 @@ QSharedPointer FSHost::getCurrentActiveCall() return QSharedPointer(); } -void FSHost::printEventHeaders(switch_event_t *event) +void FSHost::printEventHeaders(QSharedPointerevent) { 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"; diff --git a/fscomm/fshost.h b/fscomm/fshost.h index f20cd036d2..980ed092d4 100644 --- a/fscomm/fshost.h +++ b/fscomm/fshost.h @@ -35,6 +35,7 @@ #include #include #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(QSharedPointerevent); QSharedPointer getCallByUUID(QString uuid) { return _active_calls.value(uuid); } QSharedPointer getCurrentActiveCall(); QList > 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); void answered(QSharedPointer); void newOutgoingCall(QSharedPointer); void callFailed(QSharedPointer); void hungup(QSharedPointer); + + /* Account signals */ void accountStateChange(QSharedPointer); void newAccount(QSharedPointer); void delAccount(QSharedPointer); @@ -73,16 +79,39 @@ signals: private slots: /* We need to wait for the gateway deletion before reloading it */ void accountReloadSlot(QSharedPointer); - 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(QSharedPointerevent); + + /*FSM State handlers*/ + /** Channel Related*/ + void eventChannelCreate(QSharedPointer event, QString uuid); + void eventChannelAnswer(QSharedPointer event, QString uuid); + void eventChannelState(QSharedPointerevent, QString uuid); + void eventChannelExecute(QSharedPointerevent, QString uuid); + void eventChannelExecuteComplete(QSharedPointerevent, QString uuid); + void eventChannelOutgoing(QSharedPointerevent, QString uuid); + void eventChannelOriginate(QSharedPointerevent, QString uuid); + void eventChannelProgress(QSharedPointerevent, QString uuid); + void eventChannelProgressMedia(QSharedPointerevent, QString uuid); + void eventChannelBridge(QSharedPointerevent, QString uuid); + void eventChannelHangup(QSharedPointerevent, QString uuid); + void eventChannelUnbridge(QSharedPointerevent, QString uuid); + void eventChannelHangupComplete(QSharedPointerevent, QString uuid); + void eventChannelDestroy(QSharedPointerevent, QString uuid); + + /** Others*/ + void eventCodec(QSharedPointerevent, QString uuid); + void eventCallUpdate(QSharedPointerevent, QString uuid); + void eventRecvInfo(QSharedPointerevent, QString uuid); + + /* Structures to keep track of things */ QHash > _active_calls; QHash > _accounts; - QHash _bleg_uuids; + QHash > _channels; QList _reloading_Accounts; QList _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 e(clone); + g_FSHost.generalEventHandler(e); } - switch_safe_free(clone); } #endif // FSHOST_H diff --git a/fscomm/mainwindow.cpp b/fscomm/mainwindow.cpp index 54143da947..38892c6add 100644 --- a/fscomm/mainwindow.cpp +++ b/fscomm/mainwindow.cpp @@ -133,7 +133,7 @@ void MainWindow::updateCallTimers() QSharedPointer 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("

Could not get active call to start/stop recording." "

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) { - 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) for (int i=0; itableCalls->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) for (int i=0; itableCalls->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) for (int i=0; itableCalls->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) for (int i=0; itableCalls->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.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); diff --git a/fscomm/preferences/prefdialog.ui b/fscomm/preferences/prefdialog.ui index 4b0bfbec94..1192631e70 100644 --- a/fscomm/preferences/prefdialog.ui +++ b/fscomm/preferences/prefdialog.ui @@ -201,7 +201,7 @@ - 2 + 0 @@ -490,28 +490,17 @@ Codecs + + QFormLayout::AllNonFixedFieldsGrow + - - - codec-prefs - - - - - - - CELT@48000h,G7221@32000h,G7221@16000h,G722,PCMU,PCMA,GSM - - - - inbound-codec-negotiation - + @@ -525,15 +514,15 @@ - + Codecs - - + + @@ -1028,6 +1017,14 @@ + + + CodecWidget + QWidget +

widgets/codecwidget.h
+ 1 + + diff --git a/fscomm/preferences/prefsofia.cpp b/fscomm/preferences/prefsofia.cpp index 3642b3a34e..01347184ff 100644 --- a/fscomm/preferences/prefsofia.cpp +++ b/fscomm/preferences/prefsofia.cpp @@ -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()); diff --git a/fscomm/widgets/codecwidget.cpp b/fscomm/widgets/codecwidget.cpp new file mode 100644 index 0000000000..049fc4ba4d --- /dev/null +++ b/fscomm/widgets/codecwidget.cpp @@ -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() +{ + QListitems = 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() +{ + QListitems = 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() +{ + QListitems = ui->listAvailCodecs->selectedItems(); + foreach(QListWidgetItem *item, items) + { + ui->listEnabledCodecs->insertItem(0,item->text()); + delete item; + } +} + +void CodecWidget::disableCodecs() +{ + QListitems = 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 > implList; + QHash 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 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; ilistEnabledCodecs->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; + } + } +} diff --git a/fscomm/widgets/codecwidget.h b/fscomm/widgets/codecwidget.h new file mode 100644 index 0000000000..0e836b1a6f --- /dev/null +++ b/fscomm/widgets/codecwidget.h @@ -0,0 +1,33 @@ +#ifndef CODECWIDGET_H +#define CODECWIDGET_H + +#include + +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 > > _listCodecs; +}; + +#endif // CODECWIDGET_H diff --git a/fscomm/widgets/codecwidget.ui b/fscomm/widgets/codecwidget.ui new file mode 100644 index 0000000000..91a749075e --- /dev/null +++ b/fscomm/widgets/codecwidget.ui @@ -0,0 +1,157 @@ + + + CodecWidget + + + + 0 + 0 + 612 + 235 + + + + Form + + + + + + + + + 0 + 0 + + + + Available Codecs + + + Qt::AlignCenter + + + + + + + true + + + QAbstractItemView::DragDrop + + + Qt::MoveAction + + + true + + + QAbstractItemView::ExtendedSelection + + + true + + + + + + + + + + + ... + + + Qt::RightArrow + + + + + + + ... + + + Qt::LeftArrow + + + + + + + + + + + Enabled Codecs + + + Qt::AlignCenter + + + + + + + true + + + QAbstractItemView::DragDrop + + + Qt::MoveAction + + + true + + + QAbstractItemView::ExtendedSelection + + + false + + + + + + + + + + + ... + + + Qt::UpArrow + + + + + + + false + + + ... + + + + + + + ... + + + Qt::DownArrow + + + + + + + + + + diff --git a/libs/.gitignore b/libs/.gitignore index 5cce65bcdb..93c55e4cd5 100644 --- a/libs/.gitignore +++ b/libs/.gitignore @@ -1,992 +1,1073 @@ -apr-util/.make.dirs -apr-util/Makefile -apr-util/apr-util.pc -apr-util/aprutil.exp -apr-util/apu-1-config -apr-util/build/apr_common.m4 -apr-util/build/config.guess -apr-util/build/config.sub -apr-util/build/find_apr.m4 -apr-util/build/get-version.sh -apr-util/build/install.sh -apr-util/build/pkg/pkginfo -apr-util/build/rules.mk -apr-util/config.log -apr-util/config.nice -apr-util/config.status -apr-util/configure -apr-util/export_vars.c -apr-util/export_vars.sh -apr-util/exports.c -apr-util/include/apr_ldap.h -apr-util/include/apu.h -apr-util/include/apu_want.h -apr-util/include/private/apu_config.h -apr-util/include/private/apu_config.h.in -apr-util/include/private/apu_select_dbm.h -apr-util/test/Makefile -apr-util/xml/expat/Makefile -apr-util/xml/expat/aclocal.m4 -apr-util/xml/expat/config.h -apr-util/xml/expat/config.h.in -apr-util/xml/expat/config.log -apr-util/xml/expat/config.status -apr-util/xml/expat/configure -apr-util/xml/expat/conftools/ltmain.sh -apr-util/xml/expat/lib/Makefile -apr-util/xml/expat/lib/expat.h -apr-util/xml/expat/libtool -apr/.make.dirs -apr/Makefile -apr/apr-1-config -apr/apr.exp -apr/apr.pc -apr/build/apr_rules.mk -apr/build/config.guess -apr/build/config.sub -apr/build/libtool.m4 -apr/build/ltmain.sh -apr/build/pkg/pkginfo -apr/config.log -apr/config.nice -apr/config.status -apr/configure -apr/export_vars.c -apr/exports.c -apr/include/apr.h -apr/include/arch/unix/apr_private.h -apr/include/arch/unix/apr_private.h.in -apr/libtool -apr/test/Makefile -apr/test/internal/Makefile -broadvoice/Makefile -broadvoice/Makefile.in -broadvoice/aclocal.m4 -broadvoice/broadvoice.pc -broadvoice/config-h.in -broadvoice/config.log -broadvoice/config.status -broadvoice/config/config.guess -broadvoice/config/config.sub -broadvoice/config/depcomp -broadvoice/config/install-sh -broadvoice/config/ltmain.sh -broadvoice/config/missing -broadvoice/configure -broadvoice/doc/Makefile -broadvoice/doc/Makefile.in -broadvoice/libtool -broadvoice/src/Makefile -broadvoice/src/Makefile.in -broadvoice/src/broadvoice.h -broadvoice/src/config.h -broadvoice/src/stamp-h1 -broadvoice/tests/regression_tests.sh -curl/Makefile -curl/Makefile.in -curl/aclocal.m4 -curl/config.guess -curl/config.log -curl/config.status -curl/config.sub -curl/configure -curl/curl-config -curl/depcomp -curl/include/Makefile -curl/include/Makefile.in -curl/include/curl/Makefile -curl/include/curl/Makefile.in -curl/install-sh -curl/lib/Makefile -curl/lib/Makefile.in -curl/lib/config.h -curl/lib/config.h.in -curl/lib/stamp-h1 -curl/libcurl.pc -curl/libtool -curl/ltmain.sh -curl/missing -curl/packages/AIX/Makefile -curl/packages/AIX/Makefile.in -curl/packages/AIX/RPM/Makefile -curl/packages/AIX/RPM/Makefile.in -curl/packages/AIX/RPM/curl.spec -curl/packages/DOS/Makefile -curl/packages/DOS/Makefile.in -curl/packages/EPM/Makefile -curl/packages/EPM/Makefile.in -curl/packages/EPM/curl.list -curl/packages/Linux/Makefile -curl/packages/Linux/Makefile.in -curl/packages/Linux/RPM/Makefile -curl/packages/Linux/RPM/Makefile.in -curl/packages/Linux/RPM/curl-ssl.spec -curl/packages/Linux/RPM/curl.spec -curl/packages/Makefile -curl/packages/Makefile.in -curl/packages/Solaris/Makefile -curl/packages/Solaris/Makefile.in -curl/packages/Win32/Makefile -curl/packages/Win32/Makefile.in -curl/packages/Win32/cygwin/Makefile -curl/packages/Win32/cygwin/Makefile.in -curl/packages/vms/Makefile -curl/packages/vms/Makefile.in -curl/src/Makefile -curl/src/Makefile.in -curl/src/config.h -curl/src/stamp-h2 -iksemel/Makefile -iksemel/Makefile.in -iksemel/aclocal.m4 -iksemel/build/compile -iksemel/build/config.guess -iksemel/build/config.sub -iksemel/build/depcomp -iksemel/build/install-sh -iksemel/build/ltmain.sh -iksemel/build/missing -iksemel/config.log -iksemel/config.status -iksemel/configure -iksemel/doc/Makefile -iksemel/doc/Makefile.in -iksemel/iksemel.pc -iksemel/include/Makefile -iksemel/include/Makefile.in -iksemel/include/config.h -iksemel/include/config.h.in -iksemel/include/stamp-h1 -iksemel/libtool -iksemel/src/Makefile -iksemel/src/Makefile.in -iksemel/test/Makefile -iksemel/test/Makefile.in -iksemel/tools/Makefile -iksemel/tools/Makefile.in -ilbc/Makefile -ilbc/Makefile.in -ilbc/aclocal.m4 -ilbc/config-h.in -ilbc/config.log -ilbc/config.status -ilbc/config/config.guess -ilbc/config/config.sub -ilbc/config/depcomp -ilbc/config/install-sh -ilbc/config/ltmain.sh -ilbc/config/missing -ilbc/configure -ilbc/doc/Makefile -ilbc/doc/Makefile.in -ilbc/libtool -ilbc/localtests/Makefile -ilbc/localtests/Makefile.in -ilbc/src/Makefile -ilbc/src/Makefile.in -ilbc/src/config.h -ilbc/src/ilbc.h -ilbc/src/stamp-h1 -ilbc/tests/Makefile -ilbc/tests/Makefile.in -js/Makefile -js/aclocal.m4 -js/config.guess -js/config.h -js/config.h.in -js/config.log -js/config.status -js/config.sub -js/configure -js/js -js/js-config.sh -js/js.pc -js/jscpucfg -js/libtool -js/ltmain.sh -js/nsprpub/Makefile -js/nsprpub/aclocal.m4 -js/nsprpub/build/autoconf/config.guess -js/nsprpub/build/autoconf/config.sub -js/nsprpub/build/autoconf/install-sh -js/nsprpub/build/autoconf/ltmain.sh -js/nsprpub/build/autoconf/missing -js/nsprpub/config.log -js/nsprpub/config.status -js/nsprpub/config/Makefile -js/nsprpub/config/autoconf.mk -js/nsprpub/config/nfspwd -js/nsprpub/config/now -js/nsprpub/config/nsinstall -js/nsprpub/config/nspr-config -js/nsprpub/config/nsprincl.mk -js/nsprpub/config/nsprincl.sh -js/nsprpub/configure -js/nsprpub/dist/ -js/nsprpub/lib/Makefile -js/nsprpub/lib/ds/Makefile -js/nsprpub/lib/ds/_pl_bld.h -js/nsprpub/lib/libc/Makefile -js/nsprpub/lib/libc/include/Makefile -js/nsprpub/lib/libc/src/Makefile -js/nsprpub/lib/libc/src/_pl_bld.h -js/nsprpub/lib/tests/Makefile -js/nsprpub/libtool -js/nsprpub/pkg/Makefile -js/nsprpub/pkg/linux/Makefile -js/nsprpub/pkg/solaris/Makefile -js/nsprpub/pkg/solaris/SUNWpr/Makefile -js/nsprpub/pkg/solaris/SUNWprd/Makefile -js/nsprpub/pr/Makefile -js/nsprpub/pr/include/Makefile -js/nsprpub/pr/include/md/Makefile -js/nsprpub/pr/include/obsolete/Makefile -js/nsprpub/pr/include/private/Makefile -js/nsprpub/pr/src/Makefile -js/nsprpub/pr/src/_pr_bld.h -js/nsprpub/pr/src/io/Makefile -js/nsprpub/pr/src/linking/Makefile -js/nsprpub/pr/src/malloc/Makefile -js/nsprpub/pr/src/md/Makefile -js/nsprpub/pr/src/md/unix/Makefile -js/nsprpub/pr/src/memory/Makefile -js/nsprpub/pr/src/misc/Makefile -js/nsprpub/pr/src/pthreads/Makefile -js/nsprpub/pr/src/threads/Makefile -js/nsprpub/pr/tests/Makefile -js/nsprpub/pr/tests/dll/Makefile -js/src/jsautocfg.h -js/src/perlconnect/Makefile.PL -libdingaling/Makefile -libdingaling/Makefile.in -libdingaling/aclocal.m4 -libdingaling/build/compile -libdingaling/build/config.guess -libdingaling/build/config.sub -libdingaling/build/depcomp -libdingaling/build/install-sh -libdingaling/build/ltmain.sh -libdingaling/build/missing -libdingaling/config.log -libdingaling/config.status -libdingaling/configure -libdingaling/libtool -libdingaling/src/config.h -libdingaling/src/config.h.in -libdingaling/src/stamp-h1 -libedit/Makefile -libedit/Makefile.in -libedit/aclocal.m4 -libedit/config.guess -libedit/config.h -libedit/config.h.in -libedit/config.log -libedit/config.status -libedit/config.sub -libedit/configure -libedit/depcomp -libedit/doc/Makefile -libedit/doc/Makefile.in -libedit/doc/editline.3 -libedit/doc/editrc.5 -libedit/examples/Makefile -libedit/examples/Makefile.in -libedit/examples/fileman -libedit/examples/test -libedit/install-sh -libedit/libedit.pc -libedit/libtool -libedit/ltmain.sh -libedit/missing -libedit/src/Makefile -libedit/src/Makefile.in -libedit/src/common.h -libedit/src/emacs.h -libedit/src/fcns.c -libedit/src/fcns.h -libedit/src/help.c -libedit/src/help.h -libedit/src/vi.h -libedit/stamp-h1 -libg722_1/Makefile -libg722_1/Makefile.in -libg722_1/aclocal.m4 -libg722_1/config-h.in -libg722_1/config.log -libg722_1/config.status -libg722_1/config/config.guess -libg722_1/config/config.sub -libg722_1/config/install-sh -libg722_1/config/ltmain.sh -libg722_1/configure -libg722_1/doc/Makefile -libg722_1/doc/Makefile.in -libg722_1/g722_1.spec -libg722_1/libtool -libg722_1/src/Makefile -libg722_1/src/Makefile.in -libg722_1/src/config.h -libg722_1/src/dct4.h -libg722_1/src/g722_1.h -libg722_1/src/make_dct4_tables -libg722_1/src/make_tables -libg722_1/src/stamp-h1 -libg722_1/test-data/Makefile -libg722_1/test-data/Makefile.in -libg722_1/test-data/itu/Makefile -libg722_1/test-data/itu/Makefile.in -libg722_1/test-data/local/Makefile -libg722_1/test-data/local/Makefile.in -libg722_1/tests/Makefile -libg722_1/tests/Makefile.in -libg722_1/tests/regression_tests.sh -libsndfile/Cfg/compile -libsndfile/Cfg/config.guess -libsndfile/Cfg/config.sub -libsndfile/Cfg/depcomp -libsndfile/Cfg/install-sh -libsndfile/Cfg/ltmain.sh -libsndfile/Cfg/missing -libsndfile/M4/Makefile -libsndfile/M4/Makefile.in -libsndfile/Makefile -libsndfile/Makefile.in -libsndfile/Octave/Makefile -libsndfile/Octave/Makefile.in -libsndfile/Win32/Makefile -libsndfile/Win32/Makefile.in -libsndfile/aclocal.m4 -libsndfile/config.log -libsndfile/config.status -libsndfile/configure -libsndfile/doc/Makefile -libsndfile/doc/Makefile.in -libsndfile/examples/Makefile -libsndfile/examples/Makefile.in -libsndfile/libsndfile.spec -libsndfile/libtool -libsndfile/man/Makefile -libsndfile/man/Makefile.in -libsndfile/programs/Makefile -libsndfile/programs/Makefile.in -libsndfile/regtest/Makefile -libsndfile/regtest/Makefile.in -libsndfile/sndfile.pc -libsndfile/src/G72x/Makefile -libsndfile/src/G72x/Makefile.in -libsndfile/src/G72x/g72x_test -libsndfile/src/GSM610/Makefile -libsndfile/src/GSM610/Makefile.in -libsndfile/src/Makefile -libsndfile/src/Makefile.in -libsndfile/src/config.h -libsndfile/src/config.h.in -libsndfile/src/sndfile.h -libsndfile/src/stamp-h1 -libsndfile/src/test_main -libsndfile/tests/Makefile -libsndfile/tests/Makefile.in -libsndfile/tests/test_wrapper.sh -openzap/COPYING -openzap/INSTALL -openzap/Makefile.in -openzap/build/compile -openzap/build/depcomp -openzap/build/install-sh -openzap/build/ltmain.sh -openzap/build/missing -openzap/openzap.pc -pcre/Makefile -pcre/Makefile.in -pcre/aclocal.m4 -pcre/config.guess -pcre/config.h -pcre/config.h.in -pcre/config.log -pcre/config.status -pcre/config.sub -pcre/configure -pcre/install-sh -pcre/libpcre.pc -pcre/libpcrecpp.pc -pcre/libtool -pcre/ltmain.sh -pcre/missing -pcre/pcre-config -pcre/pcre_chartables.c -pcre/pcre_scanner_unittest -pcre/pcre_stringpiece.h -pcre/pcre_stringpiece_unittest -pcre/pcrecpp_unittest -pcre/pcrecpparg.h -pcre/pcregrep -pcre/pcretest -pcre/stamp-h1 -portaudio/Makefile -portaudio/aclocal.m4 -portaudio/config.guess -portaudio/config.log -portaudio/config.status -portaudio/config.sub -portaudio/configure -portaudio/install-sh -portaudio/libtool -portaudio/ltmain.sh -portaudio/missing -portaudio/portaudio-2.0.pc -silk/Makefile -silk/Makefile.in -silk/aclocal.m4 -silk/compile -silk/config.guess -silk/config.log -silk/config.status -silk/config.sub -silk/configure -silk/depcomp -silk/install-sh -silk/libtool -silk/ltmain.sh -silk/missing -sofia-sip/Makefile -sofia-sip/Makefile.in -sofia-sip/aclocal.m4 -sofia-sip/compile -sofia-sip/config.guess -sofia-sip/config.h -sofia-sip/config.h.in -sofia-sip/config.log -sofia-sip/config.status -sofia-sip/config.sub -sofia-sip/configure -sofia-sip/depcomp -sofia-sip/install-sh -sofia-sip/libsofia-sip-ua-glib/Makefile -sofia-sip/libsofia-sip-ua-glib/Makefile.in -sofia-sip/libsofia-sip-ua-glib/su-glib/Doxyfile -sofia-sip/libsofia-sip-ua-glib/su-glib/Makefile -sofia-sip/libsofia-sip-ua-glib/su-glib/Makefile.in -sofia-sip/libsofia-sip-ua/Makefile -sofia-sip/libsofia-sip-ua/Makefile.in -sofia-sip/libsofia-sip-ua/bnf/Doxyfile -sofia-sip/libsofia-sip-ua/bnf/Makefile -sofia-sip/libsofia-sip-ua/bnf/Makefile.in -sofia-sip/libsofia-sip-ua/docs/Doxyfile -sofia-sip/libsofia-sip-ua/docs/Doxyfile.rfc -sofia-sip/libsofia-sip-ua/docs/Doxyfile.version -sofia-sip/libsofia-sip-ua/docs/Makefile -sofia-sip/libsofia-sip-ua/docs/Makefile.in -sofia-sip/libsofia-sip-ua/docs/sofia-footer.html -sofia-sip/libsofia-sip-ua/features/Doxyfile -sofia-sip/libsofia-sip-ua/features/Makefile -sofia-sip/libsofia-sip-ua/features/Makefile.in -sofia-sip/libsofia-sip-ua/features/sofia-sip/sofia_features.h -sofia-sip/libsofia-sip-ua/http/Doxyfile -sofia-sip/libsofia-sip-ua/http/Makefile -sofia-sip/libsofia-sip-ua/http/Makefile.in -sofia-sip/libsofia-sip-ua/http/http_parser_table.c -sofia-sip/libsofia-sip-ua/http/http_tag.c -sofia-sip/libsofia-sip-ua/http/http_tag_ref.c -sofia-sip/libsofia-sip-ua/http/sofia-sip/http_protos.h -sofia-sip/libsofia-sip-ua/http/sofia-sip/http_tag.h -sofia-sip/libsofia-sip-ua/ipt/Doxyfile -sofia-sip/libsofia-sip-ua/ipt/Makefile -sofia-sip/libsofia-sip-ua/ipt/Makefile.in -sofia-sip/libsofia-sip-ua/iptsec/Doxyfile -sofia-sip/libsofia-sip-ua/iptsec/Makefile -sofia-sip/libsofia-sip-ua/iptsec/Makefile.in -sofia-sip/libsofia-sip-ua/iptsec/auth_tag_ref.c -sofia-sip/libsofia-sip-ua/msg/Doxyfile -sofia-sip/libsofia-sip-ua/msg/Makefile -sofia-sip/libsofia-sip-ua/msg/Makefile.in -sofia-sip/libsofia-sip-ua/msg/msg_mime_table.c -sofia-sip/libsofia-sip-ua/msg/sofia-sip/msg_mime_protos.h -sofia-sip/libsofia-sip-ua/msg/sofia-sip/msg_protos.h -sofia-sip/libsofia-sip-ua/msg/test_protos.h -sofia-sip/libsofia-sip-ua/msg/test_table.c -sofia-sip/libsofia-sip-ua/nea/Doxyfile -sofia-sip/libsofia-sip-ua/nea/Makefile -sofia-sip/libsofia-sip-ua/nea/Makefile.in -sofia-sip/libsofia-sip-ua/nea/nea_tag_ref.c -sofia-sip/libsofia-sip-ua/nta/Doxyfile -sofia-sip/libsofia-sip-ua/nta/Makefile -sofia-sip/libsofia-sip-ua/nta/Makefile.in -sofia-sip/libsofia-sip-ua/nta/nta_tag_ref.c -sofia-sip/libsofia-sip-ua/nth/Doxyfile -sofia-sip/libsofia-sip-ua/nth/Makefile -sofia-sip/libsofia-sip-ua/nth/Makefile.in -sofia-sip/libsofia-sip-ua/nth/nth_tag_ref.c -sofia-sip/libsofia-sip-ua/nua/Doxyfile -sofia-sip/libsofia-sip-ua/nua/Makefile -sofia-sip/libsofia-sip-ua/nua/Makefile.in -sofia-sip/libsofia-sip-ua/nua/nua_tag_ref.c -sofia-sip/libsofia-sip-ua/sdp/Doxyfile -sofia-sip/libsofia-sip-ua/sdp/Makefile -sofia-sip/libsofia-sip-ua/sdp/Makefile.in -sofia-sip/libsofia-sip-ua/sdp/sdp_tag_ref.c -sofia-sip/libsofia-sip-ua/sip/Doxyfile -sofia-sip/libsofia-sip-ua/sip/Makefile -sofia-sip/libsofia-sip-ua/sip/Makefile.in -sofia-sip/libsofia-sip-ua/sip/sip_parser_table.c -sofia-sip/libsofia-sip-ua/sip/sip_tag.c -sofia-sip/libsofia-sip-ua/sip/sip_tag_ref.c -sofia-sip/libsofia-sip-ua/sip/sofia-sip/sip_extra.h -sofia-sip/libsofia-sip-ua/sip/sofia-sip/sip_hclasses.h -sofia-sip/libsofia-sip-ua/sip/sofia-sip/sip_protos.h -sofia-sip/libsofia-sip-ua/sip/sofia-sip/sip_tag.h -sofia-sip/libsofia-sip-ua/soa/Doxyfile -sofia-sip/libsofia-sip-ua/soa/Makefile -sofia-sip/libsofia-sip-ua/soa/Makefile.in -sofia-sip/libsofia-sip-ua/soa/soa_tag_ref.c -sofia-sip/libsofia-sip-ua/sresolv/Doxyfile -sofia-sip/libsofia-sip-ua/sresolv/Makefile -sofia-sip/libsofia-sip-ua/sresolv/Makefile.in -sofia-sip/libsofia-sip-ua/stun/Doxyfile -sofia-sip/libsofia-sip-ua/stun/Makefile -sofia-sip/libsofia-sip-ua/stun/Makefile.in -sofia-sip/libsofia-sip-ua/stun/stun_tag_ref.c -sofia-sip/libsofia-sip-ua/stun/stunc -sofia-sip/libsofia-sip-ua/su/Doxyfile -sofia-sip/libsofia-sip-ua/su/Makefile -sofia-sip/libsofia-sip-ua/su/Makefile.in -sofia-sip/libsofia-sip-ua/su/addrinfo -sofia-sip/libsofia-sip-ua/su/localinfo -sofia-sip/libsofia-sip-ua/su/sofia-sip/stamp-h2 -sofia-sip/libsofia-sip-ua/su/sofia-sip/su_configure.h -sofia-sip/libsofia-sip-ua/su/su_tag_ref.c -sofia-sip/libsofia-sip-ua/tport/Doxyfile -sofia-sip/libsofia-sip-ua/tport/Makefile -sofia-sip/libsofia-sip-ua/tport/Makefile.in -sofia-sip/libsofia-sip-ua/tport/tport_tag_ref.c -sofia-sip/libsofia-sip-ua/url/Doxyfile -sofia-sip/libsofia-sip-ua/url/Makefile -sofia-sip/libsofia-sip-ua/url/Makefile.in -sofia-sip/libsofia-sip-ua/url/url_tag_ref.c -sofia-sip/libtool -sofia-sip/ltmain.sh -sofia-sip/missing -sofia-sip/open_c/Makefile -sofia-sip/open_c/Makefile.in -sofia-sip/open_c/config.h -sofia-sip/packages/Makefile -sofia-sip/packages/Makefile.in -sofia-sip/packages/sofia-sip-1.12.10devel.spec -sofia-sip/packages/sofia-sip-ua-glib.pc -sofia-sip/packages/sofia-sip-ua.pc -sofia-sip/s2check/Makefile -sofia-sip/s2check/Makefile.in -sofia-sip/stamp-h1 -sofia-sip/tests/Makefile -sofia-sip/tests/Makefile.in -sofia-sip/utils/Doxyfile -sofia-sip/utils/Makefile -sofia-sip/utils/Makefile.in -sofia-sip/win32/Makefile -sofia-sip/win32/Makefile.in -sofia-sip/win32/config.h -spandsp/Makefile -spandsp/Makefile.in -spandsp/aclocal.m4 -spandsp/config-h.in -spandsp/config.log -spandsp/config.status -spandsp/config/config.guess -spandsp/config/config.sub -spandsp/config/depcomp -spandsp/config/install-sh -spandsp/config/ltmain.sh -spandsp/config/missing -spandsp/configure -spandsp/doc/Makefile -spandsp/doc/Makefile.in -spandsp/doc/doxygen -spandsp/libtool -spandsp/spandsp-sim/Makefile -spandsp/spandsp-sim/Makefile.in -spandsp/spandsp.pc -spandsp/src/Makefile -spandsp/src/Makefile.in -spandsp/src/at_interpreter_dictionary.h -spandsp/src/config.h -spandsp/src/make_at_dictionary -spandsp/src/make_modem_filter -spandsp/src/spandsp.h -spandsp/src/stamp-h1 -spandsp/src/v17_v32bis_rx_fixed_rrc.h -spandsp/src/v17_v32bis_rx_floating_rrc.h -spandsp/src/v17_v32bis_tx_fixed_rrc.h -spandsp/src/v17_v32bis_tx_floating_rrc.h -spandsp/src/v22bis_rx_1200_fixed_rrc.h -spandsp/src/v22bis_rx_1200_floating_rrc.h -spandsp/src/v22bis_rx_2400_fixed_rrc.h -spandsp/src/v22bis_rx_2400_floating_rrc.h -spandsp/src/v22bis_tx_fixed_rrc.h -spandsp/src/v22bis_tx_floating_rrc.h -spandsp/src/v27ter_rx_2400_fixed_rrc.h -spandsp/src/v27ter_rx_2400_floating_rrc.h -spandsp/src/v27ter_rx_4800_fixed_rrc.h -spandsp/src/v27ter_rx_4800_floating_rrc.h -spandsp/src/v27ter_tx_2400_fixed_rrc.h -spandsp/src/v27ter_tx_2400_floating_rrc.h -spandsp/src/v27ter_tx_4800_fixed_rrc.h -spandsp/src/v27ter_tx_4800_floating_rrc.h -spandsp/src/v29rx_fixed_rrc.h -spandsp/src/v29rx_floating_rrc.h -spandsp/src/v29tx_fixed_rrc.h -spandsp/src/v29tx_floating_rrc.h -spandsp/test-data/Makefile -spandsp/test-data/Makefile.in -spandsp/test-data/etsi/Makefile -spandsp/test-data/etsi/Makefile.in -spandsp/test-data/etsi/fax/Makefile -spandsp/test-data/etsi/fax/Makefile.in -spandsp/test-data/itu/Makefile -spandsp/test-data/itu/Makefile.in -spandsp/test-data/itu/fax/Makefile -spandsp/test-data/itu/fax/Makefile.in -spandsp/test-data/local/Makefile -spandsp/test-data/local/Makefile.in -spandsp/tests/Makefile -spandsp/tests/Makefile.in -speex/Makefile -speex/Makefile.in -speex/aclocal.m4 -speex/config.guess -speex/config.h -speex/config.h.in -speex/config.log -speex/config.status -speex/config.sub -speex/configure -speex/depcomp -speex/include/Makefile -speex/include/Makefile.in -speex/include/speex/Makefile -speex/include/speex/Makefile.in -speex/include/speex/speex_config_types.h -speex/install-sh -speex/libspeex/Makefile -speex/libspeex/Makefile.in -speex/libtool -speex/ltmain.sh -speex/missing -speex/speex.pc -speex/speexdsp.pc -speex/src/Makefile -speex/src/Makefile.in -speex/stamp-h1 -speex/symbian/Makefile -speex/symbian/Makefile.in -speex/ti/Makefile -speex/ti/Makefile.in -speex/ti/speex_C54_test/Makefile -speex/ti/speex_C54_test/Makefile.in -speex/ti/speex_C55_test/Makefile -speex/ti/speex_C55_test/Makefile.in -speex/ti/speex_C64_test/Makefile -speex/ti/speex_C64_test/Makefile.in -speex/win32/Makefile -speex/win32/Makefile.in -speex/win32/VS2003/Makefile -speex/win32/VS2003/Makefile.in -speex/win32/VS2003/libspeex/Makefile -speex/win32/VS2003/libspeex/Makefile.in -speex/win32/VS2003/libspeexdsp/Makefile -speex/win32/VS2003/libspeexdsp/Makefile.in -speex/win32/VS2003/speexdec/Makefile -speex/win32/VS2003/speexdec/Makefile.in -speex/win32/VS2003/speexenc/Makefile -speex/win32/VS2003/speexenc/Makefile.in -speex/win32/VS2003/tests/Makefile -speex/win32/VS2003/tests/Makefile.in -speex/win32/VS2005/Makefile -speex/win32/VS2005/Makefile.in -speex/win32/VS2005/libspeex/Makefile -speex/win32/VS2005/libspeex/Makefile.in -speex/win32/VS2005/libspeexdsp/Makefile -speex/win32/VS2005/libspeexdsp/Makefile.in -speex/win32/VS2005/speexdec/Makefile -speex/win32/VS2005/speexdec/Makefile.in -speex/win32/VS2005/speexenc/Makefile -speex/win32/VS2005/speexenc/Makefile.in -speex/win32/VS2005/tests/Makefile -speex/win32/VS2005/tests/Makefile.in -speex/win32/VS2008/Makefile -speex/win32/VS2008/Makefile.in -speex/win32/VS2008/libspeex/Makefile -speex/win32/VS2008/libspeex/Makefile.in -speex/win32/VS2008/libspeexdsp/Makefile -speex/win32/VS2008/libspeexdsp/Makefile.in -speex/win32/VS2008/speexdec/Makefile -speex/win32/VS2008/speexdec/Makefile.in -speex/win32/VS2008/speexenc/Makefile -speex/win32/VS2008/speexenc/Makefile.in -speex/win32/VS2008/tests/Makefile -speex/win32/VS2008/tests/Makefile.in -speex/win32/libspeex/Makefile -speex/win32/libspeex/Makefile.in -speex/win32/speexdec/Makefile -speex/win32/speexdec/Makefile.in -speex/win32/speexenc/Makefile -speex/win32/speexenc/Makefile.in -sqlite/Makefile -sqlite/aclocal.m4 -sqlite/config.guess -sqlite/config.log -sqlite/config.status -sqlite/config.sub -sqlite/configure -sqlite/install-sh -sqlite/keywordhash.h -sqlite/lemon -sqlite/lempar.c -sqlite/libtool -sqlite/ltmain.sh -sqlite/missing -sqlite/mkkeywordhash -sqlite/opcodes.c -sqlite/opcodes.h -sqlite/parse.c -sqlite/parse.h -sqlite/parse.h.temp -sqlite/parse.out -sqlite/parse.y -sqlite/sqlite3 -sqlite/sqlite3.h -sqlite/sqlite3.pc -srtp/Makefile -srtp/Makefile.in -srtp/aclocal.m4 -srtp/aes_tables -srtp/build/config.guess -srtp/build/config.sub -srtp/build/depcomp -srtp/build/install-sh -srtp/build/ltmain.sh -srtp/build/missing -srtp/config.log -srtp/config.status -srtp/config_in.h -srtp/configure -srtp/crypto/Makefile -srtp/crypto/include/config.h -srtp/crypto/include/stamp-h1 -srtp/doc/Makefile -srtp/libtool -srtp/srtp-1.42.pc -srtp/test/Makefile -srtp/test/Makefile.in -tiff-3.8.2/Makefile -tiff-3.8.2/Makefile.in -tiff-3.8.2/aclocal.m4 -tiff-3.8.2/config.log -tiff-3.8.2/config.status -tiff-3.8.2/config/config.guess -tiff-3.8.2/config/config.sub -tiff-3.8.2/config/install-sh -tiff-3.8.2/config/ltmain.sh -tiff-3.8.2/configure -tiff-3.8.2/contrib/Makefile -tiff-3.8.2/contrib/Makefile.in -tiff-3.8.2/contrib/acorn/Makefile -tiff-3.8.2/contrib/acorn/Makefile.in -tiff-3.8.2/contrib/addtiffo/Makefile -tiff-3.8.2/contrib/addtiffo/Makefile.in -tiff-3.8.2/contrib/addtiffo/addtiffo -tiff-3.8.2/contrib/dbs/Makefile -tiff-3.8.2/contrib/dbs/Makefile.in -tiff-3.8.2/contrib/dbs/tiff-bi -tiff-3.8.2/contrib/dbs/tiff-grayscale -tiff-3.8.2/contrib/dbs/tiff-palette -tiff-3.8.2/contrib/dbs/tiff-rgb -tiff-3.8.2/contrib/dbs/xtiff/Makefile -tiff-3.8.2/contrib/dbs/xtiff/Makefile.in -tiff-3.8.2/contrib/iptcutil/Makefile -tiff-3.8.2/contrib/iptcutil/Makefile.in -tiff-3.8.2/contrib/iptcutil/iptcutil -tiff-3.8.2/contrib/mac-cw/Makefile -tiff-3.8.2/contrib/mac-cw/Makefile.in -tiff-3.8.2/contrib/mac-mpw/Makefile -tiff-3.8.2/contrib/mac-mpw/Makefile.in -tiff-3.8.2/contrib/mfs/Makefile -tiff-3.8.2/contrib/mfs/Makefile.in -tiff-3.8.2/contrib/ojpeg/Makefile -tiff-3.8.2/contrib/ojpeg/Makefile.in -tiff-3.8.2/contrib/pds/Makefile -tiff-3.8.2/contrib/pds/Makefile.in -tiff-3.8.2/contrib/ras/Makefile -tiff-3.8.2/contrib/ras/Makefile.in -tiff-3.8.2/contrib/stream/Makefile -tiff-3.8.2/contrib/stream/Makefile.in -tiff-3.8.2/contrib/tags/Makefile -tiff-3.8.2/contrib/tags/Makefile.in -tiff-3.8.2/contrib/win_dib/Makefile -tiff-3.8.2/contrib/win_dib/Makefile.in -tiff-3.8.2/html/Makefile -tiff-3.8.2/html/Makefile.in -tiff-3.8.2/html/images/Makefile -tiff-3.8.2/html/images/Makefile.in -tiff-3.8.2/html/man/Makefile -tiff-3.8.2/html/man/Makefile.in -tiff-3.8.2/libtiff/Makefile -tiff-3.8.2/libtiff/Makefile.in -tiff-3.8.2/libtiff/mkg3states -tiff-3.8.2/libtiff/stamp-h1 -tiff-3.8.2/libtiff/stamp-h2 -tiff-3.8.2/libtiff/tif_config.h -tiff-3.8.2/libtiff/tif_config.h.in -tiff-3.8.2/libtiff/tiffconf.h -tiff-3.8.2/libtool -tiff-3.8.2/man/Makefile -tiff-3.8.2/man/Makefile.in -tiff-3.8.2/port/Makefile -tiff-3.8.2/port/Makefile.in -tiff-3.8.2/test/Makefile -tiff-3.8.2/test/Makefile.in -tiff-3.8.2/tools/Makefile -tiff-3.8.2/tools/Makefile.in -tiff-3.8.2/tools/bmp2tiff -tiff-3.8.2/tools/fax2ps -tiff-3.8.2/tools/fax2tiff -tiff-3.8.2/tools/gif2tiff -tiff-3.8.2/tools/pal2rgb -tiff-3.8.2/tools/ppm2tiff -tiff-3.8.2/tools/ras2tiff -tiff-3.8.2/tools/raw2tiff -tiff-3.8.2/tools/rgb2ycbcr -tiff-3.8.2/tools/thumbnail -tiff-3.8.2/tools/tiff2bw -tiff-3.8.2/tools/tiff2pdf -tiff-3.8.2/tools/tiff2ps -tiff-3.8.2/tools/tiff2rgba -tiff-3.8.2/tools/tiffcmp -tiff-3.8.2/tools/tiffcp -tiff-3.8.2/tools/tiffdither -tiff-3.8.2/tools/tiffdump -tiff-3.8.2/tools/tiffinfo -tiff-3.8.2/tools/tiffmedian -tiff-3.8.2/tools/tiffset -tiff-3.8.2/tools/tiffsplit -unimrcp/Makefile -unimrcp/Makefile.in -unimrcp/aclocal.m4 -unimrcp/build/Makefile -unimrcp/build/Makefile.in -unimrcp/build/config.guess -unimrcp/build/config.sub -unimrcp/build/depcomp -unimrcp/build/install-sh -unimrcp/build/ltmain.sh -unimrcp/build/missing -unimrcp/build/pkgconfig/Makefile -unimrcp/build/pkgconfig/Makefile.in -unimrcp/build/pkgconfig/unimrcpclient.pc -unimrcp/build/pkgconfig/unimrcpplugin.pc -unimrcp/build/pkgconfig/unimrcpserver.pc -unimrcp/conf/Makefile -unimrcp/conf/Makefile.in -unimrcp/config.log -unimrcp/config.status -unimrcp/configure -unimrcp/data/Makefile -unimrcp/data/Makefile.in -unimrcp/libs/Makefile -unimrcp/libs/Makefile.in -unimrcp/libs/apr-toolkit/Makefile -unimrcp/libs/apr-toolkit/Makefile.in -unimrcp/libs/mpf/Makefile -unimrcp/libs/mpf/Makefile.in -unimrcp/libs/mrcp-client/Makefile -unimrcp/libs/mrcp-client/Makefile.in -unimrcp/libs/mrcp-engine/Makefile -unimrcp/libs/mrcp-engine/Makefile.in -unimrcp/libs/mrcp-server/Makefile -unimrcp/libs/mrcp-server/Makefile.in -unimrcp/libs/mrcp-signaling/Makefile -unimrcp/libs/mrcp-signaling/Makefile.in -unimrcp/libs/mrcp/Makefile -unimrcp/libs/mrcp/Makefile.in -unimrcp/libs/mrcpv2-transport/Makefile -unimrcp/libs/mrcpv2-transport/Makefile.in -unimrcp/libs/uni-rtsp/Makefile -unimrcp/libs/uni-rtsp/Makefile.in -unimrcp/libtool -unimrcp/modules/Makefile -unimrcp/modules/Makefile.in -unimrcp/modules/mrcp-sofiasip/Makefile -unimrcp/modules/mrcp-sofiasip/Makefile.in -unimrcp/modules/mrcp-unirtsp/Makefile -unimrcp/modules/mrcp-unirtsp/Makefile.in -unimrcp/platforms/Makefile -unimrcp/platforms/Makefile.in -unimrcp/platforms/asr-client/Makefile -unimrcp/platforms/asr-client/Makefile.in -unimrcp/platforms/libasr-client/Makefile -unimrcp/platforms/libasr-client/Makefile.in -unimrcp/platforms/libunimrcp-client/Makefile -unimrcp/platforms/libunimrcp-client/Makefile.in -unimrcp/platforms/libunimrcp-server/Makefile -unimrcp/platforms/libunimrcp-server/Makefile.in -unimrcp/platforms/umc/Makefile -unimrcp/platforms/umc/Makefile.in -unimrcp/platforms/unimrcp-client/Makefile -unimrcp/platforms/unimrcp-client/Makefile.in -unimrcp/platforms/unimrcp-server/Makefile -unimrcp/platforms/unimrcp-server/Makefile.in -unimrcp/plugins/Makefile -unimrcp/plugins/Makefile.in -unimrcp/plugins/demo-recog/Makefile -unimrcp/plugins/demo-recog/Makefile.in -unimrcp/plugins/demo-synth/Makefile -unimrcp/plugins/demo-synth/Makefile.in -unimrcp/plugins/mrcp-cepstral/Makefile -unimrcp/plugins/mrcp-cepstral/Makefile.in -unimrcp/plugins/mrcp-flite/Makefile -unimrcp/plugins/mrcp-flite/Makefile.in -unimrcp/plugins/mrcp-pocketsphinx/Makefile -unimrcp/plugins/mrcp-pocketsphinx/Makefile.in -unimrcp/plugins/mrcp-recorder/Makefile -unimrcp/plugins/mrcp-recorder/Makefile.in -unimrcp/tests/Makefile -unimrcp/tests/Makefile.in -unimrcp/tests/apttest/Makefile -unimrcp/tests/apttest/Makefile.in -unimrcp/tests/mpftest/Makefile -unimrcp/tests/mpftest/Makefile.in -unimrcp/tests/mrcptest/Makefile -unimrcp/tests/mrcptest/Makefile.in -unimrcp/tests/rtsptest/Makefile -unimrcp/tests/rtsptest/Makefile.in -unimrcp/tests/strtablegen/Makefile -unimrcp/tests/strtablegen/Makefile.in -xmlrpc-c/include/xmlrpc-c/config.h -xmlrpc-c/stamp-h2 -xmlrpc-c/xmlrpc_amconfig.h -xmlrpc-c/xmlrpc_config.h -apr/build/install-sh -js/install-sh -js/nsprpub/lib/ds/libplds4.dylib -js/nsprpub/lib/libc/src/libplc4.dylib -js/nsprpub/pr/src/libnspr4.dylib -libsndfile/M4/libtool.m4 -libsndfile/M4/ltoptions.m4 -libsndfile/M4/ltsugar.m4 -libsndfile/M4/ltversion.m4 -sofia-sip/m4/libtool.m4 -sofia-sip/m4/ltoptions.m4 -sofia-sip/m4/ltsugar.m4 -sofia-sip/m4/ltversion.m4 -sofia-sip/m4/lt~obsolete.m4 -sqlite/lemon.dSYM/ -sqlite/mkkeywordhash.dSYM/ -sqlite/sqlite3.dSYM/ -tiff-3.8.2/m4/libtool.m4 -tiff-3.8.2/m4/ltoptions.m4 -tiff-3.8.2/m4/ltsugar.m4 -tiff-3.8.2/m4/ltversion.m4 -tiff-3.8.2/m4/lt~obsolete.m4 -unimrcp/build/acmacros/libtool.m4 -unimrcp/build/acmacros/ltoptions.m4 -unimrcp/build/acmacros/ltsugar.m4 -unimrcp/build/acmacros/ltversion.m4 -unimrcp/build/acmacros/lt~obsolete.m4 +/apr-util/.make.dirs +/apr-util/Makefile +/apr-util/apr-util.pc +/apr-util/aprutil.exp +/apr-util/apu-1-config +/apr-util/build/apr_common.m4 +/apr-util/build/config.guess +/apr-util/build/config.sub +/apr-util/build/find_apr.m4 +/apr-util/build/get-version.sh +/apr-util/build/install.sh +/apr-util/build/pkg/pkginfo +/apr-util/build/rules.mk +/apr-util/config.log +/apr-util/config.nice +/apr-util/config.status +/apr-util/configure +/apr-util/export_vars.c +/apr-util/export_vars.sh +/apr-util/exports.c +/apr-util/include/apr_ldap.h +/apr-util/include/apu.h +/apr-util/include/apu_want.h +/apr-util/include/private/apu_config.h +/apr-util/include/private/apu_config.h.in +/apr-util/include/private/apu_select_dbm.h +/apr-util/test/Makefile +/apr-util/xml/expat/Makefile +/apr-util/xml/expat/aclocal.m4 +/apr-util/xml/expat/config.h +/apr-util/xml/expat/config.h.in +/apr-util/xml/expat/config.log +/apr-util/xml/expat/config.status +/apr-util/xml/expat/configure +/apr-util/xml/expat/conftools/ltmain.sh +/apr-util/xml/expat/lib/Makefile +/apr-util/xml/expat/lib/expat.h +/apr-util/xml/expat/libtool +/apr/.make.dirs +/apr/Makefile +/apr/aclocal.m4 +/apr/apr-1-config +/apr/apr.exp +/apr/apr.pc +/apr/build/apr_rules.mk +/apr/build/config.guess +/apr/build/config.sub +/apr/build/libtool.m4 +/apr/build/ltmain.sh +/apr/build/pkg/pkginfo +/apr/config.log +/apr/config.nice +/apr/config.status +/apr/configure +/apr/export_vars.c +/apr/exports.c +/apr/include/apr.h +/apr/include/arch/unix/apr_private.h +/apr/include/arch/unix/apr_private.h.in +/apr/libtool +/apr/test/Makefile +/apr/test/internal/Makefile +/broadvoice/Makefile +/broadvoice/Makefile.in +/broadvoice/aclocal.m4 +/broadvoice/broadvoice.pc +/broadvoice/config-h.in +/broadvoice/config.log +/broadvoice/config.status +/broadvoice/config/config.guess +/broadvoice/config/config.sub +/broadvoice/config/depcomp +/broadvoice/config/install-sh +/broadvoice/config/ltmain.sh +/broadvoice/config/missing +/broadvoice/configure +/broadvoice/doc/Makefile +/broadvoice/doc/Makefile.in +/broadvoice/libtool +/broadvoice/src/Makefile +/broadvoice/src/Makefile.in +/broadvoice/src/broadvoice.h +/broadvoice/src/config.h +/broadvoice/src/stamp-h1 +/broadvoice/tests/regression_tests.sh +/curl/Makefile +/curl/Makefile.in +/curl/aclocal.m4 +/curl/config.guess +/curl/config.log +/curl/config.status +/curl/config.sub +/curl/configure +/curl/curl-config +/curl/depcomp +/curl/include/Makefile +/curl/include/Makefile.in +/curl/include/curl/Makefile +/curl/include/curl/Makefile.in +/curl/install-sh +/curl/lib/Makefile +/curl/lib/Makefile.in +/curl/lib/config.h +/curl/lib/config.h.in +/curl/lib/stamp-h1 +/curl/libcurl.pc +/curl/libtool +/curl/ltmain.sh +/curl/missing +/curl/packages/AIX/Makefile +/curl/packages/AIX/Makefile.in +/curl/packages/AIX/RPM/Makefile +/curl/packages/AIX/RPM/Makefile.in +/curl/packages/AIX/RPM/curl.spec +/curl/packages/DOS/Makefile +/curl/packages/DOS/Makefile.in +/curl/packages/EPM/Makefile +/curl/packages/EPM/Makefile.in +/curl/packages/EPM/curl.list +/curl/packages/Linux/Makefile +/curl/packages/Linux/Makefile.in +/curl/packages/Linux/RPM/Makefile +/curl/packages/Linux/RPM/Makefile.in +/curl/packages/Linux/RPM/curl-ssl.spec +/curl/packages/Linux/RPM/curl.spec +/curl/packages/Makefile +/curl/packages/Makefile.in +/curl/packages/Solaris/Makefile +/curl/packages/Solaris/Makefile.in +/curl/packages/Win32/Makefile +/curl/packages/Win32/Makefile.in +/curl/packages/Win32/cygwin/Makefile +/curl/packages/Win32/cygwin/Makefile.in +/curl/packages/vms/Makefile +/curl/packages/vms/Makefile.in +/curl/src/Makefile +/curl/src/Makefile.in +/curl/src/config.h +/curl/src/stamp-h2 +/iksemel/Makefile +/iksemel/Makefile.in +/iksemel/aclocal.m4 +/iksemel/build/compile +/iksemel/build/config.guess +/iksemel/build/config.sub +/iksemel/build/depcomp +/iksemel/build/install-sh +/iksemel/build/ltmain.sh +/iksemel/build/missing +/iksemel/config.log +/iksemel/config.status +/iksemel/configure +/iksemel/doc/Makefile +/iksemel/doc/Makefile.in +/iksemel/iksemel.pc +/iksemel/include/Makefile +/iksemel/include/Makefile.in +/iksemel/include/config.h +/iksemel/include/config.h.in +/iksemel/include/stamp-h1 +/iksemel/libtool +/iksemel/src/Makefile +/iksemel/src/Makefile.in +/iksemel/test/Makefile +/iksemel/test/Makefile.in +/iksemel/tools/Makefile +/iksemel/tools/Makefile.in +/ilbc/Makefile +/ilbc/Makefile.in +/ilbc/aclocal.m4 +/ilbc/config-h.in +/ilbc/config.log +/ilbc/config.status +/ilbc/config/config.guess +/ilbc/config/config.sub +/ilbc/config/depcomp +/ilbc/config/install-sh +/ilbc/config/ltmain.sh +/ilbc/config/missing +/ilbc/configure +/ilbc/doc/Makefile +/ilbc/doc/Makefile.in +/ilbc/libtool +/ilbc/localtests/Makefile +/ilbc/localtests/Makefile.in +/ilbc/src/Makefile +/ilbc/src/Makefile.in +/ilbc/src/config.h +/ilbc/src/ilbc.h +/ilbc/src/stamp-h1 +/ilbc/tests/Makefile +/ilbc/tests/Makefile.in +/js/nsprpub/lib/ds/libplds4.so.1 +/js/nsprpub/lib/libc/src/libplc4.so.1 +/js/nsprpub/pr/src/libnspr4.so.1 +/js/Makefile +/js/aclocal.m4 +/js/config.guess +/js/config.h +/js/config.h.in +/js/config.log +/js/config.status +/js/config.sub +/js/configure +/js/js +/js/js-config.sh +/js/js.pc +/js/jscpucfg +/js/libtool +/js/ltmain.sh +/js/nsprpub/Makefile +/js/nsprpub/aclocal.m4 +/js/nsprpub/build/autoconf/config.guess +/js/nsprpub/build/autoconf/config.sub +/js/nsprpub/build/autoconf/install-sh +/js/nsprpub/build/autoconf/ltmain.sh +/js/nsprpub/build/autoconf/missing +/js/nsprpub/config.log +/js/nsprpub/config.status +/js/nsprpub/config/Makefile +/js/nsprpub/config/autoconf.mk +/js/nsprpub/config/nfspwd +/js/nsprpub/config/now +/js/nsprpub/config/nsinstall +/js/nsprpub/config/nspr-config +/js/nsprpub/config/nsprincl.mk +/js/nsprpub/config/nsprincl.sh +/js/nsprpub/configure +/js/nsprpub/dist/ +/js/nsprpub/lib/Makefile +/js/nsprpub/lib/ds/Makefile +/js/nsprpub/lib/ds/_pl_bld.h +/js/nsprpub/lib/libc/Makefile +/js/nsprpub/lib/libc/include/Makefile +/js/nsprpub/lib/libc/src/Makefile +/js/nsprpub/lib/libc/src/_pl_bld.h +/js/nsprpub/lib/tests/Makefile +/js/nsprpub/libtool +/js/nsprpub/pkg/Makefile +/js/nsprpub/pkg/linux/Makefile +/js/nsprpub/pkg/solaris/Makefile +/js/nsprpub/pkg/solaris/SUNWpr/Makefile +/js/nsprpub/pkg/solaris/SUNWprd/Makefile +/js/nsprpub/pr/Makefile +/js/nsprpub/pr/include/Makefile +/js/nsprpub/pr/include/md/Makefile +/js/nsprpub/pr/include/obsolete/Makefile +/js/nsprpub/pr/include/private/Makefile +/js/nsprpub/pr/src/Makefile +/js/nsprpub/pr/src/_pr_bld.h +/js/nsprpub/pr/src/io/Makefile +/js/nsprpub/pr/src/linking/Makefile +/js/nsprpub/pr/src/malloc/Makefile +/js/nsprpub/pr/src/md/Makefile +/js/nsprpub/pr/src/md/unix/Makefile +/js/nsprpub/pr/src/memory/Makefile +/js/nsprpub/pr/src/misc/Makefile +/js/nsprpub/pr/src/pthreads/Makefile +/js/nsprpub/pr/src/threads/Makefile +/js/nsprpub/pr/tests/Makefile +/js/nsprpub/pr/tests/dll/Makefile +/js/src/jsautocfg.h +/js/src/perlconnect/Makefile.PL +/libdingaling/Makefile +/libdingaling/Makefile.in +/libdingaling/aclocal.m4 +/libdingaling/build/compile +/libdingaling/build/config.guess +/libdingaling/build/config.sub +/libdingaling/build/depcomp +/libdingaling/build/install-sh +/libdingaling/build/ltmain.sh +/libdingaling/build/missing +/libdingaling/config.log +/libdingaling/config.status +/libdingaling/configure +/libdingaling/libtool +/libdingaling/src/config.h +/libdingaling/src/config.h.in +/libdingaling/src/stamp-h1 +/libedit/Makefile +/libedit/Makefile.in +/libedit/aclocal.m4 +/libedit/config.guess +/libedit/config.h +/libedit/config.h.in +/libedit/config.log +/libedit/config.status +/libedit/config.sub +/libedit/configure +/libedit/depcomp +/libedit/doc/Makefile +/libedit/doc/Makefile.in +/libedit/doc/editline.3 +/libedit/doc/editrc.5 +/libedit/examples/Makefile +/libedit/examples/Makefile.in +/libedit/examples/fileman +/libedit/examples/test +/libedit/install-sh +/libedit/libedit.pc +/libedit/libtool +/libedit/ltmain.sh +/libedit/missing +/libedit/src/Makefile +/libedit/src/Makefile.in +/libedit/src/common.h +/libedit/src/emacs.h +/libedit/src/fcns.c +/libedit/src/fcns.h +/libedit/src/help.c +/libedit/src/help.h +/libedit/src/vi.h +/libedit/stamp-h1 +/libg722_1/Makefile +/libg722_1/Makefile.in +/libg722_1/aclocal.m4 +/libg722_1/config-h.in +/libg722_1/config.log +/libg722_1/config.status +/libg722_1/config/config.guess +/libg722_1/config/config.sub +/libg722_1/config/install-sh +/libg722_1/config/ltmain.sh +/libg722_1/configure +/libg722_1/doc/Makefile +/libg722_1/doc/Makefile.in +/libg722_1/g722_1.spec +/libg722_1/libtool +/libg722_1/src/Makefile +/libg722_1/src/Makefile.in +/libg722_1/src/config.h +/libg722_1/src/dct4.h +/libg722_1/src/g722_1.h +/libg722_1/src/make_dct4_tables +/libg722_1/src/make_tables +/libg722_1/src/stamp-h1 +/libg722_1/test-data/Makefile +/libg722_1/test-data/Makefile.in +/libg722_1/test-data/itu/Makefile +/libg722_1/test-data/itu/Makefile.in +/libg722_1/test-data/local/Makefile +/libg722_1/test-data/local/Makefile.in +/libg722_1/tests/Makefile +/libg722_1/tests/Makefile.in +/libg722_1/tests/regression_tests.sh +/libsndfile/Cfg/compile +/libsndfile/Cfg/config.guess +/libsndfile/Cfg/config.sub +/libsndfile/Cfg/depcomp +/libsndfile/Cfg/install-sh +/libsndfile/Cfg/ltmain.sh +/libsndfile/Cfg/missing +/libsndfile/M4/Makefile +/libsndfile/M4/Makefile.in +/libsndfile/Makefile +/libsndfile/Makefile.in +/libsndfile/Octave/Makefile +/libsndfile/Octave/Makefile.in +/libsndfile/Win32/Makefile +/libsndfile/Win32/Makefile.in +/libsndfile/aclocal.m4 +/libsndfile/config.log +/libsndfile/config.status +/libsndfile/configure +/libsndfile/doc/Makefile +/libsndfile/doc/Makefile.in +/libsndfile/examples/Makefile +/libsndfile/examples/Makefile.in +/libsndfile/libsndfile.spec +/libsndfile/libtool +/libsndfile/man/Makefile +/libsndfile/man/Makefile.in +/libsndfile/programs/Makefile +/libsndfile/programs/Makefile.in +/libsndfile/regtest/Makefile +/libsndfile/regtest/Makefile.in +/libsndfile/sndfile.pc +/libsndfile/src/G72x/Makefile +/libsndfile/src/G72x/Makefile.in +/libsndfile/src/G72x/g72x_test +/libsndfile/src/GSM610/Makefile +/libsndfile/src/GSM610/Makefile.in +/libsndfile/src/Makefile +/libsndfile/src/Makefile.in +/libsndfile/src/config.h +/libsndfile/src/config.h.in +/libsndfile/src/sndfile.h +/libsndfile/src/stamp-h1 +/libsndfile/src/test_main +/libsndfile/tests/Makefile +/libsndfile/tests/Makefile.in +/libsndfile/tests/test_wrapper.sh +/openzap/COPYING +/openzap/INSTALL +/openzap/Makefile.in +/openzap/build/compile +/openzap/build/depcomp +/openzap/build/install-sh +/openzap/build/ltmain.sh +/openzap/build/missing +/openzap/openzap.pc +/pcre/Makefile +/pcre/Makefile.in +/pcre/aclocal.m4 +/pcre/config.guess +/pcre/config.h +/pcre/config.h.in +/pcre/config.log +/pcre/config.status +/pcre/config.sub +/pcre/configure +/pcre/install-sh +/pcre/libpcre.pc +/pcre/libpcrecpp.pc +/pcre/libtool +/pcre/ltmain.sh +/pcre/missing +/pcre/pcre-config +/pcre/pcre_chartables.c +/pcre/pcre_scanner_unittest +/pcre/pcre_stringpiece.h +/pcre/pcre_stringpiece_unittest +/pcre/pcrecpp_unittest +/pcre/pcrecpparg.h +/pcre/pcregrep +/pcre/pcretest +/pcre/stamp-h1 +/portaudio/Makefile +/portaudio/aclocal.m4 +/portaudio/config.guess +/portaudio/config.log +/portaudio/config.status +/portaudio/config.sub +/portaudio/configure +/portaudio/install-sh +/portaudio/libtool +/portaudio/ltmain.sh +/portaudio/missing +/portaudio/portaudio-2.0.pc +!/portaudio/bindings/cpp/build/gnu/aclocal.m4 +!/portaudio/bindings/cpp/build/gnu/configure +/silk/Makefile +/silk/Makefile.in +/silk/aclocal.m4 +/silk/compile +/silk/config.guess +/silk/config.log +/silk/config.status +/silk/config.sub +/silk/configure +/silk/depcomp +/silk/install-sh +/silk/libtool +/silk/ltmain.sh +/silk/missing +/sofia-sip/Makefile +/sofia-sip/Makefile.in +/sofia-sip/aclocal.m4 +/sofia-sip/compile +/sofia-sip/config.guess +/sofia-sip/config.h +/sofia-sip/config.h.in +/sofia-sip/config.log +/sofia-sip/config.status +/sofia-sip/config.sub +/sofia-sip/configure +/sofia-sip/depcomp +/sofia-sip/install-sh +/sofia-sip/libsofia-sip-ua-glib/Makefile +/sofia-sip/libsofia-sip-ua-glib/Makefile.in +/sofia-sip/libsofia-sip-ua-glib/su-glib/Doxyfile +/sofia-sip/libsofia-sip-ua-glib/su-glib/Makefile +/sofia-sip/libsofia-sip-ua-glib/su-glib/Makefile.in +/sofia-sip/libsofia-sip-ua/Makefile +/sofia-sip/libsofia-sip-ua/Makefile.in +/sofia-sip/libsofia-sip-ua/bnf/Doxyfile +/sofia-sip/libsofia-sip-ua/bnf/Makefile +/sofia-sip/libsofia-sip-ua/bnf/Makefile.in +/sofia-sip/libsofia-sip-ua/docs/Doxyfile +/sofia-sip/libsofia-sip-ua/docs/Doxyfile.rfc +/sofia-sip/libsofia-sip-ua/docs/Doxyfile.version +/sofia-sip/libsofia-sip-ua/docs/Makefile +/sofia-sip/libsofia-sip-ua/docs/Makefile.in +/sofia-sip/libsofia-sip-ua/docs/sofia-footer.html +/sofia-sip/libsofia-sip-ua/features/Doxyfile +/sofia-sip/libsofia-sip-ua/features/Makefile +/sofia-sip/libsofia-sip-ua/features/Makefile.in +/sofia-sip/libsofia-sip-ua/features/sofia-sip/sofia_features.h +/sofia-sip/libsofia-sip-ua/http/Doxyfile +/sofia-sip/libsofia-sip-ua/http/Makefile +/sofia-sip/libsofia-sip-ua/http/Makefile.in +/sofia-sip/libsofia-sip-ua/http/http_parser_table.c +/sofia-sip/libsofia-sip-ua/http/http_tag.c +/sofia-sip/libsofia-sip-ua/http/http_tag_ref.c +/sofia-sip/libsofia-sip-ua/http/sofia-sip/http_protos.h +/sofia-sip/libsofia-sip-ua/http/sofia-sip/http_tag.h +/sofia-sip/libsofia-sip-ua/ipt/Doxyfile +/sofia-sip/libsofia-sip-ua/ipt/Makefile +/sofia-sip/libsofia-sip-ua/ipt/Makefile.in +/sofia-sip/libsofia-sip-ua/iptsec/Doxyfile +/sofia-sip/libsofia-sip-ua/iptsec/Makefile +/sofia-sip/libsofia-sip-ua/iptsec/Makefile.in +/sofia-sip/libsofia-sip-ua/iptsec/auth_tag_ref.c +/sofia-sip/libsofia-sip-ua/msg/Doxyfile +/sofia-sip/libsofia-sip-ua/msg/Makefile +/sofia-sip/libsofia-sip-ua/msg/Makefile.in +/sofia-sip/libsofia-sip-ua/msg/msg_mime_table.c +/sofia-sip/libsofia-sip-ua/msg/sofia-sip/msg_mime_protos.h +/sofia-sip/libsofia-sip-ua/msg/sofia-sip/msg_protos.h +/sofia-sip/libsofia-sip-ua/msg/test_protos.h +/sofia-sip/libsofia-sip-ua/msg/test_table.c +/sofia-sip/libsofia-sip-ua/nea/Doxyfile +/sofia-sip/libsofia-sip-ua/nea/Makefile +/sofia-sip/libsofia-sip-ua/nea/Makefile.in +/sofia-sip/libsofia-sip-ua/nea/nea_tag_ref.c +/sofia-sip/libsofia-sip-ua/nta/Doxyfile +/sofia-sip/libsofia-sip-ua/nta/Makefile +/sofia-sip/libsofia-sip-ua/nta/Makefile.in +/sofia-sip/libsofia-sip-ua/nta/nta_tag_ref.c +/sofia-sip/libsofia-sip-ua/nth/Doxyfile +/sofia-sip/libsofia-sip-ua/nth/Makefile +/sofia-sip/libsofia-sip-ua/nth/Makefile.in +/sofia-sip/libsofia-sip-ua/nth/nth_tag_ref.c +/sofia-sip/libsofia-sip-ua/nua/Doxyfile +/sofia-sip/libsofia-sip-ua/nua/Makefile +/sofia-sip/libsofia-sip-ua/nua/Makefile.in +/sofia-sip/libsofia-sip-ua/nua/nua_tag_ref.c +/sofia-sip/libsofia-sip-ua/sdp/Doxyfile +/sofia-sip/libsofia-sip-ua/sdp/Makefile +/sofia-sip/libsofia-sip-ua/sdp/Makefile.in +/sofia-sip/libsofia-sip-ua/sdp/sdp_tag_ref.c +/sofia-sip/libsofia-sip-ua/sip/Doxyfile +/sofia-sip/libsofia-sip-ua/sip/Makefile +/sofia-sip/libsofia-sip-ua/sip/Makefile.in +/sofia-sip/libsofia-sip-ua/sip/sip_parser_table.c +/sofia-sip/libsofia-sip-ua/sip/sip_tag.c +/sofia-sip/libsofia-sip-ua/sip/sip_tag_ref.c +/sofia-sip/libsofia-sip-ua/sip/sofia-sip/sip_extra.h +/sofia-sip/libsofia-sip-ua/sip/sofia-sip/sip_hclasses.h +/sofia-sip/libsofia-sip-ua/sip/sofia-sip/sip_protos.h +/sofia-sip/libsofia-sip-ua/sip/sofia-sip/sip_tag.h +/sofia-sip/libsofia-sip-ua/soa/Doxyfile +/sofia-sip/libsofia-sip-ua/soa/Makefile +/sofia-sip/libsofia-sip-ua/soa/Makefile.in +/sofia-sip/libsofia-sip-ua/soa/soa_tag_ref.c +/sofia-sip/libsofia-sip-ua/sresolv/Doxyfile +/sofia-sip/libsofia-sip-ua/sresolv/Makefile +/sofia-sip/libsofia-sip-ua/sresolv/Makefile.in +/sofia-sip/libsofia-sip-ua/stun/Doxyfile +/sofia-sip/libsofia-sip-ua/stun/Makefile +/sofia-sip/libsofia-sip-ua/stun/Makefile.in +/sofia-sip/libsofia-sip-ua/stun/stun_tag_ref.c +/sofia-sip/libsofia-sip-ua/stun/stunc +/sofia-sip/libsofia-sip-ua/su/Doxyfile +/sofia-sip/libsofia-sip-ua/su/Makefile +/sofia-sip/libsofia-sip-ua/su/Makefile.in +/sofia-sip/libsofia-sip-ua/su/addrinfo +/sofia-sip/libsofia-sip-ua/su/localinfo +/sofia-sip/libsofia-sip-ua/su/sofia-sip/stamp-h2 +/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_configure.h +/sofia-sip/libsofia-sip-ua/su/su_tag_ref.c +/sofia-sip/libsofia-sip-ua/tport/Doxyfile +/sofia-sip/libsofia-sip-ua/tport/Makefile +/sofia-sip/libsofia-sip-ua/tport/Makefile.in +/sofia-sip/libsofia-sip-ua/tport/tport_tag_ref.c +/sofia-sip/libsofia-sip-ua/url/Doxyfile +/sofia-sip/libsofia-sip-ua/url/Makefile +/sofia-sip/libsofia-sip-ua/url/Makefile.in +/sofia-sip/libsofia-sip-ua/url/url_tag_ref.c +/sofia-sip/libtool +/sofia-sip/ltmain.sh +/sofia-sip/missing +/sofia-sip/open_c/Makefile +/sofia-sip/open_c/Makefile.in +/sofia-sip/open_c/config.h +/sofia-sip/packages/Makefile +/sofia-sip/packages/Makefile.in +/sofia-sip/packages/sofia-sip-1.12.10devel.spec +/sofia-sip/packages/sofia-sip-ua-glib.pc +/sofia-sip/packages/sofia-sip-ua.pc +/sofia-sip/s2check/Makefile +/sofia-sip/s2check/Makefile.in +/sofia-sip/stamp-h1 +/sofia-sip/tests/Makefile +/sofia-sip/tests/Makefile.in +/sofia-sip/utils/Doxyfile +/sofia-sip/utils/Makefile +/sofia-sip/utils/Makefile.in +/sofia-sip/win32/Makefile +/sofia-sip/win32/Makefile.in +/sofia-sip/win32/config.h +/spandsp/Makefile +/spandsp/Makefile.in +/spandsp/aclocal.m4 +/spandsp/config-h.in +/spandsp/config.log +/spandsp/config.status +/spandsp/config/config.guess +/spandsp/config/config.sub +/spandsp/config/depcomp +/spandsp/config/install-sh +/spandsp/config/ltmain.sh +/spandsp/config/missing +/spandsp/configure +/spandsp/doc/Makefile +/spandsp/doc/Makefile.in +/spandsp/doc/doxygen +/spandsp/libtool +/spandsp/spandsp-sim/Makefile +/spandsp/spandsp-sim/Makefile.in +/spandsp/spandsp.pc +/spandsp/src/Makefile +/spandsp/src/Makefile.in +/spandsp/src/at_interpreter_dictionary.h +/spandsp/src/config.h +/spandsp/src/make_at_dictionary +/spandsp/src/make_modem_filter +/spandsp/src/spandsp.h +/spandsp/src/stamp-h1 +/spandsp/src/v17_v32bis_rx_fixed_rrc.h +/spandsp/src/v17_v32bis_rx_floating_rrc.h +/spandsp/src/v17_v32bis_tx_fixed_rrc.h +/spandsp/src/v17_v32bis_tx_floating_rrc.h +/spandsp/src/v22bis_rx_1200_fixed_rrc.h +/spandsp/src/v22bis_rx_1200_floating_rrc.h +/spandsp/src/v22bis_rx_2400_fixed_rrc.h +/spandsp/src/v22bis_rx_2400_floating_rrc.h +/spandsp/src/v22bis_tx_fixed_rrc.h +/spandsp/src/v22bis_tx_floating_rrc.h +/spandsp/src/v27ter_rx_2400_fixed_rrc.h +/spandsp/src/v27ter_rx_2400_floating_rrc.h +/spandsp/src/v27ter_rx_4800_fixed_rrc.h +/spandsp/src/v27ter_rx_4800_floating_rrc.h +/spandsp/src/v27ter_tx_2400_fixed_rrc.h +/spandsp/src/v27ter_tx_2400_floating_rrc.h +/spandsp/src/v27ter_tx_4800_fixed_rrc.h +/spandsp/src/v27ter_tx_4800_floating_rrc.h +/spandsp/src/v29rx_fixed_rrc.h +/spandsp/src/v29rx_floating_rrc.h +/spandsp/src/v29tx_fixed_rrc.h +/spandsp/src/v29tx_floating_rrc.h +/spandsp/test-data/Makefile +/spandsp/test-data/Makefile.in +/spandsp/test-data/etsi/Makefile +/spandsp/test-data/etsi/Makefile.in +/spandsp/test-data/etsi/fax/Makefile +/spandsp/test-data/etsi/fax/Makefile.in +/spandsp/test-data/itu/Makefile +/spandsp/test-data/itu/Makefile.in +/spandsp/test-data/itu/fax/Makefile +/spandsp/test-data/itu/fax/Makefile.in +/spandsp/test-data/local/Makefile +/spandsp/test-data/local/Makefile.in +/spandsp/tests/Makefile +/spandsp/tests/Makefile.in +/speex/Makefile +/speex/Makefile.in +/speex/aclocal.m4 +/speex/config.guess +/speex/config.h +/speex/config.h.in +/speex/config.log +/speex/config.status +/speex/config.sub +/speex/configure +/speex/depcomp +/speex/include/Makefile +/speex/include/Makefile.in +/speex/include/speex/Makefile +/speex/include/speex/Makefile.in +/speex/include/speex/speex_config_types.h +/speex/install-sh +/speex/libspeex/Makefile +/speex/libspeex/Makefile.in +/speex/libtool +/speex/ltmain.sh +/speex/missing +/speex/speex.pc +/speex/speexdsp.pc +/speex/src/Makefile +/speex/src/Makefile.in +/speex/stamp-h1 +/speex/symbian/Makefile +/speex/symbian/Makefile.in +/speex/ti/Makefile +/speex/ti/Makefile.in +/speex/ti/speex_C54_test/Makefile +/speex/ti/speex_C54_test/Makefile.in +/speex/ti/speex_C55_test/Makefile +/speex/ti/speex_C55_test/Makefile.in +/speex/ti/speex_C64_test/Makefile +/speex/ti/speex_C64_test/Makefile.in +/speex/win32/Makefile +/speex/win32/Makefile.in +/speex/win32/VS2003/Makefile +/speex/win32/VS2003/Makefile.in +/speex/win32/VS2003/libspeex/Makefile +/speex/win32/VS2003/libspeex/Makefile.in +/speex/win32/VS2003/libspeexdsp/Makefile +/speex/win32/VS2003/libspeexdsp/Makefile.in +/speex/win32/VS2003/speexdec/Makefile +/speex/win32/VS2003/speexdec/Makefile.in +/speex/win32/VS2003/speexenc/Makefile +/speex/win32/VS2003/speexenc/Makefile.in +/speex/win32/VS2003/tests/Makefile +/speex/win32/VS2003/tests/Makefile.in +/speex/win32/VS2005/Makefile +/speex/win32/VS2005/Makefile.in +/speex/win32/VS2005/libspeex/Makefile +/speex/win32/VS2005/libspeex/Makefile.in +/speex/win32/VS2005/libspeexdsp/Makefile +/speex/win32/VS2005/libspeexdsp/Makefile.in +/speex/win32/VS2005/speexdec/Makefile +/speex/win32/VS2005/speexdec/Makefile.in +/speex/win32/VS2005/speexenc/Makefile +/speex/win32/VS2005/speexenc/Makefile.in +/speex/win32/VS2005/tests/Makefile +/speex/win32/VS2005/tests/Makefile.in +/speex/win32/VS2008/Makefile +/speex/win32/VS2008/Makefile.in +/speex/win32/VS2008/libspeex/Makefile +/speex/win32/VS2008/libspeex/Makefile.in +/speex/win32/VS2008/libspeexdsp/Makefile +/speex/win32/VS2008/libspeexdsp/Makefile.in +/speex/win32/VS2008/speexdec/Makefile +/speex/win32/VS2008/speexdec/Makefile.in +/speex/win32/VS2008/speexenc/Makefile +/speex/win32/VS2008/speexenc/Makefile.in +/speex/win32/VS2008/tests/Makefile +/speex/win32/VS2008/tests/Makefile.in +/speex/win32/libspeex/Makefile +/speex/win32/libspeex/Makefile.in +/speex/win32/speexdec/Makefile +/speex/win32/speexdec/Makefile.in +/speex/win32/speexenc/Makefile +/speex/win32/speexenc/Makefile.in +/sqlite/Makefile +/sqlite/aclocal.m4 +/sqlite/config.guess +/sqlite/config.log +/sqlite/config.status +/sqlite/config.sub +/sqlite/configure +/sqlite/install-sh +/sqlite/keywordhash.h +/sqlite/lemon +/sqlite/lempar.c +/sqlite/libtool +/sqlite/ltmain.sh +/sqlite/missing +/sqlite/mkkeywordhash +/sqlite/opcodes.c +/sqlite/opcodes.h +/sqlite/parse.c +/sqlite/parse.h +/sqlite/parse.h.temp +/sqlite/parse.out +/sqlite/parse.y +/sqlite/sqlite3 +/sqlite/sqlite3.h +/sqlite/sqlite3.pc +/srtp/Makefile +/srtp/Makefile.in +/srtp/aclocal.m4 +/srtp/aes_tables +/srtp/build/config.guess +/srtp/build/config.sub +/srtp/build/depcomp +/srtp/build/install-sh +/srtp/build/ltmain.sh +/srtp/build/missing +/srtp/config.log +/srtp/config.status +/srtp/config_in.h +/srtp/configure +/srtp/crypto/Makefile +/srtp/crypto/include/config.h +/srtp/crypto/include/stamp-h1 +/srtp/doc/Makefile +/srtp/libtool +/srtp/srtp-1.42.pc +/srtp/test/Makefile +/srtp/test/Makefile.in +/tiff-3.8.2/Makefile +/tiff-3.8.2/Makefile.in +/tiff-3.8.2/aclocal.m4 +/tiff-3.8.2/config.log +/tiff-3.8.2/config.status +/tiff-3.8.2/config/config.guess +/tiff-3.8.2/config/config.sub +/tiff-3.8.2/config/install-sh +/tiff-3.8.2/config/ltmain.sh +/tiff-3.8.2/configure +/tiff-3.8.2/contrib/Makefile +/tiff-3.8.2/contrib/Makefile.in +/tiff-3.8.2/contrib/acorn/Makefile +/tiff-3.8.2/contrib/acorn/Makefile.in +/tiff-3.8.2/contrib/addtiffo/Makefile +/tiff-3.8.2/contrib/addtiffo/Makefile.in +/tiff-3.8.2/contrib/addtiffo/addtiffo +/tiff-3.8.2/contrib/dbs/Makefile +/tiff-3.8.2/contrib/dbs/Makefile.in +/tiff-3.8.2/contrib/dbs/tiff-bi +/tiff-3.8.2/contrib/dbs/tiff-grayscale +/tiff-3.8.2/contrib/dbs/tiff-palette +/tiff-3.8.2/contrib/dbs/tiff-rgb +/tiff-3.8.2/contrib/dbs/xtiff/Makefile +/tiff-3.8.2/contrib/dbs/xtiff/Makefile.in +/tiff-3.8.2/contrib/iptcutil/Makefile +/tiff-3.8.2/contrib/iptcutil/Makefile.in +/tiff-3.8.2/contrib/iptcutil/iptcutil +/tiff-3.8.2/contrib/mac-cw/Makefile +/tiff-3.8.2/contrib/mac-cw/Makefile.in +/tiff-3.8.2/contrib/mac-mpw/Makefile +/tiff-3.8.2/contrib/mac-mpw/Makefile.in +/tiff-3.8.2/contrib/mfs/Makefile +/tiff-3.8.2/contrib/mfs/Makefile.in +/tiff-3.8.2/contrib/ojpeg/Makefile +/tiff-3.8.2/contrib/ojpeg/Makefile.in +/tiff-3.8.2/contrib/pds/Makefile +/tiff-3.8.2/contrib/pds/Makefile.in +/tiff-3.8.2/contrib/ras/Makefile +/tiff-3.8.2/contrib/ras/Makefile.in +/tiff-3.8.2/contrib/stream/Makefile +/tiff-3.8.2/contrib/stream/Makefile.in +/tiff-3.8.2/contrib/tags/Makefile +/tiff-3.8.2/contrib/tags/Makefile.in +/tiff-3.8.2/contrib/win_dib/Makefile +/tiff-3.8.2/contrib/win_dib/Makefile.in +/tiff-3.8.2/html/Makefile +/tiff-3.8.2/html/Makefile.in +/tiff-3.8.2/html/images/Makefile +/tiff-3.8.2/html/images/Makefile.in +/tiff-3.8.2/html/man/Makefile +/tiff-3.8.2/html/man/Makefile.in +/tiff-3.8.2/libtiff/Makefile +/tiff-3.8.2/libtiff/Makefile.in +/tiff-3.8.2/libtiff/mkg3states +/tiff-3.8.2/libtiff/stamp-h1 +/tiff-3.8.2/libtiff/stamp-h2 +/tiff-3.8.2/libtiff/tif_config.h +/tiff-3.8.2/libtiff/tif_config.h.in +/tiff-3.8.2/libtiff/tiffconf.h +/tiff-3.8.2/libtool +/tiff-3.8.2/man/Makefile +/tiff-3.8.2/man/Makefile.in +/tiff-3.8.2/port/Makefile +/tiff-3.8.2/port/Makefile.in +/tiff-3.8.2/test/Makefile +/tiff-3.8.2/test/Makefile.in +/tiff-3.8.2/tools/Makefile +/tiff-3.8.2/tools/Makefile.in +/tiff-3.8.2/tools/bmp2tiff +/tiff-3.8.2/tools/fax2ps +/tiff-3.8.2/tools/fax2tiff +/tiff-3.8.2/tools/gif2tiff +/tiff-3.8.2/tools/pal2rgb +/tiff-3.8.2/tools/ppm2tiff +/tiff-3.8.2/tools/ras2tiff +/tiff-3.8.2/tools/raw2tiff +/tiff-3.8.2/tools/rgb2ycbcr +/tiff-3.8.2/tools/thumbnail +/tiff-3.8.2/tools/tiff2bw +/tiff-3.8.2/tools/tiff2pdf +/tiff-3.8.2/tools/tiff2ps +/tiff-3.8.2/tools/tiff2rgba +/tiff-3.8.2/tools/tiffcmp +/tiff-3.8.2/tools/tiffcp +/tiff-3.8.2/tools/tiffdither +/tiff-3.8.2/tools/tiffdump +/tiff-3.8.2/tools/tiffinfo +/tiff-3.8.2/tools/tiffmedian +/tiff-3.8.2/tools/tiffset +/tiff-3.8.2/tools/tiffsplit +/unimrcp/Makefile +/unimrcp/Makefile.in +/unimrcp/aclocal.m4 +/unimrcp/build/Makefile +/unimrcp/build/Makefile.in +/unimrcp/build/config.guess +/unimrcp/build/config.sub +/unimrcp/build/depcomp +/unimrcp/build/install-sh +/unimrcp/build/ltmain.sh +/unimrcp/build/missing +/unimrcp/build/pkgconfig/Makefile +/unimrcp/build/pkgconfig/Makefile.in +/unimrcp/build/pkgconfig/unimrcpclient.pc +/unimrcp/build/pkgconfig/unimrcpplugin.pc +/unimrcp/build/pkgconfig/unimrcpserver.pc +/unimrcp/conf/Makefile +/unimrcp/conf/Makefile.in +/unimrcp/config.log +/unimrcp/config.status +/unimrcp/configure +/unimrcp/data/Makefile +/unimrcp/data/Makefile.in +/unimrcp/libs/Makefile +/unimrcp/libs/Makefile.in +/unimrcp/libs/apr-toolkit/Makefile +/unimrcp/libs/apr-toolkit/Makefile.in +/unimrcp/libs/mpf/Makefile +/unimrcp/libs/mpf/Makefile.in +/unimrcp/libs/mrcp-client/Makefile +/unimrcp/libs/mrcp-client/Makefile.in +/unimrcp/libs/mrcp-engine/Makefile +/unimrcp/libs/mrcp-engine/Makefile.in +/unimrcp/libs/mrcp-server/Makefile +/unimrcp/libs/mrcp-server/Makefile.in +/unimrcp/libs/mrcp-signaling/Makefile +/unimrcp/libs/mrcp-signaling/Makefile.in +/unimrcp/libs/mrcp/Makefile +/unimrcp/libs/mrcp/Makefile.in +/unimrcp/libs/mrcpv2-transport/Makefile +/unimrcp/libs/mrcpv2-transport/Makefile.in +/unimrcp/libs/uni-rtsp/Makefile +/unimrcp/libs/uni-rtsp/Makefile.in +/unimrcp/libtool +/unimrcp/modules/Makefile +/unimrcp/modules/Makefile.in +/unimrcp/modules/mrcp-sofiasip/Makefile +/unimrcp/modules/mrcp-sofiasip/Makefile.in +/unimrcp/modules/mrcp-unirtsp/Makefile +/unimrcp/modules/mrcp-unirtsp/Makefile.in +/unimrcp/platforms/Makefile +/unimrcp/platforms/Makefile.in +/unimrcp/platforms/asr-client/Makefile +/unimrcp/platforms/asr-client/Makefile.in +/unimrcp/platforms/libasr-client/Makefile +/unimrcp/platforms/libasr-client/Makefile.in +/unimrcp/platforms/libunimrcp-client/Makefile +/unimrcp/platforms/libunimrcp-client/Makefile.in +/unimrcp/platforms/libunimrcp-server/Makefile +/unimrcp/platforms/libunimrcp-server/Makefile.in +/unimrcp/platforms/umc/Makefile +/unimrcp/platforms/umc/Makefile.in +/unimrcp/platforms/unimrcp-client/Makefile +/unimrcp/platforms/unimrcp-client/Makefile.in +/unimrcp/platforms/unimrcp-server/Makefile +/unimrcp/platforms/unimrcp-server/Makefile.in +/unimrcp/plugins/Makefile +/unimrcp/plugins/Makefile.in +/unimrcp/plugins/demo-recog/Makefile +/unimrcp/plugins/demo-recog/Makefile.in +/unimrcp/plugins/demo-synth/Makefile +/unimrcp/plugins/demo-synth/Makefile.in +/unimrcp/plugins/mrcp-cepstral/Makefile +/unimrcp/plugins/mrcp-cepstral/Makefile.in +/unimrcp/plugins/mrcp-flite/Makefile +/unimrcp/plugins/mrcp-flite/Makefile.in +/unimrcp/plugins/mrcp-pocketsphinx/Makefile +/unimrcp/plugins/mrcp-pocketsphinx/Makefile.in +/unimrcp/plugins/mrcp-recorder/Makefile +/unimrcp/plugins/mrcp-recorder/Makefile.in +/unimrcp/tests/Makefile +/unimrcp/tests/Makefile.in +/unimrcp/tests/apttest/Makefile +/unimrcp/tests/apttest/Makefile.in +/unimrcp/tests/mpftest/Makefile +/unimrcp/tests/mpftest/Makefile.in +/unimrcp/tests/mrcptest/Makefile +/unimrcp/tests/mrcptest/Makefile.in +/unimrcp/tests/rtsptest/Makefile +/unimrcp/tests/rtsptest/Makefile.in +/unimrcp/tests/strtablegen/Makefile +/unimrcp/tests/strtablegen/Makefile.in +/xmlrpc-c/include/xmlrpc-c/config.h +/xmlrpc-c/stamp-h2 +/xmlrpc-c/xmlrpc_amconfig.h +/xmlrpc-c/xmlrpc_config.h +/apr/build/install-sh +/js/install-sh +/js/nsprpub/lib/ds/libplds4.dylib +/js/nsprpub/lib/libc/src/libplc4.dylib +/js/nsprpub/pr/src/libnspr4.dylib +/libsndfile/M4/libtool.m4 +/libsndfile/M4/ltoptions.m4 +/libsndfile/M4/ltsugar.m4 +/libsndfile/M4/ltversion.m4 +/sofia-sip/m4/libtool.m4 +/sofia-sip/m4/ltoptions.m4 +/sofia-sip/m4/ltsugar.m4 +/sofia-sip/m4/ltversion.m4 +/sofia-sip/m4/lt~obsolete.m4 +/sqlite/lemon.dSYM/ +/sqlite/mkkeywordhash.dSYM/ +/sqlite/sqlite3.dSYM/ +/tiff-3.8.2/m4/libtool.m4 +/tiff-3.8.2/m4/ltoptions.m4 +/tiff-3.8.2/m4/ltsugar.m4 +/tiff-3.8.2/m4/ltversion.m4 +/tiff-3.8.2/m4/lt~obsolete.m4 +/unimrcp/build/acmacros/libtool.m4 +/unimrcp/build/acmacros/ltoptions.m4 +/unimrcp/build/acmacros/ltsugar.m4 +/unimrcp/build/acmacros/ltversion.m4 +/unimrcp/build/acmacros/lt~obsolete.m4 +/*.tar.gz +/celt-0.7.1/ +/flite-1.3.99/ +/freeradius-client-1.1.6/ +/iksemel/test/tst-dom +/iksemel/test/tst-filter +/iksemel/test/tst-iks +/iksemel/test/tst-ikstack +/iksemel/test/tst-jid +/iksemel/test/tst-md5 +/iksemel/test/tst-sax +/iksemel/test/tst-sha +/iksemel/tools/ikslint +/iksemel/tools/iksperf +/iksemel/tools/iksroster +/json-c-0.9/ +/lame-3.97/ +/libmemcached-0.32/ +/libshout-2.2.2/ +/mpg123/ +/openldap-2.4.19/ +/pocketsphinx-0.5.99/ +/portaudio/bin-stamp +/portaudio/bin/ +/portaudio/lib-stamp +/silk/Decoder +/silk/Encoder +/silk/signalCompare +/soundtouch-1.3.1/ +/sphinxbase-0.4.99/ +/unimrcp/platforms/asr-client/asrclient +/unimrcp/platforms/umc/umc +/unimrcp/platforms/unimrcp-client/unimrcpclient +/unimrcp/platforms/unimrcp-server/unimrcpserver +!/unimrcp/configure.gnu +!/unimrcp/build/tools/unimrcpservice.exe.manifest +/yaml/config.h +/yaml/stamp-h1 +/yaml/tests/example-deconstructor +/yaml/tests/example-deconstructor-alt +/yaml/tests/example-reformatter +/yaml/tests/example-reformatter-alt +/yaml/tests/run-dumper +/yaml/tests/run-emitter +/yaml/tests/run-loader +/yaml/tests/run-parser +/yaml/tests/run-scanner +!/yaml/aclocal.m4 +!/yaml/configure +/Communicator_semi_40.cd_semi_6000/ +/libogg-1.1.3/ +/pthreads-w32-2-7-0-release/ +/sounds/ +/sphinxbase-0.4.99/ +/sofia-sip/libsofia-sip-ua/http/http_tag_dll.c +/sofia-sip/libsofia-sip-ua/iptsec/auth_tag_dll.c +/sofia-sip/libsofia-sip-ua/msg/msg_tag_dll.c +/sofia-sip/libsofia-sip-ua/msg/msg_tag_ref.c +/sofia-sip/libsofia-sip-ua/nea/nea_tag_dll.c +/sofia-sip/libsofia-sip-ua/nta/nta_tag_dll.c +/sofia-sip/libsofia-sip-ua/nth/nth_tag_dll.c +/sofia-sip/libsofia-sip-ua/nua/nua_tag_dll.c +/sofia-sip/libsofia-sip-ua/sdp/sdp_tag_dll.c +/sofia-sip/libsofia-sip-ua/sip/sip_tag_dll.c +/sofia-sip/libsofia-sip-ua/soa/soa_tag_dll.c +/sofia-sip/libsofia-sip-ua/stun/stun_tag_dll.c +/sofia-sip/libsofia-sip-ua/su/su_tag_dll.c +/sofia-sip/libsofia-sip-ua/tport/tport_tag_dll.c +/sofia-sip/libsofia-sip-ua/url/url_tag_dll.c +/win32/pcre/pcre_chartables.c +/apr-util/include/apu_config.h +/apr-util/include/apu_select_dbm.h +/include/ +/js/nsprpub/pr/include/prcpucfg.h +/apr-util/xml/expat/lib/config.h diff --git a/libs/apr-util/test/data/.empty b/libs/apr-util/test/data/.empty new file mode 100644 index 0000000000..e69de29bb2 diff --git a/libs/esl/java/classes/.empty b/libs/esl/java/classes/.empty new file mode 100644 index 0000000000..e69de29bb2 diff --git a/libs/freetdm/Makefile.am b/libs/freetdm/Makefile.am index 5f829b6614..b322d65138 100644 --- a/libs/freetdm/Makefile.am +++ b/libs/freetdm/Makefile.am @@ -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) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 468bcf10de..3268e55926 100644 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -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 * " %s\n" " %s\n" " %s\n" + " %3.2f\n" + " %3.2f\n" " %s\n" " %s\n" " %s\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"); diff --git a/libs/freetdm/src/ftdm_cpu_monitor.c b/libs/freetdm/src/ftdm_cpu_monitor.c new file mode 100644 index 0000000000..eebf922b98 --- /dev/null +++ b/libs/freetdm/src/ftdm_cpu_monitor.c @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2010, Sangoma Technologies + * Moises Silva + * 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 + * + */ + +#ifdef WIN32 +#define _WIN32_WINNT 0x0501 // To make GetSystemTimes visible in windows.h +#include +#else /* LINUX */ + +#include +#include +#include +#include +#include +#include +#include +#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: + */ diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 6a1b21c6ad..82301c0a5c 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -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(); diff --git a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c index 3445599d13..e980ab8936 100644 --- a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c +++ b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c @@ -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; diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c index 929a874657..871769e49e 100644 --- a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c +++ b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c @@ -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; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c index e7317e3679..baaa301818 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c @@ -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; diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index 0900c62800..0b8b43dbf8 100644 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -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); diff --git a/libs/freetdm/src/include/ftdm_cpu_monitor.h b/libs/freetdm/src/include/ftdm_cpu_monitor.h new file mode 100644 index 0000000000..5d6bfb7eba --- /dev/null +++ b/libs/freetdm/src/include/ftdm_cpu_monitor.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2010, Sangoma Technologies + * Moises Silva + * 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 + * + */ + +/*! \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: + */ diff --git a/libs/freetdm/src/include/ftdm_types.h b/libs/freetdm/src/include/ftdm_types.h index 7260358c8f..cf12bc9a2c 100644 --- a/libs/freetdm/src/include/ftdm_types.h +++ b/libs/freetdm/src/include/ftdm_types.h @@ -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 { diff --git a/libs/js/nsprpub/include/.empty b/libs/js/nsprpub/include/.empty new file mode 100644 index 0000000000..e69de29bb2 diff --git a/libs/js/nsprpub/macbuild/.empty b/libs/js/nsprpub/macbuild/.empty new file mode 100644 index 0000000000..e69de29bb2 diff --git a/libs/js/nsprpub/pkg/solaris/SUNWnspr/.empty b/libs/js/nsprpub/pkg/solaris/SUNWnspr/.empty new file mode 100644 index 0000000000..e69de29bb2 diff --git a/libs/js/nsprpub/pkg/solaris/SUNWnsprx/.empty b/libs/js/nsprpub/pkg/solaris/SUNWnsprx/.empty new file mode 100644 index 0000000000..e69de29bb2 diff --git a/libs/js/nsprpub/pkg/solaris/SUNWpr-devl/.empty b/libs/js/nsprpub/pkg/solaris/SUNWpr-devl/.empty new file mode 100644 index 0000000000..e69de29bb2 diff --git a/libs/js/nsprpub/pkg/solaris/SUNWprdx/.empty b/libs/js/nsprpub/pkg/solaris/SUNWprdx/.empty new file mode 100644 index 0000000000..e69de29bb2 diff --git a/libs/js/nsprpub/pkg/solaris/SUNWprx-devl/.empty b/libs/js/nsprpub/pkg/solaris/SUNWprx-devl/.empty new file mode 100644 index 0000000000..e69de29bb2 diff --git a/libs/js/nsprpub/pkg/solaris/SUNWprx/.empty b/libs/js/nsprpub/pkg/solaris/SUNWprx/.empty new file mode 100644 index 0000000000..e69de29bb2 diff --git a/libs/js/nsprpub/pr/src/cthreads/.empty b/libs/js/nsprpub/pr/src/cthreads/.empty new file mode 100644 index 0000000000..e69de29bb2 diff --git a/libs/js/nsprpub/pr/tests/macbuild/.empty b/libs/js/nsprpub/pr/tests/macbuild/.empty new file mode 100644 index 0000000000..e69de29bb2 diff --git a/libs/portaudio/doc/html/.empty b/libs/portaudio/doc/html/.empty new file mode 100644 index 0000000000..e69de29bb2 diff --git a/libs/sofia-sip/configure.ac b/libs/sofia-sip/configure.ac index fcedf33260..0eb2418ad9 100644 --- a/libs/sofia-sip/configure.ac +++ b/libs/sofia-sip/configure.ac @@ -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 ### ----------------------- diff --git a/libs/sofia-sip/libsofia-sip-ua/sofia.am b/libs/sofia-sip/libsofia-sip-ua/sofia.am index b5e5ec88f2..a7d8c346d6 100644 --- a/libs/sofia-sip/libsofia-sip-ua/sofia.am +++ b/libs/sofia-sip/libsofia-sip-ua/sofia.am @@ -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 diff --git a/libs/sofia-sip/rules/sofia.am b/libs/sofia-sip/rules/sofia.am index 3d3b88f50f..a312e1355f 100644 --- a/libs/sofia-sip/rules/sofia.am +++ b/libs/sofia-sip/rules/sofia.am @@ -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) diff --git a/libs/sqlite/art/tmp/.empty b/libs/sqlite/art/tmp/.empty new file mode 100644 index 0000000000..e69de29bb2 diff --git a/libs/sqlite/notes/.empty b/libs/sqlite/notes/.empty new file mode 100644 index 0000000000..e69de29bb2 diff --git a/libs/sqlite/src/ex/.empty b/libs/sqlite/src/ex/.empty new file mode 100644 index 0000000000..e69de29bb2 diff --git a/libs/unimrcp/.gitignore b/libs/unimrcp/.gitignore index b4bc3851b3..90ec22bee1 100644 --- a/libs/unimrcp/.gitignore +++ b/libs/unimrcp/.gitignore @@ -1,4 +1 @@ .svn -.gitignore -.update -configure.gnu diff --git a/scripts/tagscript.sh b/scripts/tagscript.sh index 9ba4826dbc..44797b3640 100755 --- a/scripts/tagscript.sh +++ b/scripts/tagscript.sh @@ -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 < * - * mod_cidlookup.c -- API for querying cid->name services + * mod_cidlookup.c -- API for querying cid->name services and local data * */ diff --git a/src/mod/applications/mod_distributor/.gitignore b/src/mod/applications/mod_distributor/.gitignore new file mode 100644 index 0000000000..f3c7a7c5da --- /dev/null +++ b/src/mod/applications/mod_distributor/.gitignore @@ -0,0 +1 @@ +Makefile diff --git a/src/mod/applications/mod_enum/Makefile.am b/src/mod/applications/mod_enum/Makefile.am index 65199901d0..c512f7691d 100644 --- a/src/mod/applications/mod_enum/Makefile.am +++ b/src/mod/applications/mod_enum/Makefile.am @@ -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 diff --git a/src/mod/applications/mod_snapshot/.gitignore b/src/mod/applications/mod_snapshot/.gitignore new file mode 100644 index 0000000000..f3c7a7c5da --- /dev/null +++ b/src/mod/applications/mod_snapshot/.gitignore @@ -0,0 +1 @@ +Makefile diff --git a/src/mod/applications/mod_vmd/.gitignore b/src/mod/applications/mod_vmd/.gitignore new file mode 100644 index 0000000000..f3c7a7c5da --- /dev/null +++ b/src/mod/applications/mod_vmd/.gitignore @@ -0,0 +1 @@ +Makefile diff --git a/src/mod/asr_tts/mod_tts_commandline/.gitignore b/src/mod/asr_tts/mod_tts_commandline/.gitignore new file mode 100644 index 0000000000..f3c7a7c5da --- /dev/null +++ b/src/mod/asr_tts/mod_tts_commandline/.gitignore @@ -0,0 +1 @@ +Makefile diff --git a/src/mod/endpoints/mod_gsmopen/.gitignore b/src/mod/endpoints/mod_gsmopen/.gitignore new file mode 100644 index 0000000000..9fdeeb1412 --- /dev/null +++ b/src/mod/endpoints/mod_gsmopen/.gitignore @@ -0,0 +1,2 @@ +!/gsmlib/gsmlib-*/aclocal.m4 +!/gsmlib/gsmlib-*/configure diff --git a/src/mod/endpoints/mod_portaudio/Makefile.am b/src/mod/endpoints/mod_portaudio/Makefile.am index 56f82daf79..88d8754868 100644 --- a/src/mod/endpoints/mod_portaudio/Makefile.am +++ b/src/mod/endpoints/mod_portaudio/Makefile.am @@ -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) diff --git a/src/mod/endpoints/mod_skinny/Makefile.am b/src/mod/endpoints/mod_skinny/Makefile.am index 212aa924ac..1ac0cd30c2 100644 --- a/src/mod/endpoints/mod_skinny/Makefile.am +++ b/src/mod/endpoints/mod_skinny/Makefile.am @@ -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 diff --git a/src/mod/endpoints/mod_skinny/Net/Skinny/Message.pm b/src/mod/endpoints/mod_skinny/Net/Skinny/Message.pm index e69a80f4ba..6a1a0ef1cf 100644 --- a/src/mod/endpoints/mod_skinny/Net/Skinny/Message.pm +++ b/src/mod/endpoints/mod_skinny/Net/Skinny/Message.pm @@ -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); diff --git a/src/mod/endpoints/mod_skinny/mod_skinny.c b/src/mod/endpoints/mod_skinny/mod_skinny.c index 3107138b73..571223ccac 100644 --- a/src/mod/endpoints/mod_skinny/mod_skinny.c +++ b/src/mod/endpoints/mod_skinny/mod_skinny.c @@ -33,15 +33,14 @@ #include "mod_skinny.h" #include "skinny_protocol.h" #include "skinny_tables.h" +#include "skinny_api.h" SWITCH_MODULE_LOAD_FUNCTION(mod_skinny_load); SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_skinny_shutdown); -SWITCH_MODULE_RUNTIME_FUNCTION(mod_skinny_runtime); -SWITCH_MODULE_DEFINITION(mod_skinny, mod_skinny_load, mod_skinny_shutdown, mod_skinny_runtime); +SWITCH_MODULE_DEFINITION(mod_skinny, mod_skinny_load, mod_skinny_shutdown, NULL); switch_endpoint_interface_t *skinny_endpoint_interface; -static switch_memory_pool_t *module_pool = NULL; skinny_globals_t globals; @@ -65,6 +64,7 @@ static char lines_sql[] = " device_name VARCHAR(16),\n" " device_instance INTEGER,\n" " position INTEGER,\n" + " line_instance INTEGER,\n" " label VARCHAR(40),\n" " value VARCHAR(24),\n" " caller_name VARCHAR(44),\n" @@ -88,10 +88,20 @@ static char buttons_sql[] = " settings VARCHAR(44)\n" ");\n"; +static char active_lines_sql[] = + "CREATE TABLE skinny_active_lines (\n" + " device_name VARCHAR(16),\n" + " device_instance INTEGER,\n" + " line_instance INTEGER,\n" + " channel_uuid VARCHAR(256),\n" + " call_id INTEGER,\n" + " call_state INTEGER\n" + ");\n"; + /*****************************************************************************/ /* PROFILES FUNCTIONS */ /*****************************************************************************/ -static switch_status_t dump_profile(const skinny_profile_t *profile, switch_stream_handle_t *stream) +switch_status_t skinny_profile_dump(const skinny_profile_t *profile, switch_stream_handle_t *stream) { const char *line = "================================================================================================="; switch_assert(profile); @@ -120,12 +130,16 @@ static switch_status_t dump_profile(const skinny_profile_t *profile, switch_stre } -static skinny_profile_t *skinny_find_profile(const char *profile_name) +skinny_profile_t *skinny_find_profile(const char *profile_name) { - return (skinny_profile_t *) switch_core_hash_find(globals.profile_hash, profile_name); + skinny_profile_t *profile; + switch_mutex_lock(globals.mutex); + profile = (skinny_profile_t *) switch_core_hash_find(globals.profile_hash, profile_name); + switch_mutex_unlock(globals.mutex); + return profile; } -static 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(skinny_profile_t *profile, const char *device_name, listener_t **listener) { switch_mutex_lock(profile->listener_mutex); for (listener_t *l = profile->listeners; l; l = l->next) { @@ -138,48 +152,105 @@ static switch_status_t skinny_profile_find_listener_by_device_name(skinny_profil return SWITCH_STATUS_SUCCESS; } -struct skinny_profile_find_listener_helper { +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) +{ + switch_mutex_lock(profile->listener_mutex); + for (listener_t *l = profile->listeners; l; l = l->next) { + if (!strcmp(l->device_name, device_name) && (l->device_instance == device_instance)) { + *listener = l; + } + } + switch_mutex_unlock(profile->listener_mutex); + + return SWITCH_STATUS_SUCCESS; +} + +struct skinny_profile_find_session_uuid_helper { skinny_profile_t *profile; - listener_t *listener; - uint32_t line; + char *channel_uuid; + uint32_t line_instance; }; -static int skinny_profile_find_listener_callback(void *pArg, int argc, char **argv, char **columnNames) +int skinny_profile_find_session_uuid_callback(void *pArg, int argc, char **argv, char **columnNames) { - struct skinny_profile_find_listener_helper *helper = pArg; - skinny_profile_t *profile = helper->profile; - char *device_name = argv[0]; - /* uint32_t position = atoi(argv[1]); */ - uint32_t relative_position = atoi(argv[2]); + struct skinny_profile_find_session_uuid_helper *helper = pArg; - skinny_profile_find_listener_by_device_name(profile, device_name, &helper->listener); + char *channel_uuid = argv[0]; + uint32_t line_instance = atoi(argv[1]); - if(helper->listener) { - helper->line = relative_position; + if(helper->channel_uuid == NULL) { + helper->channel_uuid = switch_mprintf("%s", channel_uuid); + helper->line_instance = line_instance; } + return 0; } -static switch_status_t skinny_profile_find_listener_by_dest(skinny_profile_t *profile, const char *dest, listener_t **l, uint32_t *line) +char * skinny_profile_find_session_uuid(skinny_profile_t *profile, listener_t *listener, uint32_t *line_instance_p, uint32_t call_id) { + struct skinny_profile_find_session_uuid_helper helper = {0}; char *sql; - struct skinny_profile_find_listener_helper helper = {0}; + char *device_condition = NULL; + char *line_instance_condition = NULL; + char *call_id_condition = NULL; + + switch_assert(profile); helper.profile = profile; - - if ((sql = switch_mprintf("SELECT device_name, position, " - "(SELECT count(*) from skinny_lines sl2 " - "WHERE sl2.device_name= sl1.device_name AND sl2.device_instance= sl1.device_instance AND sl2.position <= sl1.position) AS relative_position " - "FROM skinny_lines sl1 WHERE value='%s'", - dest))) { - skinny_execute_sql_callback(profile, profile->listener_mutex, sql, skinny_profile_find_listener_callback, &helper); + helper.channel_uuid = NULL; + + if(listener) { + device_condition = switch_mprintf("device_name='%s' AND device_instance=%d", + listener->device_name, listener->device_instance); + } else { + device_condition = switch_mprintf("1=1"); + } + switch_assert(device_condition); + if(*line_instance_p > 0) { + line_instance_condition = switch_mprintf("line_instance=%d", *line_instance_p); + } else { + line_instance_condition = switch_mprintf("1=1"); + } + switch_assert(line_instance_condition); + if(call_id > 0) { + call_id_condition = switch_mprintf("call_id=%d", call_id); + } else { + call_id_condition = switch_mprintf("1=1"); + } + switch_assert(call_id_condition); + if((sql = switch_mprintf( + "SELECT channel_uuid, line_instance " + "FROM skinny_active_lines " + "WHERE %s AND %s AND %s " + "ORDER BY channel_uuid DESC", + device_condition, line_instance_condition, call_id_condition + ))) { + skinny_execute_sql_callback(profile, profile->sql_mutex, sql, + skinny_profile_find_session_uuid_callback, &helper); switch_safe_free(sql); } + switch_safe_free(device_condition); + switch_safe_free(line_instance_condition); + switch_safe_free(call_id_condition); + *line_instance_p = helper.line_instance; + return helper.channel_uuid; +} +switch_core_session_t * skinny_profile_find_session(skinny_profile_t *profile, listener_t *listener, uint32_t *line_instance_p, uint32_t call_id) +{ + char *uuid; + switch_core_session_t *result = NULL; + uuid = skinny_profile_find_session_uuid(profile, listener, line_instance_p, call_id); - *line = helper.line; - *l = helper.listener; - - return SWITCH_STATUS_SUCCESS; + if(!zstr(uuid)) { + result = switch_core_session_locate(uuid); + if(!result) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, + "Unable to find session %s on %s:%d, line %d\n", + uuid, listener->device_name, listener->device_instance, *line_instance_p); + } + switch_safe_free(uuid); + } + return result; } /*****************************************************************************/ @@ -262,28 +333,73 @@ switch_bool_t skinny_execute_sql_callback(skinny_profile_t *profile, /*****************************************************************************/ /* 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) +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) { + switch_event_t *event = NULL; switch_assert(listener); - + + skinny_device_event(listener, &event, SWITCH_EVENT_CUSTOM, SKINNY_EVENT_CALL_STATE); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-Line-Instance", "%d", line_instance); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-Call-Id", "%d", call_id); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-Call-State", "%d", call_state); + switch_event_fire(&event); switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_DEBUG, - "Device %s, line %d State Change %s (%d) -> %s (%d) (no session)\n", - listener->device_name, instance, - skinny_soft_key_set2str(listener->line_state[instance]), listener->line_state[instance], - skinny_soft_key_set2str(state), state); - - send_select_soft_keys(listener, instance, call_id, state, 0xffff); - listener->line_state[instance] = state; - - return listener->line_state[instance]; + "Device %s:%d, Line %d, Call %d Change State to %s (%d)\n", + listener->device_name, listener->device_instance, line_instance, call_id, + skinny_call_state2str(call_state), call_state); } -uint32_t skinny_line_get_state(listener_t *listener, uint32_t instance) + +struct skinny_line_get_state_helper { + uint32_t call_state; +}; + +int skinny_line_get_state_callback(void *pArg, int argc, char **argv, char **columnNames) { + struct skinny_line_get_state_helper *helper = pArg; + helper->call_state = atoi(argv[0]); + return 0; +} + +uint32_t skinny_line_get_state(listener_t *listener, uint32_t line_instance, uint32_t call_id) +{ + char *line_instance_condition; + char *call_id_condition; + char *sql; + struct skinny_line_get_state_helper helper = {0}; + switch_assert(listener); - return listener->line_state[instance]; + if(line_instance > 0) { + line_instance_condition = switch_mprintf("line_instance=%d", line_instance); + } else { + line_instance_condition = switch_mprintf("1=1"); + } + switch_assert(line_instance_condition); + if(call_id > 0) { + call_id_condition = switch_mprintf("call_id=%d", call_id); + } else { + call_id_condition = switch_mprintf("1=1"); + } + switch_assert(call_id_condition); + + if ((sql = switch_mprintf( + "SELECT call_state FROM skinny_active_lines " + "WHERE device_name='%s' AND device_instance=%d " + "AND %s AND %s", + listener->device_name, listener->device_instance, + line_instance_condition, call_id_condition + ))) { + skinny_execute_sql_callback(listener->profile, listener->profile->sql_mutex, sql, skinny_line_get_state_callback, &helper); + switch_safe_free(sql); + } + switch_safe_free(line_instance_condition); + switch_safe_free(call_id_condition); + + return helper.call_state; } + + switch_status_t skinny_tech_set_codec(private_t *tech_pvt, int force) { int ms; @@ -302,11 +418,11 @@ switch_status_t skinny_tech_set_codec(private_t *tech_pvt, int force) if (strcasecmp(tech_pvt->read_impl.iananame, tech_pvt->iananame) || tech_pvt->read_impl.samples_per_second != tech_pvt->rm_rate || tech_pvt->codec_ms != (uint32_t)tech_pvt->read_impl.microseconds_per_packet / 1000) { - + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Changing Codec from %s@%dms to %s@%dms\n", tech_pvt->read_impl.iananame, tech_pvt->read_impl.microseconds_per_packet / 1000, tech_pvt->rm_encoding, tech_pvt->codec_ms); - + switch_core_session_lock_codec_write(tech_pvt->session); switch_core_session_lock_codec_read(tech_pvt->session); resetting = 1; @@ -317,7 +433,7 @@ switch_status_t skinny_tech_set_codec(private_t *tech_pvt, int force) switch_goto_status(SWITCH_STATUS_SUCCESS, end); } } - + if (switch_core_codec_init(&tech_pvt->read_codec, tech_pvt->iananame, tech_pvt->rm_fmtp, @@ -358,9 +474,7 @@ switch_status_t skinny_tech_set_codec(private_t *tech_pvt, int force) tech_pvt->read_impl.microseconds_per_packet, tech_pvt->read_impl.samples_per_packet ) != SWITCH_STATUS_SUCCESS) { - switch_channel_t *channel = NULL; - channel = switch_core_session_get_channel(tech_pvt->session); - assert(channel != NULL); + switch_channel_t *channel = switch_core_session_get_channel(tech_pvt->session); switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); switch_goto_status(SWITCH_STATUS_FALSE, end); @@ -407,28 +521,19 @@ switch_status_t skinny_tech_set_codec(private_t *tech_pvt, int force) return status; } -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) { - struct line_stat_res_message *button = NULL; - switch_assert(tech_pvt); switch_assert(session); - switch_assert(listener); - + tech_pvt->read_frame.data = tech_pvt->databuf; tech_pvt->read_frame.buflen = sizeof(tech_pvt->databuf); switch_mutex_init(&tech_pvt->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session)); switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session)); - tech_pvt->call_id = listener->profile->next_call_id++; - tech_pvt->listener = listener; - tech_pvt->line = line; + tech_pvt->call_id = ++profile->next_call_id; + tech_pvt->profile = profile; switch_core_session_set_private(session, tech_pvt); tech_pvt->session = session; - - skinny_line_get(listener, line, &button); - tech_pvt->line_name = switch_core_strdup(listener->pool, button->name); - tech_pvt->line_shortname = switch_core_strdup(listener->pool, button->shortname); - tech_pvt->line_displayname = switch_core_strdup(listener->pool, button->displayname); } /* @@ -438,14 +543,9 @@ void tech_init(private_t *tech_pvt, switch_core_session_t *session, listener_t * */ switch_status_t channel_on_init(switch_core_session_t *session) { - switch_channel_t *channel; - private_t *tech_pvt = NULL; + switch_channel_t *channel = switch_core_session_get_channel(session); + private_t *tech_pvt = switch_core_session_get_private(session); - tech_pvt = switch_core_session_get_private(session); - assert(tech_pvt != NULL); - - channel = switch_core_session_get_channel(session); - assert(channel != NULL); switch_set_flag_locked(tech_pvt, TFLAG_IO); /* Move channel's state machine to ROUTING. This means the call is trying @@ -453,9 +553,6 @@ switch_status_t channel_on_init(switch_core_session_t *session) where a destination has been identified. If the channel is simply left in the initial state, nothing will happen. */ switch_channel_set_state(channel, CS_ROUTING); - switch_mutex_lock(globals.calls_mutex); - globals.calls++; - switch_mutex_unlock(globals.calls_mutex); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s CHANNEL INIT\n", switch_channel_get_name(channel)); @@ -464,14 +561,7 @@ switch_status_t channel_on_init(switch_core_session_t *session) switch_status_t channel_on_routing(switch_core_session_t *session) { - switch_channel_t *channel = NULL; - private_t *tech_pvt = NULL; - - channel = switch_core_session_get_channel(session); - assert(channel != NULL); - - tech_pvt = switch_core_session_get_private(session); - assert(tech_pvt != NULL); + switch_channel_t *channel = switch_core_session_get_channel(session); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s CHANNEL ROUTING\n", switch_channel_get_name(channel)); @@ -480,15 +570,7 @@ switch_status_t channel_on_routing(switch_core_session_t *session) switch_status_t channel_on_execute(switch_core_session_t *session) { - - switch_channel_t *channel = NULL; - private_t *tech_pvt = NULL; - - channel = switch_core_session_get_channel(session); - assert(channel != NULL); - - tech_pvt = switch_core_session_get_private(session); - assert(tech_pvt != NULL); + switch_channel_t *channel = switch_core_session_get_channel(session); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s CHANNEL EXECUTE\n", switch_channel_get_name(channel)); @@ -498,19 +580,14 @@ switch_status_t channel_on_execute(switch_core_session_t *session) switch_status_t channel_on_destroy(switch_core_session_t *session) { - switch_channel_t *channel = NULL; - private_t *tech_pvt = NULL; - - channel = switch_core_session_get_channel(session); - assert(channel != NULL); - - tech_pvt = switch_core_session_get_private(session); + switch_channel_t *channel = switch_core_session_get_channel(session); + private_t *tech_pvt = switch_core_session_get_private(session); if (tech_pvt) { if (switch_core_codec_ready(&tech_pvt->read_codec)) { switch_core_codec_destroy(&tech_pvt->read_codec); } - + if (switch_core_codec_ready(&tech_pvt->write_codec)) { switch_core_codec_destroy(&tech_pvt->write_codec); } @@ -521,73 +598,92 @@ switch_status_t channel_on_destroy(switch_core_session_t *session) return SWITCH_STATUS_SUCCESS; } +struct channel_on_hangup_helper { + private_t *tech_pvt; +}; + +int channel_on_hangup_callback(void *pArg, int argc, char **argv, char **columnNames) +{ + struct channel_on_hangup_helper *helper = pArg; + listener_t *listener = NULL; + + char *device_name = argv[0]; + uint32_t device_instance = atoi(argv[1]); + /* uint32_t position = atoi(argv[2]); */ + uint32_t line_instance = atoi(argv[3]); + /* char *label = argv[4]; */ + /* char *value = argv[5]; */ + /* char *caller_name = argv[6]; */ + /* uint32_t ring_on_idle = atoi(argv[7]); */ + /* uint32_t ring_on_active = atoi(argv[8]); */ + /* uint32_t busy_trigger = atoi(argv[9]); */ + /* char *forward_all = argv[10]; */ + /* char *forward_busy = argv[11]; */ + /* char *forward_noanswer = argv[12]; */ + /* uint32_t noanswer_duration = atoi(argv[13]); */ + /* char *channel_uuid = argv[14]; */ + uint32_t call_id = atoi(argv[15]); + uint32_t call_state = atoi(argv[16]); + + skinny_profile_find_listener_by_device_name_and_instance(helper->tech_pvt->profile, device_name, device_instance, &listener); + if(listener) { + if(call_state == SKINNY_CONNECTED) { + send_stop_tone(listener, line_instance, call_id); + } + send_set_lamp(listener, SKINNY_BUTTON_LINE, line_instance, SKINNY_LAMP_OFF); + send_clear_prompt_status(listener, line_instance, call_id); + if(call_state == SKINNY_CONNECTED) { /* calling parties */ + send_close_receive_channel(listener, + call_id, /* uint32_t conference_id, */ + helper->tech_pvt->party_id, /* uint32_t pass_thru_party_id, */ + call_id /* uint32_t conference_id2, */ + ); + send_stop_media_transmission(listener, + call_id, /* uint32_t conference_id, */ + helper->tech_pvt->party_id, /* uint32_t pass_thru_party_id, */ + call_id /* uint32_t conference_id2, */ + ); + } + + skinny_line_set_state(listener, line_instance, call_id, SKINNY_ON_HOOK); + send_select_soft_keys(listener, line_instance, call_id, SKINNY_KEY_SET_ON_HOOK, 0xffff); + /* TODO: DefineTimeDate */ + send_set_speaker_mode(listener, SKINNY_SPEAKER_OFF); + send_set_ringer(listener, SKINNY_RING_OFF, SKINNY_RING_FOREVER, 0, call_id); + + } + return 0; +} switch_status_t channel_on_hangup(switch_core_session_t *session) { - switch_channel_t *channel = NULL; - private_t *tech_pvt = NULL; - listener_t *listener = NULL; + struct channel_on_hangup_helper helper = {0}; + switch_channel_t *channel = switch_core_session_get_channel(session); + private_t *tech_pvt = switch_core_session_get_private(session); + char *sql; - channel = switch_core_session_get_channel(session); - assert(channel != NULL); - - tech_pvt = switch_core_session_get_private(session); - assert(tech_pvt != NULL); - - listener = tech_pvt->listener; - assert(listener != NULL); - switch_clear_flag_locked(tech_pvt, TFLAG_IO); switch_clear_flag_locked(tech_pvt, TFLAG_VOICE); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s CHANNEL HANGUP\n", switch_channel_get_name(channel)); - listener->session[tech_pvt->line] = NULL; + helper.tech_pvt= tech_pvt; - stop_tone(listener, tech_pvt->line, tech_pvt->call_id); - set_lamp(listener, SKINNY_BUTTON_LINE, tech_pvt->line, SKINNY_LAMP_OFF); - clear_prompt_status(listener, tech_pvt->line, tech_pvt->call_id); - - if( skinny_line_get_state(tech_pvt->listener, tech_pvt->line) == SKINNY_KEY_SET_CONNECTED ) { - close_receive_channel(listener, - tech_pvt->call_id, /* uint32_t conference_id, */ - tech_pvt->party_id, /* uint32_t pass_thru_party_id, */ - tech_pvt->call_id /* uint32_t conference_id2, */ - ); - stop_media_transmission(listener, - tech_pvt->call_id, /* uint32_t conference_id, */ - tech_pvt->party_id, /* uint32_t pass_thru_party_id, */ - tech_pvt->call_id /* uint32_t conference_id2, */ - ); - switch_mutex_lock(globals.calls_mutex); - globals.calls--; - if (globals.calls < 0) { - globals.calls = 0; - } - switch_mutex_unlock(globals.calls_mutex); + skinny_session_walk_lines(tech_pvt->profile, switch_core_session_get_uuid(session), channel_on_hangup_callback, &helper); + if ((sql = switch_mprintf( + "DELETE FROM skinny_active_lines WHERE channel_uuid='%s'", + switch_core_session_get_uuid(session) + ))) { + skinny_execute_sql(tech_pvt->profile, sql, tech_pvt->profile->sql_mutex); + switch_safe_free(sql); } - send_call_state(listener, - SKINNY_ON_HOOK, - tech_pvt->line, - tech_pvt->call_id); - skinny_line_set_state(listener, tech_pvt->line, SKINNY_KEY_SET_ON_HOOK, tech_pvt->call_id); - /* TODO: DefineTimeDate */ - set_speaker_mode(listener, SKINNY_SPEAKER_OFF); - set_ringer(listener, SKINNY_RING_OFF, SKINNY_RING_FOREVER, 0); - return SWITCH_STATUS_SUCCESS; } switch_status_t channel_kill_channel(switch_core_session_t *session, int sig) { - switch_channel_t *channel = NULL; - private_t *tech_pvt = NULL; - - channel = switch_core_session_get_channel(session); - assert(channel != NULL); - - tech_pvt = switch_core_session_get_private(session); - assert(tech_pvt != NULL); + switch_channel_t *channel = switch_core_session_get_channel(session); + private_t *tech_pvt = switch_core_session_get_private(session); switch (sig) { case SWITCH_SIG_KILL: @@ -601,7 +697,7 @@ switch_status_t channel_kill_channel(switch_core_session_t *session, int sig) default: break; } - + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s CHANNEL KILL %d\n", switch_channel_get_name(channel), sig); return SWITCH_STATUS_SUCCESS; @@ -631,16 +727,10 @@ switch_status_t channel_send_dtmf(switch_core_session_t *session, const switch_d switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id) { - switch_channel_t *channel = NULL; - private_t *tech_pvt = NULL; + switch_channel_t *channel = switch_core_session_get_channel(session); + private_t *tech_pvt = switch_core_session_get_private(session); int payload = 0; - channel = switch_core_session_get_channel(session); - assert(channel != NULL); - - tech_pvt = switch_core_session_get_private(session); - assert(tech_pvt != NULL); - while (!(tech_pvt->read_codec.implementation && switch_rtp_ready(tech_pvt->rtp_session))) { if (switch_channel_ready(channel)) { switch_yield(10000); @@ -705,16 +795,9 @@ switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_ switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id) { - switch_channel_t *channel = NULL; - private_t *tech_pvt = NULL; + private_t *tech_pvt = switch_core_session_get_private(session); //switch_frame_t *pframe; switch_status_t status = SWITCH_STATUS_SUCCESS; - - channel = switch_core_session_get_channel(session); - assert(channel != NULL); - - tech_pvt = switch_core_session_get_private(session); - assert(tech_pvt != NULL); if (!switch_test_flag(tech_pvt, TFLAG_IO)) { return SWITCH_STATUS_FALSE; @@ -737,31 +820,12 @@ switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame switch_status_t channel_answer_channel(switch_core_session_t *session) { - private_t *tech_pvt; - switch_channel_t *channel = NULL; - - channel = switch_core_session_get_channel(session); - assert(channel != NULL); - - tech_pvt = switch_core_session_get_private(session); - assert(tech_pvt != NULL); - - return SWITCH_STATUS_SUCCESS; } switch_status_t channel_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg) { - switch_channel_t *channel; - private_t *tech_pvt; - - channel = switch_core_session_get_channel(session); - assert(channel != NULL); - - tech_pvt = (private_t *) switch_core_session_get_private(session); - assert(tech_pvt != NULL); - switch (msg->message_id) { case SWITCH_MESSAGE_INDICATE_ANSWER: { @@ -785,11 +849,10 @@ switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, swi switch_call_cause_t cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; switch_core_session_t *nsession = NULL; private_t *tech_pvt; - + char *profile_name, *dest; skinny_profile_t *profile = NULL; - listener_t *listener = NULL; - uint32_t line = 0; + char *sql; char name[128]; switch_channel_t *channel; switch_caller_profile_t *caller_profile; @@ -827,32 +890,13 @@ switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, swi cause = SWITCH_CAUSE_UNALLOCATED_NUMBER; goto error; } - + snprintf(name, sizeof(name), "SKINNY/%s/%s", profile->name, dest); channel = switch_core_session_get_channel(nsession); switch_channel_set_name(channel, name); - - if ((skinny_profile_find_listener_by_dest(profile, dest, &listener, &line) != SWITCH_STATUS_SUCCESS)) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Problem while retrieving listener and line for destination %s in profile %s\n", dest, profile_name); - cause = SWITCH_CAUSE_UNALLOCATED_NUMBER; - goto error; - } - - if (!listener) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid destination or phone not registred %s in profile %s\n", dest, profile_name); - cause = SWITCH_CAUSE_UNALLOCATED_NUMBER; - goto error; - } - - if (line == 0) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid destination or phone not registred %s in profile %s\n", dest, profile_name); - cause = SWITCH_CAUSE_UNALLOCATED_NUMBER; - goto error; - } - - tech_init(tech_pvt, nsession, listener, line); + tech_init(tech_pvt, profile, nsession); caller_profile = switch_caller_profile_clone(nsession, outbound_profile); switch_channel_set_caller_profile(channel, caller_profile); @@ -861,19 +905,23 @@ switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, swi switch_channel_set_flag(channel, CF_OUTBOUND); switch_set_flag_locked(tech_pvt, TFLAG_OUTBOUND); - if(tech_pvt->listener->session[tech_pvt->line]) { /* Line is busy */ - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Device line is busy %s in profile %s\n", dest, profile_name); - cause = SWITCH_CAUSE_USER_BUSY; + if ((sql = switch_mprintf( + "INSERT INTO skinny_active_lines " + "(device_name, device_instance, line_instance, channel_uuid, call_id, call_state) " + "SELECT device_name, device_instance, line_instance, '%s', %d, %d " + "FROM skinny_lines " + "WHERE value='%s'", + switch_core_session_get_uuid(nsession), tech_pvt->call_id, SKINNY_ON_HOOK, dest + ))) { + skinny_execute_sql(profile, sql, profile->sql_mutex); + switch_safe_free(sql); + } + + cause = skinny_ring_lines(tech_pvt); + + if(cause != SWITCH_CAUSE_SUCCESS) { goto error; } - tech_pvt->listener->session[tech_pvt->line] = nsession; - send_call_state(tech_pvt->listener, SKINNY_RING_IN, tech_pvt->line, tech_pvt->call_id); - skinny_line_set_state(tech_pvt->listener, tech_pvt->line, SKINNY_KEY_SET_RING_IN, tech_pvt->call_id); - display_prompt_status(tech_pvt->listener, 0, "\200\027tel", tech_pvt->line, tech_pvt->call_id); - /* displayprinotifiymessage */ - skinny_send_call_info(nsession); - set_lamp(tech_pvt->listener, SKINNY_BUTTON_LINE, tech_pvt->line, SKINNY_LAMP_BLINK); - set_ringer(tech_pvt->listener, SKINNY_RING_OUTSIDE, SKINNY_RING_FOREVER, 0); *new_session = nsession; @@ -950,6 +998,15 @@ switch_io_routines_t skinny_io_routines = { /* LISTENER FUNCTIONS */ /*****************************************************************************/ +uint8_t listener_is_ready(listener_t *listener) +{ + return globals.running + && listener + && listener->sock + && switch_test_flag(listener, LFLAG_RUNNING) + && listener->profile->listener_ready; +} + static void add_listener(listener_t *listener) { skinny_profile_t *profile; @@ -992,8 +1049,9 @@ static void walk_listeners(skinny_listener_callback_func_t callback, void *pvt) void *val; skinny_profile_t *profile; listener_t *l; - + /* walk listeners */ + 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; @@ -1004,6 +1062,7 @@ static void walk_listeners(skinny_listener_callback_func_t callback, void *pvt) } switch_mutex_unlock(profile->listener_mutex); } + switch_mutex_unlock(globals.mutex); } static void flush_listener(listener_t *listener, switch_bool_t flush_log, switch_bool_t flush_events) @@ -1012,12 +1071,12 @@ static void flush_listener(listener_t *listener, switch_bool_t flush_log, switch if(!zstr(listener->device_name)) { skinny_profile_t *profile = listener->profile; char *sql; - + if ((sql = switch_mprintf( "DELETE FROM skinny_devices " "WHERE name='%s' and instance=%d", listener->device_name, listener->device_instance))) { - skinny_execute_sql(profile, sql, profile->listener_mutex); + skinny_execute_sql(profile, sql, profile->sql_mutex); switch_safe_free(sql); } @@ -1025,7 +1084,7 @@ static void flush_listener(listener_t *listener, switch_bool_t flush_log, switch "DELETE FROM skinny_lines " "WHERE device_name='%s' and device_instance=%d", listener->device_name, listener->device_instance))) { - skinny_execute_sql(profile, sql, profile->listener_mutex); + skinny_execute_sql(profile, sql, profile->sql_mutex); switch_safe_free(sql); } @@ -1033,7 +1092,7 @@ static void flush_listener(listener_t *listener, switch_bool_t flush_log, switch "DELETE FROM skinny_buttons " "WHERE device_name='%s' and device_instance=%d", listener->device_name, listener->device_instance))) { - skinny_execute_sql(profile, sql, profile->listener_mutex); + skinny_execute_sql(profile, sql, profile->sql_mutex); switch_safe_free(sql); } @@ -1069,12 +1128,13 @@ static int dump_device_callback(void *pArg, int argc, char **argv, char **column return 0; } -static switch_status_t dump_device(skinny_profile_t *profile, const char *device_name, switch_stream_handle_t *stream) +switch_status_t dump_device(skinny_profile_t *profile, const char *device_name, switch_stream_handle_t *stream) { char *sql; - if ((sql = switch_mprintf("SELECT * FROM skinny_devices WHERE name LIKE '%s'", + if ((sql = switch_mprintf("SELECT name, user_id, instance, ip, type, max_streams, port, codec_string " + "FROM skinny_devices WHERE name='%s'", device_name))) { - skinny_execute_sql_callback(profile, profile->listener_mutex, sql, dump_device_callback, stream); + skinny_execute_sql_callback(profile, profile->sql_mutex, sql, dump_device_callback, stream); switch_safe_free(sql); } @@ -1120,7 +1180,7 @@ switch_status_t keepalive_listener(listener_t *listener, void *pvt) switch_assert(listener); assert(listener->profile); profile = listener->profile; - + listener->expire_time = switch_epoch_time_now(NULL)+profile->keep_alive*110/100; return SWITCH_STATUS_SUCCESS; @@ -1141,9 +1201,9 @@ static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj) switch_mutex_lock(profile->listener_mutex); profile->listener_threads++; switch_mutex_unlock(profile->listener_mutex); - + switch_assert(listener != NULL); - + switch_socket_opt_set(listener->sock, SWITCH_SO_TCP_NODELAY, TRUE); switch_socket_opt_set(listener->sock, SWITCH_SO_NONBLOCK, TRUE); @@ -1161,7 +1221,7 @@ static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj) add_listener(listener); - while (globals.running && switch_test_flag(listener, LFLAG_RUNNING) && profile->listener_ready) { + while (listener_is_ready(listener)) { status = skinny_read_packet(listener, &request); if (status != SWITCH_STATUS_SUCCESS) { @@ -1200,6 +1260,7 @@ static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Connection Closed\n"); } + /* TODO for(int line = 0 ; line < SKINNY_MAX_BUTTON_COUNT ; line++) { if(listener->session[line]) { switch_channel_clear_flag(switch_core_session_get_channel(listener->session[line]), CF_CONTROLLED); @@ -1208,6 +1269,7 @@ static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj) destroy_pool = 0; } } + */ if(destroy_pool == 0) { goto no_destroy_pool; } @@ -1237,25 +1299,26 @@ static void launch_listener_thread(listener_t *listener) switch_thread_create(&thread, thd_attr, listener_run, listener, listener->pool); } -int skinny_socket_create_and_bind(skinny_profile_t *profile) +static void *SWITCH_THREAD_FUNC skinny_profile_run(switch_thread_t *thread, void *obj) { + skinny_profile_t *profile = (skinny_profile_t *) obj; switch_status_t rv; switch_sockaddr_t *sa; switch_socket_t *inbound_socket = NULL; listener_t *listener; - switch_memory_pool_t *pool = NULL, *listener_pool = NULL; + switch_memory_pool_t *tmp_pool = NULL, *listener_pool = NULL; uint32_t errs = 0; - if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) { + if (switch_core_new_memory_pool(&tmp_pool) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "OH OH no pool\n"); - return SWITCH_STATUS_TERM; + return NULL; } while(globals.running) { - rv = switch_sockaddr_info_get(&sa, profile->ip, SWITCH_INET, profile->port, 0, pool); + rv = switch_sockaddr_info_get(&sa, profile->ip, SWITCH_INET, profile->port, 0, tmp_pool); if (rv) goto fail; - rv = switch_socket_create(&profile->sock, switch_sockaddr_get_family(sa), SOCK_STREAM, SWITCH_PROTO_TCP, pool); + rv = switch_socket_create(&profile->sock, switch_sockaddr_get_family(sa), SOCK_STREAM, SWITCH_PROTO_TCP, tmp_pool); if (rv) goto sock_fail; rv = switch_socket_opt_set(profile->sock, SWITCH_SO_REUSEADDR, 1); @@ -1299,7 +1362,7 @@ int skinny_socket_create_and_bind(skinny_profile_t *profile) errs = 0; } - + if (!(listener = switch_core_alloc(listener_pool, sizeof(*listener)))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory Error\n"); break; @@ -1325,9 +1388,9 @@ int skinny_socket_create_and_bind(skinny_profile_t *profile) end: close_socket(&profile->sock, profile); - - if (pool) { - switch_core_destroy_memory_pool(&pool); + + if (tmp_pool) { + switch_core_destroy_memory_pool(&tmp_pool); } if (listener_pool) { @@ -1336,7 +1399,7 @@ int skinny_socket_create_and_bind(skinny_profile_t *profile) fail: - return SWITCH_STATUS_TERM; + return NULL; } /*****************************************************************************/ @@ -1353,18 +1416,18 @@ static void skinny_profile_set(skinny_profile_t *profile, char *var, char *val) return; if (!strcasecmp(var, "domain")) { - profile->domain = switch_core_strdup(module_pool, val); + profile->domain = switch_core_strdup(profile->pool, val); } else if (!strcasecmp(var, "ip")) { - profile->ip = switch_core_strdup(module_pool, val); + profile->ip = switch_core_strdup(profile->pool, val); } else if (!strcasecmp(var, "dialplan")) { - profile->dialplan = switch_core_strdup(module_pool, val); + profile->dialplan = switch_core_strdup(profile->pool, val); } else if (!strcasecmp(var, "context")) { - profile->context = switch_core_strdup(module_pool, val); + profile->context = switch_core_strdup(profile->pool, val); } else if (!strcasecmp(var, "date-format")) { strncpy(profile->date_format, val, 6); } else if (!strcasecmp(var, "odbc-dsn") && !zstr(val)) { if (switch_odbc_available()) { - profile->odbc_dsn = switch_core_strdup(module_pool, val); + profile->odbc_dsn = switch_core_strdup(profile->pool, val); if ((profile->odbc_user = strchr(profile->odbc_dsn, ':'))) { *profile->odbc_user++ = '\0'; if ((profile->odbc_pass = strchr(profile->odbc_user, ':'))) { @@ -1382,18 +1445,12 @@ static switch_status_t load_skinny_config(void) char *cf = "skinny.conf"; switch_xml_t xcfg, xml, xprofiles, xprofile; - memset(&globals, 0, sizeof(globals)); - globals.running = 1; - - switch_core_hash_init(&globals.profile_hash, module_pool); - - switch_mutex_init(&globals.calls_mutex, SWITCH_MUTEX_NESTED, module_pool); - if (!(xml = switch_xml_open_cfg(cf, &xcfg, NULL))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", cf); return SWITCH_STATUS_TERM; } + switch_mutex_lock(globals.mutex); if ((xprofiles = switch_xml_child(xcfg, "profiles"))) { for (xprofile = switch_xml_child(xprofiles, "profile"); xprofile; xprofile = xprofile->next) { char *profile_name = (char *) switch_xml_attr_soft(xprofile, "name"); @@ -1404,14 +1461,23 @@ static switch_status_t load_skinny_config(void) continue; } if (xsettings) { + switch_memory_pool_t *profile_pool = NULL; char dbname[256]; switch_core_db_t *db; skinny_profile_t *profile = NULL; switch_xml_t param; - - profile = switch_core_alloc(module_pool, sizeof(skinny_profile_t)); + + if (switch_core_new_memory_pool(&profile_pool) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "OH OH no pool\n"); + return SWITCH_STATUS_TERM; + } + profile = switch_core_alloc(profile_pool, sizeof(skinny_profile_t)); + profile->pool = profile_pool; profile->name = profile_name; - + switch_mutex_init(&profile->listener_mutex, SWITCH_MUTEX_NESTED, profile->pool); + switch_mutex_init(&profile->sql_mutex, SWITCH_MUTEX_NESTED, profile->pool); + switch_mutex_init(&profile->sock_mutex, SWITCH_MUTEX_NESTED, profile->pool); + for (param = switch_xml_child(xsettings, "param"); param; param = param->next) { char *var = (char *) switch_xml_attr_soft(param, "name"); char *val = (char *) switch_xml_attr_soft(param, "value"); @@ -1436,7 +1502,7 @@ static switch_status_t load_skinny_config(void) profile->debug = atoi(val); } } /* param */ - + if (!profile->dialplan) { skinny_profile_set(profile, "dialplan","default"); } @@ -1450,7 +1516,7 @@ static switch_status_t load_skinny_config(void) } switch_snprintf(dbname, sizeof(dbname), "skinny_%s", profile->name); - profile->dbname = switch_core_strdup(module_pool, dbname); + profile->dbname = switch_core_strdup(profile->pool, dbname); if (switch_odbc_available() && profile->odbc_dsn) { if (!(profile->master_odbc = switch_odbc_handle_new(profile->odbc_dsn, profile->odbc_user, profile->odbc_pass))) { @@ -1467,23 +1533,28 @@ static switch_status_t load_skinny_config(void) switch_odbc_handle_exec(profile->master_odbc, devices_sql, NULL, NULL); switch_odbc_handle_exec(profile->master_odbc, lines_sql, NULL, NULL); switch_odbc_handle_exec(profile->master_odbc, buttons_sql, NULL, NULL); + switch_odbc_handle_exec(profile->master_odbc, active_lines_sql, NULL, NULL); } else { if ((db = switch_core_db_open_file(profile->dbname))) { switch_core_db_test_reactive(db, "SELECT * FROM skinny_devices", NULL, devices_sql); switch_core_db_test_reactive(db, "SELECT * FROM skinny_lines", NULL, lines_sql); switch_core_db_test_reactive(db, "SELECT * FROM skinny_buttons", NULL, buttons_sql); + switch_core_db_test_reactive(db, "SELECT * FROM skinny_active_lines", NULL, active_lines_sql); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot Open SQL Database!\n"); continue; } switch_core_db_close(db); } - - skinny_execute_sql_callback(profile, profile->listener_mutex, "DELETE FROM skinny_devices", NULL, NULL); - skinny_execute_sql_callback(profile, profile->listener_mutex, "DELETE FROM skinny_lines", NULL, NULL); - skinny_execute_sql_callback(profile, profile->listener_mutex, "DELETE FROM skinny_buttons", NULL, NULL); + + skinny_execute_sql_callback(profile, profile->sql_mutex, "DELETE FROM skinny_devices", NULL, NULL); + skinny_execute_sql_callback(profile, profile->sql_mutex, "DELETE FROM skinny_lines", NULL, NULL); + skinny_execute_sql_callback(profile, profile->sql_mutex, "DELETE FROM skinny_buttons", NULL, NULL); + skinny_execute_sql_callback(profile, profile->sql_mutex, "DELETE FROM skinny_active_lines", NULL, NULL); - switch_core_hash_insert(globals.profile_hash, profile->name, profile); + switch_mutex_lock(globals.mutex); + switch_core_hash_insert(globals.profile_hash, profile->name, profile); + switch_mutex_unlock(globals.mutex); profile = NULL; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, @@ -1492,498 +1563,170 @@ static switch_status_t load_skinny_config(void) } /* profile */ } switch_xml_free(xml); + switch_mutex_unlock(globals.mutex); return SWITCH_STATUS_SUCCESS; } -static switch_status_t cmd_status_profile(const char *profile_name, switch_stream_handle_t *stream) -{ - skinny_profile_t *profile; - if ((profile = skinny_find_profile(profile_name))) { - dump_profile(profile, stream); - } else { - stream->write_function(stream, "Profile not found!\n"); - } - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t 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 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) { - set_ringer(listener, skinny_str2ring_type(ring_type), skinny_str2ring_mode(ring_mode), 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 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) { - 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 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) { - 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 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 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; -} - -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 \n" - "skinny status profile device \n" - "skinny profile device send ResetMessage [DeviceReset|DeviceRestart]\n" - "skinny profile device send SetRingerMessage \n" - "skinny profile device send SetLampMessage \n" - "skinny profile device send SetSpeakerModeMessage \n" - "skinny profile device send CallStateMessage \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 */ - status = 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 device */ - status = 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 device send ... */ - switch(skinny_str2message_type(argv[5])) { - case SET_RINGER_MESSAGE: - if(argc == 8) { - /* SetRingerMessage */ - status = cmd_profile_device_send_ringer_message(argv[1], argv[3], argv[6], argv[7], stream); - } - break; - case SET_LAMP_MESSAGE: - if (argc == 9) { - /* SetLampMessage */ - status = 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 */ - status = cmd_profile_device_send_speaker_mode_message(argv[1], argv[3], argv[6], stream); - } - break; - case CALL_STATE_MESSAGE: - if (argc == 9) { - /* CallStateMessage */ - status = 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 */ - status = 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; -} - static void event_handler(switch_event_t *event) { + char *subclass; + if (event->event_id == SWITCH_EVENT_HEARTBEAT) { walk_listeners(kill_expired_listener, NULL); - } -} + } else if ((subclass = switch_event_get_header_nil(event, "Event-Subclass")) && !strcasecmp(subclass, SKINNY_EVENT_CALL_STATE)) { + char *profile_name = switch_event_get_header_nil(event, "Skinny-Profile-Name"); + char *device_name = switch_event_get_header_nil(event, "Skinny-Device-Name"); + uint32_t device_instance = atoi(switch_event_get_header_nil(event, "Skinny-Station-Instance")); + uint32_t line_instance = atoi(switch_event_get_header_nil(event, "Skinny-Line-Instance")); + uint32_t call_id = atoi(switch_event_get_header_nil(event, "Skinny-Call-Id")); + uint32_t call_state = atoi(switch_event_get_header_nil(event, "Skinny-Call-State")); + skinny_profile_t *profile; + listener_t *listener = NULL; + char *line_instance_condition, *call_id_condition; + char *sql; -static switch_status_t skinny_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 */ - 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; + if ((profile = skinny_find_profile(profile_name))) { + skinny_profile_find_listener_by_device_name_and_instance(profile, device_name, device_instance, &listener); + if(listener) { + if(line_instance > 0) { + line_instance_condition = switch_mprintf("line_instance=%d", line_instance); + } else { + line_instance_condition = switch_mprintf("1=1"); + } + switch_assert(line_instance_condition); + if(call_id > 0) { + call_id_condition = switch_mprintf("call_id=%d", call_id); + } else { + call_id_condition = switch_mprintf("1=1"); + } + switch_assert(call_id_condition); - switch_console_push_match(&my_matches, profile->name); - } - - 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_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_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 = skinny_find_profile(argv[2]); - } else if(!strcasecmp(argv[2], "profile")) {/* skinny status profile ... */ - profile = skinny_find_profile(argv[3]); - } - - if(profile) { - if ((sql = switch_mprintf("SELECT name FROM skinny_devices"))) { - skinny_execute_sql_callback(profile, profile->listener_mutex, sql, skinny_list_devices_callback, &h); - switch_safe_free(sql); + if ((sql = switch_mprintf( + "UPDATE skinny_active_lines " + "SET call_state=%d " + "WHERE device_name='%s' AND device_instance=%d " + "AND %s AND %s", + call_state, + listener->device_name, listener->device_instance, + line_instance_condition, call_id_condition + ))) { + skinny_execute_sql(listener->profile, sql, listener->profile->sql_mutex); + switch_safe_free(sql); + send_call_state(listener, call_state, line_instance, call_id); + } + switch_safe_free(line_instance_condition); + switch_safe_free(call_id_condition); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, + "Device %s:%d in profile '%s' not found.\n", device_name, device_instance, profile_name); + } + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, + "Profile '%s' not found.\n", profile_name); } } - - if (h.my_matches) { - *matches = h.my_matches; - status = SWITCH_STATUS_SUCCESS; - } - - return status; } -static switch_status_t skinny_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_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_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_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_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, ""); - switch_console_push_match(&my_matches, "0"); - - if (my_matches) { - *matches = my_matches; - status = SWITCH_STATUS_SUCCESS; - } - return status; -} - -static switch_status_t skinny_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_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_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_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, ""); - - if (my_matches) { - *matches = my_matches; - status = SWITCH_STATUS_SUCCESS; - } - return status; -} - -static switch_status_t skinny_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, ""); - - if (my_matches) { - *matches = my_matches; - status = SWITCH_STATUS_SUCCESS; - } - return status; -} /*****************************************************************************/ SWITCH_MODULE_LOAD_FUNCTION(mod_skinny_load) { switch_hash_index_t *hi; - void *val; - skinny_profile_t *profile; + /* globals init */ + memset(&globals, 0, sizeof(globals)); - switch_api_interface_t *api_interface; - - module_pool = pool; + if (switch_core_new_memory_pool(&globals.pool) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "OH OH no pool\n"); + return SWITCH_STATUS_TERM; + } + switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, globals.pool); + switch_core_hash_init(&globals.profile_hash, globals.pool); + globals.running = 1; load_skinny_config(); - /* init listeners */ - 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_mutex_init(&profile->listener_mutex, SWITCH_MUTEX_NESTED, module_pool); - switch_mutex_init(&profile->sock_mutex, SWITCH_MUTEX_NESTED, module_pool); - - } - + /* bind to events */ if ((switch_event_bind_removable(modname, SWITCH_EVENT_HEARTBEAT, NULL, event_handler, NULL, &globals.heartbeat_node) != SWITCH_STATUS_SUCCESS)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind our heartbeat handler!\n"); /* Not such severe to prevent loading */ } + if ((switch_event_bind_removable(modname, SWITCH_EVENT_CUSTOM, SKINNY_EVENT_CALL_STATE, event_handler, NULL, &globals.call_state_node) != SWITCH_STATUS_SUCCESS)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind our call_state handler!\n"); + return SWITCH_STATUS_TERM; + } + /* reserve events */ if (switch_event_reserve_subclass(SKINNY_EVENT_REGISTER) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", SKINNY_EVENT_REGISTER); return SWITCH_STATUS_TERM; } + if (switch_event_reserve_subclass(SKINNY_EVENT_UNREGISTER) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", SKINNY_EVENT_UNREGISTER); + return SWITCH_STATUS_TERM; + } + if (switch_event_reserve_subclass(SKINNY_EVENT_EXPIRE) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", SKINNY_EVENT_EXPIRE); + return SWITCH_STATUS_TERM; + } + if (switch_event_reserve_subclass(SKINNY_EVENT_ALARM) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", SKINNY_EVENT_ALARM); + return SWITCH_STATUS_TERM; + } + if (switch_event_reserve_subclass(SKINNY_EVENT_CALL_STATE) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", SKINNY_EVENT_CALL_STATE); + return SWITCH_STATUS_TERM; + } /* connect my internal structure to the blank pointer passed to me */ - *module_interface = switch_loadable_module_create_module_interface(pool, modname); + *module_interface = switch_loadable_module_create_module_interface(globals.pool, modname); skinny_endpoint_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE); skinny_endpoint_interface->interface_name = "skinny"; skinny_endpoint_interface->io_routines = &skinny_io_routines; skinny_endpoint_interface->state_handler = &skinny_state_handlers; + skinny_api_register(module_interface); - SWITCH_ADD_API(api_interface, "skinny", "Skinny Controls", skinny_function, " "); - switch_console_set_complete("add skinny help"); + /* launch listeners */ + switch_mutex_lock(globals.mutex); + for (hi = switch_hash_first(NULL, globals.profile_hash); hi; hi = switch_hash_next(hi)) { + void *val; + skinny_profile_t *profile; + switch_thread_t *thread; + switch_threadattr_t *thd_attr = NULL; - 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_hash_this(hi, NULL, NULL, &val); + profile = (skinny_profile_t *) val; - 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_list_profiles); - switch_console_add_complete_func("::skinny::list_devices", skinny_list_devices); - switch_console_add_complete_func("::skinny::list_reset_types", skinny_list_reset_types); - switch_console_add_complete_func("::skinny::list_ring_types", skinny_list_ring_types); - switch_console_add_complete_func("::skinny::list_ring_modes", skinny_list_ring_modes); - switch_console_add_complete_func("::skinny::list_stimuli", skinny_list_stimuli); - switch_console_add_complete_func("::skinny::list_stimulus_instances", skinny_list_stimulus_instances); - switch_console_add_complete_func("::skinny::list_stimulus_modes", skinny_list_stimulus_modes); - switch_console_add_complete_func("::skinny::list_speaker_modes", skinny_list_speaker_modes); - switch_console_add_complete_func("::skinny::list_call_states", skinny_list_call_states); - switch_console_add_complete_func("::skinny::list_line_instances", skinny_list_line_instances); - switch_console_add_complete_func("::skinny::list_call_ids", skinny_list_call_ids); + switch_threadattr_create(&thd_attr, profile->pool); + switch_threadattr_detach_set(thd_attr, 1); + switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); + switch_thread_create(&thread, thd_attr, skinny_profile_run, profile, profile->pool); + } + switch_mutex_unlock(globals.mutex); /* indicate that the module should continue to be loaded */ return SWITCH_STATUS_SUCCESS; } -SWITCH_MODULE_RUNTIME_FUNCTION(mod_skinny_runtime) -{ - switch_status_t status = SWITCH_STATUS_SUCCESS; - switch_hash_index_t *hi; - void *val; - skinny_profile_t *profile; - - /* launch listeners */ - 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; - - status = skinny_socket_create_and_bind(profile); - if(status != SWITCH_STATUS_SUCCESS) { - return status; - } - } - return status; -} - SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_skinny_shutdown) { switch_hash_index_t *hi; void *val; - skinny_profile_t *profile; + switch_memory_pool_t *pool = globals.pool; + switch_mutex_t *mutex = globals.mutex; int sanity = 0; - switch_event_free_subclass(SKINNY_EVENT_REGISTER); + /* release events */ switch_event_unbind(&globals.heartbeat_node); + switch_event_unbind(&globals.call_state_node); + switch_event_free_subclass(SKINNY_EVENT_REGISTER); + switch_event_free_subclass(SKINNY_EVENT_UNREGISTER); + switch_event_free_subclass(SKINNY_EVENT_EXPIRE); + switch_event_free_subclass(SKINNY_EVENT_ALARM); + switch_event_free_subclass(SKINNY_EVENT_CALL_STATE); + + switch_mutex_lock(mutex); globals.running = 0; @@ -1991,7 +1734,9 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_skinny_shutdown) walk_listeners(kill_listener, NULL); /* close sockets */ + switch_mutex_lock(globals.mutex); for (hi = switch_hash_first(NULL, globals.profile_hash); hi; hi = switch_hash_next(hi)) { + skinny_profile_t *profile; switch_hash_this(hi, NULL, NULL, &val); profile = (skinny_profile_t *) val; @@ -2004,8 +1749,14 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_skinny_shutdown) break; } } + switch_core_destroy_memory_pool(&profile->pool); } + switch_mutex_unlock(globals.mutex); + switch_core_hash_destroy(&globals.profile_hash); + memset(&globals, 0, sizeof(globals)); + switch_mutex_unlock(mutex); + switch_core_destroy_memory_pool(&pool); return SWITCH_STATUS_SUCCESS; } diff --git a/src/mod/endpoints/mod_skinny/mod_skinny.h b/src/mod/endpoints/mod_skinny/mod_skinny.h index 88a5b70287..7bcc40b96c 100644 --- a/src/mod/endpoints/mod_skinny/mod_skinny.h +++ b/src/mod/endpoints/mod_skinny/mod_skinny.h @@ -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: + */ + diff --git a/src/mod/endpoints/mod_skinny/skinny_api.c b/src/mod/endpoints/mod_skinny/skinny_api.c new file mode 100644 index 0000000000..25ec6da702 --- /dev/null +++ b/src/mod/endpoints/mod_skinny/skinny_api.c @@ -0,0 +1,473 @@ +/* + * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * Copyright (C) 2010, Mathieu Parent + * + * 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 + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Mathieu Parent + * + * + * skinny_api.c -- Skinny Call Control Protocol (SCCP) Endpoint Module + * + */ + +#include +#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 = skinny_find_profile(argv[2]); + } else if(!strcasecmp(argv[2], "profile")) {/* skinny status profile ... */ + 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, ""); + 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, ""); + + 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, ""); + + 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 \n" + "skinny status profile device \n" + "skinny profile device send ResetMessage [DeviceReset|DeviceRestart]\n" + "skinny profile device send SetRingerMessage \n" + "skinny profile device send SetLampMessage \n" + "skinny profile device send SetSpeakerModeMessage \n" + "skinny profile device send CallStateMessage \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 */ + 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 device */ + 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 device send ... */ + switch(skinny_str2message_type(argv[5])) { + case SET_RINGER_MESSAGE: + if(argc == 8) { + /* SetRingerMessage */ + 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 */ + 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 */ + 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 */ + 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 */ + 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, " "); + 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: + */ + diff --git a/src/mod/endpoints/mod_skinny/skinny_api.h b/src/mod/endpoints/mod_skinny/skinny_api.h new file mode 100644 index 0000000000..fc405c2515 --- /dev/null +++ b/src/mod/endpoints/mod_skinny/skinny_api.h @@ -0,0 +1,50 @@ +/* + * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * Copyright (C) 2010, Mathieu Parent + * + * 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 + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Mathieu Parent + * + * + * 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: + */ + diff --git a/src/mod/endpoints/mod_skinny/skinny_protocol.c b/src/mod/endpoints/mod_skinny/skinny_protocol.c index a7438c05cc..533a922f32 100644 --- a/src/mod/endpoints/mod_skinny/skinny_protocol.c +++ b/src/mod/endpoints/mod_skinny/skinny_protocol.c @@ -141,14 +141,14 @@ switch_status_t skinny_read_packet(listener_t *listener, skinny_message_t **req) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to allocate memory.\n"); return SWITCH_STATUS_MEMERR; } - - if (!globals.running) { + + if (!listener_is_ready(listener)) { return SWITCH_STATUS_FALSE; } ptr = mbuf; - while (listener->sock && globals.running) { + while (listener_is_ready(listener)) { uint8_t do_sleep = 1; if(bytes < SKINNY_MESSAGE_FIELD_SIZE) { /* We have nothing yet, get length header field */ @@ -159,15 +159,15 @@ switch_status_t skinny_read_packet(listener_t *listener, skinny_message_t **req) } status = switch_socket_recv(listener->sock, ptr, &mlen); - - if (!globals.running || (!SWITCH_STATUS_IS_BREAK(status) && status != SWITCH_STATUS_SUCCESS)) { + + if (!listener_is_ready(listener) || (!SWITCH_STATUS_IS_BREAK(status) && status != SWITCH_STATUS_SUCCESS)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Socket break.\n"); return SWITCH_STATUS_FALSE; } - + if(mlen) { bytes += mlen; - + if(bytes >= SKINNY_MESSAGE_FIELD_SIZE) { do_sleep = 0; ptr += mlen; @@ -218,23 +218,25 @@ int skinny_device_event_callback(void *pArg, int argc, char **argv, char **colum { switch_event_t *event = (switch_event_t *) pArg; - char *device_name = argv[0]; - char *user_id = argv[1]; - char *instance = argv[2]; - char *ip = argv[3]; - char *device_type = argv[4]; - char *max_streams = argv[5]; - char *port = argv[6]; - char *codec_string = argv[7]; + char *profile_name = argv[0]; + char *device_name = argv[1]; + char *user_id = argv[2]; + char *device_instance = argv[3]; + char *ip = argv[4]; + char *device_type = argv[5]; + char *max_streams = argv[6]; + char *port = argv[7]; + char *codec_string = argv[8]; - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Skinny-Device-Name", device_name); - switch_event_add_header( event, SWITCH_STACK_BOTTOM, "Skinny-User-Id", "%s", user_id); - switch_event_add_header( event, SWITCH_STACK_BOTTOM, "Skinny-Instance", "%s", instance); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Skinny-IP", ip); - switch_event_add_header( event, SWITCH_STACK_BOTTOM, "Skinny-Device-Type", "%s", device_type); - switch_event_add_header( event, SWITCH_STACK_BOTTOM, "Skinny-Max-Streams", "%s", max_streams); - switch_event_add_header( event, SWITCH_STACK_BOTTOM, "Skinny-Port", "%s", port); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Skinny-Codecs", codec_string); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-Profile-Name", "%s", profile_name); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-Device-Name", "%s", device_name); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-Station-User-Id", "%s", user_id); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-Station-Instance", "%s", device_instance); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-IP-Address", "%s", ip); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-Device-Type", "%s", device_type); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-Max-Streams", "%s", max_streams); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-Port", "%s", port); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-Codecs", "%s", codec_string); return 0; } @@ -249,8 +251,12 @@ switch_status_t skinny_device_event(listener_t *listener, switch_event_t **ev, s switch_event_create_subclass(&event, event_id, subclass_name); switch_assert(event); - if ((sql = switch_mprintf("SELECT * FROM skinny_devices WHERE name='%s' AND instance=%d", listener->device_name, listener->device_instance))) { - skinny_execute_sql_callback(profile, profile->listener_mutex, sql, skinny_device_event_callback, event); + if ((sql = switch_mprintf("SELECT '%s', name, user_id, instance, ip, type, max_streams, port, codec_string " + "FROM skinny_devices " + "WHERE name='%s' AND instance=%d", + listener->profile->name, + listener->device_name, listener->device_instance))) { + skinny_execute_sql_callback(profile, profile->sql_mutex, sql, skinny_device_event_callback, event); switch_safe_free(sql); } @@ -259,30 +265,30 @@ switch_status_t skinny_device_event(listener_t *listener, switch_event_t **ev, s } /*****************************************************************************/ -switch_status_t skinny_send_call_info(switch_core_session_t *session) +switch_status_t skinny_send_call_info(switch_core_session_t *session, listener_t *listener, uint32_t line_instance) { private_t *tech_pvt; switch_channel_t *channel; - listener_t *listener; - + char calling_party_name[40] = "UNKNOWN"; char calling_party[24] = "0000000000"; char called_party_name[40] = "UNKNOWN"; char called_party[24] = "0000000000"; - - tech_pvt = switch_core_session_get_private(session); - switch_assert(tech_pvt != NULL); - channel = switch_core_session_get_channel(session); - switch_assert(channel != NULL); - listener = tech_pvt->listener; - switch_assert(listener != NULL); + channel = switch_core_session_get_channel(session); + tech_pvt = switch_core_session_get_private(session); switch_assert(tech_pvt->caller_profile != NULL); - + if( switch_channel_test_flag(channel, CF_OUTBOUND) ) { - strncpy(calling_party_name, tech_pvt->line_displayname, 40); - strncpy(calling_party, tech_pvt->line_name, 24); + struct line_stat_res_message *button = NULL; + + skinny_line_get(listener, line_instance, &button); + + if (button) { + strncpy(calling_party_name, button->displayname, 40); + strncpy(calling_party, button->name, 24); + } strncpy(called_party_name, tech_pvt->caller_profile->caller_id_name, 40); strncpy(called_party, tech_pvt->caller_profile->caller_id_number, 24); } else { @@ -290,12 +296,12 @@ switch_status_t skinny_send_call_info(switch_core_session_t *session) strncpy(calling_party, tech_pvt->caller_profile->caller_id_number, 24); /* TODO called party */ } - send_call_info(tech_pvt->listener, + send_call_info(listener, calling_party_name, /* char calling_party_name[40], */ calling_party, /* char calling_party[24], */ called_party_name, /* char called_party_name[40], */ called_party, /* char called_party[24], */ - tech_pvt->line, /* uint32_t line_instance, */ + line_instance, /* uint32_t line_instance, */ tech_pvt->call_id, /* uint32_t call_id, */ SKINNY_OUTBOUND_CALL, /* uint32_t call_type, */ "", /* TODO char original_called_party_name[40], */ @@ -316,169 +322,429 @@ switch_status_t skinny_send_call_info(switch_core_session_t *session) } /*****************************************************************************/ -switch_status_t skinny_create_session(listener_t *listener, uint32_t line, uint32_t to_state) +switch_status_t skinny_session_walk_lines(skinny_profile_t *profile, char *channel_uuid, switch_core_db_callback_func_t callback, void *data) { - switch_core_session_t *session; + char *sql; + if ((sql = switch_mprintf( + "SELECT skinny_lines.*, channel_uuid, call_id, call_state " + "FROM skinny_active_lines " + "INNER JOIN skinny_lines " + "ON skinny_active_lines.device_name = skinny_lines.device_name " + "AND skinny_active_lines.device_instance = skinny_lines.device_instance " + "AND skinny_active_lines.line_instance = skinny_lines.line_instance " + "WHERE channel_uuid='%s'", + channel_uuid))) { + skinny_execute_sql_callback(profile, profile->sql_mutex, sql, callback, data); + switch_safe_free(sql); + } + return SWITCH_STATUS_SUCCESS; +} + +switch_status_t skinny_session_walk_lines_by_call_id(skinny_profile_t *profile, uint32_t call_id, switch_core_db_callback_func_t callback, void *data) +{ + char *sql; + if ((sql = switch_mprintf( + "SELECT skinny_lines.*, channel_uuid, call_id, call_state " + "FROM skinny_active_lines " + "INNER JOIN skinny_lines " + "ON skinny_active_lines.device_name = skinny_lines.device_name " + "AND skinny_active_lines.device_instance = skinny_lines.device_instance " + "AND skinny_active_lines.line_instance = skinny_lines.line_instance " + "WHERE call_id='%d'", + call_id))) { + skinny_execute_sql_callback(profile, profile->sql_mutex, sql, callback, data); + switch_safe_free(sql); + } + return SWITCH_STATUS_SUCCESS; +} + +/*****************************************************************************/ +struct skinny_ring_lines_helper { + private_t *tech_pvt; + uint32_t lines_count; +}; + +int skinny_ring_lines_callback(void *pArg, int argc, char **argv, char **columnNames) +{ + struct skinny_ring_lines_helper *helper = pArg; + char *tmp; + + char *device_name = argv[0]; + uint32_t device_instance = atoi(argv[1]); + /* uint32_t position = atoi(argv[2]); */ + uint32_t line_instance = atoi(argv[3]); + /* char *label = argv[4]; */ + /* char *value = argv[5]; */ + /* char *caller_name = argv[6]; */ + /* uint32_t ring_on_idle = atoi(argv[7]); */ + /* uint32_t ring_on_active = atoi(argv[8]); */ + /* uint32_t busy_trigger = atoi(argv[9]); */ + /* char *forward_all = argv[10]; */ + /* char *forward_busy = argv[11]; */ + /* char *forward_noanswer = argv[12]; */ + /* uint32_t noanswer_duration = atoi(argv[13]); */ + /* char *channel_uuid = argv[14]; */ + /* uint32_t call_id = atoi(argv[15]); */ + /* uint32_t call_state = atoi(argv[16]); */ + + listener_t *listener = NULL; + + skinny_profile_find_listener_by_device_name_and_instance(helper->tech_pvt->profile, + device_name, device_instance, &listener); + if(listener) { + helper->lines_count++; + skinny_line_set_state(listener, line_instance, helper->tech_pvt->call_id, SKINNY_RING_IN); + send_select_soft_keys(listener, line_instance, helper->tech_pvt->call_id, SKINNY_KEY_SET_RING_IN, 0xffff); + if ((tmp = switch_mprintf("\200\027%s", helper->tech_pvt->caller_profile->destination_number))) { + send_display_prompt_status(listener, 0, tmp, line_instance, helper->tech_pvt->call_id); + switch_safe_free(tmp); + } + if ((tmp = switch_mprintf("\005\000\000\000%s", helper->tech_pvt->caller_profile->destination_number))) { + send_display_pri_notify(listener, 10 /* message_timeout */, 5 /* priority */, tmp); + switch_safe_free(tmp); + } + skinny_send_call_info(helper->tech_pvt->session, listener, line_instance); + send_set_lamp(listener, SKINNY_BUTTON_LINE, line_instance, SKINNY_LAMP_BLINK); + send_set_ringer(listener, SKINNY_RING_INSIDE, SKINNY_RING_FOREVER, 0, helper->tech_pvt->call_id); + } + return 0; +} + +switch_call_cause_t skinny_ring_lines(private_t *tech_pvt) +{ + switch_status_t status; + struct skinny_ring_lines_helper helper = {0}; + + switch_assert(tech_pvt); + switch_assert(tech_pvt->profile); + switch_assert(tech_pvt->session); + + helper.tech_pvt = tech_pvt; + helper.lines_count = 0; + + status = skinny_session_walk_lines(tech_pvt->profile, + switch_core_session_get_uuid(tech_pvt->session), skinny_ring_lines_callback, &helper); + if(status != SWITCH_STATUS_SUCCESS) { + return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; + } else if(helper.lines_count == 0) { + return SWITCH_CAUSE_UNALLOCATED_NUMBER; + } else { + return SWITCH_CAUSE_SUCCESS; + } +} + +/*****************************************************************************/ +switch_status_t skinny_create_ingoing_session(listener_t *listener, uint32_t *line_instance_p, switch_core_session_t **session) +{ + uint32_t line_instance; + switch_core_session_t *nsession; switch_channel_t *channel; private_t *tech_pvt; char name[128]; + char *sql; + struct line_stat_res_message *button = NULL; - if(listener->session[line]) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "There is already a session on line %d of device %s\n", - line, listener->device_name); - - session = listener->session[line]; - - channel = switch_core_session_get_channel(session); - assert(channel != NULL); - - tech_pvt = switch_core_session_get_private(session); - assert(tech_pvt != NULL); - } else { - - if (!(session = switch_core_session_request(skinny_get_endpoint_interface(), SWITCH_CALL_DIRECTION_INBOUND, NULL))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error Creating Session\n"); - goto error; - } - - if (!(tech_pvt = (struct private_object *) switch_core_session_alloc(session, sizeof(*tech_pvt)))) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Error Creating Session private object\n"); - goto error; - } - - switch_core_session_add_stream(session, NULL); - - tech_init(tech_pvt, session, listener, line); - - channel = switch_core_session_get_channel(session); - - snprintf(name, sizeof(name), "SKINNY/%s/%s:%d/%d", listener->profile->name, listener->device_name, listener->device_instance, tech_pvt->line); - switch_channel_set_name(channel, name); - - if (switch_core_session_thread_launch(session) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Error Creating Session thread\n"); - goto error; - } - - if (!(tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session), - NULL, listener->profile->dialplan, tech_pvt->line_displayname, tech_pvt->line_name, listener->remote_ip, NULL, NULL, NULL, "skinny" /* modname */, listener->profile->context, tech_pvt->dest)) != 0) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Error Creating Session caller profile\n"); - goto error; - } - - switch_channel_set_caller_profile(channel, tech_pvt->caller_profile); - + line_instance = *line_instance_p; + if((nsession = skinny_profile_find_session(listener->profile, listener, line_instance_p, 0))) { + switch_core_session_rwunlock(nsession); + if(skinny_line_get_state(listener, *line_instance_p, 0) == SKINNY_OFF_HOOK) { + /* Reuse existing session */ + *session = nsession; + return SWITCH_STATUS_SUCCESS; + } + skinny_session_hold_line(nsession, listener, *line_instance_p); } - - set_ringer(listener, SKINNY_RING_OFF, SKINNY_RING_FOREVER, 0); - set_speaker_mode(listener, SKINNY_SPEAKER_ON); - set_lamp(listener, SKINNY_BUTTON_LINE, tech_pvt->line, SKINNY_LAMP_ON); - send_call_state(listener, - SKINNY_OFF_HOOK, - tech_pvt->line, - tech_pvt->call_id); - skinny_line_set_state(listener, tech_pvt->line, to_state, tech_pvt->call_id); - display_prompt_status(listener, - 0, - "\200\000", - tech_pvt->line, - tech_pvt->call_id); - activate_call_plane(listener, tech_pvt->line); - start_tone(listener, SKINNY_TONE_DIALTONE, 0, tech_pvt->line, tech_pvt->call_id); + *line_instance_p = line_instance; + if(*line_instance_p == 0) { + *line_instance_p = 1; + } + + skinny_line_get(listener, *line_instance_p, &button); + + if (!button || !button->shortname) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Line %d not found on device %s %d\n", + *line_instance_p, listener->device_name, listener->device_instance); + goto error; + } + + if (!(nsession = switch_core_session_request(skinny_get_endpoint_interface(), + SWITCH_CALL_DIRECTION_INBOUND, NULL))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error Creating Session\n"); + goto error; + } + + if (!(tech_pvt = (struct private_object *) switch_core_session_alloc(nsession, sizeof(*tech_pvt)))) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(nsession), SWITCH_LOG_CRIT, + "Error Creating Session private object\n"); + goto error; + } + + switch_core_session_add_stream(nsession, NULL); + + tech_init(tech_pvt, listener->profile, nsession); + + channel = switch_core_session_get_channel(nsession); + + snprintf(name, sizeof(name), "SKINNY/%s/%s:%d/%d", listener->profile->name, + listener->device_name, listener->device_instance, *line_instance_p); + switch_channel_set_name(channel, name); + + if (switch_core_session_thread_launch(nsession) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(nsession), SWITCH_LOG_CRIT, + "Error Creating Session thread\n"); + goto error; + } + + if (!(tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(nsession), + NULL, listener->profile->dialplan, + button->shortname, button->name, + listener->remote_ip, NULL, NULL, NULL, + "skinny" /* modname */, + listener->profile->context, + "")) != 0) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(nsession), SWITCH_LOG_CRIT, + "Error Creating Session caller profile\n"); + goto error; + } + + switch_channel_set_caller_profile(channel, tech_pvt->caller_profile); + + if ((sql = switch_mprintf( + "INSERT INTO skinny_active_lines " + "(device_name, device_instance, line_instance, channel_uuid, call_id, call_state) " + "SELECT device_name, device_instance, line_instance, '%s', %d, %d " + "FROM skinny_lines " + "WHERE value='%s'", + switch_core_session_get_uuid(nsession), tech_pvt->call_id, SKINNY_ON_HOOK, button->shortname + ))) { + skinny_execute_sql(listener->profile, sql, listener->profile->sql_mutex); + switch_safe_free(sql); + } + + send_set_ringer(listener, SKINNY_RING_OFF, SKINNY_RING_FOREVER, 0, tech_pvt->call_id); + send_set_speaker_mode(listener, SKINNY_SPEAKER_ON); + send_set_lamp(listener, SKINNY_BUTTON_LINE, *line_instance_p, SKINNY_LAMP_ON); + skinny_line_set_state(listener, *line_instance_p, tech_pvt->call_id, SKINNY_OFF_HOOK); + send_select_soft_keys(listener, *line_instance_p, tech_pvt->call_id, SKINNY_KEY_SET_OFF_HOOK, 0xffff); + send_display_prompt_status(listener, 0, "\200\000", + *line_instance_p, tech_pvt->call_id); + send_activate_call_plane(listener, *line_instance_p); goto done; error: - if (session) { - switch_core_session_destroy(&session); + if (nsession) { + switch_core_session_destroy(&nsession); } return SWITCH_STATUS_FALSE; done: - listener->session[line] = session; + *session = nsession; return SWITCH_STATUS_SUCCESS; } -switch_status_t skinny_process_dest(listener_t *listener, uint32_t line) +switch_status_t skinny_session_process_dest(switch_core_session_t *session, listener_t *listener, uint32_t line_instance, char *dest, char append_dest, uint32_t backspace) { switch_channel_t *channel = NULL; private_t *tech_pvt = NULL; - channel = switch_core_session_get_channel(listener->session[line]); - assert(channel != NULL); + switch_assert(session); + switch_assert(listener); + switch_assert(listener->profile); + + channel = switch_core_session_get_channel(session); + tech_pvt = switch_core_session_get_private(session); - tech_pvt = switch_core_session_get_private(listener->session[line]); - assert(tech_pvt != NULL); - - tech_pvt->caller_profile->destination_number = switch_core_strdup(tech_pvt->caller_profile->pool, tech_pvt->dest); - if(strlen(tech_pvt->dest) >= 4) { /* TODO Number is complete -> check against dialplan */ - if (switch_channel_get_state(channel) == CS_NEW) { - switch_channel_set_state(channel, CS_INIT); - } - - send_dialed_number(listener, tech_pvt->dest, tech_pvt->line, tech_pvt->call_id); - skinny_answer(listener->session[line]); + if(!dest) { + if(append_dest == '\0') {/* no digit yet */ + send_start_tone(listener, SKINNY_TONE_DIALTONE, 0, line_instance, tech_pvt->call_id); + } else { + if(strlen(tech_pvt->caller_profile->destination_number) == 0) {/* first digit */ + send_stop_tone(listener, line_instance, tech_pvt->call_id); + send_select_soft_keys(listener, line_instance, tech_pvt->call_id, + SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT, 0xffff); + } + tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, + "%s%c", tech_pvt->caller_profile->destination_number, append_dest); + } + } else { + tech_pvt->caller_profile->destination_number = switch_core_strdup(tech_pvt->caller_profile->pool, + dest); } + /* TODO Number is complete -> check against dialplan */ + if((strlen(tech_pvt->caller_profile->destination_number) >= 4) || dest) { + send_dialed_number(listener, tech_pvt->caller_profile->destination_number, line_instance, tech_pvt->call_id); + skinny_line_set_state(listener, line_instance, tech_pvt->call_id, SKINNY_PROCEED); + skinny_send_call_info(session, listener, line_instance); + skinny_session_start_media(session, listener, line_instance); + } + + switch_core_session_rwunlock(session); + return SWITCH_STATUS_SUCCESS; } -switch_status_t skinny_answer(switch_core_session_t *session) +switch_status_t skinny_session_ring_out(switch_core_session_t *session, listener_t *listener, uint32_t line_instance) { + switch_channel_t *channel = NULL; + private_t *tech_pvt = NULL; + + switch_assert(session); + switch_assert(listener); + switch_assert(listener->profile); + + channel = switch_core_session_get_channel(session); + tech_pvt = switch_core_session_get_private(session); + + skinny_line_set_state(listener, line_instance, tech_pvt->call_id, SKINNY_RING_OUT); + send_select_soft_keys(listener, line_instance, tech_pvt->call_id, + SKINNY_KEY_SET_RING_OUT, 0xffff); + send_display_prompt_status(listener, 0, "\200\026", + line_instance, tech_pvt->call_id); + skinny_send_call_info(session, listener, line_instance); + + switch_core_session_rwunlock(session); + + return SWITCH_STATUS_SUCCESS; +} + + +struct skinny_session_answer_helper { private_t *tech_pvt; listener_t *listener; - - tech_pvt = switch_core_session_get_private(session); - switch_assert(tech_pvt != NULL); - - listener = tech_pvt->listener; - switch_assert(listener != NULL); + uint32_t line_instance; +}; + +int skinny_session_answer_callback(void *pArg, int argc, char **argv, char **columnNames) +{ + struct skinny_session_answer_helper *helper = pArg; + listener_t *listener = NULL; + + char *device_name = argv[0]; + uint32_t device_instance = atoi(argv[1]); + /* uint32_t position = atoi(argv[2]); */ + uint32_t line_instance = atoi(argv[3]); + /* char *label = argv[4]; */ + /* char *value = argv[5]; */ + /* char *caller_name = argv[6]; */ + /* uint32_t ring_on_idle = atoi(argv[7]); */ + /* uint32_t ring_on_active = atoi(argv[8]); */ + /* uint32_t busy_trigger = atoi(argv[9]); */ + /* char *forward_all = argv[10]; */ + /* char *forward_busy = argv[11]; */ + /* char *forward_noanswer = argv[12]; */ + /* uint32_t noanswer_duration = atoi(argv[13]); */ + /* char *channel_uuid = argv[14]; */ + /* uint32_t call_id = atoi(argv[15]); */ + /* uint32_t call_state = atoi(argv[16]); */ + + skinny_profile_find_listener_by_device_name_and_instance(helper->tech_pvt->profile, device_name, device_instance, &listener); + if(listener) { + if(!strcmp(device_name, helper->listener->device_name) + && (device_instance == helper->listener->device_instance) + && (line_instance == helper->line_instance)) {/* the answering line */ + + + send_set_ringer(listener, SKINNY_RING_OFF, SKINNY_RING_FOREVER, 0, helper->tech_pvt->call_id); + send_set_speaker_mode(listener, SKINNY_SPEAKER_ON); + send_set_lamp(listener, SKINNY_BUTTON_LINE, line_instance, SKINNY_LAMP_ON); + skinny_line_set_state(listener, line_instance, helper->tech_pvt->call_id, SKINNY_OFF_HOOK); + /* send_select_soft_keys(listener, line_instance, helper->tech_pvt->call_id, SKINNY_KEY_SET_OFF_HOOK, 0xffff); */ + /* display_prompt_status(listener, 0, "\200\000", + line_instance, tech_pvt->call_id); */ + send_activate_call_plane(listener, line_instance); + } + } + return 0; +} + +switch_status_t skinny_session_answer(switch_core_session_t *session, listener_t *listener, uint32_t line_instance) +{ + struct skinny_session_answer_helper helper = {0}; + switch_channel_t *channel = NULL; + private_t *tech_pvt = NULL; + + switch_assert(session); + switch_assert(listener); + switch_assert(listener->profile); + + channel = switch_core_session_get_channel(session); + tech_pvt = switch_core_session_get_private(session); + + helper.tech_pvt = tech_pvt; + helper.listener = listener; + helper.line_instance = line_instance; + + skinny_session_walk_lines(tech_pvt->profile, switch_core_session_get_uuid(session), skinny_session_answer_callback, &helper); + + skinny_session_start_media(session, listener, line_instance); + + switch_core_session_rwunlock(session); - set_ringer(listener, SKINNY_RING_OFF, SKINNY_RING_FOREVER, 0); /* TODO : here ? */ - stop_tone(listener, tech_pvt->line, tech_pvt->call_id); - open_receive_channel(listener, - tech_pvt->call_id, /* uint32_t conference_id, */ - 0, /* uint32_t pass_thru_party_id, */ - 20, /* uint32_t packets, */ - SKINNY_CODEC_ULAW_64K, /* uint32_t payload_capacity, */ - 0, /* uint32_t echo_cancel_type, */ - 0, /* uint32_t g723_bitrate, */ - 0, /* uint32_t conference_id2, */ - 0 /* uint32_t reserved[10] */ - ); - send_call_state(listener, - SKINNY_CONNECTED, - tech_pvt->line, - tech_pvt->call_id); - skinny_line_set_state(listener, tech_pvt->line, SKINNY_KEY_SET_CONNECTED, tech_pvt->call_id); - display_prompt_status(listener, - 0, - "\200\030", - tech_pvt->line, - tech_pvt->call_id); - skinny_send_call_info(session); return SWITCH_STATUS_SUCCESS; } -switch_status_t skinny_hold_line(listener_t *listener, uint32_t line) +switch_status_t skinny_session_start_media(switch_core_session_t *session, listener_t *listener, uint32_t line_instance) { switch_channel_t *channel = NULL; private_t *tech_pvt = NULL; - channel = switch_core_session_get_channel(listener->session[line]); - assert(channel != NULL); + switch_assert(session); + switch_assert(listener); + switch_assert(listener->profile); + + channel = switch_core_session_get_channel(session); + tech_pvt = switch_core_session_get_private(session); + + send_stop_tone(listener, line_instance, tech_pvt->call_id); + send_open_receive_channel(listener, + tech_pvt->call_id, /* uint32_t conference_id, */ + tech_pvt->call_id, /* uint32_t pass_thru_party_id, */ + 20, /* uint32_t packets, */ + SKINNY_CODEC_ULAW_64K, /* uint32_t payload_capacity, */ + 0, /* uint32_t echo_cancel_type, */ + 0, /* uint32_t g723_bitrate, */ + 0, /* uint32_t conference_id2, */ + 0 /* uint32_t reserved[10] */ + ); + skinny_line_set_state(listener, line_instance, tech_pvt->call_id, SKINNY_CONNECTED); + send_select_soft_keys(listener, line_instance, tech_pvt->call_id, + SKINNY_KEY_SET_CONNECTED, 0xffff); + send_display_prompt_status(listener, + 0, + "\200\030", + line_instance, + tech_pvt->call_id); + skinny_send_call_info(session, listener, line_instance); - tech_pvt = switch_core_session_get_private(listener->session[line]); - assert(tech_pvt != NULL); + switch_core_session_rwunlock(session); + + return SWITCH_STATUS_SUCCESS; +} + +switch_status_t skinny_session_hold_line(switch_core_session_t *session, listener_t *listener, uint32_t line_instance) +{ + switch_channel_t *channel = NULL; + private_t *tech_pvt = NULL; + + switch_assert(session); + switch_assert(listener); + switch_assert(listener->profile); + + channel = switch_core_session_get_channel(session); + tech_pvt = switch_core_session_get_private(session); /* TODO */ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Hold is not implemented yet. Hanging up the line.\n"); switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); + switch_core_session_rwunlock(session); + return SWITCH_STATUS_SUCCESS; } -switch_status_t skinny_unhold_line(listener_t *listener, uint32_t line) +switch_status_t skinny_session_unhold_line(switch_core_session_t *session, listener_t *listener, uint32_t line_instance) { /* TODO */ return SWITCH_STATUS_SUCCESS; @@ -516,7 +782,7 @@ void skinny_line_get(listener_t *listener, uint32_t instance, struct line_stat_r switch_assert(listener->device_name); helper.button = switch_core_alloc(listener->pool, sizeof(struct line_stat_res_message)); - + if ((sql = switch_mprintf( "SELECT '%d' AS wanted_position, position, label, value, caller_name " "FROM skinny_lines " @@ -525,7 +791,7 @@ void skinny_line_get(listener_t *listener, uint32_t instance, struct line_stat_r instance, listener->device_name, listener->device_instance ))) { - skinny_execute_sql_callback(listener->profile, listener->profile->listener_mutex, sql, skinny_line_get_callback, &helper); + skinny_execute_sql_callback(listener->profile, listener->profile->sql_mutex, sql, skinny_line_get_callback, &helper); switch_safe_free(sql); } *button = helper.button; @@ -559,7 +825,7 @@ void skinny_speed_dial_get(listener_t *listener, uint32_t instance, struct speed switch_assert(listener->device_name); helper.button = switch_core_alloc(listener->pool, sizeof(struct speed_dial_stat_res_message)); - + if ((sql = switch_mprintf( "SELECT '%d' AS wanted_position, position, label, value, settings " "FROM skinny_buttons " @@ -569,7 +835,7 @@ void skinny_speed_dial_get(listener_t *listener, uint32_t instance, struct speed listener->device_name, listener->device_instance, SKINNY_BUTTON_SPEED_DIAL ))) { - skinny_execute_sql_callback(listener->profile, listener->profile->listener_mutex, sql, skinny_speed_dial_get_callback, &helper); + skinny_execute_sql_callback(listener->profile, listener->profile->sql_mutex, sql, skinny_speed_dial_get_callback, &helper); switch_safe_free(sql); } *button = helper.button; @@ -603,7 +869,7 @@ void skinny_service_url_get(listener_t *listener, uint32_t instance, struct serv switch_assert(listener->device_name); helper.button = switch_core_alloc(listener->pool, sizeof(struct service_url_stat_res_message)); - + if ((sql = switch_mprintf( "SELECT '%d' AS wanted_position, position, label, value, settings " "FROM skinny_buttons " @@ -614,7 +880,7 @@ void skinny_service_url_get(listener_t *listener, uint32_t instance, struct serv listener->device_instance, SKINNY_BUTTON_SERVICE_URL ))) { - skinny_execute_sql_callback(listener->profile, listener->profile->listener_mutex, sql, skinny_service_url_get_callback, &helper); + skinny_execute_sql_callback(listener->profile, listener->profile->sql_mutex, sql, skinny_service_url_get_callback, &helper); switch_safe_free(sql); } *button = helper.button; @@ -649,7 +915,7 @@ void skinny_feature_get(listener_t *listener, uint32_t instance, struct feature_ switch_assert(listener->device_name); helper.button = switch_core_alloc(listener->pool, sizeof(struct feature_stat_res_message)); - + if ((sql = switch_mprintf( "SELECT '%d' AS wanted_position, position, label, value, settings " "FROM skinny_buttons " @@ -660,7 +926,7 @@ void skinny_feature_get(listener_t *listener, uint32_t instance, struct feature_ listener->device_instance, SKINNY_BUTTON_SPEED_DIAL, SKINNY_BUTTON_SERVICE_URL ))) { - skinny_execute_sql_callback(listener->profile, listener->profile->listener_mutex, sql, skinny_feature_get_callback, &helper); + skinny_execute_sql_callback(listener->profile, listener->profile->sql_mutex, sql, skinny_feature_get_callback, &helper); switch_safe_free(sql); } *button = helper.button; @@ -669,7 +935,26 @@ void skinny_feature_get(listener_t *listener, uint32_t instance, struct feature_ /*****************************************************************************/ /* SKINNY MESSAGE SENDER */ /*****************************************************************************/ -switch_status_t start_tone(listener_t *listener, +switch_status_t send_register_ack(listener_t *listener, + uint32_t keep_alive, + char *date_format, + char *reserved, + uint32_t secondary_keep_alive, + char *reserved2) +{ + skinny_message_t *message; + message = switch_core_alloc(listener->pool, 12+sizeof(message->data.reg_ack)); + message->type = REGISTER_ACK_MESSAGE; + message->length = 4 + sizeof(message->data.reg_ack); + message->data.reg_ack.keep_alive = keep_alive; + strncpy(message->data.reg_ack.date_format, date_format, 6); + strncpy(message->data.reg_ack.reserved, reserved, 2); + message->data.reg_ack.secondary_keep_alive = keep_alive; + strncpy(message->data.reg_ack.reserved2, reserved2, 4); + return skinny_send_reply(listener, message); +} + +switch_status_t send_start_tone(listener_t *listener, uint32_t tone, uint32_t reserved, uint32_t line_instance, @@ -683,11 +968,10 @@ switch_status_t start_tone(listener_t *listener, message->data.start_tone.reserved = reserved; message->data.start_tone.line_instance = line_instance; message->data.start_tone.call_id = call_id; - skinny_send_reply(listener, message); - return SWITCH_STATUS_SUCCESS; + return skinny_send_reply(listener, message); } -switch_status_t stop_tone(listener_t *listener, +switch_status_t send_stop_tone(listener_t *listener, uint32_t line_instance, uint32_t call_id) { @@ -697,14 +981,14 @@ switch_status_t stop_tone(listener_t *listener, message->length = 4 + sizeof(message->data.stop_tone); message->data.stop_tone.line_instance = line_instance; message->data.stop_tone.call_id = call_id; - skinny_send_reply(listener, message); - return SWITCH_STATUS_SUCCESS; + return skinny_send_reply(listener, message); } -switch_status_t set_ringer(listener_t *listener, +switch_status_t send_set_ringer(listener_t *listener, uint32_t ring_type, uint32_t ring_mode, - uint32_t unknown) + uint32_t line_instance, + uint32_t call_id) { skinny_message_t *message; message = switch_core_alloc(listener->pool, 12+sizeof(message->data.ringer)); @@ -712,12 +996,12 @@ switch_status_t set_ringer(listener_t *listener, message->length = 4 + sizeof(message->data.ringer); message->data.ringer.ring_type = ring_type; message->data.ringer.ring_mode = ring_mode; - message->data.ringer.unknown = unknown; - skinny_send_reply(listener, message); - return SWITCH_STATUS_SUCCESS; + message->data.ringer.line_instance = line_instance; + message->data.ringer.call_id = call_id; + return skinny_send_reply(listener, message); } -switch_status_t set_lamp(listener_t *listener, +switch_status_t send_set_lamp(listener_t *listener, uint32_t stimulus, uint32_t stimulus_instance, uint32_t mode) @@ -729,11 +1013,10 @@ switch_status_t set_lamp(listener_t *listener, message->data.lamp.stimulus = stimulus; message->data.lamp.stimulus_instance = stimulus_instance; message->data.lamp.mode = mode; - skinny_send_reply(listener, message); - return SWITCH_STATUS_SUCCESS; + return skinny_send_reply(listener, message); } -switch_status_t set_speaker_mode(listener_t *listener, +switch_status_t send_set_speaker_mode(listener_t *listener, uint32_t mode) { skinny_message_t *message; @@ -741,11 +1024,10 @@ switch_status_t set_speaker_mode(listener_t *listener, message->type = SET_SPEAKER_MODE_MESSAGE; message->length = 4 + sizeof(message->data.speaker_mode); message->data.speaker_mode.mode = mode; - skinny_send_reply(listener, message); - return SWITCH_STATUS_SUCCESS; + return skinny_send_reply(listener, message); } -switch_status_t start_media_transmission(listener_t *listener, +switch_status_t send_start_media_transmission(listener_t *listener, uint32_t conference_id, uint32_t pass_thru_party_id, uint32_t remote_ip, @@ -772,11 +1054,10 @@ switch_status_t start_media_transmission(listener_t *listener, message->data.start_media.max_frames_per_packet = max_frames_per_packet; message->data.start_media.g723_bitrate = g723_bitrate; /* ... */ - skinny_send_reply(listener, message); - return SWITCH_STATUS_SUCCESS; + return skinny_send_reply(listener, message); } -switch_status_t stop_media_transmission(listener_t *listener, +switch_status_t send_stop_media_transmission(listener_t *listener, uint32_t conference_id, uint32_t pass_thru_party_id, uint32_t conference_id2) @@ -789,8 +1070,7 @@ switch_status_t stop_media_transmission(listener_t *listener, message->data.stop_media.pass_thru_party_id = pass_thru_party_id; message->data.stop_media.conference_id2 = conference_id2; /* ... */ - skinny_send_reply(listener, message); - return SWITCH_STATUS_SUCCESS; + return skinny_send_reply(listener, message); } switch_status_t send_call_info(listener_t *listener, @@ -819,31 +1099,95 @@ switch_status_t send_call_info(listener_t *listener, message = switch_core_alloc(listener->pool, 12+sizeof(message->data.call_info)); message->type = CALL_INFO_MESSAGE; message->length = 4 + sizeof(message->data.call_info); - strcpy(message->data.call_info.calling_party_name, calling_party_name); - strcpy(message->data.call_info.calling_party, calling_party); - strcpy(message->data.call_info.called_party_name, called_party_name); - strcpy(message->data.call_info.called_party, called_party); + strncpy(message->data.call_info.calling_party_name, calling_party_name, 40); + strncpy(message->data.call_info.calling_party, calling_party, 24); + strncpy(message->data.call_info.called_party_name, called_party_name, 40); + strncpy(message->data.call_info.called_party, called_party, 24); message->data.call_info.line_instance = line_instance; message->data.call_info.call_id = call_id; message->data.call_info.call_type = call_type; - strcpy(message->data.call_info.original_called_party_name, original_called_party_name); - strcpy(message->data.call_info.original_called_party, original_called_party); - strcpy(message->data.call_info.last_redirecting_party_name, last_redirecting_party_name); - strcpy(message->data.call_info.last_redirecting_party, last_redirecting_party); + strncpy(message->data.call_info.original_called_party_name, original_called_party_name, 40); + strncpy(message->data.call_info.original_called_party, original_called_party, 24); + strncpy(message->data.call_info.last_redirecting_party_name, last_redirecting_party_name, 40); + strncpy(message->data.call_info.last_redirecting_party, last_redirecting_party, 24); message->data.call_info.original_called_party_redirect_reason = original_called_party_redirect_reason; message->data.call_info.last_redirecting_reason = last_redirecting_reason; - strcpy(message->data.call_info.calling_party_voice_mailbox, calling_party_voice_mailbox); - strcpy(message->data.call_info.called_party_voice_mailbox, called_party_voice_mailbox); - strcpy(message->data.call_info.original_called_party_voice_mailbox, original_called_party_voice_mailbox); - strcpy(message->data.call_info.last_redirecting_voice_mailbox, last_redirecting_voice_mailbox); + strncpy(message->data.call_info.calling_party_voice_mailbox, calling_party_voice_mailbox, 24); + strncpy(message->data.call_info.called_party_voice_mailbox, called_party_voice_mailbox, 24); + strncpy(message->data.call_info.original_called_party_voice_mailbox, original_called_party_voice_mailbox, 24); + strncpy(message->data.call_info.last_redirecting_voice_mailbox, last_redirecting_voice_mailbox, 24); message->data.call_info.call_instance = call_instance; message->data.call_info.call_security_status = call_security_status; message->data.call_info.party_pi_restriction_bits = party_pi_restriction_bits; - skinny_send_reply(listener, message); - return SWITCH_STATUS_SUCCESS; + return skinny_send_reply(listener, message); } -switch_status_t open_receive_channel(listener_t *listener, +switch_status_t send_define_time_date(listener_t *listener, + uint32_t year, + uint32_t month, + uint32_t day_of_week, /* monday = 1 */ + uint32_t day, + uint32_t hour, + uint32_t minute, + uint32_t seconds, + uint32_t milliseconds, + uint32_t timestamp) +{ + skinny_message_t *message; + message = switch_core_alloc(listener->pool, 12+sizeof(message->data.define_time_date)); + message->type = DEFINE_TIME_DATE_MESSAGE; + message->length = 4+sizeof(message->data.define_time_date); + message->data.define_time_date.year = year; + message->data.define_time_date.month = month; + message->data.define_time_date.day_of_week = day_of_week; + message->data.define_time_date.day = day; + message->data.define_time_date.hour = hour; + message->data.define_time_date.minute = minute; + message->data.define_time_date.seconds = seconds; + message->data.define_time_date.milliseconds = milliseconds; + message->data.define_time_date.timestamp = timestamp; + return skinny_send_reply(listener, message); +} + +switch_status_t send_define_current_time_date(listener_t *listener) +{ + switch_time_t ts; + switch_time_exp_t tm; + ts = switch_micro_time_now(); + switch_time_exp_lt(&tm, ts); + return send_define_time_date(listener, + tm.tm_year + 1900, + tm.tm_mon + 1, + tm.tm_wday, + tm.tm_yday + 1, + tm.tm_hour, + tm.tm_min, + tm.tm_sec + 1, + tm.tm_usec / 1000, + ts / 1000000); +} + +switch_status_t send_capabilities_req(listener_t *listener) +{ + skinny_message_t *message; + message = switch_core_alloc(listener->pool, 12); + message->type = CAPABILITIES_REQ_MESSAGE; + message->length = 4; + return skinny_send_reply(listener, message); +} + +switch_status_t send_register_reject(listener_t *listener, + char *error) +{ + skinny_message_t *message; + message = switch_core_alloc(listener->pool, 12+sizeof(message->data.reg_rej)); + message->type = REGISTER_REJECT_MESSAGE; + message->length = 4 + sizeof(message->data.reg_rej); + strncpy(message->data.reg_rej.error, error, 33); + return skinny_send_reply(listener, message); +} + +switch_status_t send_open_receive_channel(listener_t *listener, uint32_t conference_id, uint32_t pass_thru_party_id, uint32_t packets, @@ -876,11 +1220,10 @@ switch_status_t open_receive_channel(listener_t *listener, message->data.open_receive_channel.reserved[8] = reserved[8]; message->data.open_receive_channel.reserved[9] = reserved[9]; */ - skinny_send_reply(listener, message); - return SWITCH_STATUS_SUCCESS; + return skinny_send_reply(listener, message); } -switch_status_t close_receive_channel(listener_t *listener, +switch_status_t send_close_receive_channel(listener_t *listener, uint32_t conference_id, uint32_t pass_thru_party_id, uint32_t conference_id2) @@ -892,8 +1235,7 @@ switch_status_t close_receive_channel(listener_t *listener, message->data.close_receive_channel.conference_id = conference_id; message->data.close_receive_channel.pass_thru_party_id = pass_thru_party_id; message->data.close_receive_channel.conference_id2 = conference_id2; - skinny_send_reply(listener, message); - return SWITCH_STATUS_SUCCESS; + return skinny_send_reply(listener, message); } switch_status_t send_select_soft_keys(listener_t *listener, @@ -910,8 +1252,7 @@ switch_status_t send_select_soft_keys(listener_t *listener, message->data.select_soft_keys.call_id = call_id; message->data.select_soft_keys.soft_key_set = soft_key_set; message->data.select_soft_keys.valid_key_mask = valid_key_mask; - skinny_send_reply(listener, message); - return SWITCH_STATUS_SUCCESS; + return skinny_send_reply(listener, message); } switch_status_t send_call_state(listener_t *listener, @@ -926,11 +1267,10 @@ switch_status_t send_call_state(listener_t *listener, message->data.call_state.call_state = call_state; message->data.call_state.line_instance = line_instance; message->data.call_state.call_id = call_id; - skinny_send_reply(listener, message); - return SWITCH_STATUS_SUCCESS; + return skinny_send_reply(listener, message); } -switch_status_t display_prompt_status(listener_t *listener, +switch_status_t send_display_prompt_status(listener_t *listener, uint32_t timeout, char display[32], uint32_t line_instance, @@ -941,14 +1281,13 @@ switch_status_t display_prompt_status(listener_t *listener, message->type = DISPLAY_PROMPT_STATUS_MESSAGE; message->length = 4 + sizeof(message->data.display_prompt_status); message->data.display_prompt_status.timeout = timeout; - strcpy(message->data.display_prompt_status.display, display); + strncpy(message->data.display_prompt_status.display, display, 32); message->data.display_prompt_status.line_instance = line_instance; message->data.display_prompt_status.call_id = call_id; - skinny_send_reply(listener, message); - return SWITCH_STATUS_SUCCESS; + return skinny_send_reply(listener, message); } -switch_status_t clear_prompt_status(listener_t *listener, +switch_status_t send_clear_prompt_status(listener_t *listener, uint32_t line_instance, uint32_t call_id) { @@ -958,11 +1297,10 @@ switch_status_t clear_prompt_status(listener_t *listener, message->length = 4 + sizeof(message->data.clear_prompt_status); message->data.clear_prompt_status.line_instance = line_instance; message->data.clear_prompt_status.call_id = call_id; - skinny_send_reply(listener, message); - return SWITCH_STATUS_SUCCESS; + return skinny_send_reply(listener, message); } -switch_status_t activate_call_plane(listener_t *listener, +switch_status_t send_activate_call_plane(listener_t *listener, uint32_t line_instance) { skinny_message_t *message; @@ -970,8 +1308,7 @@ switch_status_t activate_call_plane(listener_t *listener, message->type = ACTIVATE_CALL_PLANE_MESSAGE; message->length = 4 + sizeof(message->data.activate_call_plane); message->data.activate_call_plane.line_instance = line_instance; - skinny_send_reply(listener, message); - return SWITCH_STATUS_SUCCESS; + return skinny_send_reply(listener, message); } switch_status_t send_dialed_number(listener_t *listener, @@ -983,23 +1320,36 @@ switch_status_t send_dialed_number(listener_t *listener, message = switch_core_alloc(listener->pool, 12+sizeof(message->data.dialed_number)); message->type = DIALED_NUMBER_MESSAGE; message->length = 4 + sizeof(message->data.dialed_number); - strcpy(message->data.dialed_number.called_party, called_party); + strncpy(message->data.dialed_number.called_party, called_party, 24); message->data.dialed_number.line_instance = line_instance; message->data.dialed_number.call_id = call_id; - skinny_send_reply(listener, message); - return SWITCH_STATUS_SUCCESS; + return skinny_send_reply(listener, message); } -switch_status_t send_reset(listener_t *listener, - uint32_t reset_type) +switch_status_t send_display_pri_notify(listener_t *listener, + uint32_t message_timeout, + uint32_t priority, + char *notify) +{ + skinny_message_t *message; + message = switch_core_alloc(listener->pool, 12+sizeof(message->data.display_pri_notify)); + message->type = DISPLAY_PRI_NOTIFY_MESSAGE; + message->length = 4 + sizeof(message->data.display_pri_notify); + message->data.display_pri_notify.message_timeout = message_timeout; + message->data.display_pri_notify.priority = priority; + strncpy(message->data.display_pri_notify.notify, notify, 32); + return skinny_send_reply(listener, message); +} + + +switch_status_t send_reset(listener_t *listener, uint32_t reset_type) { skinny_message_t *message; message = switch_core_alloc(listener->pool, 12+sizeof(message->data.reset)); message->type = RESET_MESSAGE; message->length = 4 + sizeof(message->data.reset); message->data.reset.reset_type = reset_type; - skinny_send_reply(listener, message); - return SWITCH_STATUS_SUCCESS; + return skinny_send_reply(listener, message); } /* Message handling */ @@ -1020,14 +1370,13 @@ switch_status_t skinny_handle_alarm(listener_t *listener, skinny_message_t *requ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-Alarm-Param1", "%d", request->data.alarm.alarm_param1); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-Alarm-Param2", "%d", request->data.alarm.alarm_param2); switch_event_fire(&event); - + return SWITCH_STATUS_SUCCESS; } switch_status_t skinny_handle_register(listener_t *listener, skinny_message_t *request) { switch_status_t status = SWITCH_STATUS_FALSE; - skinny_message_t *message; skinny_profile_t *profile; switch_event_t *event = NULL; switch_event_t *params = NULL; @@ -1041,11 +1390,7 @@ switch_status_t skinny_handle_register(listener_t *listener, skinny_message_t *r if(!zstr(listener->device_name)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "A device is already registred on this listener.\n"); - message = switch_core_alloc(listener->pool, 12+sizeof(message->data.reg_rej)); - message->type = REGISTER_REJ_MESSAGE; - message->length = 4 + sizeof(message->data.reg_rej); - strcpy(message->data.reg_rej.error, "A device is already registred on this listener"); - skinny_send_reply(listener, message); + send_register_reject(listener, "A device is already registred on this listener"); return SWITCH_STATUS_FALSE; } @@ -1057,11 +1402,7 @@ switch_status_t skinny_handle_register(listener_t *listener, skinny_message_t *r switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Can't find device [%s@%s]\n" "You must define a domain called '%s' in your directory and add a user with id=\"%s\".\n" , request->data.reg.device_name, profile->domain, profile->domain, request->data.reg.device_name); - message = switch_core_alloc(listener->pool, 12+sizeof(message->data.reg_rej)); - message->type = REGISTER_REJ_MESSAGE; - message->length = 4 + sizeof(message->data.reg_rej); - strcpy(message->data.reg_rej.error, "Device not found"); - skinny_send_reply(listener, message); + send_register_reject(listener, "Device not found"); status = SWITCH_STATUS_FALSE; goto end; } @@ -1078,18 +1419,19 @@ switch_status_t skinny_handle_register(listener_t *listener, skinny_message_t *r request->data.reg.max_streams, "" /* codec_string */ ))) { - skinny_execute_sql(profile, sql, profile->listener_mutex); + skinny_execute_sql(profile, sql, profile->sql_mutex); switch_safe_free(sql); } - strcpy(listener->device_name, request->data.reg.device_name); + strncpy(listener->device_name, request->data.reg.device_name, 16); listener->device_instance = request->data.reg.instance; xskinny = switch_xml_child(xuser, "skinny"); if (xskinny) { xbuttons = switch_xml_child(xskinny, "buttons"); if (xbuttons) { + uint32_t line_instance = 1; for (xbutton = switch_xml_child(xbuttons, "button"); xbutton; xbutton = xbutton->next) { uint32_t position = atoi(switch_xml_attr_soft(xbutton, "position")); uint32_t type = skinny_str2button(switch_xml_attr_soft(xbutton, "type")); @@ -1106,16 +1448,16 @@ switch_status_t skinny_handle_register(listener_t *listener, skinny_message_t *r uint32_t noanswer_duration = atoi(switch_xml_attr_soft(xbutton, "noanswer-duration")); if ((sql = switch_mprintf( "INSERT INTO skinny_lines " - "(device_name, device_instance, position, " + "(device_name, device_instance, position, line_instance, " "label, value, caller_name, " "ring_on_idle, ring_on_active, busy_trigger, " - "forward_all, forward_busy, forward_noanswer, noanswer_duration) " - "VALUES('%s', %d, %d, '%s', '%s', '%s', %d, %d, %d, '%s', '%s', '%s', %d)", - request->data.reg.device_name, request->data.reg.instance, position, + "forward_all, forward_busy, forward_noanswer, noanswer_duration) " + "VALUES('%s', %d, %d, %d, '%s', '%s', '%s', %d, %d, %d, '%s', '%s', '%s', %d)", + request->data.reg.device_name, request->data.reg.instance, position, line_instance++, label, value, caller_name, ring_on_idle, ring_on_active, busy_trigger, - forward_all, forward_busy, forward_noanswer, noanswer_duration))) { - skinny_execute_sql(profile, sql, profile->listener_mutex); + forward_all, forward_busy, forward_noanswer, noanswer_duration))) { + skinny_execute_sql(profile, sql, profile->sql_mutex); switch_safe_free(sql); } } else { @@ -1131,7 +1473,7 @@ switch_status_t skinny_handle_register(listener_t *listener, skinny_message_t *r label, value, settings))) { - skinny_execute_sql(profile, sql, profile->listener_mutex); + skinny_execute_sql(profile, sql, profile->sql_mutex); switch_safe_free(sql); } } @@ -1142,38 +1484,29 @@ switch_status_t skinny_handle_register(listener_t *listener, skinny_message_t *r status = SWITCH_STATUS_SUCCESS; /* Reply with RegisterAckMessage */ - message = switch_core_alloc(listener->pool, 12+sizeof(message->data.reg_ack)); - message->type = REGISTER_ACK_MESSAGE; - message->length = 4 + sizeof(message->data.reg_ack); - message->data.reg_ack.keepAlive = profile->keep_alive; - memcpy(message->data.reg_ack.dateFormat, profile->date_format, 6); - message->data.reg_ack.secondaryKeepAlive = profile->keep_alive; - skinny_send_reply(listener, message); + send_register_ack(listener, profile->keep_alive, profile->date_format, "", profile->keep_alive, ""); /* Send CapabilitiesReqMessage */ - message = switch_core_alloc(listener->pool, 12); - message->type = CAPABILITIES_REQ_MESSAGE; - message->length = 4; - skinny_send_reply(listener, message); + send_capabilities_req(listener); /* skinny::register event */ skinny_device_event(listener, &event, SWITCH_EVENT_CUSTOM, SKINNY_EVENT_REGISTER); switch_event_fire(&event); - + keepalive_listener(listener, NULL); end: if(params) { switch_event_destroy(¶ms); } - + return status; } switch_status_t skinny_headset_status_message(listener_t *listener, skinny_message_t *request) { skinny_check_data_length(request, sizeof(request->data.headset_status)); - + /* Nothing to do */ return SWITCH_STATUS_SUCCESS; } @@ -1188,12 +1521,12 @@ int skinny_config_stat_res_callback(void *pArg, int argc, char **argv, char **co char *server_name = argv[4]; int number_lines = atoi(argv[5]); int number_speed_dials = atoi(argv[6]); - - strcpy(message->data.config_res.device_name, device_name); + + strncpy(message->data.config_res.device_name, device_name, 16); message->data.config_res.user_id = user_id; message->data.config_res.instance = instance; - strcpy(message->data.config_res.user_name, user_name); - strcpy(message->data.config_res.server_name, server_name); + strncpy(message->data.config_res.user_name, user_name, 40); + strncpy(message->data.config_res.server_name, server_name, 40); message->data.config_res.number_lines = number_lines; message->data.config_res.number_speed_dials = number_speed_dials; @@ -1227,7 +1560,7 @@ switch_status_t skinny_handle_config_stat_request(listener_t *listener, skinny_m SKINNY_BUTTON_SPEED_DIAL, listener->device_name ))) { - skinny_execute_sql_callback(profile, profile->listener_mutex, sql, skinny_config_stat_res_callback, message); + skinny_execute_sql_callback(profile, profile->sql_mutex, sql, skinny_config_stat_res_callback, message); switch_safe_free(sql); } skinny_send_reply(listener, message); @@ -1244,7 +1577,7 @@ switch_status_t skinny_handle_capabilities_response(listener_t *listener, skinny uint32_t n = 0; char *codec_order[SWITCH_MAX_CODECS]; char *codec_string; - + size_t string_len, string_pos, pos; switch_assert(listener->profile); @@ -1287,10 +1620,10 @@ switch_status_t skinny_handle_capabilities_response(listener_t *listener, skinny codec_string, listener->device_name ))) { - skinny_execute_sql(profile, sql, profile->listener_mutex); + skinny_execute_sql(profile, sql, profile->sql_mutex); switch_safe_free(sql); } - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Codecs %s supported.\n", codec_string); return SWITCH_STATUS_SUCCESS; } @@ -1309,11 +1642,11 @@ switch_status_t skinny_handle_port_message(listener_t *listener, skinny_message_ if ((sql = switch_mprintf( "UPDATE skinny_devices SET port=%d WHERE name='%s' and instance=%d", - request->data.as_uint16, + request->data.port.port, listener->device_name, listener->device_instance ))) { - skinny_execute_sql(profile, sql, profile->listener_mutex); + skinny_execute_sql(profile, sql, profile->sql_mutex); switch_safe_free(sql); } return SWITCH_STATUS_SUCCESS; @@ -1366,7 +1699,7 @@ switch_status_t skinny_handle_button_template_request(listener_t *listener, skin message->data.button_template.button_offset = 0; message->data.button_template.button_count = 0; message->data.button_template.total_button_count = 0; - + helper.message = message; /* Add buttons */ @@ -1378,10 +1711,10 @@ switch_status_t skinny_handle_button_template_request(listener_t *listener, skin SKINNY_BUTTON_UNDEFINED, listener->device_name, listener->device_instance ))) { - skinny_execute_sql_callback(profile, profile->listener_mutex, sql, skinny_handle_button_template_request_callback, &helper); + skinny_execute_sql_callback(profile, profile->sql_mutex, sql, skinny_handle_button_template_request_callback, &helper); switch_safe_free(sql); } - + /* Add lines */ if ((sql = switch_mprintf( "SELECT device_name, device_instance, position, %d AS type " @@ -1391,10 +1724,10 @@ switch_status_t skinny_handle_button_template_request(listener_t *listener, skin SKINNY_BUTTON_LINE, listener->device_name, listener->device_instance ))) { - skinny_execute_sql_callback(profile, profile->listener_mutex, sql, skinny_handle_button_template_request_callback, &helper); + skinny_execute_sql_callback(profile, profile->sql_mutex, sql, skinny_handle_button_template_request_callback, &helper); switch_safe_free(sql); } - + /* Fill remaining buttons with Undefined */ for(int i = 0; i+1 < helper.max_position; i++) { if(message->data.button_template.btn[i].button_definition == SKINNY_BUTTON_UNKNOWN) { @@ -1427,11 +1760,11 @@ switch_status_t skinny_handle_soft_key_template_request(listener_t *listener, sk message->data.soft_key_template.soft_key_offset = 0; message->data.soft_key_template.soft_key_count = 21; message->data.soft_key_template.total_soft_key_count = 21; - + memcpy(message->data.soft_key_template.soft_key, soft_key_template_default, sizeof(soft_key_template_default)); - + skinny_send_reply(listener, message); return SWITCH_STATUS_SUCCESS; @@ -1454,7 +1787,7 @@ switch_status_t skinny_handle_soft_key_set_request(listener_t *listener, skinny_ message->data.soft_key_set.soft_key_set_offset = 0; message->data.soft_key_set.soft_key_set_count = 11; message->data.soft_key_set.total_soft_key_set_count = 11; - + /* TODO fill the set */ message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOOK].soft_key_template_index[0] = SOFTKEY_REDIAL; message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOOK].soft_key_template_index[1] = SOFTKEY_NEWCALL; @@ -1464,8 +1797,8 @@ switch_status_t skinny_handle_soft_key_set_request(listener_t *listener, skinny_ skinny_send_reply(listener, message); /* Init the states */ - skinny_line_set_state(listener, 0, SKINNY_KEY_SET_ON_HOOK, 0); - + send_select_soft_keys(listener, 0, 0, SKINNY_KEY_SET_ON_HOOK, 0xffff); + return SWITCH_STATUS_SUCCESS; } @@ -1479,7 +1812,7 @@ switch_status_t skinny_handle_line_stat_request(listener_t *listener, skinny_mes message = switch_core_alloc(listener->pool, 12+sizeof(message->data.line_res)); message->type = LINE_STAT_RES_MESSAGE; message->length = 4 + sizeof(message->data.line_res); - + skinny_line_get(listener, request->data.line_req.number, &button); memcpy(&message->data.line_res, button, sizeof(struct line_stat_res_message)); @@ -1499,7 +1832,7 @@ switch_status_t skinny_handle_speed_dial_stat_request(listener_t *listener, skin message = switch_core_alloc(listener->pool, 12+sizeof(message->data.speed_dial_res)); message->type = SPEED_DIAL_STAT_RES_MESSAGE; message->length = 4 + sizeof(message->data.speed_dial_res); - + skinny_speed_dial_get(listener, request->data.speed_dial_req.number, &button); memcpy(&message->data.speed_dial_res, button, sizeof(struct speed_dial_stat_res_message)); @@ -1519,7 +1852,7 @@ switch_status_t skinny_handle_service_url_stat_request(listener_t *listener, ski message = switch_core_alloc(listener->pool, 12+sizeof(message->data.service_url_res)); message->type = SERVICE_URL_STAT_RES_MESSAGE; message->length = 4 + sizeof(message->data.service_url_res); - + skinny_service_url_get(listener, request->data.service_url_req.service_url_index, &button); memcpy(&message->data.service_url_res, button, sizeof(struct service_url_stat_res_message)); @@ -1539,7 +1872,7 @@ switch_status_t skinny_handle_feature_stat_request(listener_t *listener, skinny_ message = switch_core_alloc(listener->pool, 12+sizeof(message->data.feature_res)); message->type = FEATURE_STAT_RES_MESSAGE; message->length = 4 + sizeof(message->data.feature_res); - + skinny_feature_get(listener, request->data.feature_req.feature_index, &button); memcpy(&message->data.feature_res, button, sizeof(struct feature_stat_res_message)); @@ -1559,26 +1892,7 @@ switch_status_t skinny_handle_register_available_lines_message(listener_t *liste switch_status_t skinny_handle_time_date_request(listener_t *listener, skinny_message_t *request) { - skinny_message_t *message; - switch_time_t ts; - switch_time_exp_t tm; - - message = switch_core_alloc(listener->pool, 12+sizeof(message->data.define_time_date)); - message->type = DEFINE_TIME_DATE_MESSAGE; - message->length = 4+sizeof(message->data.define_time_date); - ts = switch_micro_time_now(); - switch_time_exp_lt(&tm, ts); - message->data.define_time_date.year = tm.tm_year + 1900; - message->data.define_time_date.month = tm.tm_mon + 1; - message->data.define_time_date.day_of_week = tm.tm_wday; - message->data.define_time_date.day = tm.tm_yday + 1; - message->data.define_time_date.hour = tm.tm_hour; - message->data.define_time_date.minute = tm.tm_min; - message->data.define_time_date.seconds = tm.tm_sec + 1; - message->data.define_time_date.milliseconds = tm.tm_usec / 1000; - message->data.define_time_date.timestamp = ts / 1000000; - skinny_send_reply(listener, message); - return SWITCH_STATUS_SUCCESS; + return send_define_current_time_date(listener); } switch_status_t skinny_handle_keep_alive_message(listener_t *listener, skinny_message_t *request) @@ -1596,173 +1910,128 @@ switch_status_t skinny_handle_keep_alive_message(listener_t *listener, skinny_me switch_status_t skinny_handle_soft_key_event_message(listener_t *listener, skinny_message_t *request) { switch_status_t status = SWITCH_STATUS_SUCCESS; - - skinny_profile_t *profile; + uint32_t line_instance = 0; + switch_core_session_t *session = NULL; switch_channel_t *channel = NULL; - uint32_t line; private_t *tech_pvt = NULL; - + switch_assert(listener); switch_assert(listener->profile); - switch_assert(listener->device_name); - - profile = listener->profile; - + skinny_check_data_length(request, sizeof(request->data.soft_key_event)); - if(request->data.soft_key_event.line_instance) { - line = request->data.soft_key_event.line_instance; - } else { - line = 1; - } - /* Close/Hold busy lines */ - for(int i = 0 ; i < SKINNY_MAX_BUTTON_COUNT ; i++) { - if(i == line) { - continue; - } - if(listener->session[i]) { - channel = switch_core_session_get_channel(listener->session[i]); - assert(channel != NULL); - if((skinny_line_get_state(listener, i) == SKINNY_KEY_SET_ON_HOOK) - || (skinny_line_get_state(listener, i) == SKINNY_KEY_SET_OFF_HOOK) - || (skinny_line_get_state(listener, i) == SKINNY_KEY_SET_RING_OUT) - || (skinny_line_get_state(listener, i) == SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT) - || (skinny_line_get_state(listener, i) == SKINNY_KEY_SET_OFF_HOOK_WITH_FEATURES)) { + line_instance = request->data.soft_key_event.line_instance; - switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); - channel = NULL; - } else if((skinny_line_get_state(listener, i) == SKINNY_KEY_SET_RING_IN) - || (skinny_line_get_state(listener, i) == SKINNY_KEY_SET_CONNECTED) - || (skinny_line_get_state(listener, i) == SKINNY_KEY_SET_CONNECTED_WITH_TRANSFER) - || (skinny_line_get_state(listener, i) == SKINNY_KEY_SET_CONNECTED_WITH_CONFERENCE)) { - skinny_hold_line(listener, i); - } /* remaining: SKINNY_KEY_SET_ON_HOLD */ - } - } - - if(!listener->session[line]) { /*the line is not busy */ - switch(request->data.soft_key_event.event) { - case SOFTKEY_REDIAL: - skinny_create_session(listener, line, SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT); - - tech_pvt = switch_core_session_get_private(listener->session[line]); - assert(tech_pvt != NULL); - - strcpy(tech_pvt->dest, "redial"); - skinny_process_dest(listener, line); - break; - case SOFTKEY_NEWCALL: - skinny_create_session(listener, line, SKINNY_KEY_SET_OFF_HOOK); - break; - default: - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, - "Unknown SoftKeyEvent type while not busy: %d.\n", request->data.soft_key_event.event); - } - } else { /* the line is busy */ - if(skinny_line_get_state(listener, line) == SKINNY_KEY_SET_ON_HOLD) { - skinny_unhold_line(listener, line); - } - switch(request->data.soft_key_event.event) { - case SOFTKEY_ANSWER: - skinny_answer(listener->session[line]); - break; - case SOFTKEY_ENDCALL: - channel = switch_core_session_get_channel(listener->session[line]); - assert(channel != NULL); + switch(request->data.soft_key_event.event) { + case SOFTKEY_REDIAL: + status = skinny_create_ingoing_session(listener, &line_instance, &session); - switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); + skinny_session_process_dest(session, listener, line_instance, "redial", '\0', 0); + break; + case SOFTKEY_NEWCALL: + status = skinny_create_ingoing_session(listener, &line_instance, &session); + tech_pvt = switch_core_session_get_private(session); + assert(tech_pvt != NULL); - break; - default: - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, - "Unknown SoftKeyEvent type while busy: %d.\n", request->data.soft_key_event.event); - } + skinny_session_process_dest(session, listener, line_instance, NULL, '\0', 0); + break; + case SOFTKEY_HOLD: + session = skinny_profile_find_session(listener->profile, listener, &line_instance, request->data.soft_key_event.call_id); + + if(session) { + status = skinny_session_hold_line(session, listener, line_instance); + } + break; + case SOFTKEY_ENDCALL: + session = skinny_profile_find_session(listener->profile, listener, &line_instance, request->data.soft_key_event.call_id); + + if(session) { + channel = switch_core_session_get_channel(session); + + switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); + } + break; + case SOFTKEY_RESUME: + session = skinny_profile_find_session(listener->profile, listener, &line_instance, request->data.soft_key_event.call_id); + + if(session) { + status = skinny_session_unhold_line(session, listener, line_instance); + } + break; + case SOFTKEY_ANSWER: + session = skinny_profile_find_session(listener->profile, listener, &line_instance, request->data.soft_key_event.call_id); + + if(session) { + status = skinny_session_answer(session, listener, line_instance); + } + break; + default: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, + "Unknown SoftKeyEvent type while busy: %d.\n", request->data.soft_key_event.event); } + + if(session) { + switch_core_session_rwunlock(session); + } + return status; } switch_status_t skinny_handle_off_hook_message(listener_t *listener, skinny_message_t *request) { - skinny_profile_t *profile; - uint32_t line; - - switch_assert(listener->profile); - switch_assert(listener->device_name); - - profile = listener->profile; + uint32_t line_instance; + switch_core_session_t *session = NULL; + private_t *tech_pvt = NULL; skinny_check_data_length(request, sizeof(request->data.off_hook)); - if(request->data.off_hook.line_instance) { - line = request->data.off_hook.line_instance; + if(request->data.off_hook.line_instance > 0) { + line_instance = request->data.off_hook.line_instance; } else { - line = 1; + line_instance = 1; } - if(listener->session[line]) { /*answering a call */ - skinny_answer(listener->session[line]); + + session = skinny_profile_find_session(listener->profile, listener, &line_instance, request->data.off_hook.call_id); + + if(session) { /*answering a call */ + skinny_session_answer(session, listener, line_instance); } else { /* start a new call */ - skinny_create_session(listener, line, SKINNY_KEY_SET_OFF_HOOK); + skinny_create_ingoing_session(listener, &line_instance, &session); + tech_pvt = switch_core_session_get_private(session); + assert(tech_pvt != NULL); + + skinny_session_process_dest(session, listener, line_instance, NULL, '\0', 0); } return SWITCH_STATUS_SUCCESS; } switch_status_t skinny_handle_stimulus_message(listener_t *listener, skinny_message_t *request) { - skinny_profile_t *profile; struct speed_dial_stat_res_message *button = NULL; - uint32_t line = 0; - private_t *tech_pvt = NULL; + uint32_t line_instance = 0; + uint32_t call_id = 0; + switch_core_session_t *session = NULL; - switch_assert(listener->profile); - switch_assert(listener->device_name); + skinny_check_data_length(request, sizeof(request->data.stimulus)-sizeof(request->data.stimulus.call_id)); - profile = listener->profile; - - skinny_check_data_length(request, sizeof(request->data.stimulus)); - - if(request->data.stimulus.instance_type == SKINNY_BUTTON_LINE) {/* Choose the specified line */ - line = request->data.stimulus.instance; - } - if(line == 0) {/* If none, find the first busy line */ - for(int i = 0 ; i < SKINNY_MAX_BUTTON_COUNT ; i++) { - if(listener->session[i]) { - line = i; - break; - } - } - } - if(line == 0) {/* If none, choose the first line */ - line = 1; + if(skinny_check_data_length_soft(request, sizeof(request->data.stimulus))) { + call_id = request->data.stimulus.call_id; } + switch(request->data.stimulus.instance_type) { case SKINNY_BUTTON_LAST_NUMBER_REDIAL: - skinny_create_session(listener, line, SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT); - - tech_pvt = switch_core_session_get_private(listener->session[line]); - assert(tech_pvt != NULL); - - strcpy(tech_pvt->dest, "redial"); - skinny_process_dest(listener, line); + skinny_create_ingoing_session(listener, &line_instance, &session); + skinny_session_process_dest(session, listener, line_instance, "redial", '\0', 0); break; case SKINNY_BUTTON_VOICEMAIL: - skinny_create_session(listener, line, SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT); - - tech_pvt = switch_core_session_get_private(listener->session[line]); - assert(tech_pvt != NULL); - - strcpy(tech_pvt->dest, "vmain"); - skinny_process_dest(listener, line); + skinny_create_ingoing_session(listener, &line_instance, &session); + skinny_session_process_dest(session, listener, line_instance, "vmain", '\0', 0); break; case SKINNY_BUTTON_SPEED_DIAL: skinny_speed_dial_get(listener, request->data.stimulus.instance, &button); if(strlen(button->line) > 0) { - skinny_create_session(listener, line, SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT); - - tech_pvt = switch_core_session_get_private(listener->session[line]); - assert(tech_pvt != NULL); - - strcpy(tech_pvt->dest, button->line); - skinny_process_dest(listener, line); + skinny_create_ingoing_session(listener, &line_instance, &session); + skinny_session_process_dest(session, listener, line_instance, button->line, '\0', 0); } break; default: @@ -1774,35 +2043,21 @@ switch_status_t skinny_handle_stimulus_message(listener_t *listener, skinny_mess switch_status_t skinny_handle_open_receive_channel_ack_message(listener_t *listener, skinny_message_t *request) { switch_status_t status = SWITCH_STATUS_SUCCESS; - skinny_profile_t *profile; - uint32_t line = 0; - - switch_assert(listener->profile); - switch_assert(listener->device_name); - - profile = listener->profile; + uint32_t line_instance = 0; + switch_core_session_t *session; skinny_check_data_length(request, sizeof(request->data.open_receive_channel_ack)); - for(int i = 0 ; i < SKINNY_MAX_BUTTON_COUNT ; i++) { - if(listener->session[i]) { - private_t *tech_pvt = NULL; - tech_pvt = switch_core_session_get_private(listener->session[i]); - - if(tech_pvt->party_id == request->data.open_receive_channel_ack.pass_thru_party_id) { - line = i; - } - } - } + session = skinny_profile_find_session(listener->profile, listener, &line_instance, request->data.open_receive_channel_ack.pass_thru_party_id); - if(listener->session[line]) { + if(session) { const char *err = NULL; private_t *tech_pvt = NULL; switch_channel_t *channel = NULL; struct in_addr addr; - tech_pvt = switch_core_session_get_private(listener->session[line]); - channel = switch_core_session_get_channel(listener->session[line]); + tech_pvt = switch_core_session_get_private(session); + channel = switch_core_session_get_channel(session); /* Codec */ tech_pvt->iananame = "PCMU"; /* TODO */ @@ -1810,18 +2065,18 @@ switch_status_t skinny_handle_open_receive_channel_ack_message(listener_t *liste tech_pvt->rm_rate = 8000; /* TODO */ tech_pvt->rm_fmtp = NULL; /* TODO */ tech_pvt->agreed_pt = (switch_payload_t) 0; /* TODO */ - tech_pvt->rm_encoding = switch_core_strdup(switch_core_session_get_pool(listener->session[line]), ""); + tech_pvt->rm_encoding = switch_core_strdup(switch_core_session_get_pool(session), ""); skinny_tech_set_codec(tech_pvt, 0); if ((status = skinny_tech_set_codec(tech_pvt, 0)) != SWITCH_STATUS_SUCCESS) { goto end; } - + /* Request a local port from the core's allocator */ if (!(tech_pvt->local_sdp_audio_port = switch_rtp_request_port(listener->profile->ip))) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_CRIT, "No RTP ports available!\n"); return SWITCH_STATUS_FALSE; } - tech_pvt->local_sdp_audio_ip = switch_core_strdup(switch_core_session_get_pool(listener->session[line]), listener->profile->ip); + tech_pvt->local_sdp_audio_ip = switch_core_strdup(switch_core_session_get_pool(session), listener->profile->ip); tech_pvt->remote_sdp_audio_ip = inet_ntoa(request->data.open_receive_channel_ack.ip); tech_pvt->remote_sdp_audio_port = request->data.open_receive_channel_ack.port; @@ -1834,7 +2089,7 @@ switch_status_t skinny_handle_open_receive_channel_ack_message(listener_t *liste tech_pvt->read_impl.samples_per_packet, tech_pvt->codec_ms * 1000, (switch_rtp_flag_t) 0, "soft", &err, - switch_core_session_get_pool(listener->session[line])); + switch_core_session_get_pool(session)); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "AUDIO RTP [%s] %s:%d->%s:%d codec: %u ms: %d [%s]\n", switch_channel_get_name(channel), @@ -1846,7 +2101,7 @@ switch_status_t skinny_handle_open_receive_channel_ack_message(listener_t *liste tech_pvt->read_impl.microseconds_per_packet / 1000, switch_rtp_ready(tech_pvt->rtp_session) ? "SUCCESS" : err); inet_aton(tech_pvt->local_sdp_audio_ip, &addr); - start_media_transmission(listener, + send_start_media_transmission(listener, tech_pvt->call_id, /* uint32_t conference_id, */ tech_pvt->party_id, /* uint32_t pass_thru_party_id, */ addr.s_addr, /* uint32_t remote_ip, */ @@ -1858,7 +2113,12 @@ switch_status_t skinny_handle_open_receive_channel_ack_message(listener_t *liste 0, /* uint16_t max_frames_per_packet, */ 0 /* uint32_t g723_bitrate */ ); + if (switch_channel_get_state(channel) == CS_NEW) { + switch_channel_set_state(channel, CS_INIT); + } switch_channel_mark_answered(channel); + + switch_core_session_rwunlock(session); } end: return status; @@ -1866,35 +2126,28 @@ end: switch_status_t skinny_handle_keypad_button_message(listener_t *listener, skinny_message_t *request) { - uint32_t line = 0; + uint32_t line_instance = 0; + switch_core_session_t *session; skinny_check_data_length(request, sizeof(request->data.keypad_button)); + + if(request->data.keypad_button.line_instance) { + line_instance = request->data.keypad_button.line_instance; + } else { + line_instance = 1; + } - /* Choose the specified line */ - line = request->data.keypad_button.line_instance; - if(line == 0) {/* If none, find the first busy line */ - for(int i = 0 ; i < SKINNY_MAX_BUTTON_COUNT ; i++) { - if(listener->session[i]) { - line = i; - break; - } - } - } - if(line == 0) {/* If none, choose the first line */ - line = 1; - } - if(listener->session[line]) { + session = skinny_profile_find_session(listener->profile, listener, &line_instance, request->data.keypad_button.call_id); + + if(session) { switch_channel_t *channel = NULL; private_t *tech_pvt = NULL; char digit = '\0'; - channel = switch_core_session_get_channel(listener->session[line]); - assert(channel != NULL); + channel = switch_core_session_get_channel(session); + tech_pvt = switch_core_session_get_private(session); - tech_pvt = switch_core_session_get_private(listener->session[line]); - assert(tech_pvt != NULL); - - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(listener->session[line]), SWITCH_LOG_DEBUG, "SEND DTMF ON CALL %d [%d]\n", tech_pvt->call_id, request->data.keypad_button.button); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "SEND DTMF ON CALL %d [%d]\n", tech_pvt->call_id, request->data.keypad_button.button); if (request->data.keypad_button.button == 14) { digit = '*'; @@ -1903,21 +2156,14 @@ switch_status_t skinny_handle_keypad_button_message(listener_t *listener, skinny } else if (request->data.keypad_button.button >= 0 && request->data.keypad_button.button <= 9) { digit = '0' + request->data.keypad_button.button; } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(listener->session[line]), SWITCH_LOG_WARNING, "UNKNOW DTMF RECEIVED ON CALL %d [%d]\n", tech_pvt->call_id, request->data.keypad_button.button); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "UNKNOW DTMF RECEIVED ON CALL %d [%d]\n", tech_pvt->call_id, request->data.keypad_button.button); } /* TODO check call_id and line */ - if((skinny_line_get_state(listener, tech_pvt->line) == SKINNY_KEY_SET_OFF_HOOK) - || (skinny_line_get_state(listener, tech_pvt->line) == SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT)) { - if(strlen(tech_pvt->dest) == 0) {/* first digit */ - stop_tone(listener, tech_pvt->line, tech_pvt->call_id); - skinny_line_set_state(listener, tech_pvt->line, SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT, tech_pvt->call_id); - } - - tech_pvt->dest[strlen(tech_pvt->dest)] = digit; - - skinny_process_dest(listener, tech_pvt->line); + if((skinny_line_get_state(listener, line_instance, tech_pvt->call_id) == SKINNY_OFF_HOOK)) { + + skinny_session_process_dest(session, listener, line_instance, NULL, digit, 0); } else { if(digit != '\0') { switch_dtmf_t dtmf = { 0, switch_core_default_dtmf_duration(0)}; @@ -1925,6 +2171,7 @@ switch_status_t skinny_handle_keypad_button_message(listener_t *listener, skinny switch_channel_queue_dtmf(channel, &dtmf); } } + switch_core_session_rwunlock(session); } return SWITCH_STATUS_SUCCESS; @@ -1933,35 +2180,23 @@ switch_status_t skinny_handle_keypad_button_message(listener_t *listener, skinny switch_status_t skinny_handle_on_hook_message(listener_t *listener, skinny_message_t *request) { switch_status_t status = SWITCH_STATUS_SUCCESS; - skinny_profile_t *profile; - uint32_t line = 0; - - switch_assert(listener->profile); - switch_assert(listener->device_name); - - profile = listener->profile; + switch_core_session_t *session = NULL; + uint32_t line_instance = 0; skinny_check_data_length(request, sizeof(request->data.on_hook)); - if(request->data.on_hook.line_instance != 0) { - line = request->data.on_hook.line_instance; - } else { - /* Find first active line */ - for(int i = 0 ; i < SKINNY_MAX_BUTTON_COUNT ; i++) { - if(listener->session[i]) { - line = i; - break; - } - } - } + line_instance = request->data.on_hook.line_instance; + + session = skinny_profile_find_session(listener->profile, listener, &line_instance, request->data.on_hook.call_id); - if(listener->session[line]) { + if(session) { switch_channel_t *channel = NULL; - channel = switch_core_session_get_channel(listener->session[line]); - assert(channel != NULL); + channel = switch_core_session_get_channel(session); switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); + + switch_core_session_rwunlock(session); } return status; } @@ -2069,3 +2304,14 @@ switch_status_t skinny_perform_send_reply(listener_t *listener, const char *file 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: + */ + diff --git a/src/mod/endpoints/mod_skinny/skinny_protocol.h b/src/mod/endpoints/mod_skinny/skinny_protocol.h index c0af0b771e..ea004f12fc 100644 --- a/src/mod/endpoints/mod_skinny/skinny_protocol.h +++ b/src/mod/endpoints/mod_skinny/skinny_protocol.h @@ -49,57 +49,60 @@ /* RegisterMessage */ #define REGISTER_MESSAGE 0x0001 struct register_message { - char device_name[16]; - uint32_t user_id; - uint32_t instance; - struct in_addr ip; - uint32_t device_type; - uint32_t max_streams; + char device_name[16]; + uint32_t user_id; + uint32_t instance; + struct in_addr ip; + uint32_t device_type; + uint32_t max_streams; }; /* PortMessage */ #define PORT_MESSAGE 0x0002 +struct port_message { + uint16_t port; +}; /* KeypadButtonMessage */ #define KEYPAD_BUTTON_MESSAGE 0x0003 struct keypad_button_message { - uint32_t button; - uint32_t line_instance; - uint32_t call_id; + uint32_t button; + uint32_t line_instance; + uint32_t call_id; }; /* StimulusMessage */ #define STIMULUS_MESSAGE 0x0005 struct stimulus_message { - uint32_t instance_type; /* See enum skinny_button_definition */ - uint32_t instance; - /* uint32_t call_reference; */ + uint32_t instance_type; /* See enum skinny_button_definition */ + uint32_t instance; + uint32_t call_id; }; /* OffHookMessage */ #define OFF_HOOK_MESSAGE 0x0006 struct off_hook_message { - uint32_t line_instance; - /* uint32_t call_id; */ + uint32_t line_instance; + uint32_t call_id; }; /* OnHookMessage */ #define ON_HOOK_MESSAGE 0x0007 struct on_hook_message { - uint32_t line_instance; - uint32_t call_id; + uint32_t line_instance; + uint32_t call_id; }; /* SpeedDialStatReqMessage */ #define SPEED_DIAL_STAT_REQ_MESSAGE 0x000A struct speed_dial_stat_req_message { - uint32_t number; + uint32_t number; }; /* LineStatReqMessage */ #define LINE_STAT_REQ_MESSAGE 0x000B struct line_stat_req_message { - uint32_t number; + uint32_t number; }; /* ConfigStatReqMessage */ @@ -114,32 +117,32 @@ struct line_stat_req_message { /* CapabilitiesResMessage */ #define CAPABILITIES_RES_MESSAGE 0x0010 struct station_capabilities { - uint32_t codec; - uint16_t frames; - char reserved[10]; + uint32_t codec; + uint16_t frames; + char reserved[10]; }; struct capabilities_res_message { - uint32_t count; - struct station_capabilities caps[SWITCH_MAX_CODECS]; + uint32_t count; + struct station_capabilities caps[SWITCH_MAX_CODECS]; }; /* AlarmMessage */ #define ALARM_MESSAGE 0x0020 struct alarm_message { - uint32_t alarm_severity; - char display_message[80]; - uint32_t alarm_param1; - uint32_t alarm_param2; + uint32_t alarm_severity; + char display_message[80]; + uint32_t alarm_param1; + uint32_t alarm_param2; }; /* OpenReceiveChannelAck */ #define OPEN_RECEIVE_CHANNEL_ACK_MESSAGE 0x0022 struct open_receive_channel_ack_message { - uint32_t status; - struct in_addr ip; - uint32_t port; - uint32_t pass_thru_party_id; + uint32_t status; + struct in_addr ip; + uint32_t port; + uint32_t pass_thru_party_id; }; /* SoftKeySetReqMessage */ @@ -148,9 +151,9 @@ struct open_receive_channel_ack_message { /* SoftKeyEventMessage */ #define SOFT_KEY_EVENT_MESSAGE 0x0026 struct soft_key_event_message { - uint32_t event; - uint32_t line_instance; - uint32_t callreference; + uint32_t event; + uint32_t line_instance; + uint32_t call_id; }; /* UnregisterMessage */ @@ -162,196 +165,197 @@ struct soft_key_event_message { /* ServiceUrlStatReqMessage */ #define SERVICE_URL_STAT_REQ_MESSAGE 0x0033 struct service_url_stat_req_message { - uint32_t service_url_index; + uint32_t service_url_index; }; /* FeatureStatReqMessage */ #define FEATURE_STAT_REQ_MESSAGE 0x0034 struct feature_stat_req_message { - uint32_t feature_index; + uint32_t feature_index; }; /* HeadsetStatusMessage */ #define HEADSET_STATUS_MESSAGE 0x002B struct headset_status_message { - uint32_t mode; + uint32_t mode; }; /* RegisterAvailableLinesMessage */ #define REGISTER_AVAILABLE_LINES_MESSAGE 0x002D struct register_available_lines_message { - uint32_t count; + uint32_t count; }; /* RegisterAckMessage */ #define REGISTER_ACK_MESSAGE 0x0081 struct register_ack_message { - uint32_t keepAlive; - char dateFormat[6]; - char reserved[2]; - uint32_t secondaryKeepAlive; - char reserved2[4]; + uint32_t keep_alive; + char date_format[6]; + char reserved[2]; + uint32_t secondary_keep_alive; + char reserved2[4]; }; /* StartToneMessage */ #define START_TONE_MESSAGE 0x0082 struct start_tone_message { - uint32_t tone; /* see enum skinny_tone */ - uint32_t reserved; - uint32_t line_instance; - uint32_t call_id; + uint32_t tone; /* see enum skinny_tone */ + uint32_t reserved; + uint32_t line_instance; + uint32_t call_id; }; /* StopToneMessage */ #define STOP_TONE_MESSAGE 0x0083 struct stop_tone_message { - uint32_t line_instance; - uint32_t call_id; + uint32_t line_instance; + uint32_t call_id; }; /* SetRingerMessage */ #define SET_RINGER_MESSAGE 0x0085 struct set_ringer_message { - uint32_t ring_type; /* See enum skinny_ring_type */ - uint32_t ring_mode; /* See enum skinny_ring_mode */ - uint32_t unknown; /* ?? */ + uint32_t ring_type; /* See enum skinny_ring_type */ + uint32_t ring_mode; /* See enum skinny_ring_mode */ + uint32_t line_instance; + uint32_t call_id; }; /* SetLampMessage */ #define SET_LAMP_MESSAGE 0x0086 struct set_lamp_message { - uint32_t stimulus; /* See enum skinny_button_definition */ - uint32_t stimulus_instance; - uint32_t mode; /* See enum skinny_lamp_mode */ + uint32_t stimulus; /* See enum skinny_button_definition */ + uint32_t stimulus_instance; + uint32_t mode; /* See enum skinny_lamp_mode */ }; /* SetSpeakerModeMessage */ #define SET_SPEAKER_MODE_MESSAGE 0x0088 struct set_speaker_mode_message { - uint32_t mode; /* See enum skinny_speaker_mode */ + uint32_t mode; /* See enum skinny_speaker_mode */ }; /* StartMediaTransmissionMessage */ #define START_MEDIA_TRANSMISSION_MESSAGE 0x008A struct start_media_transmission_message { - uint32_t conference_id; - uint32_t pass_thru_party_id; - uint32_t remote_ip; - uint32_t remote_port; - uint32_t ms_per_packet; - uint32_t payload_capacity; - uint32_t precedence; - uint32_t silence_suppression; - uint16_t max_frames_per_packet; - uint32_t g723_bitrate; - /* ... */ + uint32_t conference_id; + uint32_t pass_thru_party_id; + uint32_t remote_ip; + uint32_t remote_port; + uint32_t ms_per_packet; + uint32_t payload_capacity; + uint32_t precedence; + uint32_t silence_suppression; + uint16_t max_frames_per_packet; + uint32_t g723_bitrate; + /* ... */ }; /* StopMediaTransmissionMessage */ #define STOP_MEDIA_TRANSMISSION_MESSAGE 0x008B struct stop_media_transmission_message { - uint32_t conference_id; - uint32_t pass_thru_party_id; - uint32_t conference_id2; - /* ... */ + uint32_t conference_id; + uint32_t pass_thru_party_id; + uint32_t conference_id2; + /* ... */ }; /* CallInfoMessage */ #define CALL_INFO_MESSAGE 0x008F struct call_info_message { - char calling_party_name[40]; - char calling_party[24]; - char called_party_name[40]; - char called_party[24]; - uint32_t line_instance; - uint32_t call_id; - uint32_t call_type; /* See enum skinny_call_type */ - char original_called_party_name[40]; - char original_called_party[24]; - char last_redirecting_party_name[40]; - char last_redirecting_party[24]; - uint32_t original_called_party_redirect_reason; - uint32_t last_redirecting_reason; - char calling_party_voice_mailbox[24]; - char called_party_voice_mailbox[24]; - char original_called_party_voice_mailbox[24]; - char last_redirecting_voice_mailbox[24]; - uint32_t call_instance; - uint32_t call_security_status; - uint32_t party_pi_restriction_bits; + char calling_party_name[40]; + char calling_party[24]; + char called_party_name[40]; + char called_party[24]; + uint32_t line_instance; + uint32_t call_id; + uint32_t call_type; /* See enum skinny_call_type */ + char original_called_party_name[40]; + char original_called_party[24]; + char last_redirecting_party_name[40]; + char last_redirecting_party[24]; + uint32_t original_called_party_redirect_reason; + uint32_t last_redirecting_reason; + char calling_party_voice_mailbox[24]; + char called_party_voice_mailbox[24]; + char original_called_party_voice_mailbox[24]; + char last_redirecting_voice_mailbox[24]; + uint32_t call_instance; + uint32_t call_security_status; + uint32_t party_pi_restriction_bits; }; /* SpeedDialStatMessage */ #define SPEED_DIAL_STAT_RES_MESSAGE 0x0091 struct speed_dial_stat_res_message { - uint32_t number; - char line[24]; - char label[40]; + uint32_t number; + char line[24]; + char label[40]; }; /* LineStatMessage */ #define LINE_STAT_RES_MESSAGE 0x0092 struct line_stat_res_message { - uint32_t number; - char name[24]; - char shortname[40]; - char displayname[44]; + uint32_t number; + char name[24]; + char shortname[40]; + char displayname[44]; }; /* ConfigStatMessage */ #define CONFIG_STAT_RES_MESSAGE 0x0093 struct config_stat_res_message { - char device_name[16]; - uint32_t user_id; - uint32_t instance; - char user_name[40]; - char server_name[40]; - uint32_t number_lines; - uint32_t number_speed_dials; + char device_name[16]; + uint32_t user_id; + uint32_t instance; + char user_name[40]; + char server_name[40]; + uint32_t number_lines; + uint32_t number_speed_dials; }; /* DefineTimeDate */ #define DEFINE_TIME_DATE_MESSAGE 0x0094 struct define_time_date_message { - uint32_t year; - uint32_t month; - uint32_t day_of_week; /* monday = 1 */ - uint32_t day; - uint32_t hour; - uint32_t minute; - uint32_t seconds; - uint32_t milliseconds; - uint32_t timestamp; + uint32_t year; + uint32_t month; + uint32_t day_of_week; /* monday = 1 */ + uint32_t day; + uint32_t hour; + uint32_t minute; + uint32_t seconds; + uint32_t milliseconds; + uint32_t timestamp; }; /* ButtonTemplateMessage */ #define BUTTON_TEMPLATE_RES_MESSAGE 0x0097 struct button_definition { - uint8_t instance_number; - uint8_t button_definition; /* See enum skinny_button_definition */ + uint8_t instance_number; + uint8_t button_definition; /* See enum skinny_button_definition */ }; #define SKINNY_MAX_BUTTON_COUNT 42 struct button_template_message { - uint32_t button_offset; - uint32_t button_count; - uint32_t total_button_count; - struct button_definition btn[SKINNY_MAX_BUTTON_COUNT]; + uint32_t button_offset; + uint32_t button_count; + uint32_t total_button_count; + struct button_definition btn[SKINNY_MAX_BUTTON_COUNT]; }; /* CapabilitiesReqMessage */ #define CAPABILITIES_REQ_MESSAGE 0x009B /* RegisterRejectMessage */ -#define REGISTER_REJ_MESSAGE 0x009D -struct register_rej_message { - char error[33]; +#define REGISTER_REJECT_MESSAGE 0x009D +struct register_reject_message { + char error[33]; }; /* ResetMessage */ #define RESET_MESSAGE 0x009F struct reset_message { - uint32_t reset_type; /* See enum skinny_device_reset_types */ + uint32_t reset_type; /* See enum skinny_device_reset_types */ }; /* KeepAliveAckMessage */ @@ -360,122 +364,130 @@ struct reset_message { /* OpenReceiveChannelMessage */ #define OPEN_RECEIVE_CHANNEL_MESSAGE 0x0105 struct open_receive_channel_message { - uint32_t conference_id; - uint32_t pass_thru_party_id; - uint32_t packets; - uint32_t payload_capacity; - uint32_t echo_cancel_type; - uint32_t g723_bitrate; - uint32_t conference_id2; - uint32_t reserved[10]; + uint32_t conference_id; + uint32_t pass_thru_party_id; + uint32_t packets; + uint32_t payload_capacity; + uint32_t echo_cancel_type; + uint32_t g723_bitrate; + uint32_t conference_id2; + uint32_t reserved[10]; }; /* CloseReceiveChannelMessage */ #define CLOSE_RECEIVE_CHANNEL_MESSAGE 0x0106 struct close_receive_channel_message { - uint32_t conference_id; - uint32_t pass_thru_party_id; - uint32_t conference_id2; + uint32_t conference_id; + uint32_t pass_thru_party_id; + uint32_t conference_id2; }; /* SoftKeyTemplateResMessage */ #define SOFT_KEY_TEMPLATE_RES_MESSAGE 0x0108 struct soft_key_template_definition { - char soft_key_label[16]; - uint32_t soft_key_event; + char soft_key_label[16]; + uint32_t soft_key_event; }; struct soft_key_template_res_message { - uint32_t soft_key_offset; - uint32_t soft_key_count; - uint32_t total_soft_key_count; - struct soft_key_template_definition soft_key[32]; + uint32_t soft_key_offset; + uint32_t soft_key_count; + uint32_t total_soft_key_count; + struct soft_key_template_definition soft_key[32]; }; /* SoftKeySetResMessage */ #define SOFT_KEY_SET_RES_MESSAGE 0x0109 struct soft_key_set_definition { - uint8_t soft_key_template_index[16]; /* See enum skinny_soft_key_event */ - uint16_t soft_key_info_index[16]; + uint8_t soft_key_template_index[16]; /* See enum skinny_soft_key_event */ + uint16_t soft_key_info_index[16]; }; struct soft_key_set_res_message { - uint32_t soft_key_set_offset; - uint32_t soft_key_set_count; - uint32_t total_soft_key_set_count; - struct soft_key_set_definition soft_key_set[16]; - uint32_t res; + uint32_t soft_key_set_offset; + uint32_t soft_key_set_count; + uint32_t total_soft_key_set_count; + struct soft_key_set_definition soft_key_set[16]; + uint32_t res; }; /* SelectSoftKeysMessage */ #define SELECT_SOFT_KEYS_MESSAGE 0x0110 struct select_soft_keys_message { - uint32_t line_instance; - uint32_t call_id; - uint32_t soft_key_set; /* See enum skinny_key_set */ - uint32_t valid_key_mask; + uint32_t line_instance; + uint32_t call_id; + uint32_t soft_key_set; /* See enum skinny_key_set */ + uint32_t valid_key_mask; }; /* CallStateMessage */ #define CALL_STATE_MESSAGE 0x0111 struct call_state_message { - uint32_t call_state; /* See enum skinny_call_state */ - uint32_t line_instance; - uint32_t call_id; + uint32_t call_state; /* See enum skinny_call_state */ + uint32_t line_instance; + uint32_t call_id; }; /* DisplayPromptStatusMessage */ #define DISPLAY_PROMPT_STATUS_MESSAGE 0x0112 struct display_prompt_status_message { - uint32_t timeout; - char display[32]; - uint32_t line_instance; - uint32_t call_id; + uint32_t timeout; + char display[32]; + uint32_t line_instance; + uint32_t call_id; }; /* ClearPromptStatusMessage */ #define CLEAR_PROMPT_STATUS_MESSAGE 0x0113 struct clear_prompt_status_message { - uint32_t line_instance; - uint32_t call_id; + uint32_t line_instance; + uint32_t call_id; }; /* ActivateCallPlaneMessage */ #define ACTIVATE_CALL_PLANE_MESSAGE 0x0116 struct activate_call_plane_message { - uint32_t line_instance; + uint32_t line_instance; }; /* UnregisterAckMessage */ #define UNREGISTER_ACK_MESSAGE 0x0118 struct unregister_ack_message { - uint32_t unregister_status; + uint32_t unregister_status; }; /* DialedNumberMessage */ #define DIALED_NUMBER_MESSAGE 0x011D struct dialed_number_message { - char called_party[24]; - uint32_t line_instance; - uint32_t call_id; + char called_party[24]; + uint32_t line_instance; + uint32_t call_id; }; /* FeatureStatMessage */ #define FEATURE_STAT_RES_MESSAGE 0x011F struct feature_stat_res_message { - uint32_t index; - uint32_t id; - char text_label[40]; - uint32_t status; + uint32_t index; + uint32_t id; + char text_label[40]; + uint32_t status; +}; + +/* DisplayPriNotifyMessage */ +#define DISPLAY_PRI_NOTIFY_MESSAGE 0x0120 +struct display_pri_notify_message { + uint32_t message_timeout; + uint32_t priority; + char notify[32]; }; /* ServiceUrlStatMessage */ #define SERVICE_URL_STAT_RES_MESSAGE 0x012F struct service_url_stat_res_message { - uint32_t index; - char url[256]; - char display_name[40]; + uint32_t index; + char url[256]; + char display_name[40]; }; /*****************************************************************************/ @@ -486,54 +498,56 @@ struct service_url_stat_res_message { #define SKINNY_MESSAGE_MAXSIZE 1000 union skinny_data { - struct register_message reg; - struct keypad_button_message keypad_button; - struct stimulus_message stimulus; - struct off_hook_message off_hook; - struct on_hook_message on_hook; - struct speed_dial_stat_req_message speed_dial_req; - struct line_stat_req_message line_req; - struct capabilities_res_message cap_res; - struct alarm_message alarm; - struct open_receive_channel_ack_message open_receive_channel_ack; - struct soft_key_event_message soft_key_event; - struct service_url_stat_req_message service_url_req; - struct feature_stat_req_message feature_req; - struct headset_status_message headset_status; - struct register_available_lines_message reg_lines; - struct register_ack_message reg_ack; - struct start_tone_message start_tone; - struct stop_tone_message stop_tone; - struct set_ringer_message ringer; - struct set_lamp_message lamp; - struct set_speaker_mode_message speaker_mode; - struct start_media_transmission_message start_media; - struct stop_media_transmission_message stop_media; - struct call_info_message call_info; - struct speed_dial_stat_res_message speed_dial_res; - struct line_stat_res_message line_res; - struct config_stat_res_message config_res; - struct define_time_date_message define_time_date; - struct button_template_message button_template; - struct register_rej_message reg_rej; - struct reset_message reset; - struct open_receive_channel_message open_receive_channel; - struct close_receive_channel_message close_receive_channel; - struct soft_key_template_res_message soft_key_template; - struct soft_key_set_res_message soft_key_set; - struct select_soft_keys_message select_soft_keys; - struct call_state_message call_state; - struct display_prompt_status_message display_prompt_status; - struct clear_prompt_status_message clear_prompt_status; - struct activate_call_plane_message activate_call_plane; - struct unregister_ack_message unregister_ack; - struct dialed_number_message dialed_number; - struct feature_stat_res_message feature_res; - struct service_url_stat_res_message service_url_res; - - uint16_t as_uint16; - char as_char; - void *raw; + struct register_message reg; + struct port_message port; + struct keypad_button_message keypad_button; + struct stimulus_message stimulus; + struct off_hook_message off_hook; + struct on_hook_message on_hook; + struct speed_dial_stat_req_message speed_dial_req; + struct line_stat_req_message line_req; + struct capabilities_res_message cap_res; + struct alarm_message alarm; + struct open_receive_channel_ack_message open_receive_channel_ack; + struct soft_key_event_message soft_key_event; + struct service_url_stat_req_message service_url_req; + struct feature_stat_req_message feature_req; + struct headset_status_message headset_status; + struct register_available_lines_message reg_lines; + struct register_ack_message reg_ack; + struct start_tone_message start_tone; + struct stop_tone_message stop_tone; + struct set_ringer_message ringer; + struct set_lamp_message lamp; + struct set_speaker_mode_message speaker_mode; + struct start_media_transmission_message start_media; + struct stop_media_transmission_message stop_media; + struct call_info_message call_info; + struct speed_dial_stat_res_message speed_dial_res; + struct line_stat_res_message line_res; + struct config_stat_res_message config_res; + struct define_time_date_message define_time_date; + struct button_template_message button_template; + struct register_reject_message reg_rej; + struct reset_message reset; + struct open_receive_channel_message open_receive_channel; + struct close_receive_channel_message close_receive_channel; + struct soft_key_template_res_message soft_key_template; + struct soft_key_set_res_message soft_key_set; + struct select_soft_keys_message select_soft_keys; + struct call_state_message call_state; + struct display_prompt_status_message display_prompt_status; + struct clear_prompt_status_message clear_prompt_status; + struct activate_call_plane_message activate_call_plane; + struct unregister_ack_message unregister_ack; + struct dialed_number_message dialed_number; + struct feature_stat_res_message feature_res; + struct display_pri_notify_message display_pri_notify; + struct service_url_stat_res_message service_url_res; + + uint16_t as_uint16; + char as_char; + void *raw; }; /* @@ -541,10 +555,10 @@ union skinny_data { * body is type+data */ struct skinny_message { - uint32_t length; - uint32_t reserved; - uint32_t type; - union skinny_data data; + uint32_t length; + uint32_t reserved; + uint32_t type; + union skinny_data data; }; typedef struct skinny_message skinny_message_t; @@ -552,40 +566,40 @@ typedef struct skinny_message skinny_message_t; /* SKINNY TYPES */ /*****************************************************************************/ enum skinny_codecs { - SKINNY_CODEC_ALAW_64K = 2, - SKINNY_CODEC_ALAW_56K = 3, - SKINNY_CODEC_ULAW_64K = 4, - SKINNY_CODEC_ULAW_56K = 5, - SKINNY_CODEC_G722_64K = 6, - SKINNY_CODEC_G722_56K = 7, - SKINNY_CODEC_G722_48K = 8, - SKINNY_CODEC_G723_1 = 9, - SKINNY_CODEC_G728 = 10, - SKINNY_CODEC_G729 = 11, - SKINNY_CODEC_G729A = 12, - SKINNY_CODEC_IS11172 = 13, - SKINNY_CODEC_IS13818 = 14, - SKINNY_CODEC_G729B = 15, - SKINNY_CODEC_G729AB = 16, - SKINNY_CODEC_GSM_FULL = 18, - SKINNY_CODEC_GSM_HALF = 19, - SKINNY_CODEC_GSM_EFULL = 20, - SKINNY_CODEC_WIDEBAND_256K = 25, - SKINNY_CODEC_DATA_64K = 32, - SKINNY_CODEC_DATA_56K = 33, - SKINNY_CODEC_GSM = 80, - SKINNY_CODEC_ACTIVEVOICE = 81, - SKINNY_CODEC_G726_32K = 82, - SKINNY_CODEC_G726_24K = 83, - SKINNY_CODEC_G726_16K = 84, - SKINNY_CODEC_G729B_BIS = 85, - SKINNY_CODEC_G729B_LOW = 86, - SKINNY_CODEC_H261 = 100, - SKINNY_CODEC_H263 = 101, - SKINNY_CODEC_VIDEO = 102, - SKINNY_CODEC_T120 = 105, - SKINNY_CODEC_H224 = 106, - SKINNY_CODEC_RFC2833_DYNPAYLOAD = 257 + SKINNY_CODEC_ALAW_64K = 2, + SKINNY_CODEC_ALAW_56K = 3, + SKINNY_CODEC_ULAW_64K = 4, + SKINNY_CODEC_ULAW_56K = 5, + SKINNY_CODEC_G722_64K = 6, + SKINNY_CODEC_G722_56K = 7, + SKINNY_CODEC_G722_48K = 8, + SKINNY_CODEC_G723_1 = 9, + SKINNY_CODEC_G728 = 10, + SKINNY_CODEC_G729 = 11, + SKINNY_CODEC_G729A = 12, + SKINNY_CODEC_IS11172 = 13, + SKINNY_CODEC_IS13818 = 14, + SKINNY_CODEC_G729B = 15, + SKINNY_CODEC_G729AB = 16, + SKINNY_CODEC_GSM_FULL = 18, + SKINNY_CODEC_GSM_HALF = 19, + SKINNY_CODEC_GSM_EFULL = 20, + SKINNY_CODEC_WIDEBAND_256K = 25, + SKINNY_CODEC_DATA_64K = 32, + SKINNY_CODEC_DATA_56K = 33, + SKINNY_CODEC_GSM = 80, + SKINNY_CODEC_ACTIVEVOICE = 81, + SKINNY_CODEC_G726_32K = 82, + SKINNY_CODEC_G726_24K = 83, + SKINNY_CODEC_G726_16K = 84, + SKINNY_CODEC_G729B_BIS = 85, + SKINNY_CODEC_G729B_LOW = 86, + SKINNY_CODEC_H261 = 100, + SKINNY_CODEC_H263 = 101, + SKINNY_CODEC_VIDEO = 102, + SKINNY_CODEC_T120 = 105, + SKINNY_CODEC_H224 = 106, + SKINNY_CODEC_RFC2833_DYNPAYLOAD = 257 }; typedef switch_status_t (*skinny_command_t) (char **argv, int argc, switch_stream_handle_t *stream); @@ -594,20 +608,28 @@ typedef switch_status_t (*skinny_command_t) (char **argv, int argc, switch_strea /* SKINNY FUNCTIONS */ /*****************************************************************************/ #define skinny_check_data_length(message, len) \ - if (message->length < len+4) {\ - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Received Too Short Skinny Message (Expected %" SWITCH_SIZE_T_FMT ", got %d).\n", len+4, message->length);\ - return SWITCH_STATUS_FALSE;\ - } + if (message->length < len+4) {\ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Received Too Short Skinny Message (Expected %" SWITCH_SIZE_T_FMT ", got %d).\n", len+4, message->length);\ + return SWITCH_STATUS_FALSE;\ + } +#define skinny_check_data_length_soft(message, len) \ + (message->length >= len+4) switch_status_t skinny_read_packet(listener_t *listener, skinny_message_t **req); switch_status_t skinny_device_event(listener_t *listener, switch_event_t **ev, switch_event_types_t event_id, const char *subclass_name); -switch_status_t skinny_send_call_info(switch_core_session_t *session); +switch_status_t skinny_send_call_info(switch_core_session_t *session, listener_t *listener, uint32_t line_instance); +switch_status_t skinny_session_walk_lines(skinny_profile_t *profile, char *channel_uuid, switch_core_db_callback_func_t callback, void *data); +switch_call_cause_t skinny_ring_lines(private_t *tech_pvt); -switch_status_t skinny_create_session(listener_t *listener, uint32_t line, uint32_t to_state); -switch_status_t skinny_process_dest(listener_t *listener, uint32_t line); -switch_status_t skinny_answer(switch_core_session_t *session); +switch_status_t skinny_create_ingoing_session(listener_t *listener, uint32_t *line_instance, switch_core_session_t **session); +switch_status_t skinny_session_process_dest(switch_core_session_t *session, listener_t *listener, uint32_t line_instance, char *dest, char append_dest, uint32_t backspace); +switch_status_t skinny_session_ring_out(switch_core_session_t *session, listener_t *listener, uint32_t line_instance); +switch_status_t skinny_session_answer(switch_core_session_t *session, listener_t *listener, uint32_t line_instance); +switch_status_t skinny_session_start_media(switch_core_session_t *session, listener_t *listener, uint32_t line_instance); +switch_status_t skinny_session_hold_line(switch_core_session_t *session, listener_t *listener, uint32_t line_instance); +switch_status_t skinny_session_unhold_line(switch_core_session_t *session, listener_t *listener, uint32_t line_instance); void skinny_line_get(listener_t *listener, uint32_t instance, struct line_stat_res_message **button); void skinny_speed_dial_get(listener_t *listener, uint32_t instance, struct speed_dial_stat_res_message **button); @@ -620,98 +642,131 @@ switch_status_t skinny_handle_request(listener_t *listener, skinny_message_t *re /*****************************************************************************/ /* SKINNY MESSAGE HELPER */ /*****************************************************************************/ -switch_status_t start_tone(listener_t *listener, - uint32_t tone, - uint32_t reserved, - uint32_t line_instance, - uint32_t call_id); -switch_status_t stop_tone(listener_t *listener, - uint32_t line_instance, - uint32_t call_id); -switch_status_t set_ringer(listener_t *listener, - uint32_t ring_type, - uint32_t ring_mode, - uint32_t unknown); -switch_status_t set_lamp(listener_t *listener, - uint32_t stimulus, - uint32_t stimulus_instance, - uint32_t mode); -switch_status_t set_speaker_mode(listener_t *listener, - uint32_t mode); -switch_status_t start_media_transmission(listener_t *listener, - uint32_t conference_id, - uint32_t pass_thru_party_id, - uint32_t remote_ip, - uint32_t remote_port, - uint32_t ms_per_packet, - uint32_t payload_capacity, - uint32_t precedence, - uint32_t silence_suppression, - uint16_t max_frames_per_packet, - uint32_t g723_bitrate); -switch_status_t stop_media_transmission(listener_t *listener, - uint32_t conference_id, - uint32_t pass_thru_party_id, - uint32_t conference_id2); +switch_status_t send_register_ack(listener_t *listener, + uint32_t keep_alive, + char *date_format, + char *reserved, + uint32_t secondary_keep_alive, + char *reserved2); +switch_status_t send_start_tone(listener_t *listener, + uint32_t tone, + uint32_t reserved, + uint32_t line_instance, + uint32_t call_id); +switch_status_t send_stop_tone(listener_t *listener, + uint32_t line_instance, + uint32_t call_id); +switch_status_t send_set_ringer(listener_t *listener, + uint32_t ring_type, + uint32_t ring_mode, + uint32_t line_instance, + uint32_t call_id); +switch_status_t send_set_lamp(listener_t *listener, + uint32_t stimulus, + uint32_t stimulus_instance, + uint32_t mode); +switch_status_t send_set_speaker_mode(listener_t *listener, + uint32_t mode); +switch_status_t send_start_media_transmission(listener_t *listener, + uint32_t conference_id, + uint32_t pass_thru_party_id, + uint32_t remote_ip, + uint32_t remote_port, + uint32_t ms_per_packet, + uint32_t payload_capacity, + uint32_t precedence, + uint32_t silence_suppression, + uint16_t max_frames_per_packet, + uint32_t g723_bitrate); +switch_status_t send_stop_media_transmission(listener_t *listener, + uint32_t conference_id, + uint32_t pass_thru_party_id, + uint32_t conference_id2); switch_status_t send_call_info(listener_t *listener, - char calling_party_name[40], - char calling_party[24], - char called_party_name[40], - char called_party[24], - uint32_t line_instance, - uint32_t call_id, - uint32_t call_type, - char original_called_party_name[40], - char original_called_party[24], - char last_redirecting_party_name[40], - char last_redirecting_party[24], - uint32_t original_called_party_redirect_reason, - uint32_t last_redirecting_reason, - char calling_party_voice_mailbox[24], - char called_party_voice_mailbox[24], - char original_called_party_voice_mailbox[24], - char last_redirecting_voice_mailbox[24], - uint32_t call_instance, - uint32_t call_security_status, - uint32_t party_pi_restriction_bits); -switch_status_t open_receive_channel(listener_t *listener, - uint32_t conference_id, - uint32_t pass_thru_party_id, - uint32_t packets, - uint32_t payload_capacity, - uint32_t echo_cancel_type, - uint32_t g723_bitrate, - uint32_t conference_id2, - uint32_t reserved[10]); -switch_status_t close_receive_channel(listener_t *listener, - uint32_t conference_id, - uint32_t pass_thru_party_id, - uint32_t conference_id2); + char calling_party_name[40], + char calling_party[24], + char called_party_name[40], + char called_party[24], + uint32_t line_instance, + uint32_t call_id, + uint32_t call_type, + char original_called_party_name[40], + char original_called_party[24], + char last_redirecting_party_name[40], + char last_redirecting_party[24], + uint32_t original_called_party_redirect_reason, + uint32_t last_redirecting_reason, + char calling_party_voice_mailbox[24], + char called_party_voice_mailbox[24], + char original_called_party_voice_mailbox[24], + char last_redirecting_voice_mailbox[24], + uint32_t call_instance, + uint32_t call_security_status, + uint32_t party_pi_restriction_bits); +switch_status_t send_define_time_date(listener_t *listener, + uint32_t year, + uint32_t month, + uint32_t day_of_week, /* monday = 1 */ + uint32_t day, + uint32_t hour, + uint32_t minute, + uint32_t seconds, + uint32_t milliseconds, + uint32_t timestamp); +switch_status_t send_define_current_time_date(listener_t *listener); +switch_status_t send_open_receive_channel(listener_t *listener, + uint32_t conference_id, + uint32_t pass_thru_party_id, + uint32_t packets, + uint32_t payload_capacity, + uint32_t echo_cancel_type, + uint32_t g723_bitrate, + uint32_t conference_id2, + uint32_t reserved[10]); +switch_status_t send_close_receive_channel(listener_t *listener, + uint32_t conference_id, + uint32_t pass_thru_party_id, + uint32_t conference_id2); switch_status_t send_select_soft_keys(listener_t *listener, - uint32_t line_instance, - uint32_t call_id, - uint32_t soft_key_set, - uint32_t valid_key_mask); + uint32_t line_instance, + uint32_t call_id, + uint32_t soft_key_set, + uint32_t valid_key_mask); switch_status_t send_call_state(listener_t *listener, - uint32_t call_state, - uint32_t line_instance, - uint32_t call_id); -switch_status_t display_prompt_status(listener_t *listener, - uint32_t timeout, - char display[32], - uint32_t line_instance, - uint32_t call_id); -switch_status_t clear_prompt_status(listener_t *listener, - uint32_t line_instance, - uint32_t call_id); -switch_status_t activate_call_plane(listener_t *listener, - uint32_t line_instance); + uint32_t call_state, + uint32_t line_instance, + uint32_t call_id); +switch_status_t send_display_prompt_status(listener_t *listener, + uint32_t timeout, + char display[32], + uint32_t line_instance, + uint32_t call_id); +switch_status_t send_clear_prompt_status(listener_t *listener, + uint32_t line_instance, + uint32_t call_id); +switch_status_t send_activate_call_plane(listener_t *listener, + uint32_t line_instance); switch_status_t send_dialed_number(listener_t *listener, - char called_party[24], - uint32_t line_instance, - uint32_t call_id); + char called_party[24], + uint32_t line_instance, + uint32_t call_id); +switch_status_t send_display_pri_notify(listener_t *listener, + uint32_t message_timeout, + uint32_t priority, + char *notify); switch_status_t send_reset(listener_t *listener, - uint32_t reset_type); + uint32_t reset_type); #endif /* _SKINNY_PROTOCOL_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: + */ + diff --git a/src/mod/endpoints/mod_skinny/skinny_tables.c b/src/mod/endpoints/mod_skinny/skinny_tables.c index 667ae3cd63..5ddd53ac87 100644 --- a/src/mod/endpoints/mod_skinny/skinny_tables.c +++ b/src/mod/endpoints/mod_skinny/skinny_tables.c @@ -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: + */ + diff --git a/src/mod/endpoints/mod_skinny/skinny_tables.h b/src/mod/endpoints/mod_skinny/skinny_tables.h index 5672446bc0..9e3ab3be4c 100644 --- a/src/mod/endpoints/mod_skinny/skinny_tables.h +++ b/src/mod/endpoints/mod_skinny/skinny_tables.h @@ -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: + */ + diff --git a/src/mod/endpoints/mod_skinny/test-skinny.pl b/src/mod/endpoints/mod_skinny/test-skinny.pl index 4821fc9b50..390466f530 100644 --- a/src/mod/endpoints/mod_skinny/test-skinny.pl +++ b/src/mod/endpoints/mod_skinny/test-skinny.pl @@ -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(); +} + diff --git a/src/mod/endpoints/mod_skypopen/Makefile.am b/src/mod/endpoints/mod_skypopen/Makefile.am index 466a09b7b8..d696fae783 100644 --- a/src/mod/endpoints/mod_skypopen/Makefile.am +++ b/src/mod/endpoints/mod_skypopen/Makefile.am @@ -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 diff --git a/src/mod/event_handlers/mod_event_multicast/mod_event_multicast.c b/src/mod/event_handlers/mod_event_multicast/mod_event_multicast.c index 32562adaea..cb31aa220d 100644 --- a/src/mod/event_handlers/mod_event_multicast/mod_event_multicast.c +++ b/src/mod/event_handlers/mod_event_multicast/mod_event_multicast.c @@ -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); diff --git a/src/mod/event_handlers/mod_event_test/.gitignore b/src/mod/event_handlers/mod_event_test/.gitignore new file mode 100644 index 0000000000..f3c7a7c5da --- /dev/null +++ b/src/mod/event_handlers/mod_event_test/.gitignore @@ -0,0 +1 @@ +Makefile diff --git a/src/mod/formats/mod_portaudio_stream/Makefile.am b/src/mod/formats/mod_portaudio_stream/Makefile.am index 9b9900c03a..ae9896a7b0 100644 --- a/src/mod/formats/mod_portaudio_stream/Makefile.am +++ b/src/mod/formats/mod_portaudio_stream/Makefile.am @@ -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) diff --git a/src/mod/languages/mod_managed/freeswitch_wrap.cxx b/src/mod/languages/mod_managed/freeswitch_wrap.cxx index aab23429f8..737940ec6c 100644 --- a/src/mod/languages/mod_managed/freeswitch_wrap.cxx +++ b/src/mod/languages/mod_managed/freeswitch_wrap.cxx @@ -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 ; diff --git a/src/mod/languages/mod_managed/managed/FreeSWITCH.Managed.dll b/src/mod/languages/mod_managed/managed/FreeSWITCH.Managed.dll deleted file mode 100644 index fb5f57172e..0000000000 Binary files a/src/mod/languages/mod_managed/managed/FreeSWITCH.Managed.dll and /dev/null differ diff --git a/src/mod/languages/mod_managed/managed/FreeSWITCH.Managed.pdb b/src/mod/languages/mod_managed/managed/FreeSWITCH.Managed.pdb deleted file mode 100644 index 4689e6d01a..0000000000 Binary files a/src/mod/languages/mod_managed/managed/FreeSWITCH.Managed.pdb and /dev/null differ diff --git a/src/mod/languages/mod_managed/managed/swig.cs b/src/mod/languages/mod_managed/managed/swig.cs index 90b0c57877..13756d32a6 100644 --- a/src/mod/languages/mod_managed/managed/swig.cs +++ b/src/mod/languages/mod_managed/managed/swig.cs @@ -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); diff --git a/src/mod/timers/.empty b/src/mod/timers/.empty new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/switch_apr.c b/src/switch_apr.c index a6687bf402..d857d48906 100644 --- a/src/switch_apr.c +++ b/src/switch_apr.c @@ -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 */ diff --git a/src/switch_channel.c b/src/switch_channel.c index fe661d4d66..ba9429721a 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -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) { diff --git a/src/switch_console.c b/src/switch_console.c index 68f7df3575..a5e78f28d8 100644 --- a/src/switch_console.c +++ b/src/switch_console.c @@ -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; } diff --git a/src/switch_core_session.c b/src/switch_core_session.c index 9dd3208d93..863b928092 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -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); } diff --git a/src/switch_pcm.c b/src/switch_pcm.c index 6fd63c9870..8f8b06c4c5 100644 --- a/src/switch_pcm.c +++ b/src/switch_pcm.c @@ -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) diff --git a/web/etc/.empty b/web/etc/.empty new file mode 100644 index 0000000000..e69de29bb2 diff --git a/web/planet/.empty b/web/planet/.empty new file mode 100644 index 0000000000..e69de29bb2