mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-10-16 16:24:13 +00:00
Added mod_khomp Endpoint.
This module has been developed to make a nice, affordable brazilian board called Khomp (http://www.khomp.com.br) compatible with FreeSWITCH. Supported boards: - FXS - FXO - E1 - GSM (boards and usb devices) - Passive record - kommuter
This commit is contained in:
1 parent
f8d8a395cc
commit
5fea197b78
96 files changed
+42128
No files matched your search
@@ -0,0 +1,962 @@
|
||||
/*******************************************************************************
|
||||
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2010 Khomp Ind. & Com.
|
||||
|
||||
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.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file
|
||||
under the MPL, indicate your decision by deleting the provisions above and
|
||||
replace them with the notice and other provisions required by the LGPL
|
||||
License. If you do not delete the provisions above, a recipient may use your
|
||||
version of this file under either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _APPLICATIONS_H_
|
||||
#define _APPLICATIONS_H_
|
||||
|
||||
#include "lock.h"
|
||||
#include "khomp_pvt.h"
|
||||
|
||||
struct Application
|
||||
{
|
||||
Application(Board::KhompPvt * pvt) : _pvt(pvt) {}
|
||||
~Application() {}
|
||||
|
||||
Statistics * statistics() { return _app_statistics; }
|
||||
|
||||
template <typename T>
|
||||
T* statistics() { return static_cast<T*>(_app_statistics); }
|
||||
|
||||
Board::KhompPvt *_pvt;
|
||||
Statistics *_app_statistics;
|
||||
};
|
||||
|
||||
/*************************** FAX **********************************************/
|
||||
struct Fax
|
||||
{
|
||||
Fax(Board::KhompPvt * pvt) : _pvt(pvt) {}
|
||||
|
||||
/*
|
||||
bool clear(Board::KhompPvt * pvt)
|
||||
{
|
||||
_pvt = pvt;
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
bool adjustForFax();
|
||||
|
||||
bool sendFax(switch_core_session_t * session, const char *data);
|
||||
bool receiveFax(switch_core_session_t * session, const char *data);
|
||||
|
||||
bool onFaxChannelRelease(K3L_EVENT *e);
|
||||
|
||||
bool startFaxTX(const char * orig_addr = NULL);
|
||||
bool stopFaxTX();
|
||||
bool startFaxRX(const char * filename, const char * orig_addr = NULL);
|
||||
bool stopFaxRX();
|
||||
bool addFaxFile(const char * filename, bool last = true);
|
||||
|
||||
|
||||
Board::KhompPvt *_pvt;
|
||||
|
||||
/* used by app FAX */
|
||||
SavedCondition _fax_cond;
|
||||
KFaxResult _fax_result;
|
||||
|
||||
};
|
||||
|
||||
/*************************** TRANSFER *****************************************/
|
||||
template <typename T, bool flash = true>
|
||||
struct Transfer
|
||||
{
|
||||
Transfer(Board::KhompPvt * pvt) : _pvt(pvt), _is_ok(false) {}
|
||||
|
||||
bool clear()
|
||||
{
|
||||
if(!_is_ok)
|
||||
{
|
||||
_call = dynamic_cast<T *>(_pvt->call());
|
||||
|
||||
_is_ok = true;
|
||||
|
||||
if(!_call)
|
||||
{
|
||||
DBG(FUNC, D("Error in cast"));
|
||||
_is_ok = false;
|
||||
}
|
||||
}
|
||||
|
||||
_call->_flags.clear(Kflags::XFER_DIALING);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool userTransfer(switch_core_session_t * session, const char *data)
|
||||
{
|
||||
DBG(FUNC, PVT_FMT(_pvt->target(), "c"));
|
||||
|
||||
std::string dest("");
|
||||
std::string opts("");
|
||||
|
||||
try
|
||||
{
|
||||
Strings::vector_type params;
|
||||
|
||||
Strings::tokenize((const char *)data, params, "|,", 2);
|
||||
|
||||
dest = params[0];
|
||||
|
||||
if (params.size() > 1)
|
||||
{
|
||||
// other options go here...
|
||||
}
|
||||
|
||||
ScopedPvtLock lock(_pvt);
|
||||
|
||||
int timeout = 5;
|
||||
|
||||
if(!_pvt->call()->_flags.check(Kflags::REALLY_CONNECTED) && !_pvt->loopWhileFlagTimed(Kflags::REALLY_CONNECTED, timeout, false))
|
||||
return false;
|
||||
|
||||
DBG(FUNC, PVT_FMT(_pvt->target(), "flashing channel!"));
|
||||
|
||||
_pvt->command(KHOMP_LOG, CM_FLASH);
|
||||
|
||||
lock.unlock();
|
||||
|
||||
timeout = 15; // 15 * 200000 = 3s
|
||||
|
||||
do
|
||||
{
|
||||
usleep(200000);
|
||||
timeout--;
|
||||
|
||||
ScopedPvtLock lock2(_pvt);
|
||||
|
||||
if(!_pvt->call()->_flags.check(Kflags::IS_INCOMING) && !_pvt->call()->_flags.check(Kflags::IS_OUTGOING))
|
||||
{
|
||||
DBG(FUNC, PVT_FMT(_pvt->target(), "unable to do a user transfer, channel disconnected"));
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
while(timeout);
|
||||
|
||||
ScopedPvtLock lock3(_pvt);
|
||||
|
||||
_pvt->command(KHOMP_LOG, CM_DIAL_DTMF, dest.c_str());
|
||||
|
||||
_pvt->call()->_flags.set(Kflags::WAIT_SEND_DTMF);
|
||||
|
||||
lock3.unlock();
|
||||
|
||||
timeout = 300; // 300 * 200000 = 60s
|
||||
|
||||
do
|
||||
{
|
||||
usleep(200000);
|
||||
timeout--;
|
||||
|
||||
ScopedPvtLock lock4(_pvt);
|
||||
|
||||
if(!_pvt->call()->_flags.check(Kflags::WAIT_SEND_DTMF))
|
||||
break;
|
||||
}
|
||||
while(timeout);
|
||||
|
||||
}
|
||||
catch (ScopedLockFailed & err)
|
||||
{
|
||||
LOG(ERROR, PVT_FMT(_pvt->target(),"r (unable to lock %s!)") % err._msg.c_str() );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
DBG(FUNC, PVT_FMT(_pvt->target(), "r"));
|
||||
return true;
|
||||
}
|
||||
|
||||
/* User transfer functions */
|
||||
bool doUserXferUnlocked()
|
||||
{
|
||||
DBG(FUNC, PVT_FMT(_pvt->target(), "c (flashing channel!)"));
|
||||
|
||||
bool ret = false;
|
||||
|
||||
ret = _pvt->command(KHOMP_LOG, CM_FLASH);
|
||||
|
||||
DBG(FUNC, PVT_FMT(_pvt->target(), "r (%s)") % (ret ? "true" : "false"));
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool checkUserXferUnlocked(std::string digit)
|
||||
{
|
||||
DBG(FUNC, PVT_FMT(_pvt->target(), "c (CM_FLASH)"));
|
||||
|
||||
|
||||
if (_call->_user_xfer_digits.empty())
|
||||
{
|
||||
_call->_digits_buffer += digit;
|
||||
DBG(FUNC, PVT_FMT(_pvt->target(), "r (disabled)"));
|
||||
return false;
|
||||
}
|
||||
|
||||
_call->_user_xfer_buffer += digit;
|
||||
|
||||
/* temporary buffer */
|
||||
std::string tmp = _call->_user_xfer_buffer;
|
||||
|
||||
unsigned int amount = tmp.size();
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
if (amount == _call->_user_xfer_digits.size())
|
||||
{
|
||||
if (tmp == _call->_user_xfer_digits)
|
||||
{
|
||||
bool ret = doUserXferUnlocked();
|
||||
|
||||
_call->_user_xfer_buffer.clear();
|
||||
_call->_digits_buffer.clear();
|
||||
|
||||
Board::board(_pvt->target().device)->_timers.del(_idx_xfer_dial);
|
||||
|
||||
DBG(FUNC, PVT_FMT(_pvt->target(), "r (ret=%s, done xfer)") % (ret ? "true" : "false"));
|
||||
return ret;
|
||||
}
|
||||
|
||||
_call->_digits_buffer += tmp[0];
|
||||
_call->_user_xfer_buffer.erase(0, 1);
|
||||
DBG(FUNC, PVT_FMT(_pvt->target(), "r (false, no xfer)"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (tmp == _call->_user_xfer_digits.substr(0,amount))
|
||||
{
|
||||
if (!(_call->_flags.check(Kflags::XFER_DIALING)))
|
||||
{
|
||||
_call->_flags.set(Kflags::XFER_DIALING);
|
||||
_idx_xfer_dial = Board::board(_pvt->target().device)->_timers.add(Opt::_transferdigittimeout, &userXferTimer, _pvt, TM_VAL_CALL);
|
||||
}
|
||||
else
|
||||
{
|
||||
Board::board(_pvt->target().device)->_timers.restart(_idx_xfer_dial);
|
||||
}
|
||||
|
||||
DBG(FUNC, PVT_FMT(_pvt->target(), "r (true, buffering)"));
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
catch (K3LAPI::invalid_device & err)
|
||||
{
|
||||
LOG(ERROR, PVT_FMT(_pvt->target(), "Unable to get device: %d!") % err.device);
|
||||
}
|
||||
|
||||
_call->_digits_buffer += tmp[0];
|
||||
_call->_user_xfer_buffer.erase(0, 1);
|
||||
DBG(FUNC, PVT_FMT(_pvt->target(), "r (false, buffering)"));
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
static void userXferTimer(Board::KhompPvt * pvt)
|
||||
{
|
||||
DBG(FUNC, PVT_FMT(pvt->target(), "c"));
|
||||
|
||||
T * call = static_cast<T *>(pvt->call());
|
||||
|
||||
try
|
||||
{
|
||||
ScopedPvtLock lock(pvt);
|
||||
|
||||
if (!call->_user_xfer_buffer.empty())
|
||||
{
|
||||
pvt->command(KHOMP_LOG, CM_DIAL_DTMF, call->_user_xfer_buffer.c_str());
|
||||
|
||||
/* clear the buffer that has been send */
|
||||
call->_user_xfer_buffer.clear();
|
||||
}
|
||||
|
||||
call->_flags.clear(Kflags::XFER_DIALING);
|
||||
}
|
||||
catch (ScopedLockFailed & err)
|
||||
{
|
||||
LOG(ERROR, PVT_FMT(pvt->target(),"r (unable to lock %s!)") % err._msg.c_str() );
|
||||
return;
|
||||
}
|
||||
|
||||
DBG(FUNC, PVT_FMT(pvt->target(), "r"));
|
||||
}
|
||||
|
||||
bool _is_ok;
|
||||
T * _call;
|
||||
Board::KhompPvt * _pvt;
|
||||
Board::ChanTimer::Index _idx_xfer_dial;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Transfer<T, false>
|
||||
{
|
||||
Transfer(Board::KhompPvt * pvt) : _pvt(pvt), _is_ok(false) {}
|
||||
|
||||
bool clear()
|
||||
{
|
||||
if(!_is_ok)
|
||||
{
|
||||
_call = dynamic_cast<T *>(_pvt->call());
|
||||
|
||||
_is_ok = true;
|
||||
|
||||
if(!_call)
|
||||
{
|
||||
DBG(FUNC, D("Error in cast"));
|
||||
_is_ok = false;
|
||||
}
|
||||
}
|
||||
|
||||
_call->_flags.clear(Kflags::XFER_DIALING);
|
||||
_call->_flags.clear(Kflags::XFER_QSIG_DIALING);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool userTransfer(switch_core_session_t * session, const char *data)
|
||||
{
|
||||
DBG(FUNC, PVT_FMT(_pvt->target(), "c"));
|
||||
|
||||
std::string dest("");
|
||||
|
||||
bool opt_nowait = false;
|
||||
|
||||
try
|
||||
{
|
||||
Strings::vector_type params;
|
||||
|
||||
Strings::tokenize((const char *)data, params, "|,", 2);
|
||||
|
||||
dest = params[0];
|
||||
|
||||
if (params.size() > 1)
|
||||
{
|
||||
opt_nowait = (params[1].find('n') != std::string::npos);
|
||||
|
||||
// other options go here...
|
||||
}
|
||||
|
||||
ScopedPvtLock lock(_pvt);
|
||||
|
||||
int timeout = 5;
|
||||
|
||||
if(!_pvt->call()->_flags.check(Kflags::REALLY_CONNECTED) && !_pvt->loopWhileFlagTimed(Kflags::REALLY_CONNECTED, timeout, false))
|
||||
return false;
|
||||
|
||||
DBG(FUNC, PVT_FMT(_pvt->target(), "ss_transfer on channel!"));
|
||||
|
||||
_pvt->command(KHOMP_LOG, CM_SS_TRANSFER,
|
||||
STG(FMT("transferred_to=\"%s\" await_connect=\"%d\"")
|
||||
% dest % (opt_nowait ? 0 : 1)).c_str());
|
||||
|
||||
}
|
||||
catch (ScopedLockFailed & err)
|
||||
{
|
||||
LOG(ERROR, PVT_FMT(_pvt->target(),"r (unable to lock %s!)") % err._msg.c_str() );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
DBG(FUNC, PVT_FMT(_pvt->target(), "r"));
|
||||
return true;
|
||||
}
|
||||
|
||||
/* User transfer functions */
|
||||
bool doUserXferUnlocked(void)
|
||||
{
|
||||
DBG(FUNC, PVT_FMT(_pvt->target(), "c"));
|
||||
|
||||
bool ret = false;
|
||||
|
||||
if (_call->_flags.check(Kflags::XFER_QSIG_DIALING))
|
||||
{
|
||||
DBG(FUNC, PVT_FMT(_pvt->target(), "ss_transfer on channel!"));
|
||||
|
||||
_call->_flags.clear(Kflags::XFER_DIALING);
|
||||
_call->_flags.clear(Kflags::XFER_QSIG_DIALING);
|
||||
|
||||
ret = _pvt->command(KHOMP_LOG, CM_SS_TRANSFER,
|
||||
STG(FMT("transferred_to=\"%s\" await_connect=\"1\"") % _call->_qsig_number).c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG(FUNC, PVT_FMT(_pvt->target(), "starting to store digits for ss_transfer..."));
|
||||
_call->_flags.set(Kflags::XFER_QSIG_DIALING);
|
||||
|
||||
_xfer_thread = threadCreate(Transfer<T, false>::userXferPlayback,(void*) _pvt);
|
||||
_xfer_thread->start();
|
||||
|
||||
ret = true;
|
||||
}
|
||||
|
||||
DBG(FUNC, PVT_FMT(_pvt->target(), "r (%s)") % (ret ? "true" : "false"));
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
bool checkUserXferUnlocked(std::string digit)
|
||||
{
|
||||
DBG(FUNC, PVT_FMT(_pvt->target(), "c (CM_SS_TRANSFER)"));
|
||||
|
||||
|
||||
if (_call->_user_xfer_digits.empty())
|
||||
{
|
||||
_call->_digits_buffer += digit;
|
||||
DBG(FUNC, PVT_FMT(_pvt->target(), "r (disabled)"));
|
||||
return false;
|
||||
}
|
||||
|
||||
_call->_user_xfer_buffer += digit;
|
||||
|
||||
DBG(FUNC, PVT_FMT(_pvt->target(), "c digits=[%s] buffer=[%s]") % _call->_user_xfer_digits % _call->_user_xfer_buffer );
|
||||
|
||||
/* temporary buffer */
|
||||
std::string tmp = _call->_user_xfer_buffer;
|
||||
|
||||
unsigned int amount = tmp.size();
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
if (amount == _call->_user_xfer_digits.size())
|
||||
{
|
||||
if (tmp == _call->_user_xfer_digits)
|
||||
{
|
||||
bool ret = doUserXferUnlocked();
|
||||
|
||||
_call->_user_xfer_buffer.clear();
|
||||
_call->_qsig_number.clear();
|
||||
_call->_digits_buffer.clear();
|
||||
|
||||
if(!_call->_flags.check(Kflags::XFER_QSIG_DIALING))
|
||||
{
|
||||
Board::board(_pvt->target().device)->_timers.del(_idx_xfer_dial);
|
||||
|
||||
DBG(FUNC, PVT_FMT(_pvt->target(), "r (ret=%s, done xfer)") % (ret ? "true" : "false"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Board::board(_pvt->target().device)->_timers.restart(_idx_xfer_dial);
|
||||
DBG(FUNC, PVT_FMT(_pvt->target(), "r (waiting digits for transfer)"));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (_call->_flags.check(Kflags::XFER_QSIG_DIALING))
|
||||
{
|
||||
DBG(FUNC, PVT_FMT(_pvt->target(), "putting digits ('%s') on transfer-to number!") % tmp);
|
||||
|
||||
_call->_qsig_number += tmp[0];
|
||||
_call->_user_xfer_buffer.erase(0, 1);
|
||||
Board::board(_pvt->target().device)->_timers.restart(_idx_xfer_dial);
|
||||
|
||||
DBG(FUNC, PVT_FMT(_pvt->target(), "r (true, qsig transfer)"));
|
||||
return true;
|
||||
}
|
||||
|
||||
_call->_digits_buffer += tmp[0];
|
||||
_call->_user_xfer_buffer.erase(0, 1);
|
||||
DBG(FUNC, PVT_FMT(_pvt->target(), "r (false, no qsig)"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (tmp == _call->_user_xfer_digits.substr(0,amount))
|
||||
{
|
||||
if (!(_call->_flags.check(Kflags::XFER_DIALING) || _call->_flags.check(Kflags::XFER_QSIG_DIALING)))
|
||||
{
|
||||
_call->_flags.set(Kflags::XFER_DIALING);
|
||||
_idx_xfer_dial = Board::board(_pvt->target().device)->_timers.add(Opt::_transferdigittimeout, &userXferTimer, _pvt, TM_VAL_CALL);
|
||||
}
|
||||
else
|
||||
{
|
||||
Board::board(_pvt->target().device)->_timers.restart(_idx_xfer_dial);
|
||||
}
|
||||
|
||||
DBG(FUNC, PVT_FMT(_pvt->target(), "r (true, buffering)"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_call->_flags.check(Kflags::XFER_QSIG_DIALING))
|
||||
{
|
||||
DBG(FUNC, PVT_FMT(_pvt->target(), "putting digits ('%s') on transfer-to number!") % tmp);
|
||||
|
||||
_call->_qsig_number += tmp[0];
|
||||
_call->_user_xfer_buffer.erase(0, 1);
|
||||
|
||||
Board::board(_pvt->target().device)->_timers.restart(_idx_xfer_dial);
|
||||
DBG(FUNC, PVT_FMT(_pvt->target(), "r (true, qsig buffering)"));
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
catch (K3LAPI::invalid_device & err)
|
||||
{
|
||||
LOG(ERROR, PVT_FMT(_pvt->target(), "Unable to get device: %d!") % err.device);
|
||||
}
|
||||
|
||||
_call->_digits_buffer += tmp[0];
|
||||
_call->_user_xfer_buffer.erase(0, 1);
|
||||
DBG(FUNC, PVT_FMT(_pvt->target(), "r (false, buffering)"));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void userXferTimer(Board::KhompPvt * pvt)
|
||||
{
|
||||
DBG(FUNC, PVT_FMT(pvt->target(), "c"));
|
||||
|
||||
T * call = static_cast<T *>(pvt->call());
|
||||
|
||||
try
|
||||
{
|
||||
ScopedPvtLock lock(pvt);
|
||||
|
||||
if (!call->_user_xfer_buffer.empty())
|
||||
{
|
||||
pvt->command(KHOMP_LOG, CM_DIAL_DTMF, call->_user_xfer_buffer.c_str());
|
||||
|
||||
/* clear the buffer that has been send */
|
||||
call->_user_xfer_buffer.clear();
|
||||
}
|
||||
|
||||
if (!call->_qsig_number.empty())
|
||||
{
|
||||
pvt->command(KHOMP_LOG, CM_SS_TRANSFER,
|
||||
STG(FMT("transferred_to=\"%s\" await_connect=\"1\"") % call->_qsig_number).c_str());
|
||||
|
||||
/* clear the buffer that has been send */
|
||||
call->_qsig_number.clear();
|
||||
}
|
||||
|
||||
call->_flags.clear(Kflags::XFER_DIALING);
|
||||
call->_flags.clear(Kflags::XFER_QSIG_DIALING);
|
||||
}
|
||||
catch (ScopedLockFailed & err)
|
||||
{
|
||||
LOG(ERROR, PVT_FMT(pvt->target(),"r (unable to lock %s!)") % err._msg.c_str() );
|
||||
return;
|
||||
}
|
||||
|
||||
DBG(FUNC, PVT_FMT(pvt->target(), "r"));
|
||||
}
|
||||
|
||||
static switch_status_t dtmfCallback(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen)
|
||||
{
|
||||
char sbuf[3];
|
||||
|
||||
if(!session)
|
||||
{
|
||||
DBG(FUNC,D("session is NULL"))
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
switch_channel_t * chan = switch_core_session_get_channel(session);
|
||||
|
||||
if(!chan)
|
||||
{
|
||||
DBG(FUNC,D("channel is NULL"))
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
switch_core_session_t *peer_session = switch_core_session_locate(switch_channel_get_variable(chan,SWITCH_SIGNAL_BOND_VARIABLE));
|
||||
|
||||
if(!peer_session)
|
||||
{
|
||||
DBG(FUNC,D("session is NULL"))
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
switch (itype)
|
||||
{
|
||||
case SWITCH_INPUT_TYPE_DTMF:
|
||||
{
|
||||
switch_dtmf_t *dtmf = (switch_dtmf_t *) input;
|
||||
|
||||
Board::KhompPvt * tech_pvt = static_cast< Board::KhompPvt* >(switch_core_session_get_private(peer_session));
|
||||
if(!tech_pvt)
|
||||
{
|
||||
DBG(FUNC,D("Init: pvt is NULL"))
|
||||
switch_core_session_rwunlock(peer_session);
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
char s[] = { dtmf->digit, '\0' };
|
||||
tech_pvt->sendDtmf(s);
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch_core_session_rwunlock(peer_session);
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static int userXferPlayback(void * pvt_ptr)
|
||||
{
|
||||
/* get pointer... */
|
||||
Board::KhompPvt * pvt = static_cast < Board::KhompPvt * > (pvt_ptr);
|
||||
|
||||
DBG(FUNC, PVT_FMT(pvt->target(), "c"));
|
||||
|
||||
try
|
||||
{
|
||||
ScopedPvtLock lock(pvt);
|
||||
|
||||
/* get the owner */
|
||||
switch_channel_t * chan = pvt->getFSChannel();
|
||||
|
||||
/* get other side of the bridge */
|
||||
switch_core_session_t * peer_session = NULL;
|
||||
switch_core_session_get_partner(pvt->session(),&peer_session);
|
||||
|
||||
if(!peer_session)
|
||||
{
|
||||
DBG(FUNC, PVT_FMT(pvt->target(), "r (session is null)"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch_channel_t * peer = switch_core_session_get_channel(peer_session);
|
||||
|
||||
/* put the channel in hold */
|
||||
//switch_core_session_t *session = switch_core_session_locate(switch_channel_get_variable(chan,SWITCH_SIGNAL_BOND_VARIABLE));
|
||||
//switch_channel_t *chan_core = switch_core_session_get_channel(session);
|
||||
|
||||
const char *stream;
|
||||
|
||||
if (!(stream = switch_channel_get_variable(chan, SWITCH_HOLD_MUSIC_VARIABLE)))
|
||||
{
|
||||
stream = "silence";
|
||||
}
|
||||
|
||||
DBG(FUNC, PVT_FMT(pvt->target(), "stream=%s") % stream);
|
||||
|
||||
if (stream && strcasecmp(stream, "silence"))
|
||||
{
|
||||
/* Freeswitch not get/put frames */
|
||||
//switch_channel_set_flag(channel, CF_HOLD);
|
||||
switch_ivr_broadcast(switch_core_session_get_uuid(pvt->session()),stream, SMF_ECHO_ALEG | SMF_LOOP | SMF_PRIORITY);
|
||||
}
|
||||
|
||||
switch_core_session_rwunlock(peer_session);
|
||||
lock.unlock();
|
||||
|
||||
/* kickstart my heart */
|
||||
switch_input_args_t args = {0};
|
||||
args.input_callback = dtmfCallback;
|
||||
|
||||
/* wait while xfering... */
|
||||
while (true)
|
||||
{
|
||||
switch_ivr_collect_digits_callback(peer_session,&args,1000,0);
|
||||
ScopedPvtLock lock2(pvt);
|
||||
|
||||
if (!pvt->call()->_flags.check(Kflags::XFER_QSIG_DIALING))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
lock2.unlock();
|
||||
}
|
||||
|
||||
//switch_channel_clear_flag(channel, CF_HOLD);
|
||||
|
||||
switch_channel_stop_broadcast(chan);
|
||||
switch_channel_wait_for_flag(chan, CF_BROADCAST, SWITCH_FALSE, 5000, NULL);
|
||||
switch_core_session_rwunlock(pvt->session());
|
||||
switch_core_session_rwunlock(peer_session);
|
||||
|
||||
//switch_ivr_unhold_uuid(switch_channel_get_variable(chan,SWITCH_SIGNAL_BOND_VARIABLE));
|
||||
}
|
||||
catch (ScopedLockFailed & err)
|
||||
{
|
||||
LOG(ERROR, PVT_FMT(pvt->target(),"r (unable to lock %s!)") % err._msg.c_str() );
|
||||
return NULL;
|
||||
}
|
||||
catch (Board::KhompPvt::InvalidSwitchChannel & err)
|
||||
{
|
||||
LOG(ERROR, PVT_FMT(pvt->target(), "r (%s)") % err._msg.c_str() );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DBG(FUNC, PVT_FMT(pvt->target(), "r"));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool _is_ok;
|
||||
T * _call;
|
||||
Board::KhompPvt * _pvt;
|
||||
Thread * _xfer_thread;
|
||||
Board::ChanTimer::Index _idx_xfer_dial;
|
||||
};
|
||||
|
||||
/*************************** SMS **********************************************/
|
||||
struct SMS : public Application
|
||||
{
|
||||
typedef std::list< switch_core_session_t *> OwnersList;
|
||||
|
||||
struct SMSStatistics : public Statistics
|
||||
{
|
||||
SMSStatistics():
|
||||
_sms_number_incoming(0),
|
||||
_sms_number_outgoing(0),
|
||||
_sms_number_confirm(0),
|
||||
_sms_number_broadcast(0) {};
|
||||
|
||||
void incrementIncoming()
|
||||
{
|
||||
_sms_number_incoming++;
|
||||
}
|
||||
|
||||
void incrementOutgoing()
|
||||
{
|
||||
_sms_number_outgoing++;
|
||||
}
|
||||
|
||||
void incrementConfirm()
|
||||
{
|
||||
_sms_number_confirm++;
|
||||
}
|
||||
|
||||
void incrementBroadcast()
|
||||
{
|
||||
_sms_number_broadcast++;
|
||||
}
|
||||
|
||||
std::string getDetailed()
|
||||
{
|
||||
std::string tmpBuffer;
|
||||
|
||||
tmpBuffer.append(STG(FMT("Number of incoming SMS: \t%d\n") % _sms_number_incoming));
|
||||
tmpBuffer.append(STG(FMT("Number of outgoing SMS: \t%d\n") % _sms_number_outgoing));
|
||||
tmpBuffer.append(STG(FMT("Number of broadcast SMS: \t%d\n") % _sms_number_broadcast));
|
||||
tmpBuffer.append(STG(FMT("Number of confirm SMS: \t%d\n") % _sms_number_confirm));
|
||||
|
||||
return tmpBuffer;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
_sms_number_incoming = 0;
|
||||
_sms_number_outgoing = 0;
|
||||
_sms_number_confirm = 0;
|
||||
_sms_number_broadcast = 0;
|
||||
}
|
||||
|
||||
unsigned int _sms_number_incoming;
|
||||
unsigned int _sms_number_outgoing;
|
||||
unsigned int _sms_number_confirm;
|
||||
unsigned int _sms_number_broadcast;
|
||||
};
|
||||
|
||||
SMS(Board::KhompPvt * pvt) :
|
||||
Application(pvt),
|
||||
_thread(NULL),
|
||||
_shutdown(false),
|
||||
_can_receive(false),
|
||||
_can_send(false),
|
||||
_result(0),
|
||||
_mutex(Globals::module_pool),
|
||||
_cond(Globals::module_pool),
|
||||
_buffer(8)
|
||||
{
|
||||
_cond.reset();
|
||||
_app_statistics = new SMSStatistics();
|
||||
}
|
||||
|
||||
~SMS()
|
||||
{
|
||||
stop();
|
||||
delete _app_statistics;
|
||||
}
|
||||
|
||||
struct ReceiveData
|
||||
{
|
||||
ReceiveData() {};
|
||||
|
||||
ReceiveData(const ReceiveData & o)
|
||||
{
|
||||
_type = o._type;
|
||||
_from = o._from;
|
||||
_date = o._date;
|
||||
_size = o._size;
|
||||
_coding = o._coding;
|
||||
_serial = o._serial;
|
||||
_id = o._id;
|
||||
_page = o._page;
|
||||
_pages = o._pages;
|
||||
_sc_date = o._sc_date;
|
||||
_status = o._status;
|
||||
_body = o._body;
|
||||
};
|
||||
|
||||
void clear(void)
|
||||
{
|
||||
/* reset data stuff */
|
||||
_type.clear();
|
||||
_from.clear();
|
||||
_date.clear();
|
||||
_size.clear();
|
||||
_coding.clear();
|
||||
_serial.clear();
|
||||
_id.clear();
|
||||
_page.clear();
|
||||
_pages.clear();
|
||||
_sc_date.clear();
|
||||
_status.clear();
|
||||
_body.clear();
|
||||
};
|
||||
|
||||
std::string _type;
|
||||
std::string _from;
|
||||
std::string _date;
|
||||
std::string _size;
|
||||
std::string _coding;
|
||||
std::string _serial;
|
||||
std::string _id;
|
||||
std::string _page;
|
||||
std::string _pages;
|
||||
std::string _sc_date;
|
||||
std::string _status;
|
||||
std::string _body;
|
||||
};
|
||||
|
||||
struct SendData
|
||||
{
|
||||
SendData(): _conf(false) {};
|
||||
|
||||
SendData(const SendData & o)
|
||||
{
|
||||
_dest = o._dest;
|
||||
_body = o._body;
|
||||
_conf = o._conf;
|
||||
};
|
||||
|
||||
void clear(void)
|
||||
{
|
||||
/* reset data stuff */
|
||||
_dest.clear();
|
||||
_body.clear();
|
||||
_conf = false;
|
||||
};
|
||||
|
||||
std::string _dest;
|
||||
std::string _body;
|
||||
bool _conf;
|
||||
};
|
||||
|
||||
struct Request
|
||||
{
|
||||
/* "empty" constructor */
|
||||
Request(): _finished(NULL), _cause(NULL) {};
|
||||
|
||||
/* "real" constructor */
|
||||
Request(SendData & send_sms, volatile bool * finished, volatile KGsmCallCause * cause)
|
||||
: _send_sms(send_sms), _finished(finished), _cause(cause)
|
||||
{};
|
||||
|
||||
SendData _send_sms;
|
||||
|
||||
volatile bool * _finished;
|
||||
volatile KGsmCallCause * _cause;
|
||||
};
|
||||
|
||||
bool start()
|
||||
{
|
||||
_pvt->call()->_flags.clear(Kflags::SMS_DOING_UPLOAD);
|
||||
|
||||
_thread = threadCreate(&smsThread, (void*) this);
|
||||
_thread->start();
|
||||
}
|
||||
|
||||
bool stop()
|
||||
{
|
||||
if(!_thread)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_shutdown = true;
|
||||
_cond.signal();
|
||||
_thread->join();
|
||||
delete _thread;
|
||||
_thread = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool justAlloc(unsigned int count = 0);
|
||||
bool justStart();
|
||||
|
||||
bool sendSMS(switch_core_session_t * session, const char *data);
|
||||
|
||||
|
||||
bool onNewSMS(K3L_EVENT *e);
|
||||
bool onSMSInfo(K3L_EVENT *e);
|
||||
bool onSMSData(K3L_EVENT *e);
|
||||
bool onSMSSendResult(K3L_EVENT *e);
|
||||
|
||||
Thread *_thread;
|
||||
bool _shutdown;
|
||||
bool _can_receive;
|
||||
bool _can_send;
|
||||
ReceiveData _got_sms;
|
||||
SendData _send_sms;
|
||||
int _result;
|
||||
SavedCondition _cond;
|
||||
Globals::Mutex _mutex;
|
||||
Ringbuffer < SMS::Request > _buffer;
|
||||
OwnersList _owners;
|
||||
|
||||
static int smsThread(void * sms_ptr);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
|
||||
#endif /* _APPLICATIONS_H_ */
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,211 @@
|
||||
/*******************************************************************************
|
||||
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2010 Khomp Ind. & Com.
|
||||
|
||||
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.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file
|
||||
under the MPL, indicate your decision by deleting the provisions above and
|
||||
replace them with the notice and other provisions required by the LGPL
|
||||
License. If you do not delete the provisions above, a recipient may use your
|
||||
version of this file under either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _DEFS_H_
|
||||
#define _DEFS_H_
|
||||
|
||||
/* formatation macros */
|
||||
#include "switch_version.h"
|
||||
#include "revision.h"
|
||||
|
||||
#define KHOMP_LOG __FILE__, __SWITCH_FUNC__, __LINE__
|
||||
#define KHOMP_EVENT_MAINT "khomp::maintenance"
|
||||
|
||||
#define OBJ_FMT(dev,obj,msg) \
|
||||
FMT("%s (d=%02d,c=%03d) " msg) % __SWITCH_FUNC__ % dev % obj
|
||||
|
||||
#define OBJ_MSG(dev,obj,msg) \
|
||||
"%s (d=%02d,c=%03d) " msg, __SWITCH_FUNC__, dev, obj
|
||||
|
||||
#define PVT_FMT(tgt,msg) \
|
||||
FMT("%s (d=%02hu,c=%03hu) " msg) % __SWITCH_FUNC__ % tgt.device % tgt.object
|
||||
|
||||
#define PVT_MSG(tgt,msg) \
|
||||
"%s (d=%02hu,c=%03hu) " msg, __SWITCH_FUNC__, tgt.device, tgt.object
|
||||
|
||||
#define D(x) ( FMT( "%s: " x ) % __func__ )
|
||||
|
||||
#define STR(fmt) \
|
||||
STG(fmt).c_str()
|
||||
|
||||
/* version controller macro */
|
||||
#define SWITCH_LESS_THAN(x,y,z) \
|
||||
(FS_VERSION_MICRO != -1) && \
|
||||
(((FS_VERSION_MAJOR == x) && (FS_VERSION_MINOR == y) && (FS_VERSION_MICRO <= z)) || \
|
||||
((FS_VERSION_MAJOR == x) && (FS_VERSION_MINOR < y)) || (FS_VERSION_MAJOR < x))
|
||||
|
||||
/* signalling groups macro */
|
||||
#define CASE_R2_SIG \
|
||||
case ksigR2Digital: \
|
||||
case ksigContinuousEM: \
|
||||
case ksigPulsedEM: \
|
||||
case ksigUserR2Digital: \
|
||||
case ksigOpenCAS: \
|
||||
case ksigOpenR2
|
||||
/*
|
||||
case ksigLineSide: \
|
||||
case ksigCAS_EL7: \
|
||||
case ksigE1LC
|
||||
*/
|
||||
|
||||
#define CASE_RDSI_SIG \
|
||||
case ksigPRI_EndPoint: \
|
||||
case ksigPRI_Network: \
|
||||
case ksigPRI_Passive: \
|
||||
case ksigOpenCCS
|
||||
|
||||
#define CASE_FLASH_GRP \
|
||||
case ksigLineSide: \
|
||||
case ksigCAS_EL7: \
|
||||
case ksigE1LC
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/* Buffering size constants */
|
||||
|
||||
#define SILENCE_PACKS 2
|
||||
|
||||
#define KHOMP_READ_PACKET_TIME 16 // board sample (ms)
|
||||
|
||||
#define KHOMP_READ_PACKET_SIZE (KHOMP_READ_PACKET_TIME * 8) // asterisk sample size (bytes)
|
||||
|
||||
#define KHOMP_MIN_READ_PACKET_SIZE (10 * 8) // min size to return on khomp_read
|
||||
#define KHOMP_MAX_READ_PACKET_SIZE (30 * 8) // max size to return on khomp_read
|
||||
|
||||
#define KHOMP_AUDIO_BUFFER_SIZE (KHOMP_READ_PACKET_SIZE * 8) // buffer size (bytes)
|
||||
|
||||
/* debug and log macros */
|
||||
#define DBG(x,y) \
|
||||
{ \
|
||||
if (K::Logger::Logg.classe( C_DBG_##x ).enabled()) \
|
||||
K::Logger::Logg( C_DBG_##x , y ); \
|
||||
}
|
||||
|
||||
#define LOG(x,y) \
|
||||
{ \
|
||||
K::Logger::Logg( C_##x , y ); \
|
||||
}
|
||||
|
||||
#define LOGC(x,y) \
|
||||
{ \
|
||||
if (K::Logger::Logg.classe( C_##x ).enabled()) \
|
||||
LOG( x , y ); \
|
||||
}
|
||||
|
||||
/* useful to debug arguments */
|
||||
#define DEBUG_CLI_CMD() \
|
||||
{ \
|
||||
K::Logger::Logg2(C_CLI,stream,FMT("argc: %d ") % argc); \
|
||||
for(int i = 0;i< argc;i++) \
|
||||
K::Logger::Logg2(C_CLI,stream,FMT("argv[%d]:%s ") % i % argv[i]); \
|
||||
}
|
||||
|
||||
/* macros to cli commands */
|
||||
#define ARG_CMP(a,b) (argv[a] && !strncasecmp(argv[a],b,sizeof(b)))
|
||||
#define EXEC_CLI_CMD(command) Cli::command.execute(argc,argv)
|
||||
|
||||
/* macro to string treats */
|
||||
#define SAFE_sprintf(a, ...) snprintf(a,sizeof(a), __VA_ARGS__)
|
||||
#define SAFE_strcasecmp(a,b) strncasecmp(a, b, sizeof(b))
|
||||
|
||||
/* tags for timers */
|
||||
#define TM_VAL_CALL (unsigned int)0x01
|
||||
#define TM_VAL_CHANNEL (unsigned int)0x02
|
||||
|
||||
/* macro to creating contexts */
|
||||
#define BEGIN_CONTEXT do
|
||||
#define END_CONTEXT while(false);
|
||||
|
||||
/* Define log type */
|
||||
typedef enum
|
||||
{
|
||||
C_CLI, /* cli msgs */
|
||||
|
||||
C_ERROR, /* errors */
|
||||
C_WARNING, /* warnings */
|
||||
C_MESSAGE, /* normal msgs */
|
||||
|
||||
C_EVENT, /* k3l events */
|
||||
C_COMMAND, /* k3l commands */
|
||||
|
||||
C_AUDIO_EV, /* k3l audio events */
|
||||
C_MODEM_EV, /* gsm modem events */
|
||||
C_LINK_STT, /* link status msgs */
|
||||
C_CAS_MSGS, /* cas events msgs */
|
||||
|
||||
C_DBG_FUNC,
|
||||
C_DBG_LOCK,
|
||||
C_DBG_THRD,
|
||||
C_DBG_STRM,
|
||||
|
||||
C_DBG_CONF,
|
||||
}
|
||||
class_type;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
O_CONSOLE,
|
||||
O_GENERIC,
|
||||
O_R2TRACE,
|
||||
}
|
||||
output_type;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SCE_SHOW_WARNING,
|
||||
SCE_SHOW_DEBUG,
|
||||
SCE_SHOW_SAME,
|
||||
SCE_HIDE
|
||||
}
|
||||
send_cmd_error_type;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
T_UNKNOWN = 2,
|
||||
T_TRUE = 1,
|
||||
T_FALSE = 0,
|
||||
}
|
||||
TriState;
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,160 @@
|
||||
/*******************************************************************************
|
||||
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2010 Khomp Ind. & Com.
|
||||
|
||||
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.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file
|
||||
under the MPL, indicate your decision by deleting the provisions above and
|
||||
replace them with the notice and other provisions required by the LGPL
|
||||
License. If you do not delete the provisions above, a recipient may use your
|
||||
version of this file under either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _FRAME_HPP_
|
||||
#define _FRAME_HPP_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <ringbuffer.hpp>
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
struct FrameStorage
|
||||
{
|
||||
static const unsigned int frame_count = 24;//6;
|
||||
static const unsigned int audio_count = 24;//4;
|
||||
|
||||
FrameStorage(switch_codec_t * codec, int packet_size);
|
||||
virtual ~FrameStorage();
|
||||
|
||||
inline switch_frame_t * next_frame(void)
|
||||
{
|
||||
return &(_frames[next_index()]);
|
||||
}
|
||||
|
||||
inline unsigned int next_index()
|
||||
{
|
||||
unsigned int tmp = _index;
|
||||
|
||||
if (++_index >= frame_count)
|
||||
_index = 0;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
inline switch_frame_t * cng_frame(void)
|
||||
{
|
||||
return &_cng_frame;
|
||||
}
|
||||
|
||||
char * audio_buffer()
|
||||
{
|
||||
return _buffer;
|
||||
};
|
||||
|
||||
private:
|
||||
switch_frame_t _cng_frame;
|
||||
|
||||
switch_frame_t * _frames;
|
||||
char * _buffer;
|
||||
|
||||
unsigned int _index;
|
||||
};
|
||||
|
||||
/* Internal frame array structure. */
|
||||
template < int S >
|
||||
struct FrameManager: protected FrameStorage
|
||||
{
|
||||
typedef char Packet[ S ];
|
||||
|
||||
typedef Ringbuffer < Packet > AudioBuffer;
|
||||
|
||||
FrameManager(switch_codec_t * codec)
|
||||
: FrameStorage(codec, S),
|
||||
_audio(audio_count, (Packet*)audio_buffer())
|
||||
{};
|
||||
|
||||
// ~FrameManager();
|
||||
|
||||
// may throw Ringbuffer::BufferEmpty
|
||||
switch_frame_t * pick(void)
|
||||
{
|
||||
try
|
||||
{
|
||||
/* try to consume from buffer.. */
|
||||
Packet & a = _audio.consumer_start();
|
||||
|
||||
switch_frame * f = next_frame();
|
||||
|
||||
/* adjust pointer */
|
||||
f->data = (char *)(&a);
|
||||
|
||||
/* advance now */
|
||||
_audio.consumer_commit();
|
||||
|
||||
return f;
|
||||
}
|
||||
catch (...) // AudioBuffer::BufferEmpty & e)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// may throw Ringbuffer::BufferFull
|
||||
bool give(const char * buf, unsigned int size)
|
||||
{
|
||||
return _audio.provider_partial(buf, size);
|
||||
}
|
||||
|
||||
switch_frame_t * cng(void)
|
||||
{
|
||||
return cng_frame();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
_audio.clear();
|
||||
}
|
||||
|
||||
protected:
|
||||
AudioBuffer _audio;
|
||||
|
||||
unsigned int _index;
|
||||
};
|
||||
|
||||
typedef FrameManager < Globals::switch_packet_size > FrameSwitchManager;
|
||||
typedef FrameManager < Globals::boards_packet_size > FrameBoardsManager;
|
||||
|
||||
#endif /* _FRAME_HPP_ */
|
||||
@@ -0,0 +1,119 @@
|
||||
/*******************************************************************************
|
||||
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2010 Khomp Ind. & Com.
|
||||
|
||||
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.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file
|
||||
under the MPL, indicate your decision by deleting the provisions above and
|
||||
replace them with the notice and other provisions required by the LGPL
|
||||
License. If you do not delete the provisions above, a recipient may use your
|
||||
version of this file under either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _GLOBALS_H_
|
||||
#define _GLOBALS_H_
|
||||
#include "k3lapi.hpp"
|
||||
|
||||
#include <config_options.hpp>
|
||||
#include <k3lutil.hpp>
|
||||
#include <verbose.hpp>
|
||||
#include <regex.hpp>
|
||||
#include <timer.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
|
||||
#include <simple_lock.hpp>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include <switch.h>
|
||||
}
|
||||
|
||||
/* As this is a static-variable-only struct, member variable *
|
||||
* names need not to get "_" in front of the name */
|
||||
|
||||
struct Globals
|
||||
{
|
||||
typedef void * global_timer_data;
|
||||
typedef void (global_timer_func)(global_timer_data);
|
||||
typedef TimerTemplate < global_timer_func, global_timer_data > GlobalTimer;
|
||||
|
||||
typedef SimpleNonBlockLock<25,100> Mutex;
|
||||
|
||||
/* FreeSWITCH variables for packets and buffer */
|
||||
// in ms
|
||||
static const unsigned int switch_packet_duration = 30;
|
||||
static const unsigned int boards_packet_duration = 24;
|
||||
// in bytes
|
||||
static const unsigned int switch_packet_size = switch_packet_duration * 8;
|
||||
static const unsigned int boards_packet_size = boards_packet_duration * 8;
|
||||
static const unsigned int cng_buffer_size = (switch_packet_size > boards_packet_size ? switch_packet_size : boards_packet_size);
|
||||
|
||||
/* Father */
|
||||
static K3LAPI k3lapi;
|
||||
|
||||
/* Son */
|
||||
static K3LUtil k3lutil;
|
||||
|
||||
/* Holy Spirit */
|
||||
static Verbose verbose;
|
||||
|
||||
/* Global timer */
|
||||
static GlobalTimer * global_timer;
|
||||
|
||||
/* Mutex to KhompPvt allocation */
|
||||
static Mutex khomp_alloc_mutex;
|
||||
|
||||
/* Config options class */
|
||||
static ConfigOptions options;
|
||||
|
||||
/* FreeSWITCH Articular Ligaments */
|
||||
static switch_endpoint_interface_t * khomp_endpoint_interface;
|
||||
static switch_endpoint_interface_t * khomp_sms_endpoint_interface;
|
||||
static switch_endpoint_interface_t * khomp_pr_endpoint_interface;
|
||||
static switch_application_interface_t * khomp_app_inteface;
|
||||
static switch_api_interface_t * api_interface;
|
||||
static switch_memory_pool_t * module_pool;
|
||||
|
||||
/* Still a nice workaround */
|
||||
volatile static bool logs_being_rotated;
|
||||
|
||||
/* Trace flags */
|
||||
static bool flag_trace_rdsi;
|
||||
};
|
||||
|
||||
#endif /* _GLOBALS_H_ */
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,376 @@
|
||||
/*******************************************************************************
|
||||
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2010 Khomp Ind. & Com.
|
||||
|
||||
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.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file
|
||||
under the MPL, indicate your decision by deleting the provisions above and
|
||||
replace them with the notice and other provisions required by the LGPL
|
||||
License. If you do not delete the provisions above, a recipient may use your
|
||||
version of this file under either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _KHOMP_PVT_FXO_H_
|
||||
#define _KHOMP_PVT_FXO_H_
|
||||
|
||||
#include "khomp_pvt.h"
|
||||
#include "applications.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/********************************* FXO Board **********************************/
|
||||
/******************************************************************************/
|
||||
struct BoardFXO: public Board
|
||||
{
|
||||
/******************************************************************************/
|
||||
/******************************** FXO Channel *********************************/
|
||||
struct KhompPvtFXO: public KhompPvt
|
||||
{
|
||||
/********************************** FXO Call **********************************/
|
||||
struct CallFXO : public Call
|
||||
{
|
||||
CallFXO() {}
|
||||
|
||||
bool process(std::string name, std::string value = "")
|
||||
{
|
||||
if (name == "pre")
|
||||
{
|
||||
DBG(FUNC, D("pre digits adjusted (%s).") % value);
|
||||
_pre_digits = value;
|
||||
}
|
||||
else if (name == "answer_info")
|
||||
{
|
||||
_call_info_report = true;
|
||||
}
|
||||
else if (name == "drop_on")
|
||||
{
|
||||
_call_info_report = true;
|
||||
|
||||
Strings::vector_type drop_item;
|
||||
Strings::tokenize (value, drop_item, ".+");
|
||||
|
||||
for (Strings::vector_type::iterator i = drop_item.begin(); i != drop_item.end(); i++)
|
||||
{
|
||||
|
||||
if ((*i) == "message_box") _call_info_drop |= CI_MESSAGE_BOX;
|
||||
else if ((*i) == "human_answer") _call_info_drop |= CI_HUMAN_ANSWER;
|
||||
else if ((*i) == "answering_machine") _call_info_drop |= CI_ANSWERING_MACHINE;
|
||||
else if ((*i) == "carrier_message") _call_info_drop |= CI_CARRIER_MESSAGE;
|
||||
else if ((*i) == "unknown") _call_info_drop |= CI_UNKNOWN;
|
||||
else
|
||||
{
|
||||
LOG(ERROR, FMT("unknown paramenter to 'calldrop' Dial option: '%s'.") % (*i));
|
||||
continue;
|
||||
}
|
||||
|
||||
DBG(FUNC, FMT("droping call on '%s'.") % (*i));
|
||||
}
|
||||
}
|
||||
else if (name == "usr_xfer")
|
||||
{
|
||||
_user_xfer_digits = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Call::process(name, value);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool clear()
|
||||
{
|
||||
_pre_digits.clear();
|
||||
_call_info_report = false;
|
||||
_call_info_drop = 0;
|
||||
|
||||
_user_xfer_digits = Opt::_user_xfer;
|
||||
_user_xfer_buffer.clear();
|
||||
_digits_buffer.clear();
|
||||
|
||||
_var_fax_adjust = T_UNKNOWN;
|
||||
|
||||
return Call::clear();
|
||||
}
|
||||
|
||||
std::string _pre_digits;
|
||||
|
||||
/* report what we got? */
|
||||
bool _call_info_report;
|
||||
|
||||
/* what call info flags should make us drop the call? */
|
||||
long int _call_info_drop;
|
||||
|
||||
/* used for xfer on user signaling */
|
||||
std::string _user_xfer_digits;
|
||||
std::string _user_xfer_buffer;
|
||||
std::string _digits_buffer;
|
||||
|
||||
TriState _var_fax_adjust;
|
||||
|
||||
//ChanTimer::Index _idx_disconnect;
|
||||
};
|
||||
/******************************************************************************/
|
||||
KhompPvtFXO(K3LAPI::target & target) : KhompPvt(target)
|
||||
{
|
||||
_fax = new Fax(this);
|
||||
_transfer = new Transfer<CallFXO>(this);
|
||||
command(KHOMP_LOG, CM_ENABLE_CALL_ANSWER_INFO);
|
||||
}
|
||||
|
||||
~KhompPvtFXO()
|
||||
{
|
||||
delete _fax;
|
||||
delete _transfer;
|
||||
}
|
||||
|
||||
CallFXO * callFXO()
|
||||
{
|
||||
return (CallFXO *)call();
|
||||
}
|
||||
|
||||
int makeCall(std::string params = "");
|
||||
bool doChannelAnswer(CommandRequest &);
|
||||
|
||||
bool onNewCall(K3L_EVENT *e);
|
||||
bool onDisconnect(K3L_EVENT *e);
|
||||
bool onChannelRelease(K3L_EVENT *e);
|
||||
bool onCallSuccess(K3L_EVENT *e);
|
||||
bool onCallFail(K3L_EVENT *e);
|
||||
bool onAudioStatus(K3L_EVENT *e);
|
||||
bool onSeizeSuccess(K3L_EVENT *e);
|
||||
bool onDtmfDetected(K3L_EVENT *e);
|
||||
bool onDtmfSendFinish(K3L_EVENT *);
|
||||
bool onCallAnswerInfo(K3L_EVENT *e);
|
||||
|
||||
virtual bool eventHandler(K3L_EVENT *e)
|
||||
{
|
||||
DBG(STRM, D("(FXO) c"));
|
||||
|
||||
bool ret = true;
|
||||
|
||||
switch(e->Code)
|
||||
{
|
||||
case EV_NEW_CALL:
|
||||
ret = onNewCall(e);
|
||||
break;
|
||||
case EV_DISCONNECT:
|
||||
ret = onDisconnect(e);
|
||||
break;
|
||||
case EV_CHANNEL_FREE:
|
||||
case EV_CHANNEL_FAIL:
|
||||
ret = onChannelRelease(e);
|
||||
break;
|
||||
case EV_CALL_SUCCESS:
|
||||
ret = onCallSuccess(e);
|
||||
break;
|
||||
case EV_CALL_FAIL:
|
||||
ret = onCallFail(e);
|
||||
break;
|
||||
case EV_AUDIO_STATUS:
|
||||
ret = onAudioStatus(e);
|
||||
break;
|
||||
case EV_SEIZE_SUCCESS:
|
||||
ret = onSeizeSuccess(e);
|
||||
break;
|
||||
case EV_DTMF_DETECTED:
|
||||
case EV_PULSE_DETECTED:
|
||||
ret = onDtmfDetected(e);
|
||||
break;
|
||||
case EV_DTMF_SEND_FINISH:
|
||||
ret = onDtmfSendFinish(e);
|
||||
break;
|
||||
case EV_CALL_ANSWER_INFO:
|
||||
ret = onCallAnswerInfo(e);
|
||||
break;
|
||||
case EV_FAX_CHANNEL_FREE:
|
||||
ret = _fax->onFaxChannelRelease(e);
|
||||
break;
|
||||
case EV_FAX_FILE_SENT:
|
||||
case EV_FAX_FILE_FAIL:
|
||||
case EV_FAX_TX_TIMEOUT:
|
||||
case EV_FAX_PAGE_CONFIRMATION:
|
||||
case EV_FAX_REMOTE_INFO:
|
||||
break;
|
||||
case EV_POLARITY_REVERSAL:
|
||||
break;
|
||||
default:
|
||||
ret = KhompPvt::eventHandler(e);
|
||||
break;
|
||||
}
|
||||
|
||||
DBG(STRM, D("(FXO) r"));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool application(ApplicationType type, switch_core_session_t * session, const char *data);
|
||||
|
||||
bool setupConnection();
|
||||
bool autoGainControl(bool enable);
|
||||
void setAnswerInfo(int answer_info);
|
||||
bool indicateBusyUnlocked(int cause, bool sent_signaling = false);
|
||||
void reportFailToReceive(int fail_code);
|
||||
bool validContexts(Board::KhompPvt::ContextListType & contexts, std::string extra_context = "");
|
||||
|
||||
bool isOK(void);
|
||||
|
||||
bool isPhysicalFree()
|
||||
{
|
||||
K3L_CHANNEL_STATUS status;
|
||||
|
||||
if (k3lGetDeviceStatus (_target.device, _target.object + ksoChannel, &status, sizeof (status)) != ksSuccess)
|
||||
return false;
|
||||
|
||||
bool physically_free = (status.AddInfo == kfcsEnabled);
|
||||
|
||||
if(status.CallStatus != kcsFree || !physically_free)
|
||||
{
|
||||
DBG(FUNC, PVT_FMT(_target, "call status not free, or not physically free!"));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool cleanup(CleanupType type = CLN_HARD)
|
||||
{
|
||||
//Board::board(_target.device)->_timers.del(callFXO()->_idx_disconnect);
|
||||
//callFXO()->_idx_disconnect.reset();
|
||||
|
||||
call()->_flags.clear(Kflags::CALL_WAIT_SEIZE);
|
||||
call()->_flags.clear(Kflags::EARLY_RINGBACK);
|
||||
|
||||
_transfer->clear();
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case CLN_HARD:
|
||||
case CLN_FAIL:
|
||||
call()->_flags.clear(Kflags::FAX_DETECTED);
|
||||
break;
|
||||
case CLN_SOFT:
|
||||
break;
|
||||
}
|
||||
|
||||
return KhompPvt::cleanup(type);
|
||||
}
|
||||
|
||||
virtual void getSpecialVariables()
|
||||
{
|
||||
try
|
||||
{
|
||||
const char * str_fax = getFSChannelVar("KAdjustForFax");
|
||||
|
||||
callFXO()->_var_fax_adjust = (str_fax ? (!SAFE_strcasecmp(str_fax, "true") ? T_TRUE : T_FALSE) : T_UNKNOWN);
|
||||
}
|
||||
catch(Board::KhompPvt::InvalidSwitchChannel & err)
|
||||
{
|
||||
LOG(ERROR, PVT_FMT(_target, "(FXO) %s") % err._msg.c_str());
|
||||
}
|
||||
|
||||
KhompPvt::getSpecialVariables();
|
||||
}
|
||||
|
||||
bool sendDtmf(std::string digit);
|
||||
|
||||
/* used by app FAX */
|
||||
Fax * _fax;
|
||||
|
||||
Transfer<CallFXO> * _transfer;
|
||||
|
||||
// static void delayedDisconnect(Board::KhompPvt * pvt);
|
||||
|
||||
};
|
||||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
BoardFXO(int id) : Board(id) {}
|
||||
|
||||
void initializeChannels(void)
|
||||
{
|
||||
LOG(MESSAGE, "(FXO) loading channels ...");
|
||||
|
||||
for (unsigned obj = 0; obj < Globals::k3lapi.channel_count(_device_id); obj++)
|
||||
{
|
||||
K3LAPI::target tgt(Globals::k3lapi, K3LAPI::target::CHANNEL, _device_id, obj);
|
||||
KhompPvt * pvt;
|
||||
|
||||
switch(Globals::k3lapi.channel_config(_device_id, obj).Signaling)
|
||||
{
|
||||
case ksigAnalog:
|
||||
pvt = new BoardFXO::KhompPvtFXO(tgt);
|
||||
pvt->_call = new BoardFXO::KhompPvtFXO::CallFXO();
|
||||
DBG(FUNC, "(FXO) FXO channel");
|
||||
break;
|
||||
default:
|
||||
pvt = new Board::KhompPvt(tgt);
|
||||
pvt->_call = new Board::KhompPvt::Call();
|
||||
DBG(FUNC, FMT("(FXO) signaling %d unknown") % Globals::k3lapi.channel_config(_device_id, obj).Signaling);
|
||||
break;
|
||||
}
|
||||
|
||||
_channels.push_back(pvt);
|
||||
|
||||
pvt->cleanup();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
virtual bool eventHandler(const int obj, K3L_EVENT *e)
|
||||
{
|
||||
DBG(STRM, D("(FXO Board) c"));
|
||||
|
||||
bool ret = true;
|
||||
|
||||
switch(e->Code)
|
||||
{
|
||||
case :
|
||||
break;
|
||||
default:
|
||||
ret = Board::eventHandler(obj, e);
|
||||
break;
|
||||
}
|
||||
|
||||
DBG(STRM, D("(FXO Board) r"));
|
||||
|
||||
return ret;
|
||||
}
|
||||
*/
|
||||
|
||||
};
|
||||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
#endif /* _KHOMP_PVT_FXO_H_*/
|
||||
|
||||
@@ -0,0 +1,332 @@
|
||||
/*******************************************************************************
|
||||
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2010 Khomp Ind. & Com.
|
||||
|
||||
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.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file
|
||||
under the MPL, indicate your decision by deleting the provisions above and
|
||||
replace them with the notice and other provisions required by the LGPL
|
||||
License. If you do not delete the provisions above, a recipient may use your
|
||||
version of this file under either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _KHOMP_PVT_GSM_H_
|
||||
#define _KHOMP_PVT_GSM_H_
|
||||
|
||||
#include "khomp_pvt.h"
|
||||
#include "applications.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/********************************* GSM Board **********************************/
|
||||
/******************************************************************************/
|
||||
struct BoardGSM: public Board
|
||||
{
|
||||
/******************************************************************************/
|
||||
/******************************** GSM Channel *********************************/
|
||||
struct KhompPvtGSM: public KhompPvt
|
||||
{
|
||||
/********************************** GSM Call **********************************/
|
||||
struct CallGSM : public Call
|
||||
{
|
||||
CallGSM() {}
|
||||
|
||||
bool process(std::string name, std::string value = "")
|
||||
{
|
||||
if (name == "answer_info")
|
||||
{
|
||||
_call_info_report = true;
|
||||
}
|
||||
else if (name == "drop_on")
|
||||
{
|
||||
_call_info_report = true;
|
||||
|
||||
Strings::vector_type drop_item;
|
||||
Strings::tokenize (value, drop_item, ".+");
|
||||
|
||||
for (Strings::vector_type::iterator i = drop_item.begin(); i != drop_item.end(); i++)
|
||||
{
|
||||
|
||||
if ((*i) == "message_box") _call_info_drop |= CI_MESSAGE_BOX;
|
||||
else if ((*i) == "human_answer") _call_info_drop |= CI_HUMAN_ANSWER;
|
||||
else if ((*i) == "answering_machine") _call_info_drop |= CI_ANSWERING_MACHINE;
|
||||
else if ((*i) == "carrier_message") _call_info_drop |= CI_CARRIER_MESSAGE;
|
||||
else if ((*i) == "unknown") _call_info_drop |= CI_UNKNOWN;
|
||||
else
|
||||
{
|
||||
LOG(ERROR, FMT("unknown paramenter to 'calldrop' Dial option: '%s'.") % (*i));
|
||||
continue;
|
||||
}
|
||||
|
||||
DBG(FUNC, FMT("droping call on '%s'.") % (*i));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return Call::process(name, value);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool clear()
|
||||
{
|
||||
_call_info_report = false;
|
||||
_call_info_drop = 0;
|
||||
|
||||
return Call::clear();
|
||||
}
|
||||
|
||||
/* report what we got? */
|
||||
bool _call_info_report;
|
||||
|
||||
/* what call info flags should make us drop the call? */
|
||||
long int _call_info_drop;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
KhompPvtGSM(K3LAPI::target & target) : KhompPvt(target)
|
||||
{
|
||||
_sms = new SMS(this);
|
||||
command(KHOMP_LOG, CM_ENABLE_CALL_ANSWER_INFO);
|
||||
}
|
||||
|
||||
~KhompPvtGSM()
|
||||
{
|
||||
delete _sms;
|
||||
}
|
||||
|
||||
CallGSM * callGSM()
|
||||
{
|
||||
return (CallGSM *)call();
|
||||
}
|
||||
|
||||
int makeCall(std::string params = "");
|
||||
bool doChannelAnswer(CommandRequest &);
|
||||
bool doChannelHangup(CommandRequest &);
|
||||
|
||||
//bool onNewCall(K3L_EVENT *e);
|
||||
bool onChannelRelease(K3L_EVENT *e);
|
||||
bool onCallFail(K3L_EVENT *e);
|
||||
bool onCallSuccess(K3L_EVENT *e);
|
||||
bool onCallAnswerInfo(K3L_EVENT *e);
|
||||
bool onDisconnect(K3L_EVENT *e);
|
||||
//bool onDtmfDetected(K3L_EVENT *e);
|
||||
|
||||
virtual bool eventHandler(K3L_EVENT *e)
|
||||
{
|
||||
DBG(STRM, D("(GSM) c"));
|
||||
|
||||
bool ret = true;
|
||||
|
||||
switch(e->Code)
|
||||
{
|
||||
/*
|
||||
case EV_NEW_CALL:
|
||||
onNewCall(e);
|
||||
break;
|
||||
*/
|
||||
case EV_CHANNEL_FREE:
|
||||
case EV_CHANNEL_FAIL:
|
||||
ret = onChannelRelease(e);
|
||||
break;
|
||||
case EV_CALL_SUCCESS:
|
||||
ret = onCallSuccess(e);
|
||||
break;
|
||||
case EV_DISCONNECT:
|
||||
ret = onDisconnect(e);
|
||||
break;
|
||||
case EV_CALL_FAIL:
|
||||
ret = onCallFail(e);
|
||||
break;
|
||||
case EV_CALL_ANSWER_INFO:
|
||||
ret = onCallAnswerInfo(e);
|
||||
break;
|
||||
case EV_RECV_FROM_MODEM:
|
||||
break;
|
||||
case EV_NEW_SMS:
|
||||
ret = _sms->onNewSMS(e);
|
||||
break;
|
||||
case EV_SMS_INFO:
|
||||
ret = _sms->onSMSInfo(e);
|
||||
break;
|
||||
case EV_SMS_DATA:
|
||||
ret = _sms->onSMSData(e);
|
||||
break;
|
||||
case EV_SMS_SEND_RESULT:
|
||||
ret = _sms->onSMSSendResult(e);
|
||||
break;
|
||||
default:
|
||||
ret = KhompPvt::eventHandler(e);
|
||||
break;
|
||||
}
|
||||
|
||||
DBG(STRM, D("(GSM) r"));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool application(ApplicationType type, switch_core_session_t * session, const char *data);
|
||||
|
||||
bool setupConnection();
|
||||
void setAnswerInfo(int answer_info);
|
||||
bool indicateBusyUnlocked(int cause, bool sent_signaling = false);
|
||||
void reportFailToReceive(int fail_code);
|
||||
int causeFromCallFail(int fail);
|
||||
int callFailFromCause(int cause);
|
||||
bool isOK(void);
|
||||
|
||||
bool isPhysicalFree()
|
||||
{
|
||||
K3L_CHANNEL_STATUS status;
|
||||
|
||||
if (k3lGetDeviceStatus (_target.device, _target.object + ksoChannel, &status, sizeof (status)) != ksSuccess)
|
||||
return false;
|
||||
|
||||
bool physically_free = (status.AddInfo == kgsmIdle);
|
||||
|
||||
if(status.CallStatus != kcsFree || !physically_free)
|
||||
{
|
||||
DBG(FUNC, PVT_FMT(_target, "call status not free, or not physically free!"));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool sendPreAudio(int rb_value = RingbackDefs::RB_SEND_NOTHING)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool selectSimCard(const char * sim_card)
|
||||
{
|
||||
return command(KHOMP_LOG, CM_SIM_CARD_SELECT, sim_card);
|
||||
}
|
||||
|
||||
std::string getStatistics(Statistics::Type type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case Statistics::DETAILED:
|
||||
{
|
||||
/* buffer our data to return at the end */
|
||||
std::string strBuffer;
|
||||
|
||||
strBuffer.append(_pvt_statistics->getDetailed());
|
||||
strBuffer.append(_sms->statistics()->getDetailed());
|
||||
return strBuffer;
|
||||
}
|
||||
case Statistics::ROW:
|
||||
{
|
||||
return _pvt_statistics->getRow();
|
||||
}
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
void clearStatistics()
|
||||
{
|
||||
KhompPvt::clearStatistics();
|
||||
_sms->statistics()->clear();
|
||||
}
|
||||
|
||||
bool validContexts(Board::KhompPvt::ContextListType & contexts, std::string extra_context = "");
|
||||
|
||||
SMS * _sms;
|
||||
|
||||
};
|
||||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
BoardGSM(int id) : Board(id) {}
|
||||
|
||||
void initializeChannels(void)
|
||||
{
|
||||
LOG(MESSAGE, "(GSM) loading channels ...");
|
||||
|
||||
for (unsigned obj = 0; obj < Globals::k3lapi.channel_count(_device_id); obj++)
|
||||
{
|
||||
K3LAPI::target tgt(Globals::k3lapi, K3LAPI::target::CHANNEL, _device_id, obj);
|
||||
KhompPvt * pvt;
|
||||
|
||||
switch(Globals::k3lapi.channel_config(_device_id, obj).Signaling)
|
||||
{
|
||||
case ksigGSM:
|
||||
pvt = new BoardGSM::KhompPvtGSM(tgt);
|
||||
pvt->_call = new BoardGSM::KhompPvtGSM::CallGSM();
|
||||
((BoardGSM::KhompPvtGSM *)pvt)->_sms->start();
|
||||
DBG(FUNC, "(GSM) GSM channel");
|
||||
break;
|
||||
default:
|
||||
pvt = new Board::KhompPvt(tgt);
|
||||
pvt->_call = new Board::KhompPvt::Call();
|
||||
DBG(FUNC, FMT("(GSM) signaling %d unknown") % Globals::k3lapi.channel_config(_device_id, obj).Signaling);
|
||||
break;
|
||||
}
|
||||
|
||||
_channels.push_back(pvt);
|
||||
|
||||
pvt->cleanup();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
virtual bool eventHandler(const int obj, K3L_EVENT *e)
|
||||
{
|
||||
DBG(STRM, D("(GSM Board) c"));
|
||||
|
||||
bool ret = true;
|
||||
|
||||
switch(e->Code)
|
||||
{
|
||||
case :
|
||||
break;
|
||||
default:
|
||||
ret = Board::eventHandler(obj, e);
|
||||
break;
|
||||
}
|
||||
|
||||
DBG(STRM, D("(GSM Board) r"));
|
||||
|
||||
return ret;
|
||||
}
|
||||
*/
|
||||
|
||||
};
|
||||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
#endif /* _KHOMP_PVT_GSM_H_*/
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,304 @@
|
||||
/*******************************************************************************
|
||||
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2010 Khomp Ind. & Com.
|
||||
|
||||
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.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file
|
||||
under the MPL, indicate your decision by deleting the provisions above and
|
||||
replace them with the notice and other provisions required by the LGPL
|
||||
License. If you do not delete the provisions above, a recipient may use your
|
||||
version of this file under either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _KHOMP_PVT_PASSIVE_H_
|
||||
#define _KHOMP_PVT_PASSIVE_H_
|
||||
|
||||
#include "khomp_pvt.h"
|
||||
#include "applications.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/******************************** Passive Board *******************************/
|
||||
/******************************************************************************/
|
||||
struct BoardPassive: public Board
|
||||
{
|
||||
/******************************************************************************/
|
||||
/******************************** Passive Channel *****************************/
|
||||
struct KhompPvtPassive: public KhompPvt
|
||||
{
|
||||
/******************************** Passive Call ********************************/
|
||||
/*
|
||||
struct CallPassive : public Call
|
||||
{
|
||||
CallPassive() {}
|
||||
|
||||
bool process(std::string name, std::string value = "")
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
return Call::process(name, value);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool clear()
|
||||
{
|
||||
return Call::clear();
|
||||
}
|
||||
|
||||
};
|
||||
*/
|
||||
/******************************************************************************/
|
||||
KhompPvtPassive(K3LAPI::target & target) : KhompPvt(target)
|
||||
{
|
||||
}
|
||||
|
||||
~KhompPvtPassive()
|
||||
{
|
||||
}
|
||||
/*
|
||||
CallPassive * callPassive()
|
||||
{
|
||||
return (CallPassive *)call();
|
||||
}
|
||||
*/
|
||||
|
||||
virtual bool eventHandler(K3L_EVENT *e)
|
||||
{
|
||||
DBG(STRM, D("(Passive) c"));
|
||||
|
||||
bool ret = true;
|
||||
|
||||
switch(e->Code)
|
||||
{
|
||||
case EV_CHANNEL_FREE:
|
||||
case EV_CHANNEL_FAIL:
|
||||
ret = onChannelRelease(e);
|
||||
break;
|
||||
/*
|
||||
case EV_CALL_SUCCESS:
|
||||
case EV_CALL_FAIL:
|
||||
case EV_PULSE_DETECTED:
|
||||
*/
|
||||
case EV_DISCONNECT:
|
||||
case EV_DTMF_DETECTED:
|
||||
case EV_AUDIO_STATUS:
|
||||
break;
|
||||
default:
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
|
||||
DBG(STRM, D("(Passive) r"));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool validContexts(Board::KhompPvt::ContextListType & contexts, std::string extra_context = "");
|
||||
|
||||
/*
|
||||
virtual bool cleanup(CleanupType type = CLN_HARD)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case CLN_HARD:
|
||||
case CLN_FAIL:
|
||||
break;
|
||||
case CLN_SOFT:
|
||||
break;
|
||||
}
|
||||
|
||||
return KhompPvt::cleanup(type);
|
||||
}
|
||||
*/
|
||||
|
||||
};
|
||||
/******************************************************************************/
|
||||
/********************************** HI Channel ********************************/
|
||||
struct KhompPvtHI: public KhompPvtPassive
|
||||
{
|
||||
KhompPvtHI(K3LAPI::target & target) : KhompPvtPassive(target)
|
||||
{
|
||||
}
|
||||
|
||||
~KhompPvtHI()
|
||||
{
|
||||
}
|
||||
|
||||
bool onSeizureStart(K3L_EVENT *e);
|
||||
|
||||
virtual bool eventHandler(K3L_EVENT *e)
|
||||
{
|
||||
DBG(STRM, D("(HI) c"));
|
||||
|
||||
bool ret = true;
|
||||
|
||||
switch(e->Code)
|
||||
{
|
||||
case EV_SEIZURE_START:
|
||||
ret = onSeizureStart(e);
|
||||
break;
|
||||
case EV_RING_DETECTED:
|
||||
case EV_POLARITY_REVERSAL:
|
||||
break;
|
||||
default:
|
||||
ret = KhompPvtPassive::eventHandler(e);
|
||||
break;
|
||||
}
|
||||
|
||||
DBG(STRM, D("(HI) r"));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
};
|
||||
/******************************************************************************/
|
||||
/********************************* KPR Channel ********************************/
|
||||
struct KhompPvtKPR: public KhompPvtPassive
|
||||
{
|
||||
KhompPvtKPR(K3LAPI::target & target) : KhompPvtPassive(target)
|
||||
{
|
||||
}
|
||||
|
||||
~KhompPvtKPR()
|
||||
{
|
||||
}
|
||||
|
||||
bool onNewCall(K3L_EVENT *e);
|
||||
/*
|
||||
bool onConnect(K3L_EVENT *e);
|
||||
*/
|
||||
|
||||
virtual bool eventHandler(K3L_EVENT *e)
|
||||
{
|
||||
DBG(STRM, D("(KPR) c"));
|
||||
|
||||
bool ret = true;
|
||||
|
||||
switch(e->Code)
|
||||
{
|
||||
case EV_NEW_CALL:
|
||||
ret = onNewCall(e);
|
||||
break;
|
||||
case EV_CONNECT:
|
||||
break;
|
||||
case EV_SEIZURE_START:
|
||||
case EV_CAS_MFC_RECV:
|
||||
case EV_CAS_LINE_STT_CHANGED:
|
||||
case EV_LINK_STATUS:
|
||||
break;
|
||||
default:
|
||||
ret = KhompPvtPassive::eventHandler(e);
|
||||
break;
|
||||
}
|
||||
|
||||
DBG(STRM, D("(KPR) r"));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool obtainBoth();
|
||||
|
||||
};
|
||||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
BoardPassive(int id) : Board(id) {}
|
||||
|
||||
void initializeChannels(void)
|
||||
{
|
||||
LOG(MESSAGE, "(Passive) loading channels ...");
|
||||
|
||||
for (unsigned obj = 0; obj < Globals::k3lapi.channel_count(_device_id); obj++)
|
||||
{
|
||||
K3LAPI::target tgt(Globals::k3lapi, K3LAPI::target::CHANNEL, _device_id, obj);
|
||||
KhompPvt * pvt;
|
||||
|
||||
switch(Globals::k3lapi.channel_config(_device_id, obj).Signaling)
|
||||
{
|
||||
case ksigAnalog:
|
||||
pvt = new BoardPassive::KhompPvtHI(tgt);
|
||||
pvt->_call = new BoardPassive::KhompPvtHI::Call();
|
||||
DBG(FUNC, "(Passive) HI channel");
|
||||
break;
|
||||
CASE_RDSI_SIG:
|
||||
CASE_R2_SIG:
|
||||
CASE_FLASH_GRP:
|
||||
case ksigAnalogTerminal:
|
||||
pvt = new BoardPassive::KhompPvtKPR(tgt);
|
||||
pvt->_call = new BoardPassive::KhompPvtKPR::Call();
|
||||
DBG(FUNC, "(Passive) KPR channel");
|
||||
break;
|
||||
default:
|
||||
pvt = new Board::KhompPvt(tgt);
|
||||
pvt->_call = new Board::KhompPvt::Call();
|
||||
DBG(FUNC, FMT("(Passive) signaling %d unknown") % Globals::k3lapi.channel_config(_device_id, obj).Signaling);
|
||||
break;
|
||||
}
|
||||
|
||||
_channels.push_back(pvt);
|
||||
|
||||
pvt->cleanup();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
virtual bool eventHandler(const int obj, K3L_EVENT *e)
|
||||
{
|
||||
DBG(STRM, D("(Passive Board) c"));
|
||||
|
||||
bool ret = true;
|
||||
|
||||
switch(e->Code)
|
||||
{
|
||||
case :
|
||||
break;
|
||||
default:
|
||||
ret = Board::eventHandler(obj, e);
|
||||
break;
|
||||
}
|
||||
|
||||
DBG(STRM, D("(Passive Board) r"));
|
||||
|
||||
return ret;
|
||||
}
|
||||
*/
|
||||
|
||||
};
|
||||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
#endif /* _KHOMP_PVT_PASSIVE_H_*/
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
/*******************************************************************************
|
||||
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2010 Khomp Ind. & Com.
|
||||
|
||||
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.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file
|
||||
under the MPL, indicate your decision by deleting the provisions above and
|
||||
replace them with the notice and other provisions required by the LGPL
|
||||
License. If you do not delete the provisions above, a recipient may use your
|
||||
version of this file under either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef CHAN_LOCK_H
|
||||
#define CHAN_LOCK_H
|
||||
|
||||
#include <scoped_lock.hpp>
|
||||
#include "khomp_pvt.h"
|
||||
|
||||
|
||||
struct ScopedLockFailed
|
||||
{
|
||||
typedef enum { NULL_PVT, NULL_SOFT_CHAN, FAILED, ALLOC_FAILED } FailType;
|
||||
|
||||
ScopedLockFailed(FailType fail, std::string msg)
|
||||
: _fail(fail), _msg(msg) {};
|
||||
|
||||
FailType _fail;
|
||||
std::string _msg;
|
||||
};
|
||||
|
||||
|
||||
struct ScopedPvtLock: public ScopedLockBasic
|
||||
{
|
||||
typedef Board::KhompPvt KhompPvt;
|
||||
|
||||
ScopedPvtLock(KhompPvt * pvt);
|
||||
~ScopedPvtLock();
|
||||
|
||||
void unlock();
|
||||
|
||||
protected:
|
||||
KhompPvt * _pvt;
|
||||
};
|
||||
|
||||
|
||||
struct ScopedAllocLock : public ScopedLockBasic
|
||||
{
|
||||
ScopedAllocLock();
|
||||
~ScopedAllocLock();
|
||||
|
||||
void unlock();
|
||||
|
||||
};
|
||||
|
||||
#endif /* CHAN_LOCK_H */
|
||||
@@ -0,0 +1,141 @@
|
||||
/*******************************************************************************
|
||||
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2010 Khomp Ind. & Com.
|
||||
|
||||
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.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file
|
||||
under the MPL, indicate your decision by deleting the provisions above and
|
||||
replace them with the notice and other provisions required by the LGPL
|
||||
License. If you do not delete the provisions above, a recipient may use your
|
||||
version of this file under either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _Logger_H_
|
||||
#define _Logger_H_
|
||||
|
||||
#include <switch.h>
|
||||
#include <string>
|
||||
#include <simple_lock.hpp>
|
||||
#include <logger.hpp>
|
||||
#include <configurator/configfile.hpp>
|
||||
#include <klog-config.hpp>
|
||||
#include "defs.h"
|
||||
#include "format.hpp"
|
||||
|
||||
namespace K
|
||||
{
|
||||
struct LogConfig
|
||||
{
|
||||
static bool set(Logfile &, const char *, const char *, bool);
|
||||
static bool commit(Logfile &);
|
||||
};
|
||||
|
||||
struct SwitchConsoleLog {};
|
||||
|
||||
struct SwitchPrinter: public Logger::DefaultPrinter
|
||||
{
|
||||
typedef Logger::DefaultPrinter Super;
|
||||
typedef Tagged::Union < std::ostream *, Tagged::Union < int, Tagged::Union < SwitchConsoleLog > > > BaseType;
|
||||
|
||||
SwitchPrinter(std::string & msg): Super(msg) {};
|
||||
|
||||
using Super::operator();
|
||||
|
||||
bool operator()(const SwitchConsoleLog & ignored)
|
||||
{
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN,SWITCH_LOG_CONSOLE,"%s",_msg.c_str());
|
||||
return true;
|
||||
};
|
||||
};
|
||||
|
||||
/* Log manager declaration. */
|
||||
typedef Logger::Manager <class_type, output_type, SwitchPrinter, SimpleLock> LogManager;
|
||||
|
||||
/* Forward declaration */
|
||||
struct LogInternalManager;
|
||||
|
||||
struct Logger
|
||||
{
|
||||
/* Logger instance. */
|
||||
static LogManager Logg;
|
||||
|
||||
/* Util Logger instance. */
|
||||
static LogInternalManager Logg2;
|
||||
|
||||
static bool start();
|
||||
static void stop();
|
||||
static bool rotate();
|
||||
static void processLogConsole(switch_stream_handle_t *s, const std::string options, bool invert, bool unique);
|
||||
static void processLogDisk(switch_stream_handle_t *s, const std::string options, bool invert, bool unique);
|
||||
|
||||
private:
|
||||
static std::string base_path;
|
||||
static std::ofstream generic_file;
|
||||
};
|
||||
|
||||
/* Internal logging facility declaration */
|
||||
struct LogInternalManager
|
||||
{
|
||||
bool operator()(class_type classe, switch_stream_handle_t *stream, const char *args)
|
||||
{
|
||||
switch (classe)
|
||||
{
|
||||
case C_CLI:
|
||||
stream->write_function(stream,"%s\n",args);
|
||||
return true;
|
||||
default:
|
||||
return K::Logger::Logg(classe, args);
|
||||
}
|
||||
}
|
||||
|
||||
bool operator()(class_type classe, switch_stream_handle_t *stream, Format &fmt)
|
||||
{
|
||||
return K::Logger::Logg2(classe,stream,(char*) STR(fmt));
|
||||
}
|
||||
|
||||
bool operator()(class_type classe, switch_stream_handle_t *stream, const char *fmt, const char *args)
|
||||
{
|
||||
switch (classe)
|
||||
{
|
||||
case C_CLI:
|
||||
stream->write_function(stream,fmt,args);
|
||||
return true;
|
||||
default:
|
||||
return K::Logger::Logg(classe, FMT(fmt) % args);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
#endif /* _Logger_H_ */
|
||||
@@ -0,0 +1,250 @@
|
||||
/*******************************************************************************
|
||||
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2010 Khomp Ind. & Com.
|
||||
|
||||
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.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file
|
||||
under the MPL, indicate your decision by deleting the provisions above and
|
||||
replace them with the notice and other provisions required by the LGPL
|
||||
License. If you do not delete the provisions above, a recipient may use your
|
||||
version of this file under either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _OPT_H_
|
||||
#define _OPT_H_
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include "switch.h"
|
||||
#include "utils.h"
|
||||
|
||||
struct CadenceType
|
||||
{
|
||||
CadenceType(void)
|
||||
: ring(0), ring_s(0), ring_ext(0), ring_ext_s(0) {};
|
||||
|
||||
CadenceType(unsigned int _ring, unsigned int _ring_s)
|
||||
: ring(_ring), ring_s(_ring_s), ring_ext(0), ring_ext_s(0) {};
|
||||
|
||||
CadenceType(unsigned int _ring, unsigned int _ring_s, unsigned int _ring_ext, unsigned int _ring_ext_s)
|
||||
: ring(_ring), ring_s(_ring_s), ring_ext(_ring_ext), ring_ext_s(_ring_ext_s) {};
|
||||
|
||||
unsigned int ring;
|
||||
unsigned int ring_s;
|
||||
unsigned int ring_ext;
|
||||
unsigned int ring_ext_s;
|
||||
};
|
||||
|
||||
struct CSpan {
|
||||
std::string _dialplan;
|
||||
std::string _context;
|
||||
std::string _dialstring;
|
||||
};
|
||||
|
||||
struct Opt
|
||||
{
|
||||
typedef std::pair < std::string, CadenceType > CadencesPairType;
|
||||
typedef std::map < std::string, CadenceType > CadencesMapType;
|
||||
|
||||
typedef std::map < std::string, std::string > OrigToDestMapType;
|
||||
typedef std::pair < std::string, std::string > OrigToDestPairType;
|
||||
typedef std::vector < std::string > DestVectorType;
|
||||
|
||||
typedef std::map < unsigned int, std::string > BoardToOrigMapType;
|
||||
typedef std::pair < unsigned int, std::string > BoardToOrigPairType;
|
||||
|
||||
typedef std::map < std::string, unsigned int > OrigToNseqMapType;
|
||||
typedef std::pair < std::string, unsigned int > OrigToNseqPairType;
|
||||
|
||||
typedef std::pair < unsigned int,unsigned int > ObjectIdType;
|
||||
typedef std::pair < std::string, ObjectIdType > BranchToObjectPairType;
|
||||
typedef std::map < std::string, ObjectIdType > BranchToObjectMapType;
|
||||
|
||||
typedef std::map < std::string, std::string > BranchToOptMapType;
|
||||
typedef std::pair < std::string, std::string > BranchToOptPairType;
|
||||
|
||||
typedef std::map < std::string, std::string > GroupToDestMapType;
|
||||
typedef std::pair < std::string, std::string > GroupToDestPairType;
|
||||
|
||||
typedef std::pair < std::string, CSpan > SpanPairType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GFLAG_MY_CODEC_PREFS = (1 << 0)
|
||||
}
|
||||
GFLAGS;
|
||||
|
||||
static void initialize(void);
|
||||
static void obtain(void);
|
||||
static void commit(void);
|
||||
static void printConfiguration(switch_stream_handle_t*);
|
||||
|
||||
protected:
|
||||
|
||||
static void loadConfiguration(const char *, const char **, bool show_errors = true);
|
||||
static void cleanConfiguration(void);
|
||||
|
||||
static switch_xml_t processSimpleXML(switch_xml_t &xml, const std::string& child_name);
|
||||
static void processGroupXML(switch_xml_t &xml);
|
||||
static void processCadenceXML(switch_xml_t &xml);
|
||||
static void processFXSBranchesXML(switch_xml_t &xml);
|
||||
static void processFXSHotlines(switch_xml_t &xml);
|
||||
static void processFXSOptions(switch_xml_t &xml);
|
||||
|
||||
public:
|
||||
static bool _debug;
|
||||
static std::string _dialplan;
|
||||
static std::string _context;
|
||||
static std::map < std::string, CSpan > _spans;
|
||||
static GroupToDestMapType _groups;
|
||||
static CadencesMapType _cadences;
|
||||
|
||||
static bool _echo_canceller;
|
||||
static bool _auto_gain_control;
|
||||
static bool _out_of_band_dtmfs;
|
||||
static bool _suppression_delay;
|
||||
static bool _pulse_forwarding;
|
||||
static bool _native_bridge;
|
||||
static bool _recording;
|
||||
static bool _has_ctbus;
|
||||
static bool _fxs_bina;
|
||||
static bool _fxo_send_pre_audio;
|
||||
static bool _drop_collect_call;
|
||||
static bool _ignore_letter_dtmfs;
|
||||
static bool _optimize_audio_path;
|
||||
|
||||
static bool _auto_fax_adjustment;
|
||||
static unsigned int _fax_adjustment_timeout;
|
||||
|
||||
static bool _r2_strict_behaviour;
|
||||
static unsigned int _r2_preconnect_wait;
|
||||
|
||||
static unsigned int _fxs_digit_timeout;
|
||||
|
||||
static unsigned int _transferdigittimeout;
|
||||
|
||||
static std::string _blindxfer;
|
||||
static std::string _atxfer;
|
||||
|
||||
static unsigned int _ringback_co_delay;
|
||||
static unsigned int _ringback_pbx_delay;
|
||||
|
||||
static unsigned int _disconnect_delay;
|
||||
|
||||
static int _input_volume;
|
||||
static int _output_volume;
|
||||
|
||||
static DestVectorType _fxs_co_dialtone;
|
||||
static OrigToDestMapType _fxs_hotline;
|
||||
static std::string _fxs_global_orig_base;
|
||||
|
||||
static BoardToOrigMapType _fxs_orig_base;
|
||||
static BranchToObjectMapType _fxs_branch_map;
|
||||
static BranchToOptMapType _branch_options;
|
||||
|
||||
static std::string _global_mohclass;
|
||||
static std::string _global_language;
|
||||
|
||||
static std::string _record_prefix;
|
||||
|
||||
static std::string _context_gsm_call;
|
||||
static std::string _context2_gsm_call;
|
||||
static std::string _context_gsm_sms;
|
||||
static std::string _context_fxo;
|
||||
static std::string _context2_fxo;
|
||||
static std::string _context_fxs;
|
||||
static std::string _context2_fxs;
|
||||
static std::string _context_digital;
|
||||
static std::string _context_pr;
|
||||
static std::string _user_xfer;
|
||||
|
||||
static int _amaflags;
|
||||
static std::string _callgroup;
|
||||
static std::string _pickupgroup; /* or intercept */
|
||||
|
||||
static std::string _accountcode;
|
||||
|
||||
static unsigned int _kommuter_timeout;
|
||||
static std::string _kommuter_activation;
|
||||
|
||||
static unsigned int _audio_packet_size;
|
||||
|
||||
protected:
|
||||
|
||||
struct ProcessFXSCODialtone
|
||||
{
|
||||
void operator()(std::string options);
|
||||
};
|
||||
|
||||
struct ProcessRecordPrefix
|
||||
{
|
||||
void operator()(std::string path);
|
||||
};
|
||||
|
||||
struct ProcessAMAFlags
|
||||
{
|
||||
void operator()(std::string options);
|
||||
};
|
||||
|
||||
struct ProcessCallGroup
|
||||
{
|
||||
void operator()(std::string options);
|
||||
};
|
||||
|
||||
struct ProcessPickupGroup
|
||||
{
|
||||
void operator()(std::string options);
|
||||
};
|
||||
|
||||
struct ProcessLogOptions
|
||||
{
|
||||
ProcessLogOptions(output_type output): _output(output) {};
|
||||
|
||||
void operator()(std::string options);
|
||||
|
||||
protected:
|
||||
output_type _output;
|
||||
};
|
||||
|
||||
struct ProcessTraceOptions
|
||||
{
|
||||
void operator()(std::string options);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* _OPT_H_ */
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
#define MOD_KHOMP_VERSION "1.0 - (rev: 5796)"
|
||||
@@ -0,0 +1,98 @@
|
||||
/*******************************************************************************
|
||||
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2010 Khomp Ind. & Com.
|
||||
|
||||
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.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file
|
||||
under the MPL, indicate your decision by deleting the provisions above and
|
||||
replace them with the notice and other provisions required by the LGPL
|
||||
License. If you do not delete the provisions above, a recipient may use your
|
||||
version of this file under either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _SPEC_HPP_
|
||||
#define _SPEC_HPP_
|
||||
|
||||
#include <function.hpp>
|
||||
#include "khomp_pvt.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SPR_CONTINUE,
|
||||
SPR_SUCCESS,
|
||||
SPR_FAIL,
|
||||
}
|
||||
SpecRetType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SPF_FIRST = 0x01,
|
||||
SPF_CYCLIC = 0x02,
|
||||
}
|
||||
SpecFlagType;
|
||||
|
||||
typedef unsigned int SpecFlagsType;
|
||||
|
||||
|
||||
typedef Function::Function3 < bool, unsigned int, unsigned int, SpecFlagsType & > SpecFunType;
|
||||
|
||||
|
||||
//SpecRetType processSpecAtom(std::string &, SpecFlagsType &, SpecFunType &);
|
||||
//SpecRetType processSpecAtoms(std::string &, SpecFlagsType &, SpecFunType &);
|
||||
//bool processCallChannelString(std::string &, Board::KhompPvt *&, int *, bool need_free = true);
|
||||
|
||||
/* Request a Board::KhompPvt based on dialplan string.
|
||||
|
||||
-- Format of dialplan string. --
|
||||
|
||||
Dial(Khomp/B2C58/4832625644)
|
||||
| | | |
|
||||
| | | |
|
||||
| | | |
|
||||
| | | +- Destination number.
|
||||
| | |
|
||||
| | +- Identifier for board 2, channel 58.
|
||||
| |
|
||||
| +- Khomp channel identifier.
|
||||
|
|
||||
+- Dial Application.
|
||||
*/
|
||||
|
||||
Board::KhompPvt * processDialString(const char *, int *);
|
||||
void processGroupString();
|
||||
|
||||
Board::KhompPvt * processSMSString(const char *, int *);
|
||||
|
||||
#endif /* _SPEC_HPP_ */
|
||||
|
||||
@@ -0,0 +1,772 @@
|
||||
/*******************************************************************************
|
||||
|
||||
KHOMP generic endpoint/channel library.
|
||||
Copyright (C) 2007-2010 Khomp Ind. & Com.
|
||||
|
||||
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.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of the
|
||||
"GNU Lesser General Public License 2.1" license (the “LGPL" License), in which
|
||||
case the provisions of "LGPL License" are applicable instead of those above.
|
||||
|
||||
If you wish to allow use of your version of this file only under the terms of
|
||||
the LGPL License and not to allow others to use your version of this file
|
||||
under the MPL, indicate your decision by deleting the provisions above and
|
||||
replace them with the notice and other provisions required by the LGPL
|
||||
License. If you do not delete the provisions above, a recipient may use your
|
||||
version of this file under either the MPL or the LGPL License.
|
||||
|
||||
The LGPL header follows below:
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this library; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _UTILS_H_
|
||||
#define _UTILS_H_
|
||||
|
||||
#include <bitset>
|
||||
#include <refcounter.hpp>
|
||||
#include <ringbuffer.hpp>
|
||||
#include <simple_lock.hpp>
|
||||
#include <saved_condition.hpp>
|
||||
#include <thread.hpp>
|
||||
#include "globals.h"
|
||||
#include "logger.h"
|
||||
#include "defs.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/************************** Defining applications *****************************/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
FAX_ADJUST,
|
||||
FAX_SEND,
|
||||
FAX_RECEIVE,
|
||||
USER_TRANSFER,
|
||||
SMS_CHECK,
|
||||
SMS_SEND,
|
||||
SELECT_SIM_CARD,
|
||||
}
|
||||
ApplicationType;
|
||||
|
||||
/******************************************************************************/
|
||||
/***************** Abstraction for defining channel flags *********************/
|
||||
|
||||
struct Kflags
|
||||
{
|
||||
typedef enum
|
||||
{
|
||||
CONNECTED = 0,
|
||||
REALLY_CONNECTED,
|
||||
|
||||
IS_OUTGOING,
|
||||
IS_INCOMING,
|
||||
|
||||
STREAM_UP,
|
||||
LISTEN_UP,
|
||||
|
||||
GEN_CO_RING,
|
||||
GEN_PBX_RING,
|
||||
|
||||
HAS_PRE_AUDIO,
|
||||
HAS_CALL_FAIL,
|
||||
|
||||
DROP_COLLECT,
|
||||
|
||||
NEEDS_RINGBACK_CMD, //R2
|
||||
EARLY_RINGBACK, //FXO
|
||||
|
||||
FAX_DETECTED, //Digital, FXO
|
||||
FAX_SENDING, //Digital, FXO
|
||||
FAX_RECEIVING, //Digital, FXO
|
||||
|
||||
OUT_OF_BAND_DTMFS,
|
||||
|
||||
KEEP_DTMF_SUPPRESSION,
|
||||
KEEP_ECHO_CANCELLATION,
|
||||
KEEP_AUTO_GAIN_CONTROL,
|
||||
|
||||
WAIT_SEND_DTMF,
|
||||
|
||||
CALL_WAIT_SEIZE, //FXO
|
||||
|
||||
NUMBER_DIAL_FINISHD, //R2
|
||||
NUMBER_DIAL_ONGOING, //R2
|
||||
|
||||
FXS_OFFHOOK, //FXS
|
||||
FXS_DIAL_FINISHD, //FXS
|
||||
FXS_DIAL_ONGOING, //FXS
|
||||
FXS_FLASH_TRANSFER, //FXS
|
||||
|
||||
XFER_QSIG_DIALING, //ISDN
|
||||
XFER_DIALING, //ISDN, FXO
|
||||
|
||||
SMS_DOING_UPLOAD, //GSM
|
||||
|
||||
/*
|
||||
NOW LOADING ...
|
||||
|
||||
BRIDGED,
|
||||
*/
|
||||
|
||||
/* Do not remove this last FLAG */
|
||||
INVALID_FLAG
|
||||
}
|
||||
FlagType;
|
||||
|
||||
struct Flag
|
||||
{
|
||||
const char *_name;
|
||||
bool _value;
|
||||
};
|
||||
|
||||
Kflags() { init(); };
|
||||
|
||||
void init();
|
||||
|
||||
inline const char * name(FlagType bit) { return _flags[bit]._name; }
|
||||
|
||||
inline bool check(FlagType bit)
|
||||
{
|
||||
#ifdef DEBUG_FLAGS
|
||||
DBG(FUNC, D("Flag %s=%s") % name(bit) %
|
||||
(_flags[bit]._value ? "TRUE" : "FALSE"));
|
||||
#endif
|
||||
return _flags[bit]._value;
|
||||
}
|
||||
|
||||
inline void set(FlagType bit)
|
||||
{
|
||||
#ifdef DEBUG_FLAGS
|
||||
DBG(FUNC, D("Flag %s") % name(bit));
|
||||
#endif
|
||||
_flags[bit]._value = true;
|
||||
}
|
||||
|
||||
inline void clear(FlagType bit)
|
||||
{
|
||||
#ifdef DEBUG_FLAGS
|
||||
DBG(FUNC, D("Flag %s") % name(bit));
|
||||
#endif
|
||||
_flags[bit]._value = false;
|
||||
}
|
||||
|
||||
inline void clearAll()
|
||||
{
|
||||
unsigned int index = 0;
|
||||
for(; (FlagType)index < INVALID_FLAG; index++)
|
||||
{
|
||||
if(_flags[index]._value)
|
||||
{
|
||||
DBG(FUNC, D("Flag %s was not clean!") % name((FlagType)index));
|
||||
clear((FlagType)index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
Flag _flags[INVALID_FLAG+1];
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
/************************* Commands and Events Handler ************************/
|
||||
struct CommandRequest
|
||||
{
|
||||
typedef enum
|
||||
{
|
||||
NONE = 0,
|
||||
COMMAND,
|
||||
ACTION
|
||||
}
|
||||
ReqType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CNONE = 0,
|
||||
|
||||
/* Commands */
|
||||
CMD_CALL,
|
||||
CMD_ANSWER,
|
||||
CMD_HANGUP,
|
||||
|
||||
/* Actions */
|
||||
FLUSH_REC_STREAM,
|
||||
FLUSH_REC_BRIDGE,
|
||||
START_RECORD,
|
||||
STOP_RECORD
|
||||
|
||||
}
|
||||
CodeType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
RFA_CLOSE,
|
||||
RFA_KEEP_OPEN,
|
||||
RFA_REMOVE
|
||||
}
|
||||
RecFlagType;
|
||||
|
||||
/* "empty" constructor */
|
||||
CommandRequest() :
|
||||
_type(NONE),
|
||||
_code(CNONE),
|
||||
_obj(-1)
|
||||
{}
|
||||
|
||||
CommandRequest(ReqType type, CodeType code, int obj) :
|
||||
_type(type),
|
||||
_code(code),
|
||||
_obj(obj)
|
||||
{}
|
||||
|
||||
CommandRequest(const CommandRequest & cmd) :
|
||||
_type(cmd._type),
|
||||
_code(cmd._code),
|
||||
_obj(cmd._obj)
|
||||
{}
|
||||
|
||||
~CommandRequest() {}
|
||||
|
||||
void operator=(const CommandRequest & cmd)
|
||||
{
|
||||
_type = cmd._type;
|
||||
_code = cmd._code;
|
||||
_obj = cmd._obj;
|
||||
}
|
||||
|
||||
void mirror(const CommandRequest & cmd_request)
|
||||
{
|
||||
_type = cmd_request._type;
|
||||
_code = cmd_request._code;
|
||||
_obj = cmd_request._obj;
|
||||
}
|
||||
|
||||
short type() { return _type; }
|
||||
|
||||
short code() { return _code; }
|
||||
|
||||
int obj() { return _obj; }
|
||||
|
||||
private:
|
||||
short _type;
|
||||
short _code;
|
||||
int _obj;
|
||||
};
|
||||
|
||||
struct EventRequest
|
||||
{
|
||||
/* "empty" constructor */
|
||||
EventRequest(bool can_delete = true) :
|
||||
_delete(can_delete),
|
||||
_obj(-1)
|
||||
{
|
||||
if(can_delete)
|
||||
_event = new K3L_EVENT();
|
||||
}
|
||||
|
||||
/* Temporary constructor */
|
||||
EventRequest(int obj, K3L_EVENT * ev) :
|
||||
_delete(false),
|
||||
_obj(obj),
|
||||
_event(ev)
|
||||
{}
|
||||
|
||||
//EventRequest(const EventRequest & ev) : _obj(ev._obj) {}
|
||||
|
||||
~EventRequest()
|
||||
{
|
||||
|
||||
if(!_delete || !_event)
|
||||
return;
|
||||
|
||||
if(_event->ParamSize)
|
||||
free(_event->Params);
|
||||
|
||||
delete _event;
|
||||
}
|
||||
|
||||
void operator=(const EventRequest & ev)
|
||||
{
|
||||
_delete = false;
|
||||
_obj = ev._obj;
|
||||
_event = ev._event;
|
||||
|
||||
}
|
||||
|
||||
void mirror(const EventRequest & ev_request)
|
||||
{
|
||||
//Checar o _event
|
||||
|
||||
if(_event->ParamSize)
|
||||
{
|
||||
free(_event->Params);
|
||||
}
|
||||
|
||||
_event->Params = NULL;
|
||||
|
||||
_obj = ev_request._obj;
|
||||
|
||||
K3L_EVENT * ev = ev_request._event;
|
||||
|
||||
if(!ev)
|
||||
{
|
||||
clearEvent();
|
||||
return;
|
||||
}
|
||||
|
||||
_event->Code = ev->Code; // API code
|
||||
_event->AddInfo = ev->AddInfo; // Parameter 1
|
||||
_event->DeviceId = ev->DeviceId; // Hardware information
|
||||
_event->ObjectInfo = ev->ObjectInfo; // Additional object information
|
||||
_event->ParamSize = ev->ParamSize; // Size of parameter buffer
|
||||
_event->ObjectId = ev->ObjectId; // KEventObjectId: Event thrower object id
|
||||
|
||||
if(ev->ParamSize)
|
||||
{
|
||||
// Pointer to the parameter buffer
|
||||
_event->Params = malloc(ev->ParamSize+1);
|
||||
memcpy(_event->Params, ev->Params, ev->ParamSize);
|
||||
((char *)(_event->Params))[ev->ParamSize] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool clearEvent()
|
||||
{
|
||||
_event->Code = -1;
|
||||
_event->AddInfo = -1;
|
||||
_event->DeviceId = -1;
|
||||
_event->ObjectInfo = -1;
|
||||
_event->ParamSize = 0;
|
||||
_event->ObjectId = -1;
|
||||
}
|
||||
|
||||
int obj() { return _obj; }
|
||||
|
||||
K3L_EVENT * event() { return _event; }
|
||||
|
||||
|
||||
private:
|
||||
bool _delete;
|
||||
int _obj;
|
||||
K3L_EVENT * _event;
|
||||
};
|
||||
|
||||
template < typename R, int S >
|
||||
struct GenericFifo
|
||||
{
|
||||
typedef R RequestType;
|
||||
typedef SimpleNonBlockLock<25,100> LockType;
|
||||
|
||||
GenericFifo(int device) :
|
||||
_device(device),
|
||||
_shutdown(false),
|
||||
_buffer(S),
|
||||
_mutex(Globals::module_pool),
|
||||
_cond(Globals::module_pool)
|
||||
{};
|
||||
|
||||
int _device;
|
||||
bool _shutdown;
|
||||
Ringbuffer < RequestType > _buffer;
|
||||
LockType _mutex; /* to sync write acess to event list */
|
||||
SavedCondition _cond;
|
||||
Thread *_thread;
|
||||
|
||||
};
|
||||
|
||||
typedef GenericFifo < CommandRequest, 250 > CommandFifo;
|
||||
typedef GenericFifo < EventRequest, 500 > EventFifo;
|
||||
|
||||
/* Used inside KhompPvt to represent an command handler */
|
||||
struct ChanCommandHandler: NEW_REFCOUNTER(ChanCommandHandler)
|
||||
{
|
||||
typedef int (HandlerType)(void *);
|
||||
|
||||
ChanCommandHandler(int device, HandlerType * handler)
|
||||
{
|
||||
_fifo = new CommandFifo(device);
|
||||
/* device event handler */
|
||||
_fifo->_thread = new Thread(handler, (void *)this, Globals::module_pool);
|
||||
if(_fifo->_thread->start())
|
||||
{
|
||||
DBG(FUNC,"Device command handler started");
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(ERROR, "Device command handler error");
|
||||
}
|
||||
}
|
||||
|
||||
ChanCommandHandler(const ChanCommandHandler & cmd)
|
||||
: INC_REFCOUNTER(cmd, ChanCommandHandler),
|
||||
_fifo(cmd._fifo)
|
||||
{};
|
||||
|
||||
void unreference();
|
||||
|
||||
CommandFifo * fifo()
|
||||
{
|
||||
return _fifo;
|
||||
}
|
||||
|
||||
void signal()
|
||||
{
|
||||
_fifo->_cond.signal();
|
||||
};
|
||||
|
||||
bool writeNoSignal(const CommandRequest &);
|
||||
bool write(const CommandRequest &);
|
||||
|
||||
protected:
|
||||
CommandFifo * _fifo;
|
||||
};
|
||||
|
||||
/* Used inside KhompPvt to represent an event handler */
|
||||
struct ChanEventHandler: NEW_REFCOUNTER(ChanEventHandler)
|
||||
{
|
||||
typedef int (HandlerType)(void *);
|
||||
|
||||
ChanEventHandler(int device, HandlerType * handler)
|
||||
{
|
||||
_fifo = new EventFifo(device);
|
||||
/* device event handler */
|
||||
_fifo->_thread = new Thread(handler, (void *)this, Globals::module_pool);
|
||||
if(_fifo->_thread->start())
|
||||
{
|
||||
DBG(FUNC,"Device event handler started");
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(ERROR, "Device event handler error");
|
||||
}
|
||||
}
|
||||
|
||||
ChanEventHandler(const ChanEventHandler & evt)
|
||||
: INC_REFCOUNTER(evt, ChanEventHandler),
|
||||
_fifo(evt._fifo)
|
||||
{};
|
||||
|
||||
void unreference();
|
||||
|
||||
EventFifo * fifo()
|
||||
{
|
||||
return _fifo;
|
||||
}
|
||||
|
||||
void signal()
|
||||
{
|
||||
_fifo->_cond.signal();
|
||||
};
|
||||
|
||||
bool provide(const EventRequest &);
|
||||
bool writeNoSignal(const EventRequest &);
|
||||
bool write(const EventRequest &);
|
||||
|
||||
protected:
|
||||
EventFifo * _fifo;
|
||||
};
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/****************************** Internal **************************************/
|
||||
struct RingbackDefs
|
||||
{
|
||||
enum
|
||||
{
|
||||
RB_SEND_DEFAULT = -1,
|
||||
RB_SEND_NOTHING = -2,
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
RBST_SUCCESS,
|
||||
RBST_UNSUPPORTED,
|
||||
RBST_FAILURE,
|
||||
}
|
||||
RingbackStType;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
/******************************* Others ***************************************/
|
||||
static bool checkTrueString(const char * str)
|
||||
{
|
||||
if (str && *str)
|
||||
{
|
||||
if (!SAFE_strcasecmp(str, "yes") || !SAFE_strcasecmp(str, "true") ||
|
||||
!SAFE_strcasecmp(str, "enabled") || !SAFE_strcasecmp(str, "sim"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool checkFalseString(const char * str)
|
||||
{
|
||||
if (str && *str)
|
||||
{
|
||||
if (!SAFE_strcasecmp(str, "no") || !SAFE_strcasecmp(str, "false") ||
|
||||
!SAFE_strcasecmp(str, "disabled") || !SAFE_strcasecmp(str, "não"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static TriState getTriStateValue(const char * str)
|
||||
{
|
||||
if (str)
|
||||
{
|
||||
/**/ if (checkTrueString(str)) return T_TRUE;
|
||||
else if (checkFalseString(str)) return T_FALSE;
|
||||
else /***********************************/ return T_UNKNOWN;
|
||||
}
|
||||
|
||||
return T_UNKNOWN;
|
||||
}
|
||||
|
||||
const char * answerInfoToString(int answer_info);
|
||||
|
||||
static bool replaceTemplate(std::string & haystack, const std::string & needed, int value)
|
||||
{
|
||||
Regex::Expression e(std::string(needed).c_str());
|
||||
Regex::Match r(haystack,e);
|
||||
|
||||
if(!r.matched()) return false;
|
||||
|
||||
int len;
|
||||
std::string fmt;
|
||||
std::string tmp;
|
||||
|
||||
// if needed isn't "SSSS" the length of needed will give string format
|
||||
// if needed is "SSSS" the length of value will give string format
|
||||
std::string ssss("SSSS");
|
||||
|
||||
if (ssss != needed)
|
||||
{
|
||||
len = needed.size();
|
||||
fmt = STG(FMT("%%0%dd") % len);
|
||||
tmp = STG(FMT(fmt) % value);
|
||||
}
|
||||
else
|
||||
{
|
||||
len = (STG(FMT("%d") % value)).size();
|
||||
fmt = STG(FMT("%%%dd") % len);
|
||||
tmp = STG(FMT(fmt) % value);
|
||||
}
|
||||
|
||||
haystack = r.replace(STG(FMT(fmt) % value));
|
||||
|
||||
DBG(FUNC,FMT("haystack: %s") % haystack);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static std::string timeToString (time_t time_value)
|
||||
{
|
||||
int horas = (int)time_value / 3600;
|
||||
|
||||
if (horas > 0)
|
||||
time_value -= horas * 3600;
|
||||
|
||||
int minutos = (int)time_value / 60;
|
||||
|
||||
if (minutos > 0)
|
||||
time_value -= minutos * 60;
|
||||
|
||||
return STG(FMT("%02d:%02d:%02d") % horas % minutos % (int)time_value);
|
||||
}
|
||||
/******************************************************************************/
|
||||
/******************************* Match functions ******************************/
|
||||
typedef enum
|
||||
{
|
||||
MATCH_NONE,
|
||||
MATCH_EXACT,
|
||||
MATCH_MORE
|
||||
}
|
||||
MatchType;
|
||||
|
||||
static bool canMatch(std::string & context, std::string & exten, std::string & caller_id, bool match_more = false)
|
||||
{
|
||||
switch_xml_t xml = NULL;
|
||||
switch_xml_t xcontext = NULL;
|
||||
switch_regex_t *re;
|
||||
int ovector[30];
|
||||
|
||||
if (switch_xml_locate("dialplan","context","name",context.c_str(),&xml,&xcontext, NULL,SWITCH_FALSE) == SWITCH_STATUS_SUCCESS)
|
||||
{
|
||||
switch_xml_t xexten = NULL;
|
||||
|
||||
if(!(xexten = switch_xml_child(xcontext,"extension")))
|
||||
{
|
||||
DBG(FUNC,"extension cannot match, returning");
|
||||
|
||||
if(xml)
|
||||
switch_xml_free(xml);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
while(xexten)
|
||||
{
|
||||
switch_xml_t xcond = NULL;
|
||||
|
||||
for (xcond = switch_xml_child(xexten, "condition"); xcond; xcond = xcond->next)
|
||||
{
|
||||
std::string expression;
|
||||
|
||||
if (switch_xml_child(xcond, "condition"))
|
||||
{
|
||||
LOG(ERROR,"Nested conditions are not allowed");
|
||||
}
|
||||
|
||||
switch_xml_t xexpression = switch_xml_child(xcond, "expression");
|
||||
|
||||
if ((xexpression = switch_xml_child(xcond, "expression")))
|
||||
{
|
||||
expression = switch_str_nil(xexpression->txt);
|
||||
}
|
||||
else
|
||||
{
|
||||
expression = switch_xml_attr_soft(xcond, "expression");
|
||||
}
|
||||
|
||||
if(expression.empty() || expression == "^(.*)$")
|
||||
{
|
||||
/**
|
||||
* We're not gonna take it
|
||||
* No, we ain't gonna take it
|
||||
* We're not gonna take it anymore
|
||||
**/
|
||||
continue;
|
||||
}
|
||||
|
||||
int pm = -1;
|
||||
switch_status_t is_match = SWITCH_STATUS_FALSE;
|
||||
is_match = switch_regex_match_partial(exten.c_str(),expression.c_str(),&pm);
|
||||
|
||||
if(is_match == SWITCH_STATUS_SUCCESS)
|
||||
{
|
||||
if(match_more)
|
||||
{
|
||||
if(pm == 1)
|
||||
{
|
||||
switch_xml_free(xml);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch_xml_free(xml);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// not match
|
||||
}
|
||||
}
|
||||
|
||||
xexten = xexten->next;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG(FUNC,"context cannot match, returning");
|
||||
}
|
||||
|
||||
if(xml)
|
||||
switch_xml_free(xml);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/************************** Thread helper functions ***************************/
|
||||
typedef int (HandlerType)(void *);
|
||||
static Thread * threadCreate(HandlerType * handler,void * arg)
|
||||
{
|
||||
Thread *t = new Thread(handler, (void *) arg, Globals::module_pool);
|
||||
return t;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/******************************** Kommuter ************************************/
|
||||
struct Kommuter
|
||||
{
|
||||
Kommuter() :
|
||||
_kommuter_count(-1),
|
||||
_kwtd_timer_on(false)
|
||||
{}
|
||||
|
||||
bool start()
|
||||
{
|
||||
/* Checks for kommuter */
|
||||
try
|
||||
{
|
||||
Globals::k3lapi.command(-1,-1,CM_WATCHDOG_COUNT);
|
||||
}
|
||||
catch(K3LAPI::failed_command & e)
|
||||
{
|
||||
LOG(WARNING , "libkwd.so used by Kommuter devices is not available.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool stop();
|
||||
|
||||
bool initialize(K3L_EVENT *e);
|
||||
|
||||
/* Index of the WatchDog timer */
|
||||
TimerTraits::Index _kwtd_timer_index;
|
||||
int _kommuter_count;
|
||||
bool _kwtd_timer_on;
|
||||
|
||||
/* Timer to control our dog (totó) */
|
||||
static void wtdKickTimer(void *);
|
||||
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
/******************************* Statistics ***********************************/
|
||||
struct Statistics
|
||||
{
|
||||
typedef enum
|
||||
{
|
||||
DETAILED = 0,
|
||||
ROW
|
||||
}
|
||||
Type;
|
||||
|
||||
virtual std::string getDetailed() { return ""; }
|
||||
virtual void clear() {}
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
#endif /* _UTILS_H_ */
|
||||
Reference in new issue
Block a user