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:
Geovani Ricardo Wiedenhoft committed 2010-10-18 16:17:43 -02:00
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
+211
View File
@@ -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
+160
View File
@@ -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_ */
+250
View File
@@ -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_ */
+772
View File
@@ -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_ */