- Notifies the pre_answer

- Dialplan examples
- New version of commons
- Priority of contexts
- New K3L install script - getk3l.sh
- CLI return in XML
- More options in GET and SET commands
- Events (ESL) to send/receive SMS.
- fax-adjustment-timeout implemented
- accountcode and language
- Owner destroy
- Destroy wait for resources release
- static const expression
- Hangup cause
This commit is contained in:
Geovani Ricardo Wiedenhoft 2010-12-01 16:40:35 -02:00
parent 6b52a43314
commit 5df1683c38
98 changed files with 7491 additions and 6153 deletions

View File

@ -62,6 +62,7 @@ endpoints/mod_loopback
#endpoints/mod_skinny
#endpoints/mod_skypopen
#endpoints/mod_h323
#endpoints/mod_khomp
#../../libs/openzap/mod_openzap
#../../libs/freetdm/mod_freetdm
#asr_tts/mod_unimrcp
@ -105,5 +106,4 @@ say/mod_say_ru
#say/mod_say_th
## Experimental Modules (don't cry if they're broken)
#endpoints/mod_khomp
#../../contrib/mod/xml_int/mod_xml_odbc

View File

@ -38,6 +38,7 @@
<!-- <load module="mod_openzap"/> -->
<!-- <load module="mod_unicall"/> -->
<!-- <load module="mod_skinny"/> -->
<!-- <load module="mod_khomp"/> -->
<!-- Applications -->
<load module="mod_commands"/>

View File

@ -95,16 +95,6 @@ should be opened for the channel. Limited to 25ms min, 500ms max.
<param name="r2-preconnect-wait" value="250"/>
-->
<!--
Enable/disable native bridge mode (known in pt_BR as "trombone") for calls
in the Khomp channel, passing the audio inside the board when both channels
(incoming and outgoing) are of type Khomp. This reduces the echo and the
audio delay, and frees the host from most audio processing.
(default = yes)
<param name="native-bridge" value="yes"/>
-->
<!--
Defines the incoming context for calls on E1 channels. Some wildcards are
accepted, and described in the bottom of this file.
@ -239,48 +229,30 @@ is enabled on the board configuration. Possible values:
<param name="input-volume" value="0"/>
-->
<!--
Sets the default AMA flags, affecting the categorization of entries in
the call detail records.
(default = default)
<param name="amaflags" value="default"/>
-->
<!--
Sets the account code for calls placed on the channel. The account code may
be any alphanumeric string
(default = KhompBoard)
default = <empty>)
<param name="accountcode" value="KhompBoard"/>
<param name="accountcode" value=""/>
-->
<!--
Set the language of the channel (useful for selecting audio messages of a
specific language on answer).
(default = <empty>)
<param name="language" value="pt_BR"/>
-->
<!--
Set the music on hold class of the channel (useful for selecting a group of
songs to play on hold).
(default = default)
<param name="mohclass" value="default"/>
-->
<!--
Sets the global orig (CALLERID) base for FXS boards. This number is added
to a sequencial number, which is incremented for each FXS board and FXS
channel in the system.
For more example of how to use this option, see channel README file,
section 'Opcoes do application Bridge', item '<action application="bridge" data="Khomp/r304" />'.
(default = 0)
<param name="fxs-global-orig" value="0200"/>
<param name="fxs-global-orig" value="0"/>
-->
<!--
@ -300,14 +272,6 @@ a FXS branch.
<param name="fxs-bina" value="yes"/>
-->
<!--
Enable/disable using CTbus for Khomp CTI boards in native bridge.
(WARNING: just used for internal testings!)
(default = no)
<param name="has-ctbus" value="no"/>
-->
<!--
This is the delay time to really disconnect a channel after the disconnect
event arrive. If a connect event comes up in this interval, then the
@ -337,18 +301,6 @@ not have any tone. Values are in milliseconds.
<param name="delay-ringback-pbx" value="2500"/>
-->
<!--
Defines if the channel should optimize audio delay by droping longstanding
packets from audio buffer. This guarantees the minimal audio delay for the
user, and avoid delays associated with miscoded SIP clients. However,
depending on the system's scheduling policy (some 2.6 kernel releases),
this may result on excessive drop of packets, and audible audio skipping.
This should not be changed naively.
(default = no)
<param name="optimize-audio-path" value="no"/>
-->
<!--
Defines if the channel should ignore some uncommon DTMF digits detected by
the board (A, B, C and D). This reduces the number of false positives which
@ -526,9 +478,8 @@ In the example above, the branch numbered 804 will have specific
configuration for default output volume set to +2.
Possible values to options is:
context, input-volume, output-volume language,
mohclass, amaflags, accountcode, calleridnum,
calleridname, mailbox, flash-to-digits.
context, input-volume, output-volume, language,
accountcode, calleridnum, calleridname, flash-to-digits.
-->
</fxs-options>

View File

@ -1,6 +1,9 @@
MODNAME := mod_khomp
VERBOSE := 1
#FreeSWITCH source PATH is needed:
# Set FREESWITCH_PATH
ifeq ($(strip $(FREESWITCH_PATH)),)
BASE := ../../../../
else
@ -11,12 +14,12 @@ curr_dir := $(shell pwd)
versions := -DFS_VERSION_MAJOR=$(shell bash $(curr_dir)/tools/getversion.sh "SWITCH_VERSION_MAJOR" $(BASE)) -DFS_VERSION_MINOR=$(shell bash $(curr_dir)/tools/getversion.sh "SWITCH_VERSION_MINOR" $(BASE)) -DFS_VERSION_MICRO=$(shell bash $(curr_dir)/tools/getversion.sh "SWITCH_VERSION_MICRO" $(BASE))
LOCAL_CFLAGS = -I./ -I./include -I./commons -I./support -D_REENTRANT -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -DK3L_HOSTSYSTEM -DCOMMONS_LIBRARY_USING_FREESWITCH -g -ggdb #-DDEBUG_FLAGS
LOCAL_CFLAGS = -I./ -I./include -I./commons -I./commons/base -I./support -D_REENTRANT -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -DK3L_HOSTSYSTEM -DCOMMONS_LIBRARY_USING_FREESWITCH -g -ggdb #-DDEBUG_FLAGS
LOCAL_CFLAGS += $(versions)
LOCAL_LDFLAGS = -lk3l
LOCAL_OBJS = ./commons/k3lapi.o ./commons/k3lutil.o ./commons/config_options.o ./commons/format.o ./commons/strings.o ./commons/ringbuffer.o ./commons/verbose.o ./commons/saved_condition.o ./commons/regex.o ./commons/timer.o ./commons/configurator/configfile.o ./commons/configurator/option.o ./commons/configurator/section.o ./commons/configurator/restriction.o
LOCAL_OBJS = ./commons/base/k3lapi.o ./commons/base/k3lutil.o ./commons/base/config_options.o ./commons/base/format.o ./commons/base/strings.o ./commons/base/ringbuffer.o ./commons/base/verbose.o ./commons/base/saved_condition.o ./commons/base/regex.o ./commons/base/timer.o ./commons/base/configurator/configfile.o ./commons/base/configurator/option.o ./commons/base/configurator/section.o ./commons/base/configurator/restriction.o ./commons/base/verbose_traits.o
LOCAL_OBJS += ./support/klog-config.o ./support/klog-options.o ./support/config_defaults.o
LOCAL_OBJS += ./src/globals.o ./src/opt.o ./src/frame.o ./src/utils.o ./src/lock.o ./src/spec.o ./src/applications.o ./src/khomp_pvt_fxo.o ./src/khomp_pvt_gsm.o ./src/khomp_pvt_kxe1.o ./src/khomp_pvt_passive.o ./src/khomp_pvt.o ./src/logger.o ./src/cli.o
@ -27,7 +30,20 @@ conf_file_install = $(sysconfdir)/autoload_configs
include $(BASE)/build/modmake.rules
local_depend:
@if test ! -f $(curr_dir)/commons/base/verbose_traits.hpp || test ! -f $(curr_dir)/commons/base/verbose_traits.cpp ; then \
echo "Generating verbose_traits" ;\
bash $(curr_dir)/commons/tools/generate-verbose-headers.sh commons/base/ include/k3l.h ;\
fi;
depend_install:
@if test "w`kserver --version 2>/dev/null | grep 2.1`" == "w" ; then \
echo "###############################################################################" ;\
echo "Install k3l from KHOMP." ;\
echo "Run: $(curr_dir)/tools/getk3l.sh" ;\
echo "###############################################################################" ;\
exit 1;\
fi;
@echo "Copy $(conf_file_name)"
@if test -d $(conf_file_install) ; then \
if test -f $(conf_file_dir)/$(conf_file_name) ; then \

View File

@ -64,17 +64,31 @@ namespace Atomic
PunnedType pval; pval.valtype = VAL; \
unsigned long long vexp = *(pexp.podtype); \
unsigned long long vval = *(pval.podtype); \
unsigned long long res = (unsigned long long)exp; \
unsigned long vval32 = (unsigned long)vval; \
unsigned char chg = 0; \
asm volatile("lock; cmpxchg8b %2; sete %1;" \
asm volatile( \
"xchgl %%ebx, %4;" \
"lock; cmpxchg8b %2; sete %1;" \
"movl %4, %%ebx; " \
: "+A" (vexp), /* 0 (result) */ \
"=q" (chg) /* 1 */ \
"=c" (chg) /* 1 */ \
: "m" (*(unsigned char**)(PTR)), /* 2 */ \
"b" ((unsigned long)(vval)), \
"c" ((unsigned long)(vval >> 32))); \
"c" ((unsigned long)(vval >> 32)), \
"m" (vval32)); \
*(pexp.podtype) = vexp; \
return (chg != 0 ? true : false);
// "movl %%ecx, %4;"
//
// "m" (*((unsigned long*)(*(pval.podtype)))),
// "m" ((unsigned long)(vval >> 32))
//
// "m" (*((unsigned long*)(&vval))),
// "m" ((unsigned long)(vval >> 32))
//
// unsigned long long vval = *(pval.podtype);
// unsigned long long res = (unsigned long long)exp;
//
// Types used for making CMPXCHG instructions independent from base type.
template < typename ValType, typename PodType >

View File

@ -63,7 +63,12 @@
#error Unknown implementation selected. Please define COMMONS_LIBRARY_USING_* correctly.
#endif
#define COMMONS_INCLUDE(file) <COMMONS_IMPLEMENTATION/file>
#define COMMONS_INCLUDE(file) <system/COMMONS_IMPLEMENTATION/file>
#define COMMONS_VERSION_MAJOR 1
#define COMMONS_VERSION_MINOR 1
#define COMMONS_AT_LEAST(x,y) \
(COMMONS_VERSION_MAJOR > x || (COMMONS_VERSION_MAJOR == x && COMMONS_VERSION_MINOR >= y))
#endif /* _CONFIG_COMMONS_HPP_ */

View File

@ -0,0 +1,302 @@
/*
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2009 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
*/
#include <config_options.hpp>
void Config::Restriction::checkRange(const std::string & name, const SIntType value, const Range < SIntType > & range)
{
if (value < range.minimum)
throw Failure(STG(FMT("value '%d' out-of-range for option '%s' (too low)") % value % name));
if (value > range.maximum)
throw Failure(STG(FMT("value '%d' out-of-range for option '%s' (too high)") % value % name));
if (((value - range.minimum) % range.step) != 0)
throw Failure(STG(FMT("value '%d' out-of-range for option '%s' (outside allowed step)") % value % name));
}
void Config::Restriction::checkRange(const std::string & name, const UIntType value, const Range < UIntType > & range)
{
if (value < range.minimum)
throw Failure(STG(FMT("value '%d' out-of-range for option '%s' (too low)") % value % name));
if (value > range.maximum)
throw Failure(STG(FMT("value '%d' out-of-range for option '%s' (too high)") % value % name));
if (((value - range.minimum) % range.step) != 0)
throw Failure(STG(FMT("value '%d' out-of-range for option '%s' (outside allowed step)") % value % name));
}
void Config::Restriction::checkStringSet(const std::string & name, const StringType & value, const StringSet & allowed)
{
if (allowed.empty())
return;
if (allowed.find(value) != allowed.end())
return;
std::string strlist;
for (StringSet::const_iterator i = allowed.begin(); i != allowed.end(); i++)
{
strlist += " '";
strlist += (*i);
strlist += "'";
}
throw Failure(STG(FMT("value '%s' not allowed for option '%s' (allowed values:%s)")
% value % name % strlist));
}
Config::Option::Option(std::string name, Config::Option::StringMemberType value, const StringType defvalue, StringSet & allowed, bool listme)
: _myname(name), _option(InnerStringType(name, value, defvalue, allowed)), _listme(listme), _values(NULL)
{};
Config::Option::Option(std::string name, Config::Option::StringMemberType value, const StringType defvalue, bool listme)
: _myname(name), _option(InnerStringType(name, value, defvalue)), _listme(listme), _values(NULL)
{};
Config::Option::Option(std::string name, Config::Option::BooleanMemberType value, const BooleanType defvalue, bool listme)
: _myname(name), _option(InnerBooleanType(name, value, defvalue)), _listme(listme), _values(NULL)
{};
Config::Option::Option(std::string name, Config::Option::SIntMemberType value, const SIntType defvalue,
SIntType min, SIntType max, SIntType step, bool listme)
: _myname(name), _option(InnerSIntType(name, value, defvalue, min, max, step)), _listme(listme), _values(NULL)
{};
Config::Option::Option(std::string name, Config::Option::UIntMemberType value, const UIntType defvalue,
UIntType min, UIntType max, UIntType step, bool listme)
: _myname(name), _option(InnerUIntType(name, value, defvalue, min, max, step)), _listme(listme), _values(NULL)
{};
Config::Option::Option(const Config::Option & o)
: _myname(o._myname), _option(o._option), _listme(o._listme), _values(o._values)
{};
Config::Option::Option(std::string name, Config::Option::FunctionMemberType value, const StringType defvalue, StringSet & allowed, bool listme)
: _myname(name), _option(InnerFunctionType(name, value, defvalue, allowed)), _listme(listme), _values(NULL)
{};
Config::Option::Option(std::string name, Config::Option::FunctionMemberType value, const StringType defvalue, bool listme)
: _myname(name), _option(InnerFunctionType(name, value, defvalue)), _listme(listme), _values(NULL)
{};
Config::Option::~Option(void)
{
if (_values)
{
for (unsigned int i = 0; _values[i] != NULL; i++)
delete _values[i];
delete[] _values;
_values = NULL;
}
};
const char ** Config::Option::values(void)
{
if (_values != NULL)
return _values;
/**/ if (_option.check<InnerBooleanType>())
{
_values = new const char*[3];
_values[0] = strdup("yes");
_values[1] = strdup("no");
_values[2] = NULL;
}
else if (_option.check<InnerSIntType>())
{
const InnerSIntType & tmp = _option.get<InnerSIntType>();
unsigned int count = ((tmp._range.maximum - tmp._range.minimum) / tmp._range.step) + 1;
unsigned int index = 0;
_values = new const char*[count + 1];
for (SIntType i = tmp._range.minimum; i <= tmp._range.maximum; i += tmp._range.step, ++index)
_values[index] = strdup(STG(FMT("%d") % i).c_str());
_values[index] = NULL;
}
else if (_option.check<InnerUIntType>())
{
const InnerUIntType & tmp = _option.get<InnerUIntType>();
unsigned int count = ((tmp._range.maximum - tmp._range.minimum) / tmp._range.step) + 1;
unsigned int index = 0;
_values = new const char*[count + 1];
for (UIntType i = tmp._range.minimum; i <= tmp._range.maximum; i += tmp._range.step, ++index)
_values[index] = strdup(STG(FMT("%d") % i).c_str());
_values[index] = NULL;
}
else if (_option.check<InnerStringType>())
{
const InnerStringType & tmp = _option.get<InnerStringType>();
_values = new const char*[ tmp._allowed.size() + 1 ];
unsigned int index = 0;
for (StringSet::iterator i = tmp._allowed.begin(); i != tmp._allowed.end(); ++i, ++index)
_values[index] = strdup((*i).c_str());
_values[index] = NULL;
}
else if (_option.check<InnerFunctionType>())
{
const InnerFunctionType & tmp = _option.get<InnerFunctionType>();
_values = new const char*[ tmp._allowed.size() + 1 ];
unsigned int index = 0;
for (StringSet::iterator i = tmp._allowed.begin(); i != tmp._allowed.end(); ++i, ++index)
_values[index] = strdup((*i).c_str());
_values[index] = NULL;
}
else
{
throw Failure(STG(FMT("values() not implemented for type used in option '%s'") % _myname));
}
return _values;
};
/*********************************/
Config::Options::Options(void)
: _values(NULL)
{};
Config::Options::~Options()
{
if (_values)
{
for (unsigned int i = 0; _values[i] != NULL; i++)
free((void*)(_values[i]));
delete[] _values;
_values = NULL;
}
};
bool Config::Options::add(Config::Option option)
{
std::pair<OptionMap::iterator, bool> ret = _map.insert(OptionPair(option.name(), option));
return ret.second;
}
bool Config::Options::synonym(std::string equiv_opt, std::string main_opt)
{
std::pair<SynOptionMap::iterator, bool> ret = _syn_map.insert(SynOptionPair(equiv_opt, main_opt));
return ret.second;
}
Config::StringSet Config::Options::options(void)
{
StringSet res;
for (OptionMap::iterator i = _map.begin(); i != _map.end(); i++)
res.insert(i->first);
return res;
}
const char ** Config::Options::values(const char * name)
{
OptionMap::iterator iter = find_option(name);
if (iter == _map.end())
throw Failure(STG(FMT("unknown option '%s'") % name));
return iter->second.values();
}
const char ** Config::Options::values(void)
{
if (_values != NULL)
return _values;
unsigned int count = 0;
for (OptionMap::iterator i = _map.begin(); i != _map.end(); ++i)
if (i->second.listme())
++count;
_values = new const char*[ count + 1 ];
unsigned int index = 0;
for (OptionMap::iterator i = _map.begin(); i != _map.end(); ++i)
{
if (i->second.listme())
{
_values[index] = strdup(i->first.c_str());
++index;
}
}
_values[index] = NULL;
return _values;
}
Config::Options::OptionMap::iterator Config::Options::find_option(std::string name)
{
SynOptionMap::iterator syn_iter = _syn_map.find(name);
if (syn_iter != _syn_map.end())
name = syn_iter->second;
OptionMap::iterator iter = _map.find(name);
return iter;
}

View File

@ -0,0 +1,772 @@
/*
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2009 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 _CONFIG_OPTIONS_HPP_
#define _CONFIG_OPTIONS_HPP_
#include <set>
#include <map>
#include <vector>
#include <stdexcept>
#include <strings.hpp>
#include <format.hpp>
#include <tagged_union.hpp>
#include <function.hpp>
#include <variable.hpp>
namespace Config
{
/* exceptions */
struct Failure: public std::runtime_error
{
Failure(const std::string & msg) : std::runtime_error(msg) {};
};
struct EmptyValue: public std::runtime_error
{
EmptyValue(): std::runtime_error("accessed option still not loaded from configuration") {};
};
/* types */
typedef int SIntType;
typedef unsigned int UIntType;
typedef bool BooleanType;
typedef std::string StringType;
template < typename Type >
struct Value;
template < typename Type >
struct InnerOptionBase;
template < typename Type >
struct InnerOption;
struct Option;
/* here we go! */
template < typename Type >
struct Range
{
Range(const Type _minimum, const Type _maximum, const Type _step)
: minimum(_minimum), maximum(_maximum), step(_step) {};
const Type minimum, maximum, step;
};
typedef std::set < std::string > StringSet;
template < typename Type >
struct Value: COUNTER_SUPER(Value < Type >)
{
friend class COUNTER_CLASS(Value < Type >);
friend class InnerOptionBase< Type >;
friend class InnerOption < Type >;
friend class Option;
Value()
: _tmpval(0), _stored(0), _loaded(false), _inited(false)
{};
Value(const Value & o)
: COUNTER_REFER(o, Value < Type >),
_tmpval(o._tmpval), _stored(o._stored),
_loaded(o._loaded), _inited(o._inited)
{};
const Type & operator()(void) const
{
if (!_inited)
throw EmptyValue();
if (!_stored)
return *_tmpval;
return *_stored;
};
const Type & get(void) const { return operator()(); };
bool loaded(void) const { return _loaded; };
void store(const Type val)
{
if (_tmpval)
{
delete _tmpval;
_tmpval = 0;
}
_tmpval = new Type(val);
_loaded = true;
_inited = true;
}
protected:
void unreference(void)
{
_inited = false;
_loaded = false;
if (_tmpval)
{
delete _tmpval;
_tmpval = 0;
}
if (_stored)
{
delete _stored;
_stored = 0;
}
};
protected:
void commit(Type def)
{
if (_tmpval)
{
{
delete _stored;
_stored = 0;
}
_stored = _tmpval;
_tmpval = 0;
}
else
{
if (!_stored)
_stored = new Type(def);
}
_loaded = true;
_inited = true;
};
void reset(void)
{
_loaded = false;
}
protected:
const Type * _tmpval;
const Type * _stored;
bool _loaded;
bool _inited;
};
struct FunctionValue
{
friend class InnerFunctionType;
friend class Option;
FunctionValue()
: _loaded(false), _inited(false) {};
virtual ~FunctionValue() {};
public:
virtual void operator()(const StringType & val)
{
throw Failure("undefined operator() for value");
}
const StringType & get(void) const
{
if (!_inited)
throw EmptyValue();
return _stored;
};
bool loaded(void) const { return _loaded; };
protected:
void commit(const StringType def)
{
if (_tmpval.empty())
{
_stored = def;
}
else
{
_stored = _tmpval;
_tmpval.clear();
}
operator()(_stored);
_loaded = true;
_inited = true;
};
void store(const StringType val)
{
_tmpval = val;
_loaded = true;
_inited = true;
}
void reset(void)
{
_loaded = false;
}
private:
StringType _tmpval;
StringType _stored;
bool _loaded;
bool _inited;
};
/* NOTE: we use a non-templated classe to place this functions inside the .cpp */
struct Restriction
{
static void checkRange(const std::string & name, const SIntType value, const Range < SIntType > & range);
static void checkRange(const std::string & name, const UIntType value, const Range < UIntType > & range);
static void checkStringSet(const std::string & name, const StringType & value, const StringSet & allowed);
};
template < typename Type >
struct InnerOptionBase
{
typedef Variable < Value < Type > > MemberValue;
InnerOptionBase(const std::string name, MemberValue option, const Type defvalue)
: _name(name), _option(option), _default(defvalue) {};
template < typename Object >
void reset(Object * const obj) const
{
_option(obj).reset();
}
template < typename Object >
const Type & get(const Object * const obj) const
{
return _option(obj).get();
}
template < typename Object >
bool loaded(const Object * const obj) const
{
return _option(obj).loaded();
}
protected:
const std::string _name;
MemberValue _option;
const Type _default;
};
template < >
struct InnerOption < SIntType >: public InnerOptionBase < SIntType >
{
typedef InnerOptionBase < SIntType > Super;
typedef Super::MemberValue MemberValue;
InnerOption(const std::string name, MemberValue option, const SIntType defval,
const SIntType min, const SIntType max, const SIntType step)
: Super(name, option, defval), _range(min, max, step) {};
template < typename Object >
void commit(Object * const obj) const
{
Restriction::checkRange(_name, _default, _range);
_option(obj).commit(_default);
};
template < typename Object >
void store(Object * const obj, const SIntType stored) const
{
Restriction::checkRange(_name, _default, _range);
_option(obj).store(stored);
}
using Super::reset;
using Super::get;
const Range< SIntType > _range;
};
template < >
struct InnerOption < UIntType >: public InnerOptionBase < UIntType >
{
typedef InnerOptionBase < UIntType > Super;
typedef Super::MemberValue MemberValue;
InnerOption(const std::string name, MemberValue option, const UIntType defval,
const UIntType min, const UIntType max, const UIntType step)
: Super(name, option, defval), _range(min, max, step) {};
template < typename Object >
void commit(Object * const obj) const
{
Restriction::checkRange(_name, _default, _range);
_option(obj).commit(_default);
};
template < typename Object >
void store(Object * const obj, const UIntType stored) const
{
Restriction::checkRange(_name, _default, _range);
_option(obj).store(stored);
}
using Super::reset;
using Super::get;
const Range< UIntType > _range;
};
template < >
struct InnerOption < BooleanType >: public InnerOptionBase < BooleanType >
{
typedef InnerOptionBase < BooleanType > Super;
typedef Super::MemberValue MemberValue;
InnerOption(std::string name, MemberValue option, BooleanType defval)
: Super(name, option, defval) {};
template < typename Object >
void commit(Object * obj) const
{
_option(obj).commit(_default);
};
template < typename Object >
void store(Object * obj, BooleanType stored) const
{
_option(obj).store(stored);
}
using Super::reset;
using Super::get;
};
template < >
struct InnerOption < StringType >: public InnerOptionBase < StringType >
{
typedef InnerOptionBase < StringType > Super;
typedef Super::MemberValue MemberValue;
InnerOption(const std::string name, MemberValue option, const StringType defval, const StringSet & allowed)
: Super(name, option, defval), _allowed(allowed) {};
InnerOption(const std::string name, MemberValue option, const StringType defval)
: Super(name, option, defval) {};
template < typename Object >
void commit(Object * const obj) const
{
Restriction::checkStringSet(_name, _default, _allowed);
_option(obj).commit(_default);
};
template < typename Object >
void store(Object * const obj, const StringType stored) const
{
Restriction::checkStringSet(_name, _default, _allowed);
_option(obj).store(stored);
}
using Super::reset;
using Super::get;
const StringSet _allowed;
};
struct InnerFunctionType
{
typedef Variable < FunctionValue > MemberValue;
InnerFunctionType(const std::string name, MemberValue option, const StringType defval, const StringSet & allowed)
: _name(name), _option(option), _default(defval), _allowed(allowed) {};
InnerFunctionType(const std::string name, MemberValue option, const StringType defval)
: _name(name), _option(option), _default(defval) {};
template < typename Object >
const StringType & get(const Object * const obj) const
{
return _option(obj).get();
}
template < typename Object >
bool loaded(const Object * const obj) const
{
return _option(obj).loaded();
}
template < typename Object >
void reset(Object * const obj) const
{
_option(obj).reset();
}
template < typename Object >
void commit(Object * const obj) const
{
Restriction::checkStringSet(_name, _default, _allowed);
_option(obj).commit(_default);
};
template < typename Object >
void store(Object * const obj, const StringType stored) const
{
Restriction::checkStringSet(_name, _default, _allowed);
_option(obj).store(stored);
}
protected:
const std::string _name;
MemberValue _option;
const StringType _default;
public:
const StringSet _allowed;
};
struct Option
{
typedef InnerOption < SIntType > InnerSIntType;
typedef InnerOption < UIntType > InnerUIntType;
typedef InnerOption < BooleanType > InnerBooleanType;
typedef InnerOption < StringType > InnerStringType;
typedef Variable < Value < SIntType > > SIntMemberType;
typedef Variable < Value < UIntType > > UIntMemberType;
typedef Variable < Value < BooleanType > > BooleanMemberType;
typedef Variable < Value < StringType > > StringMemberType;
typedef Variable < FunctionValue > FunctionMemberType;
typedef Tagged::Union < InnerStringType,
Tagged::Union < InnerBooleanType,
Tagged::Union < InnerSIntType ,
Tagged::Union < InnerUIntType,
Tagged::Union < InnerFunctionType > > > > >
InnerType;
explicit Option(std::string, StringMemberType, const StringType, StringSet & allowed, bool listme = true);
explicit Option(std::string, StringMemberType, const StringType = "", bool listme = true);
explicit Option(std::string, SIntMemberType, const SIntType = 0, SIntType min = INT_MIN, SIntType max = INT_MAX, SIntType step = 1, bool listme = true);
explicit Option(std::string, UIntMemberType, const UIntType = 0, UIntType min = 0, UIntType max = UINT_MAX, UIntType step = 1, bool listme = true);
explicit Option(std::string, BooleanMemberType, const BooleanType = false, bool listme = true);
explicit Option(std::string, FunctionMemberType, const StringType, StringSet & allowed, bool listme = true);
explicit Option(std::string, FunctionMemberType, const StringType = "", bool listme = true);
Option(const Option & o);
~Option(void);
template < typename Object >
void set(Object * object, std::string value)
{
try
{
/**/ if (_option.check<InnerFunctionType>()) _option.get<InnerFunctionType>().store(object, value);
else if (_option.check<InnerStringType>()) _option.get<InnerStringType>().store(object, value);
else if (_option.check<InnerBooleanType>()) _option.get<InnerBooleanType>().store(object, Strings::toboolean(value));
else if (_option.check<InnerSIntType>()) _option.get<InnerSIntType>().store(object, Strings::tolong(value));
else if (_option.check<InnerUIntType>()) _option.get<InnerUIntType>().store(object, Strings::toulong(value));
else
{
throw Failure(STG(FMT("set() not implemented for type used in option '%s'") % _myname));
}
}
catch (Strings::invalid_value & e)
{
throw Failure(STG(FMT("got invalid value '%s' for option '%s'") % value % _myname));
}
catch (EmptyVariable & e)
{
throw Failure(STG(FMT("uninitialized variable while setting value '%s' for option '%s'") % value % _myname));
}
}
template < typename Object >
std::string get(const Object * const object) const
{
try
{
/**/ if (_option.check<InnerFunctionType>()) return _option.get<InnerFunctionType>().get(object);
else if (_option.check<InnerStringType>()) return _option.get<InnerStringType>().get(object);
else if (_option.check<InnerBooleanType>()) return (_option.get<InnerBooleanType>().get(object) ? "yes" : "no");
else if (_option.check<InnerSIntType>()) return STG(FMT("%d") % _option.get<InnerSIntType>().get(object));
else if (_option.check<InnerUIntType>()) return STG(FMT("%u") % _option.get<InnerUIntType>().get(object));
else
{
throw Failure(STG(FMT("get() not implemented for type used in option '%s'") % _myname));
}
}
catch (EmptyVariable & e)
{
throw Failure(STG(FMT("uninitialized variable while getting value for option '%s'") % _myname));
}
}
template < typename Object >
bool loaded(const Object * const object) const
{
try
{
/**/ if (_option.check<InnerFunctionType>()) return _option.get<InnerFunctionType>().loaded(object);
else if (_option.check<InnerBooleanType>()) return _option.get<InnerBooleanType>().loaded(object);
else if (_option.check<InnerStringType>()) return _option.get<InnerStringType>().loaded(object);
else if (_option.check<InnerSIntType>()) return _option.get<InnerSIntType>().loaded(object);
else if (_option.check<InnerUIntType>()) return _option.get<InnerUIntType>().loaded(object);
else
{
throw Failure(STG(FMT("loaded() not implemented for type used in option '%s'") % _myname));
}
}
catch (EmptyVariable & e)
{
throw Failure(STG(FMT("uninitialized variable while checking load status for option '%s'") % _myname));
}
}
template < typename Object >
void reset(Object * const object)
{
try
{
/**/ if (_option.check<InnerFunctionType>()) _option.get<InnerFunctionType>().reset(object);
else if (_option.check<InnerBooleanType>()) _option.get<InnerBooleanType>().reset(object);
else if (_option.check<InnerStringType>()) _option.get<InnerStringType>().reset(object);
else if (_option.check<InnerSIntType>()) _option.get<InnerSIntType>().reset(object);
else if (_option.check<InnerUIntType>()) _option.get<InnerUIntType>().reset(object);
else
{
throw Failure(STG(FMT("reset() not implemented for type used in option '%s'") % _myname));
}
}
catch (EmptyVariable & e)
{
throw Failure(STG(FMT("uninitialized variable while reseting status for option '%s'") % _myname));
}
}
template < typename Object >
void commit(Object * const object)
{
try
{
/**/ if (_option.check<InnerFunctionType>()) _option.get<InnerFunctionType>().commit(object);
else if (_option.check<InnerBooleanType>()) _option.get<InnerBooleanType>().commit(object);
else if (_option.check<InnerStringType>()) _option.get<InnerStringType>().commit(object);
else if (_option.check<InnerSIntType>()) _option.get<InnerSIntType>().commit(object);
else if (_option.check<InnerUIntType>()) _option.get<InnerUIntType>().commit(object);
else
{
throw Failure(STG(FMT("commit() not implemented for type used in option '%s'") % _myname));
}
}
catch (EmptyVariable & e)
{
throw Failure(STG(FMT("uninitialized variable while commiting option '%s'") % _myname));
}
}
const std::string & name(void) const { return _myname; }
bool listme(void) const { return _listme; };
const char ** values(void);
template < typename Object >
void copyFrom(const Object * const srcobj, Object * const dstobj, bool force = false)
{
if (loaded(dstobj) && !force)
return;
if (loaded(srcobj))
set(dstobj, get(srcobj));
else
reset(dstobj);
}
protected:
const std::string _myname;
InnerType _option;
const bool _listme;
const char ** _values;
};
struct Options
{
typedef std::vector < std::string > Messages;
Options();
~Options();
typedef std::set < std::string > StringSet;
typedef std::map < std::string, Option > OptionMap;
typedef std::pair < std::string, Option > OptionPair;
typedef std::map < std::string, std::string > SynOptionMap;
typedef std::pair < std::string, std::string > SynOptionPair;
bool add(Option option);
/* only valid in "process" (for backwards compatibility config files) */
bool synonym(std::string, std::string);
template < typename Type >
void set(const std::string & name, Type value)
{
OptionMap::iterator iter = find_option(name);
if (iter == _map.end())
throw Failure(STG(FMT("unknown option: %s") % name));
iter->second.set(value);
}
template < typename Object >
std::string get(const Object * const object, const std::string & name)
{
OptionMap::iterator iter = find_option(name);
if (iter == _map.end())
throw Failure(STG(FMT("unknown option: %s") % name));
return iter->second.get(object);
}
template < typename Object >
void process(Object * const object, const char * name, const char * value)
{
OptionMap::iterator iter = find_option(name);
if (iter == _map.end())
throw Failure(STG(FMT("unknown option '%s'") % name));
iter->second.set(object, value);
}
template < typename Object >
Messages commit(Object * const object)
{
Messages msgs;
for (OptionMap::iterator i = _map.begin(); i != _map.end(); ++i)
{
try
{
i->second.commit(object);
}
catch (Failure & e)
{
msgs.push_back(e.what());
}
}
return msgs;
}
template < typename Object >
void reset(Object * object)
{
for (OptionMap::iterator i = _map.begin(); i != _map.end(); ++i)
i->second.reset(object);
}
template < typename Object >
bool loaded(Object * object, std::string name)
{
OptionMap::iterator iter = find_option(name);
if (iter == _map.end())
return false;
return iter->second.loaded(object);
}
bool exists(const std::string & name)
{
OptionMap::iterator iter = find_option(name);
return (iter != _map.end());
}
StringSet options(void);
const char ** values(const char *); /* option value */
const char ** values(void); /* values from options */
template < typename Object >
void copyFrom(const std::string & name, const Object * const src_obj, Object * const dst_obj, bool force = false)
{
OptionMap::iterator iter = find_option(name);
if (iter == _map.end())
throw Failure(STG(FMT("unknown option '%s'") % name));
iter->second.copyFrom(src_obj, dst_obj, force);
}
template < typename Object >
void copyFrom(Object * src_obj, Object * dst_obj, bool force = false)
{
for (OptionMap::iterator iter = _map.begin(); iter != _map.end(); ++iter)
iter->second.copyFrom(src_obj, dst_obj, force);
}
protected:
OptionMap::iterator find_option(std::string);
protected:
OptionMap _map;
SynOptionMap _syn_map;
const char ** _values;
};
};
#endif /* _CONFIG_OPTIONS_HPP_ */

View File

@ -0,0 +1,241 @@
/*
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2009 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
*/
#include <errno.h>
#include <configurator/configfile.hpp>
#if _MSC_VER >= 1400
#undef close
#endif
void Configfile::ignore(const std::string & str)
{
_ignores.insert(str);
};
bool Configfile::select(Section **ptr, const std::string & str)
{
/* default section == this! */
*ptr = this;
/* always success by default */
return true;
};
bool Configfile::adjust(Section * section, const std::string & opt, const std::string & val)
{
return section->load(opt, val);
};
bool Configfile::deserialize(std::ifstream & fd)
{
Section * section = NULL;
/* default selection! */
if (!select(&section))
{
_errors.push_back("default selection has failed!");
return false;
}
size_t count = 0;
while (fd.good())
{
std::string str;
/* read one line! */
std::getline(fd, str);
size_t lst = str.size() - 1;
if (str.size() >= 1 && str[lst] == '\r') //cuida das quebras de linha do tipo \r\n
{
str.erase(lst,1);
--lst;
}
/* empty line! */
if (str.size() == 0)
continue;
/* comment! */
if (str[0] == '#')
continue;
++count;
if (str[0] == '[' && str[lst] == ']')
{
str.erase(0,1); --lst;
str.erase(lst,1); --lst;
if (!select(&section, str))
{
_errors.push_back(STG(FMT("erroneous section '%s'") % str));
/* ignore this section */
section = NULL;
continue;
}
}
else
{
std::string::size_type pos = str.find('=');
if (pos == std::string::npos)
{
_errors.push_back(STG(FMT("erroneous separator '%s'") % str));
continue;
};
if (section == NULL)
{
_errors.push_back(STG(FMT("no section for option '%s'") % str));
continue;
}
std::string opt(str.substr(0,pos));
std::string val(str.substr(pos+1));
if (_ignores.find(opt) != _ignores.end())
continue;
if (val == "@") val = "";
if (adjust(section, opt, val))
continue;
_errors.push_back(STG(FMT("option '%s' does "
"not exist or '%s' is not a valid value (at section '%s')")
% opt % val % section->name()));
}
}
// retorna 'true' se arquivo tinha alguma coisa valida.
return (count != 0);
}
bool Configfile::obtain()
{
std::ifstream fd(_filename.c_str());
if (!fd.is_open())
{
_errors.push_back(STG(FMT("unable to open file '%s': %s")
% _filename % strerror(errno)));
return false;
};
if (!deserialize(fd))
{
fd.close();
return false;
}
fd.close();
return true;
};
void Configfile::recurse(std::ofstream & fd, Section * section)
{
typedef Section::SectionMap::const_iterator SectionIter;
typedef Section::OptionMap::const_iterator OptionIter;
for (OptionIter i = section->option_begin(); i != section->option_end(); i++)
{
std::string res;
if ((*i).second.store(res))
{
if (res == "") res = "@";
fd << (*i).first << "=" << res << std::endl;
}
}
if (!section->recursive())
return;
for (SectionIter j = section->section_begin(); j != section->section_end(); j++)
recurse(fd, (*j).second);
}
bool Configfile::serialize(std::ofstream & fd)
{
recurse(fd, this);
return true;
}
bool Configfile::provide()
{
std::string tmp(_filename);
tmp += ".new";
std::ofstream fd(tmp.c_str());
if (!fd.good())
{
_errors.push_back(STG(FMT("unable to open file '%s': %s")
% tmp % strerror(errno)));
return false;
}
if (!serialize(fd))
{
fd.close();
return false;
}
fd.close();
if (rename(tmp.c_str(), _filename.c_str()) != 0)
{
_errors.push_back(STG(FMT("unable to replace config file '%s': %s")
% _filename % strerror(errno)));
return false;
}
return true;
}
#if _MSC_VER >= 1400
#define close _close
#endif

View File

@ -1,7 +1,7 @@
/*
/*
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2009 Khomp Ind. & Com.
Copyright (C) 2007-2009 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/
@ -23,20 +23,20 @@
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.
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
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <vector>
@ -53,38 +53,38 @@
struct Configfile: public Section
{
typedef std::list < std::string > ErrorVector;
typedef std::set < std::string > NameSet;
typedef std::list < std::string > ErrorVector;
typedef std::set < std::string > NameSet;
Configfile(std::string name, std::string desc)
: Section(name, desc), _good(false) {};
Configfile(const std::string & name, const std::string & desc)
: Section(name, desc), _good(false) {};
virtual ~Configfile() {};
virtual ~Configfile() {};
bool good() { return _good; };
std::string & filename() { return _filename; };
bool good() const { return _good; };
const std::string & filename() const { return _filename; };
ErrorVector & errors() { return _errors; };
const ErrorVector & errors() const { return _errors; };
void ignore(std::string);
void ignore(const std::string &);
virtual bool obtain();
virtual bool provide();
virtual bool obtain();
virtual bool provide();
protected:
virtual bool select(Section **, std::string str = "");
virtual bool adjust(Section *, std::string & opt, std::string & val);
virtual bool select(Section **, const std::string & str = "");
virtual bool adjust(Section *, const std::string & opt, const std::string & val);
virtual bool deserialize(std::ifstream &);
virtual bool serialize(std::ofstream &);
virtual bool deserialize(std::ifstream &);
virtual bool serialize(std::ofstream &);
void recurse(std::ofstream &, Section *);
void recurse(std::ofstream &, Section *);
protected:
bool _good;
ErrorVector _errors;
NameSet _ignores;
std::string _filename;
bool _good;
ErrorVector _errors;
NameSet _ignores;
std::string _filename;
};
#endif /* _CONFIG_CONFIGFILE_HPP_ */

View File

@ -0,0 +1,186 @@
/*
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2009 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
*/
#include <configurator/option.hpp>
bool Option::equals(const std::string & value) const
{
switch (_restriction.numeral())
{
case Restriction::N_UNIQUE:
{
Restriction::Value my_value;
if (!_restriction.get(Restriction::F_USER, my_value))
return false;
return (my_value == value);
}
case Restriction::N_MULTIPLE:
{
Restriction::Vector my_values;
if (!_restriction.get(Restriction::F_USER, my_values))
return false;
for (Restriction::Vector::iterator i = my_values.begin(); i != my_values.end(); i++)
{
if ((*i) == value)
return true;
}
return false;
}
}
return false;
}
bool Option::load(const std::string & value)
{
bool ret = _restriction.set( (const Restriction::Format)Restriction::F_FILE, value);
if (ret) _modified = false;
return ret;
}
bool Option::change(const std::string & value)
{
bool ret = _restriction.set(Restriction::F_FILE, value);
if (ret) _modified = true;
return ret;
}
bool Option::store(std::string & value) const
{
switch (_restriction.numeral())
{
case Restriction::N_UNIQUE:
return _restriction.get(Restriction::F_FILE, value);
case Restriction::N_MULTIPLE:
{
Restriction::Vector values;
if (!_restriction.get(Restriction::F_FILE, values))
return false;
Strings::Merger strs;
for (Restriction::Vector::iterator i = values.begin(); i != values.end(); i++)
strs.add(*i);
value = strs.merge(",");
return true;
}
default:
return false;
}
}
/*
Option::Flags Option::set(const char * value)
{
std::string str_value(value);
return set(str_value);
}
*/
Option::Flags Option::set(const Restriction::Value & value)
{
Restriction::Value last_value, curr_value;
Flags flags;
bool ret1 = _restriction.get(Restriction::F_USER, last_value);
if (!_restriction.set(Restriction::F_USER, value))
return flags;
flags[F_ADJUSTED] = true;
bool ret2 = _restriction.get(Restriction::F_USER, curr_value);
if (!ret1 || (ret2 && (last_value != curr_value)))
{
flags[F_MODIFIED] = true;
_modified = true;
}
return flags;
}
Option::Flags Option::set(const Restriction::Vector & values)
{
Restriction::Vector last_values, curr_values;
Flags flags;
bool ret1 = _restriction.get(Restriction::F_USER, last_values);
if (!_restriction.set(Restriction::F_USER, values))
return flags;
flags[F_ADJUSTED] = true;
bool ret2 = _restriction.get(Restriction::F_USER, curr_values);
if (!ret1 || (ret2 && (last_values != curr_values)))
{
flags[F_MODIFIED] = true;
_modified = true;
}
return flags;
}
bool Option::get(Restriction::Value & value) const
{
return _restriction.get(Restriction::F_USER, value);
}
bool Option::get(Restriction::Vector & values) const
{
return _restriction.get(Restriction::F_USER, values);
}

View File

@ -1,7 +1,7 @@
/*
/*
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2009 Khomp Ind. & Com.
Copyright (C) 2007-2009 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/
@ -23,20 +23,20 @@
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.
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
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <iostream>
@ -45,6 +45,7 @@
#include <list>
#include <vector>
#include <format.hpp>
#include <strings.hpp>
#include <configurator/restriction.hpp>
@ -56,67 +57,72 @@ struct Option
{
enum FlagTypes
{
F_MODIFIED = 0x0, /* if option was modified */
F_ADJUSTED = 0x1, /* if option was correctly formated */
F_MODIFIED = 0x0, /* if option was modified */
F_ADJUSTED = 0x1, /* if option was correctly formated */
};
struct Flags: public std::vector<bool>
{
Flags(): std::vector<bool>(2) {};
};
struct Flags: public std::vector<bool>
{
Flags(): std::vector<bool>(2) {};
};
typedef Restriction::Value Value;
typedef Restriction::Vector Vector;
typedef Restriction::Value Value;
typedef Restriction::Vector Vector;
/* exception */
struct InvalidDefaultValue
struct InvalidDefaultValue: public std::runtime_error
{
InvalidDefaultValue(std::string name, std::string value)
: _name(name), _value(value) {};
InvalidDefaultValue(const std::string & name, const std::string & value)
: std::runtime_error(STG(FMT("invalid default value '%s' for option '%s'") % value % name)),
_name(name), _value(value)
{};
std::string & name() { return _name; };
std::string & value() { return _value; };
~InvalidDefaultValue() throw ()
{};
const std::string & name() const { return _name; };
const std::string & value() const { return _value; };
protected:
std::string _name;
std::string _value;
const std::string _name;
const std::string _value;
};
Option(std::string name, std::string desc, std::string defvalue, Restriction restriction)
: _name(name), _desc(desc), _restriction(restriction), _modified(true)
{
std::string value(defvalue);
Option(const std::string & name, const std::string & desc, const std::string & defvalue, const Restriction & restriction)
: _name(name), _description(desc), _restriction(restriction), _modified(true)
{
// std::string value(defvalue);
if (!(set(value)[F_ADJUSTED]))
if (!(set(defvalue)[F_ADJUSTED]))
throw InvalidDefaultValue(name, defvalue);
}
}
const std::string & name() { return _name; };
const std::string & description() { return _desc; };
const std::string & name() const { return _name; };
const std::string & description() const { return _description; };
Restriction & restriction() { return _restriction; };
bool modified() { return _modified; };
const Restriction & restriction() const { return _restriction; };
bool modified() const { return _modified; };
public:
bool load(std::string &);
bool change(std::string &);
bool store(std::string &);
bool load(const std::string &);
bool change(const std::string &);
bool store(std::string &) const;
Flags set(const char *);
Flags set(Value &);
Flags set(Vector &);
// Flags set(const char *);
Flags set(const Value &);
Flags set(const Vector &);
bool get(Value &);
bool get(Vector &);
bool get(Value &) const;
bool get(Vector &) const;
bool equals(std::string &);
bool equals(const std::string &) const;
protected:
std::string _name;
std::string _desc;
const std::string _name;
const std::string _description;
Restriction _restriction;
bool _modified;
Restriction _restriction;
bool _modified;
};
#endif /* _CONFIG_OPTION_HPP_ */

View File

@ -0,0 +1,358 @@
/*
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2009 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
*/
#include <math.h>
#include <string.h>
#include <iostream>
#include <strings.hpp>
#include <configurator/restriction.hpp>
/* internal helper! */
bool Restriction::equalNumber(const double a, const double b)
{
char tmp1[64];
char tmp2[64];
snprintf(tmp1, sizeof(tmp1), "%.3f", a);
snprintf(tmp2, sizeof(tmp2), "%.3f", b);
if (strncmp(tmp1, tmp2, sizeof(tmp1)))
return false;
return true;
}
/* process value to our internal representation */
bool Restriction::process(Restriction::Format fmt,
const Restriction::Value & value, Restriction::Value & final) const
{
switch (_bounds)
{
case B_RANGE:
{
if (_kind != K_NUMBER)
return false;
std::string tmpvalue;
Restriction::Value::const_iterator itr = value.begin();
Restriction::Value::const_iterator end = value.end();
tmpvalue.reserve(value.size());
// f*cking dot/comma notation!
for (; itr != end; ++itr)
tmpvalue += ((*itr) != ',' ? (*itr) : '.');
try
{
double newvalue = Strings::todouble(tmpvalue);
if (newvalue < _init && newvalue > _fini)
return false;
double res = (newvalue - _init) / _step;
if (!Restriction::equalNumber(res, rint(res)))
return false;
final = value;
return true;
}
catch (...)
{
return false;
}
}
case B_LIST:
for (List::const_iterator i = _list.begin(); i != _list.end(); i++)
{
const Value & tmp = (*i);
if (tmp == value)
{
final = value;
return true;
}
}
return false;
case B_MAPS:
switch (fmt)
{
case F_USER:
{
Map::const_iterator i = _map_from_usr.find(value);
if (i == _map_from_usr.end())
return false;
const Value & tmp = (*i).second;
final = tmp;
return true;
}
case F_FILE:
{
Map::const_iterator i = _map_from_cfg.find(value);
if (i == _map_from_cfg.end())
return false;
final = value;
return true;
}
default:
break;
}
return false;
case B_FREE:
final = value;
return true;
default:
break;
}
return false;
}
/* unprocess the value (outputs the external representation) */
bool Restriction::unprocess(Restriction::Format fmt,
const Restriction::Value & value, Restriction::Value & final) const
{
switch (_bounds)
{
case B_MAPS:
switch (fmt)
{
case F_USER:
{
Map::const_iterator i = _map_from_cfg.find(value);
if (i == _map_from_cfg.end())
return false;
final = (*i).second;
return true;
}
default:
break;
}
default:
final = value;
return true;
}
}
/***************************** *****************************/
bool Restriction::get(Restriction::Format fmt, Restriction::Value & value) const
{
if (_numeral != N_UNIQUE)
return false;
if (!unprocess(fmt, _value._unique, value))
return false;
return true;
}
bool Restriction::get(Restriction::Format fmt, Restriction::Vector & values) const
{
if (_numeral != N_MULTIPLE)
return false;
const List & my_values = _value._multiple;
for (List::const_iterator i = my_values.begin(); i != my_values.end(); i++)
{
const Value & value = (*i);
Value final;
if (!unprocess(fmt, value, final))
return false;
values.push_back(final);
};
return true;
}
/***************************** *****************************/
bool Restriction::set(Restriction::Format fmt, const Restriction::Value & value)
{
switch (_numeral)
{
case N_UNIQUE:
{
Value final;
if (!constThis().process(fmt, value, final))
return false;
_value._unique = final;
return true;
}
case N_MULTIPLE:
{
if (value == "@" || value == "#" || value == "")
{
_value._multiple.clear();
return true;
}
Strings::vector_type values;
Strings::tokenize(value, values, ",");
return set(fmt, values);
}
default:
return false;
}
}
bool Restriction::set(Restriction::Format fmt, const Restriction::Vector & values)
{
if (_numeral != N_MULTIPLE)
return false;
if (values.empty())
{
_value._multiple.clear();
}
else
{
/* list needed to store temporary values */
List finals;
for (Vector::const_iterator i = values.begin(); i != values.end(); i++)
{
const Value & value = (*i);
Value final;
if (!constThis().process(fmt, value, final))
return false;
finals.push_back(final);
}
List & lst = _value._multiple;
/* need to clear values set before */
lst.clear();
for (List::iterator i = finals.begin(); i != finals.end(); i++)
{
Value value = (*i);
lst.push_back(value);
}
};
return true;
}
/***************************** *****************************/
void Restriction::allowed(Restriction::Vector & vals) const
{
switch (_bounds)
{
case B_FREE:
return;
case B_LIST:
for (List::const_iterator i = _list.begin(); i != _list.end(); i++)
vals.push_back(*i);
break;
case B_MAPS:
for (Map::const_iterator i = _map_from_usr.begin(); i != _map_from_usr.end(); i++)
vals.push_back(i->first);
break;
case B_RANGE:
{
if (_kind != K_NUMBER)
return;
// is there any fraction?
bool has_fraction =
(!Restriction::equalNumber(_init, rint(_init))) ||
(!Restriction::equalNumber(_fini, rint(_fini))) ||
(!Restriction::equalNumber(_step, rint(_step)));
const char * format = (has_fraction ? "%.2f" : "%02.0f");
for (double i = _init; i <= _fini; i += _step)
{
char tmp[32];
snprintf(tmp, sizeof(tmp), format, i);
vals.push_back(std::string(tmp));
}
break;
}
default:
break;
}
}
void Restriction::init_class()
{
_value._unique.clear();
_value._multiple.clear();
}

View File

@ -0,0 +1,269 @@
/*
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2009 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
*/
#include <stdarg.h>
#include <string>
#include <list>
#include <vector>
#include <map>
#include <const_this.hpp>
#ifndef _CONFIG_RESTRICTION_HPP_
#define _CONFIG_RESTRICTION_HPP_
struct Restriction: public ConstThis < Restriction >
{
/* generic types */
// TODO: change this type name for something different
// to avoid conflicting with "format.hpp".
enum Format
{
F_USER,
F_FILE
};
enum Kind
{
K_STRING,
K_NUMBER // = K_INTEGER // compatibility
};
enum Bounds
{
B_FREE,
B_RANGE,
B_LIST,
B_MAPS
};
enum Numeral
{
N_UNIQUE,
N_MULTIPLE
};
typedef std::string Value;
/* types used for data input */
struct Pair
{
const char *pretty;
const char *value;
};
typedef std::pair < Value, Value > PairMap;
typedef std::list < PairMap > ListMap;
/* types used internally */
typedef std::map < Value, Value > Map;
typedef std::vector < Value > Vector;
typedef std::list < Value > List;
typedef std::pair < Value, Value > MapPair;
struct Generic
{
Value _unique;
List _multiple;
};
Restriction(Kind kind, Numeral num)
: _kind(kind), _bounds(B_FREE), _numeral(num), _unit(""),
_init(-1), _fini(-1), _step(-1)
{
init_class();
}
Restriction(Kind kind, Numeral num,
double init, double fini, double step = 1)
: _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(""),
_init(init), _fini(fini), _step(step)
{
init_class();
}
Restriction(Kind kind, Numeral num,
const char *unit, double init, double fini, double step = 1.0)
: _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(unit),
_init(init), _fini(fini), _step(step)
{
init_class();
}
Restriction(Kind kind, Numeral num,
std::string unit, double init, double fini, double step = 1.0)
: _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(unit),
_init(init), _fini(fini), _step(step)
{
init_class();
}
Restriction(Kind kind, Numeral num,
const char *first, ...)
: _kind(kind), _bounds(B_LIST), _numeral(num), _unit(""),
_init(-1), _fini(-1), _step(-1)
{
_list.push_back(std::string(first));
va_list ap;
va_start(ap, first);
while (true)
{
const char *arg = va_arg(ap, const char *);
if (arg == NULL) break;
_list.push_back(std::string(arg));
}
init_class();
}
Restriction(Kind kind, const char *unit, Numeral num,
const char *first, ...)
: _kind(kind), _bounds(B_LIST), _numeral(num), _unit(unit),
_init(-1), _fini(-1), _step(-1)
{
_list.push_back(std::string(first));
va_list ap;
va_start(ap, first);
while (true)
{
const char *arg = va_arg(ap, const char *);
if (arg == NULL) break;
_list.push_back(std::string(arg));
}
init_class();
}
Restriction(Kind kind, Numeral num,
const struct Pair first, ...)
: _kind(kind), _bounds(B_MAPS), _numeral(num), _unit(""),
_init(-1), _fini(-1), _step(-1)
{
_map_from_usr.insert(MapPair(Value(first.pretty), Value(first.value)));
_map_from_cfg.insert(MapPair(Value(first.value), Value(first.pretty)));
va_list ap;
va_start(ap, first);
while (true)
{
Pair arg = va_arg(ap, Pair);
if (arg.pretty == NULL) break;
_map_from_usr.insert(MapPair(Value(arg.pretty), Value(arg.value)));
_map_from_cfg.insert(MapPair(Value(arg.value), Value(arg.pretty)));
}
init_class();
}
Restriction(Kind kind, Numeral num, List list)
: _kind(kind), _bounds(B_LIST), _numeral(num), _unit(""),
_init(-1), _fini(-1), _step(-1), _list(list)
{
init_class();
}
Restriction(Kind kind, Numeral num, ListMap map)
: _kind(kind), _bounds(B_MAPS), _numeral(num), _unit(""),
_init(-1), _fini(-1), _step(-1)
{
for (ListMap::iterator i = map.begin(); i != map.end(); i++)
{
_map_from_usr.insert(MapPair(Value((*i).first), Value((*i).second)));
_map_from_cfg.insert(MapPair(Value((*i).second), Value((*i).first)));
}
init_class();
}
const Kind kind() const { return _kind; };
const Bounds bounds() const { return _bounds; };
const Numeral numeral() const { return _numeral; };
const std::string & unit() const { return _unit; };
bool set(Format, const Vector &);
bool set(Format, const Value &);
bool get(Format, Vector &) const;
bool get(Format, Value &) const;
void allowed(Vector &) const;
private:
bool process(const Format, const Value &, Value &) const;
bool unprocess(const Format, const Value &, Value &) const;
void init_class();
static bool equalNumber(const double, const double);
protected:
const Kind _kind;
const Bounds _bounds;
const Numeral _numeral;
Value _unit;
const double _init, _fini, _step;
Map _map_from_usr,
_map_from_cfg;
List _list;
Generic _value;
};
#endif /* _CONFIG_RESTRICTION_HPP_ */

View File

@ -1,7 +1,7 @@
/*
/*
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2009 Khomp Ind. & Com.
Copyright (C) 2007-2009 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/
@ -23,108 +23,114 @@
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.
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
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <configurator/section.hpp>
void Section::options(Section::OptionVector & vec)
void Section::options(Section::OptionVector & vec) const
{
for (OptionMap::iterator it = _options.begin(); it != _options.end();)
{
vec.push_back(&((*it).second));
++it;
}
for (OptionMap::const_iterator it = _options.begin(); it != _options.end();)
{
vec.push_back(const_cast< Option * >(&(it->second)));
++it;
}
}
void Section::sections(Section::SectionVector & vec)
void Section::sections(Section::SectionVector & vec) const
{
for (SectionMap::iterator it = _sections.begin(); it != _sections.end();)
{
vec.push_back((*it).second);
++it;
}
for (SectionMap::const_iterator it = _sections.begin(); it != _sections.end();)
{
vec.push_back(const_cast< Section * >(it->second));
++it;
}
}
/*********/
Option * Section::option_find(std::string & str, bool recurse)
Option * Section::option_find(const std::string & str, bool recurse) const
{
OptionMap::iterator i = _options.find(str);
OptionMap::const_iterator i = _options.find(str);
if (i == _options.end())
if (i == _options.end())
{
if (!recurse)
throw not_found();
throw OptionNotFound(str, _name);
// throw not_found();
for (SectionMap::iterator i = _sections.begin(); i != _sections.end(); i++)
for (SectionMap::const_iterator i = _sections.begin(); i != _sections.end(); i++)
{
try
{
return i->second->option_find(str, recurse);
}
catch (not_found & e)
catch (NotFound & e)
{
/* keep looping! */
};
}
throw not_found();
// throw not_found();
throw OptionNotFound(str, _name);
}
return &((*i).second);
return const_cast< Option * >(&(i->second));
}
/*
Option * Section::option_find(const char * str, bool recurse)
{
std::string sstr(str);
return option_find(sstr, recurse);
std::string sstr(str);
return option_find(sstr, recurse);
}
*/
/*********/
Section * Section::section_find(std::string & str, bool recurse)
Section * Section::section_find(const std::string & str, bool recurse) const
{
SectionMap::iterator i = _sections.find(str);
SectionMap::const_iterator i = _sections.find(str);
if (i == _sections.end())
if (i == _sections.end())
{
if (!recurse)
throw not_found();
throw SectionNotFound(str, _name);
for (SectionMap::iterator i = _sections.begin(); i != _sections.end(); i++)
for (SectionMap::const_iterator i = _sections.begin(); i != _sections.end(); i++)
{
try
{
return i->second->section_find(str, recurse);
}
catch (not_found & e)
catch (NotFound & e)
{
/* keep looping! */
};
}
throw not_found();
throw SectionNotFound(str, _name);
}
return ((*i).second);
return const_cast< Section * >(i->second);
}
/*
Section * Section::section_find(const char * str, bool recurse)
{
std::string sstr(str);
return section_find(sstr, recurse);
std::string sstr(str);
return section_find(sstr, recurse);
}
*/

View File

@ -0,0 +1,260 @@
/*
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2009 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 _CONFIG_SECTION_HPP_
#define _CONFIG_SECTION_HPP_
#include <string>
#include <vector>
#include <map>
#include <algorithm>
#include <iostream>
#include <format.hpp>
#include <configurator/option.hpp>
struct Section
{
typedef std::map < std::string, Option > OptionMap;
typedef std::vector< Option * > OptionVector;
typedef std::map < std::string, Section * > SectionMap;
typedef std::vector < Section * > SectionVector;
struct NotFound: public std::runtime_error
{
NotFound(const std::string & type, const std::string & name, const std::string & me)
: std::runtime_error(STG(FMT("%s '%s' not found on section '%s'") % type % name % me)) {};
};
struct OptionNotFound: public NotFound
{
OptionNotFound(const std::string & name, const std::string & me)
: NotFound("option", name, me) {};
};
struct SectionNotFound: public NotFound
{
SectionNotFound(const std::string & name, const std::string & me)
: NotFound("section", name, me) {};
};
typedef NotFound not_found; /* backward compatibility */
// protected:
Section(const std::string & name, const std::string & desc, bool recursive = true)
: _name(name), _description(desc), _recursive(recursive) {};
void add(const Option & o)
{
_options.insert(std::pair<std::string,Option>(o.name(), o));
};
void del(const std::string & name)
{
_options.erase(name);
};
void add(Section * s)
{
_sections.insert(std::pair< std::string, Section * >(s->name(), s));
};
public:
const std::string & name() const { return _name; };
const std::string & description() const { return _description; };
const bool recursive() const { return _recursive; };
OptionMap::const_iterator option_begin() const { return _options.begin(); };
OptionMap::const_iterator option_end() const { return _options.end(); };
SectionMap::const_iterator section_begin() const { return _sections.begin(); };
SectionMap::const_iterator section_end() const { return _sections.end(); };
/**/
// Option * option_find(const char *, bool recurse = false) const;
// Section * section_find(const char *, bool recurse = false) const;
Option * option_find(const std::string &, bool recurse = false) const;
Section * section_find(const std::string &, bool recurse = false) const;
/**/
void options(OptionVector &) const;
void sections(SectionVector &) const;
/**/
template < typename T, typename F >
bool search_and_apply(const std::string & key, T & value, F f)
{
OptionMap::iterator i = _options.find(key);
if (i != _options.end())
return f(i->second);
if (!_recursive)
return false;
return (find_if(_sections.begin(), _sections.end(), f) != _sections.end());
}
private:
struct ConstKeyValue
{
ConstKeyValue(const std::string & k, const std::string &v)
: _k(k), _v(v) {};
const std::string & _k;
const std::string & _v;
};
struct KeyValue
{
KeyValue(const std::string & k, std::string &v)
: _k(k), _v(v) {};
const std::string & _k;
std::string & _v;
};
struct load_section: protected ConstKeyValue
{
load_section(const std::string & k, const std::string & v): ConstKeyValue(k,v) {};
bool operator()(Option & o) { return o.load(_v); };
bool operator()(SectionMap::value_type & v) { return v.second->load(_k,_v); };
};
struct change_section: protected ConstKeyValue
{
change_section(const std::string & k, const std::string & v): ConstKeyValue(k,v) {};
bool operator()(Option & o) { return o.change(_v); };
bool operator()(SectionMap::value_type & v) { return v.second->change(_k,_v); };
};
struct store_section: protected KeyValue
{
store_section(const std::string & k, std::string & v): KeyValue(k,v) {};
bool operator()(Option & o) { return o.store(_v); };
bool operator()(SectionMap::value_type & v) { return v.second->store(_k,_v); };
};
struct set_section: protected ConstKeyValue
{
set_section(const std::string & k, const std::string & v): ConstKeyValue(k,v) {};
bool operator()(Option & o) { return (o.set(_v))[Option::F_ADJUSTED]; };
bool operator()(SectionMap::value_type & v) { return v.second->set(_k,_v); };
};
struct get_section: protected KeyValue
{
get_section(const std::string & k, std::string & v): KeyValue(k,v) {};
bool operator()(Option & o) { return o.get(_v); };
bool operator()(SectionMap::value_type & v) { return v.second->get(_k,_v); };
};
struct modified_section
{
bool operator()(const OptionMap::value_type & v) { return v.second.modified(); };
bool operator()(const SectionMap::value_type & v) { return v.second->modified(); };
};
public:
/*
bool load(const char * key, const std::string value)
{
std::string skey(key);
return search_and_apply(skey, value, load_section(skey, value));
}
*/
bool load(const std::string & key, const std::string & value)
{
return search_and_apply(key, value, load_section(key, value));
}
bool change(const std::string & key, const std::string & value)
{
return search_and_apply(key, value, change_section(key, value));
}
bool store(const std::string & key, std::string & value)
{
return search_and_apply(key, value, store_section(key, value));
}
bool set(const std::string & key, const std::string & value)
{
return search_and_apply(key, value, set_section(key, value));
}
bool get(const std::string & key, std::string & value)
{
return search_and_apply(key, value, get_section(key, value));
}
bool modified() const
{
return ((find_if(_options.begin(), _options.end(), modified_section()) != _options.end()) ||
(find_if(_sections.begin(), _sections.end(), modified_section()) != _sections.end()));
}
private:
Section(): _name(""), _description(""), _recursive(false) {};
protected:
const std::string _name;
const std::string _description;
OptionMap _options;
SectionMap _sections;
const bool _recursive;
};
#endif /* _CONFIG_SECTION_HPP_ */

View File

@ -0,0 +1,15 @@
#ifndef _CONST_THIS_H_
#define _CONST_THIS_H_
template < typename T >
struct ConstThis
{
T const & constThis() const
{
// TODO: will this return the right reference?
return static_cast<const T&>(*this);
}
};
#endif /* _CONST_THIS_H_ */

View File

@ -42,27 +42,7 @@
#include "format.hpp"
//#include <iostream>
Format::Format(const char * format_string, bool raise_exception)
: _format(format_string), _valid(true), _raise(raise_exception)
{
initialize(format_string);
}
/*
Format::Format(std::string & format_string, bool raise_exception)
: _format(NULL), _valid(true), _raise(raise_exception)
{
initialize(format_string.c_str());
}
*/
Format::Format(std::string format_string, bool raise_exception)
: _format(format_string), _valid(true), _raise(raise_exception)
{
initialize(format_string.c_str());
}
void Format::initialize(const char * format_string)
void FormatTraits::initialize(const char * format_string)
{
std::string txt;
@ -82,7 +62,6 @@ void Format::initialize(const char * format_string)
if (*ptr2 == '%')
{
txt += *ptr;
ptr += 2;
continue;
}
@ -238,36 +217,20 @@ void Format::initialize(const char * format_string)
push_argument(txt, T_LITERAL);
}
void Format::mark_invalid(std::string & msg)
void FormatTraits::push_argument(std::string & data, FormatTraits::Type type)
{
if (_valid)
{
_valid = false;
// std::cerr << "pushing type (" << type << ") with format (" << data << ")" << std::endl;
std::string finalmsg;
finalmsg += "** INVALID FORMAT: ";
finalmsg += msg;
finalmsg += " **";
_result = finalmsg;
}
_args.push(Argument(data, type));
data.clear();
}
void Format::raise_check(void)
void FormatTraits::pop_argument(void)
{
if (!_valid && _raise)
throw InvalidFormat(_result);
_args.pop();
}
bool Format::validity_check(void)
{
raise_check();
return _valid;
}
const Format::Argument * Format::next_argument(void)
const FormatTraits::Argument * FormatTraits::next_argument(void)
{
// std::cerr << "size: " << _args.size() << std::endl;
@ -294,38 +257,81 @@ const Format::Argument * Format::next_argument(void)
}
}
void Format::pop_argument(void)
/******************************************************************/
#if 0
Format::Format(const char * format_string, bool raise_exception)
: _format(format_string), _valid(true), _raise(raise_exception)
{
_args.pop();
FormatTraits::initialize(format_string);
}
void Format::push_argument(std::string & data, Format::Type type)
Format::Format(std::string format_string, bool raise_exception)
: _format(format_string), _valid(true), _raise(raise_exception)
{
// std::cerr << "pushing type (" << type << ") with format (" << data << ")" << std::endl;
FormatTraits::initialize(format_string.c_str());
}
_args.push(Argument(data, type));
data.clear();
/*
Format::Format(std::string & format_string, bool raise_exception)
: _format(NULL), _valid(true), _raise(raise_exception)
{
initialize(format_string.c_str());
}
*/
void Format::mark_invalid(std::string & msg)
{
if (_valid)
{
_valid = false;
_result = "** INVALID FORMAT: ";
_result += msg;
_result += " **";
}
}
void Format::raise(void) const
{
if (!_valid)
{
// call specialized class
FormatException::raise(_result);
}
}
bool Format::valid(void) const
{
// raise();
return _valid;
}
std::string Format::str()
{
if (!validity_check())
if (!valid())
return _result;
if (next_argument() == NULL)
// try
// {
if (next_argument() != NULL)
{
std::string msg;
msg += "too few arguments passed for format '";
msg += _format;
msg += "' (";
msg += _format;
msg += ")";
mark_invalid(msg);
return _result;
std::string msg;
msg += "too few arguments passed for format '";
msg += _format;
msg += "' (";
msg += _format;
msg += ")";
mark_invalid(msg);
return _result;
}
// catch (NoArgumentLeft e)
// {
// return _result;
// }
}
#endif

View File

@ -52,37 +52,35 @@
#include <stdio.h>
#ifdef WIN32 // WINDOWS
#include <KHostSystem.h>
# include <KHostSystem.h>
#endif
/* macros used for shortening lines and making the code clearer */
#define STG(x) (x).str()
#define FMT(x) Format(x)
struct Format
struct InvalidFormat
{
static const unsigned int strings_base_length = 64;
static const unsigned int generic_base_length = 64;
InvalidFormat(std::string _msg) : msg(_msg) {}
const std::string msg;
};
struct InvalidFormat
template < bool E >
struct FormatException
{
void raise(const std::string & msg) const
{
InvalidFormat(std::string msg) : _msg(msg) {}
std::string _msg;
/* DO NOTHING */
};
};
explicit Format(const char * format_string, bool raise_exception = false);
explicit Format(std::string format_string, bool raise_exception = false);
void initialize(const char *);
std::string str(void);
////////////////////////////////////////////////////////////
protected:
template < >
struct FormatException < true >
{
void raise(const std::string & msg) const
{
throw InvalidFormat(msg);
};
};
struct FormatTraits
{
enum Type
{
T_ANYTHING = 1,
@ -113,24 +111,240 @@ struct Format
Argument(std::string fmts, Type type)
: _fmts(fmts), _type(type) {};
Type type(void) const { return _type; }
const Type type(void) const { return _type; }
const std::string & fmts(void) const { return _fmts; }
protected:
std::string _fmts;
Type _type;
const std::string _fmts;
const Type _type;
};
typedef std::queue < Argument > ArgumentQueue;
////////////////////////////////////////////////////////////
public:
//////////////////////////////////
template < typename V >
Format & operator%( V value )
bool number_verify_signed_short( V value ) const
{
if (!validity_check())
return
((typeid(V) == typeid(short int) ||
typeid(V) == typeid(short) ||
typeid(V) == typeid(const short int) ||
typeid(V) == typeid(const short) ||
typeid(V) == typeid(volatile short int) ||
typeid(V) == typeid(volatile short)) &&
sizeof(V) == sizeof(short));
}
template < typename V >
bool number_verify_unsigned_short( V value ) const
{
return
((typeid(V) == typeid(unsigned short int) ||
typeid(V) == typeid(unsigned short) ||
typeid(V) == typeid(const unsigned short int) ||
typeid(V) == typeid(const unsigned short) ||
typeid(V) == typeid(volatile unsigned short int) ||
typeid(V) == typeid(volatile unsigned short)) &&
sizeof(V) == sizeof(unsigned short));
}
template < typename V >
bool number_verify_signed_long( V value ) const
{
return
((typeid(V) == typeid(long int) ||
typeid(V) == typeid(long) ||
typeid(V) == typeid(const long int) ||
typeid(V) == typeid(const long) ||
typeid(V) == typeid(volatile long int) ||
typeid(V) == typeid(volatile long)) &&
sizeof(V) == sizeof(long));
}
template < typename V >
bool number_verify_unsigned_long( V value ) const
{
return
((typeid(V) == typeid(unsigned long int) ||
typeid(V) == typeid(unsigned long) ||
typeid(V) == typeid(const unsigned long int) ||
typeid(V) == typeid(const unsigned long) ||
typeid(V) == typeid(volatile unsigned long int) ||
typeid(V) == typeid(volatile unsigned long)) &&
sizeof(V) == sizeof(long long));
}
template < typename V >
bool number_verify_signed_long_long( V value ) const
{
return
((typeid(V) == typeid(long long int) ||
typeid(V) == typeid(long long) ||
typeid(V) == typeid(const long long int) ||
typeid(V) == typeid(const long long) ||
typeid(V) == typeid(volatile long long) ||
typeid(V) == typeid(volatile long long int)) &&
sizeof(V) == sizeof(long long));
}
template < typename V >
bool number_verify_unsigned_long_long( V value ) const
{
return
((typeid(V) == typeid(unsigned long long int) ||
typeid(V) == typeid(unsigned long long) ||
typeid(V) == typeid(const unsigned long long int) ||
typeid(V) == typeid(const unsigned long long) ||
typeid(V) == typeid(volatile unsigned long long) ||
typeid(V) == typeid(volatile unsigned long long int)) &&
sizeof(V) == sizeof(unsigned long long));
}
template < typename V >
bool number_verify_signed_int( V value ) const
{
return
(sizeof(V) <= sizeof(int) ||
typeid(V) == typeid(int) ||
typeid(V) == typeid(const int) ||
typeid(V) == typeid(volatile int));
}
template < typename V >
bool number_verify_unsigned_int( V value ) const
{
return
(sizeof(V) <= sizeof(unsigned int) ||
typeid(V) == typeid(unsigned int) ||
typeid(V) == typeid(const unsigned int) ||
typeid(V) == typeid(volatile unsigned int));
}
template < typename V >
bool generic_verify( V value, const Type type ) const
{
switch (type)
{
/* EXCEPTION: consider any number an valid input. */
case T_SIGNED_INT:
case T_UNSIGNED_INT:
return
(number_verify_signed_int(value) ||
number_verify_unsigned_int(value) ||
number_verify_signed_long(value) ||
number_verify_unsigned_long(value) ||
number_verify_signed_short(value) ||
number_verify_unsigned_short(value));
case T_SIGNED_SHORT_SHORT:
return (typeid(V) == typeid(char) || typeid(V) == typeid(const char));
case T_SIGNED_SHORT:
return number_verify_signed_short(value);
case T_SIGNED_LONG:
return number_verify_signed_long(value);
case T_SIGNED_LONG_LONG:
return number_verify_signed_long_long(value);
case T_UNSIGNED_SHORT_SHORT:
return (typeid(V) == typeid(unsigned char) || typeid(V) == typeid(unsigned char));
case T_UNSIGNED_SHORT:
return number_verify_unsigned_short(value);
case T_UNSIGNED_LONG:
return number_verify_unsigned_long(value);
case T_UNSIGNED_LONG_LONG:
return number_verify_unsigned_long_long(value);
case T_FLOAT:
return (typeid(V) == typeid(float)) || (typeid(V) == typeid(double) ||
typeid(V) == typeid(const float)) || (typeid(V) == typeid(const double));
case T_CHAR:
return (typeid(V) == typeid(char)) || (typeid(V) == typeid(unsigned char) ||
typeid(V) == typeid(const char)) || (typeid(V) == typeid(const unsigned char));
case T_POINTER:
case T_STRING:
return false;
case T_ANYTHING:
return true;
case T_LITERAL:
return false;
}
return false;
};
const Argument * next_argument(void);
void push_argument(std::string & data, const Type type);
void pop_argument(void);
void initialize(const char *);
protected:
ArgumentQueue _args;
std::string _result;
};
template < bool E = false >
struct FormatBase: protected FormatTraits, protected FormatException < E >
{
static const unsigned int strings_base_length = 64;
static const unsigned int generic_base_length = 64;
explicit FormatBase(const char * format_string)
: _format(format_string), _valid(true)
{
FormatTraits::initialize(format_string);
};
explicit FormatBase(std::string format_string)
: _format(format_string), _valid(true)
{
FormatTraits::initialize(format_string.c_str());
};
bool valid(void) const
{
return _valid;
}
const std::string str()
{
if (valid() && (next_argument() != NULL))
{
std::string msg;
// TODO: why format appears two times?
msg += "too few arguments passed for format '";
msg += _format;
msg += "' (";
msg += _format;
msg += ")";
mark_invalid(msg);
}
raise();
return _result;
};
////////////////////////////////////////////////////////////
template < typename V >
FormatBase & operator%( V value )
{
if (!valid())
return *this;
const Argument * top = next_argument();
@ -149,7 +363,7 @@ struct Format
{
char temp[generic_base_length];
if (!generic_verify(value, top->type()))
if (!FormatTraits::generic_verify(value, top->type()))
{
std::string msg;
@ -171,14 +385,14 @@ struct Format
pop_argument();
}
raise_check();
raise();
return *this;
}
template < typename V >
Format & operator%( V * value )
FormatBase & operator%( V * value )
{
if (!validity_check())
if (!valid())
return *this;
const Argument * top = next_argument();
@ -256,20 +470,13 @@ struct Format
pop_argument();
}
raise_check();
raise();
return *this;
}
/*
Format & operator%( std::string value )
FormatBase & operator%( const std::string value )
{
return operator%(value);
}
*/
Format & operator%( const std::string value )
{
if (!validity_check())
if (!valid())
return *this;
const Argument * top = next_argument();
@ -313,200 +520,42 @@ struct Format
pop_argument();
}
raise_check();
raise();
return *this;
}
protected:
template < typename V >
bool number_verify_signed_short( V value )
protected:
void mark_invalid(std::string & msg)
{
return
((typeid(V) == typeid(short int) ||
typeid(V) == typeid(short) ||
typeid(V) == typeid(const short int) ||
typeid(V) == typeid(const short) ||
typeid(V) == typeid(volatile short int) ||
typeid(V) == typeid(volatile short)) &&
sizeof(V) == sizeof(short));
}
template < typename V >
bool number_verify_unsigned_short( V value )
{
return
((typeid(V) == typeid(unsigned short int) ||
typeid(V) == typeid(unsigned short) ||
typeid(V) == typeid(const unsigned short int) ||
typeid(V) == typeid(const unsigned short) ||
typeid(V) == typeid(volatile unsigned short int) ||
typeid(V) == typeid(volatile unsigned short)) &&
sizeof(V) == sizeof(unsigned short));
}
template < typename V >
bool number_verify_signed_long( V value )
{
return
((typeid(V) == typeid(long int) ||
typeid(V) == typeid(long) ||
typeid(V) == typeid(const long int) ||
typeid(V) == typeid(const long) ||
typeid(V) == typeid(volatile long int) ||
typeid(V) == typeid(volatile long)) &&
sizeof(V) == sizeof(long));
}
template < typename V >
bool number_verify_unsigned_long( V value )
{
return
((typeid(V) == typeid(unsigned long int) ||
typeid(V) == typeid(unsigned long) ||
typeid(V) == typeid(const unsigned long int) ||
typeid(V) == typeid(const unsigned long) ||
typeid(V) == typeid(volatile unsigned long int) ||
typeid(V) == typeid(volatile unsigned long)) &&
sizeof(V) == sizeof(long long));
}
template < typename V >
bool number_verify_signed_long_long( V value )
{
return
((typeid(V) == typeid(long long int) ||
typeid(V) == typeid(long long) ||
typeid(V) == typeid(const long long int) ||
typeid(V) == typeid(const long long) ||
typeid(V) == typeid(volatile long long) ||
typeid(V) == typeid(volatile long long int)) &&
sizeof(V) == sizeof(long long));
}
template < typename V >
bool number_verify_unsigned_long_long( V value )
{
return
((typeid(V) == typeid(unsigned long long int) ||
typeid(V) == typeid(unsigned long long) ||
typeid(V) == typeid(const unsigned long long int) ||
typeid(V) == typeid(const unsigned long long) ||
typeid(V) == typeid(volatile unsigned long long) ||
typeid(V) == typeid(volatile unsigned long long int)) &&
sizeof(V) == sizeof(unsigned long long));
}
template < typename V >
bool number_verify_signed_int( V value )
{
return
(sizeof(V) <= sizeof(int) ||
typeid(V) == typeid(int) ||
typeid(V) == typeid(const int) ||
typeid(V) == typeid(volatile int));
}
template < typename V >
bool number_verify_unsigned_int( V value )
{
return
(sizeof(V) <= sizeof(unsigned int) ||
typeid(V) == typeid(unsigned int) ||
typeid(V) == typeid(const unsigned int) ||
typeid(V) == typeid(volatile unsigned int));
}
template < typename V >
bool generic_verify( V value, Type type )
{
switch (type)
if (_valid)
{
/* EXCEPTION: consider any number an valid input. */
case T_SIGNED_INT:
case T_UNSIGNED_INT:
return
(number_verify_signed_int(value) ||
number_verify_unsigned_int(value) ||
number_verify_signed_long(value) ||
number_verify_unsigned_long(value) ||
number_verify_signed_short(value) ||
number_verify_unsigned_short(value));
_valid = false;
case T_SIGNED_SHORT_SHORT:
return (typeid(V) == typeid(char) || typeid(V) == typeid(const char));
case T_SIGNED_SHORT:
return number_verify_signed_short(value);
case T_SIGNED_LONG:
return number_verify_signed_long(value);
case T_SIGNED_LONG_LONG:
return number_verify_signed_long_long(value);
case T_UNSIGNED_SHORT_SHORT:
return (typeid(V) == typeid(unsigned char) || typeid(V) == typeid(unsigned char));
case T_UNSIGNED_SHORT:
return number_verify_unsigned_short(value);
case T_UNSIGNED_LONG:
return number_verify_unsigned_long(value);
case T_UNSIGNED_LONG_LONG:
return number_verify_unsigned_long_long(value);
case T_FLOAT:
return (typeid(V) == typeid(float)) || (typeid(V) == typeid(double) ||
typeid(V) == typeid(const float)) || (typeid(V) == typeid(const double));
case T_CHAR:
return (typeid(V) == typeid(char)) || (typeid(V) == typeid(unsigned char) ||
typeid(V) == typeid(const char)) || (typeid(V) == typeid(const unsigned char));
case T_POINTER:
case T_STRING:
return false;
case T_ANYTHING:
return true;
case T_LITERAL:
return false;
_result = "** INVALID FORMAT: ";
_result += msg;
_result += " **";
}
}
return false;
};
void mark_invalid(std::string &);
bool validity_check(void);
void raise_check(void);
/*
struct NoArgumentLeft
void raise(void) const
{
NoArgumentLeft(): empty(0) {};
unsigned int empty;
};
*/
const Argument * next_argument(void);
void pop_argument(void);
void push_argument(std::string & data, Type type);
if (!_valid)
{
// call specialized class
FormatException< E >::raise(_result);
}
}
private:
std::string _format;
bool _valid;
bool _raise;
std::string _result;
ArgumentQueue _args;
const std::string _format;
bool _valid;
};
#endif /* _FORMAT_H_ */
/* useful typedef for general usage (not generating exceptions) */
typedef FormatBase<> Format;
/* macros used for shortening lines and making the code clearer */
#define STG(x) (x).str()
#define FMT(x) Format(x)
#endif /* _FORMAT_H_ */

View File

@ -46,12 +46,13 @@
namespace Function
{
struct EmptyFunction {};
struct EmptyFunction {};
struct NonMemberFunction {};
/**/
template < typename FunctionTraits >
struct StorageBase: NEW_REFCOUNTER(StorageBase < FunctionTraits >)
struct StorageBase: COUNTER_SUPER(StorageBase < FunctionTraits >)
{
typedef typename FunctionTraits::BaseType BaseType;
@ -59,27 +60,33 @@ namespace Function
typedef typename FunctionTraits::ObjType ObjType;
template < typename Functor >
StorageBase(Functor f)
: _object(reinterpret_cast<ObjType>(new Functor(f))),
_function(reinterpret_cast<FunType>(&(Functor::operator()))),
StorageBase(const Functor f)
: _object(reinterpret_cast< ObjType >(new Functor(f))),
_function(reinterpret_cast< FunType >(&Functor::operator())),
_malloced(true)
{};
template < typename Functor >
StorageBase(Functor & f, bool malloced)
: _object(reinterpret_cast<ObjType>((malloced ? new Functor(f) : &f))),
_function(reinterpret_cast<FunType>(&(Functor::operator()))),
: _object(reinterpret_cast< ObjType >((malloced ? new Functor(f) : &f))),
_function(reinterpret_cast< FunType >(&Functor::operator())),
_malloced(malloced)
{};
StorageBase(FunType const * member)
: _object(reinterpret_cast< ObjType >(0)),
_function(reinterpret_cast< FunType >(member)),
_malloced(false)
{};
StorageBase()
: _object(reinterpret_cast<ObjType>(0)),
_function(reinterpret_cast<FunType>(0)),
: _object(reinterpret_cast< ObjType >(0)),
_function(reinterpret_cast< FunType >(0)),
_malloced(false)
{};
StorageBase(const StorageBase & o)
: INC_REFCOUNTER(o, StorageBase < FunctionTraits >),
: COUNTER_REFER(o, StorageBase < FunctionTraits >),
_object(o._object), _function(o._function), _malloced(o._malloced)
{};
@ -95,9 +102,9 @@ namespace Function
template < typename Functor >
void operator=(Functor f)
{
_object = reinterpret_cast<ObjType>(new Functor(f)),
_function = reinterpret_cast<FunType>(&(Functor::operator()));
_malloced = false;
_object = reinterpret_cast< ObjType >(new Functor(f)),
_function = reinterpret_cast< FunType >(&Functor::operator());
_malloced = true;
}
protected:
@ -229,10 +236,15 @@ namespace Function
typedef StorageBase < Function0Traits < R > > Storage;
template < typename Functor >
Function0(Functor f): Storage(f) {};
Function0(const Functor f)
: Storage(f) {};
template < typename Functor >
Function0(Functor & f, bool m): Storage(f, m) {};
Function0(Functor & f, bool m)
: Storage(f, m) {};
Function0(const typename Function0Traits < R >::FunType * m)
: Storage(m) {};
Function0() {};
@ -243,6 +255,18 @@ namespace Function
return ((Storage::_object)->*(Storage::_function))();
}
template < typename Object >
R operator()(Object * object)
{
if (reinterpret_cast<void *>(Storage::_function) == 0)
throw EmptyFunction();
if (reinterpret_cast<void *>(Storage::_object) != 0)
throw NonMemberFunction();
return (reinterpret_cast< typename Function0Traits < R >::ObjType *>(object)->*(Storage::_function))();
}
};
template < typename R, typename A0 >
@ -251,10 +275,15 @@ namespace Function
typedef StorageBase < Function1Traits < R, A0 > > Storage;
template < typename Functor >
Function1(Functor f): Storage(f) {};
Function1(const Functor f)
: Storage(f) {};
template < typename Functor >
Function1(Functor & f, bool m): Storage(f, m) {};
Function1(Functor & f, bool m)
: Storage(f, m) {};
Function1(const typename Function1Traits < R, A0 >::FunType * m)
: Storage(m) {};
Function1() {};
@ -265,6 +294,18 @@ namespace Function
return ((Storage::_object)->*(Storage::_function))(a0);
}
template < typename Object >
R operator()(Object * object, A0 a0)
{
if (reinterpret_cast<void *>(Storage::_function) == 0)
throw EmptyFunction();
if (reinterpret_cast<void *>(Storage::_object) != 0)
throw NonMemberFunction();
return (reinterpret_cast< typename Function1Traits < R, A0 >::ObjType *>(object)->*(Storage::_function))(a0);
}
};
template < typename R, typename A0, typename A1 >
@ -273,10 +314,15 @@ namespace Function
typedef StorageBase < Function2Traits < R, A0, A1 > > Storage;
template < typename Functor >
Function2(Functor f): Storage(f) {};
Function2(const Functor f)
: Storage(f) {};
template < typename Functor >
Function2(Functor & f, bool m): Storage(f, m) {};
Function2(Functor & f, bool m)
: Storage(f, m) {};
Function2(const typename Function2Traits < R, A0, A1 >::FunType * m)
: Storage(m) {};
Function2() {};
@ -287,6 +333,18 @@ namespace Function
return ((Storage::_object)->*(Storage::_function))(a0, a1);
}
template < typename Object >
R operator()(Object * object, A0 a0, A1 a1)
{
if (reinterpret_cast<void *>(Storage::_function) == 0)
throw EmptyFunction();
if (reinterpret_cast<void *>(Storage::_object) != 0)
throw NonMemberFunction();
return (reinterpret_cast< typename Function2Traits < R, A0, A1 >::ObjType *>(object)->*(Storage::_function))(a0, a1);
}
};
template < typename R, typename A0, typename A1, typename A2 >
@ -295,20 +353,37 @@ namespace Function
typedef StorageBase < Function3Traits < R, A0, A1, A2 > > Storage;
template < typename Functor >
Function3(Functor f): Storage(f) {};
Function3(const Functor f)
: Storage(f) {};
template < typename Functor >
Function3(Functor & f, bool m): Storage(f, m) {};
Function3(Functor & f, bool m)
: Storage(f, m) {};
Function3(const typename Function3Traits < R, A0, A1, A2 >::FunType * m)
: Storage(m) {};
Function3() {};
R operator()(A0 a0, A1 a1, A2 a2)
{
if (reinterpret_cast<void *>(Storage::_object) == 0)
if (reinterpret_cast<const void *>(Storage::_object) == 0)
throw EmptyFunction();
return ((Storage::_object)->*(Storage::_function))(a0, a1, a2);
}
template < typename Object >
R operator()(Object * object, A0 a0, A1 a1, A2 a2)
{
if (reinterpret_cast<void *>(Storage::_function) == 0)
throw EmptyFunction();
if (reinterpret_cast<void *>(Storage::_object) != 0)
throw NonMemberFunction();
return (reinterpret_cast< typename Function3Traits < R, A0, A1, A2 >::ObjType *>(object)->*(Storage::_function))(a0, a1, a2);
}
};
template < typename R, typename A0, typename A1, typename A2, typename A3 >
@ -317,10 +392,15 @@ namespace Function
typedef StorageBase < Function4Traits < R, A0, A1, A2, A3 > > Storage;
template < typename Functor >
Function4(Functor f): Storage(f) {};
Function4(const Functor f)
: Storage(f) {};
template < typename Functor >
Function4(Functor & f, bool m): Storage(f, m) {};
Function4(Functor & f, bool m)
: Storage(f, m) {};
Function4(const typename Function4Traits < R, A0, A1, A2, A3 >::FunType * m)
: Storage(m) {};
Function4() {};
@ -331,6 +411,18 @@ namespace Function
return ((Storage::_object)->*(Storage::_function))(a0, a1, a2, a3);
}
template < typename Object >
R operator()(Object * object, A0 a0, A1 a1, A2 a2, A3 a3)
{
if (reinterpret_cast<void *>(Storage::_function) == 0)
throw EmptyFunction();
if (reinterpret_cast<void *>(Storage::_object) != 0)
throw NonMemberFunction();
return (reinterpret_cast< typename Function4Traits < R, A0, A1, A2, A3 >::ObjType *>(object)->*(Storage::_function))(a0, a1, a2, a3);
}
};
};

View File

@ -47,32 +47,32 @@
template < typename Type >
struct Initializer: public std::vector< Type >
{
typedef std::vector< Type > super;
typedef std::vector< Type > Super;
Initializer(Type e) { push_back(e); };
Initializer(Type & e) { push_back(e); };
Initializer(Type e) { Super::push_back(e); };
Initializer(Type & e) { Super::push_back(e); };
Initializer & operator&(Initializer v)
Initializer & operator&(const Initializer v)
{
insert(super::end(), v.begin(), v.end());
Super::insert(Super::end(), v.begin(), v.end());
return *this;
};
Initializer & operator&(Initializer & v)
{
insert(super::end(), v.begin(), v.end());
Super::insert(Super::end(), v.begin(), v.end());
return *this;
};
Initializer & operator&(Type v)
{
insert(super::end(), v);
Super::insert(Super::end(), v);
return *this;
};
Initializer & operator&(Type & v)
{
insert(super::end(), v);
Super::insert(Super::end(), v);
return *this;
};
};

View File

@ -41,18 +41,16 @@
#include <k3lapi.hpp>
#include <format.hpp>
#include <verbose.hpp>
#include <string.h>
K3LAPI::K3LAPI(bool has_exceptions)
: _has_exceptions(has_exceptions),
_device_count(0), _channel_count(0), _link_count(0),
K3LAPIBase::K3LAPIBase()
: _device_count(0), _channel_count(0), _link_count(0),
_device_config(0), _channel_config(0), _link_config(0)
{};
/* initialize the whole thing! */
void K3LAPI::start(void)
void K3LAPIBase::start(void)
{
/* tie the used k3l to the compiled k3l version */
char *ret = k3lStart(k3lApiMajorVersion, k3lApiMinorVersion, 0); //k3lApiBuildVersion);
@ -64,7 +62,7 @@ void K3LAPI::start(void)
init();
}
void K3LAPI::stop(void)
void K3LAPIBase::stop(void)
{
k3lStop();
fini();
@ -72,7 +70,7 @@ void K3LAPI::stop(void)
/* envio de comandos para placa */
void K3LAPI::mixer(int32 dev, int32 obj, byte track, KMixerSource src, int32 index)
void K3LAPIBase::mixer(int32 dev, int32 obj, byte track, KMixerSource src, int32 index) const
{
KMixerCommand mix;
@ -83,7 +81,7 @@ void K3LAPI::mixer(int32 dev, int32 obj, byte track, KMixerSource src, int32 ind
command(dev, obj, CM_MIXER, (const char *) &mix);
}
void K3LAPI::mixerRecord(int32 dev, int32 obj, byte track, KMixerSource src, int32 index)
void K3LAPIBase::mixerRecord(int32 dev, KDeviceType type, int32 obj, byte track, KMixerSource src, int32 index) const
{
/* estes buffers *NAO PODEM SER ESTATICOS*! */
char cmd[] = { 0x3f, 0x03, (char)obj, (char)track, 0xff, 0xff };
@ -131,12 +129,12 @@ void K3LAPI::mixerRecord(int32 dev, int32 obj, byte track, KMixerSource src, int
break;
}
int32 dsp = get_dsp(dev, DSP_AUDIO);
int32 dsp = get_dsp(type, DSP_AUDIO);
raw_command(dev, dsp, cmd, sizeof(cmd));
}
void K3LAPI::mixerCTbus(int32 dev, int32 obj, byte track, KMixerSource src, int32 index)
void K3LAPIBase::mixerCTbus(int32 dev, int32 obj, byte track, KMixerSource src, int32 index) const
{
KMixerCommand mix;
@ -147,12 +145,12 @@ void K3LAPI::mixerCTbus(int32 dev, int32 obj, byte track, KMixerSource src, int3
command(dev, obj, CM_MIXER_CTBUS, (const char *) &mix);
}
void K3LAPI::command(int32 dev, int32 obj, int32 code, std::string & str)
void K3LAPIBase::command(int32 dev, int32 obj, int32 code, std::string & str) const
{
command(dev, obj, code, str.c_str());
}
void K3LAPI::command (int32 dev, int32 obj, int32 code, const char * parms)
void K3LAPIBase::command (int32 dev, int32 obj, int32 code, const char * parms) const
{
K3L_COMMAND cmd;
@ -166,12 +164,12 @@ void K3LAPI::command (int32 dev, int32 obj, int32 code, const char * parms)
throw failed_command(code, dev, obj, rc);
}
void K3LAPI::raw_command(int32 dev, int32 dsp, std::string & str)
void K3LAPIBase::raw_command(int32 dev, int32 dsp, std::string & str) const
{
raw_command(dev, dsp, str.data(), str.size());
}
void K3LAPI::raw_command(int32 dev, int32 dsp, const char * cmds, int32 size)
void K3LAPIBase::raw_command(int32 dev, int32 dsp, const char * cmds, int32 size) const
{
std::string str(cmds, size);
@ -181,7 +179,7 @@ void K3LAPI::raw_command(int32 dev, int32 dsp, const char * cmds, int32 size)
throw failed_raw_command(dev, dsp, rc);
}
KLibraryStatus K3LAPI::get_param(K3L_EVENT *ev, const char *name, std::string &res)
KLibraryStatus K3LAPIBase::get_param(K3L_EVENT *ev, const char *name, std::string &res) const
{
char tmp_param[256];
memset((void*)tmp_param, 0, sizeof(tmp_param));
@ -195,7 +193,7 @@ KLibraryStatus K3LAPI::get_param(K3L_EVENT *ev, const char *name, std::string &r
return ksSuccess;
}
std::string K3LAPI::get_param(K3L_EVENT *ev, const char *name)
std::string K3LAPIBase::get_param(K3L_EVENT *ev, const char *name) const
{
std::string res;
@ -207,7 +205,7 @@ std::string K3LAPI::get_param(K3L_EVENT *ev, const char *name)
return res;
}
void K3LAPI::init(void)
void K3LAPIBase::init(void)
{
if (_device_count != 0) return;
@ -217,20 +215,16 @@ void K3LAPI::init(void)
_device_config = new device_conf_type[_device_count];
_channel_config = new channel_ptr_conf_type[_device_count];
_link_config = new link_ptr_conf_type[_device_count];
_channel_count = new unsigned int[_device_count];
_link_count = new unsigned int[_device_count];
_channel_count = new unsigned int[_device_count];
_link_count = new unsigned int[_device_count];
for (unsigned int dev = 0; dev < _device_count; dev++)
{
KLibraryStatus ret = ksSuccess;
_device_type[dev] = (KDeviceType) k3lGetDeviceType(dev);
/* caches each device config */
ret = (KLibraryStatus)k3lGetDeviceConfig(dev, ksoDevice + dev, &(_device_config[dev]), sizeof(_device_config[dev]));
if (ret != ksSuccess)
throw start_failed(STG(FMT("k3lGetDeviceConfig(dev=%d): %s") % dev % Verbose::status(ret)));
if (k3lGetDeviceConfig(dev, ksoDevice + dev, &(_device_config[dev]), sizeof(_device_config[dev])) != ksSuccess)
throw start_failed("k3lGetDeviceConfig(device)");
/* adjust channel/link count for device */
_channel_count[dev] = _device_config[dev].ChannelCount;
@ -241,10 +235,9 @@ void K3LAPI::init(void)
for (unsigned int obj = 0; obj < _channel_count[dev]; obj++)
{
ret = (KLibraryStatus)k3lGetDeviceConfig(dev, ksoChannel + obj, &(_channel_config[dev][obj]), sizeof(_channel_config[dev][obj]));
if (ret != ksSuccess)
throw start_failed(STG(FMT("k3lGetDeviceConfig(dev=%d,chan=%d): %s") % dev % obj % Verbose::status(ret)));
if (k3lGetDeviceConfig(dev, ksoChannel + obj, &(_channel_config[dev][obj]),
sizeof(_channel_config[dev][obj])) != ksSuccess)
throw start_failed("k3lGetDeviceConfig(channel)");
}
/* adjust link count for device */
@ -255,15 +248,14 @@ void K3LAPI::init(void)
for (unsigned int obj = 0; obj < _link_count[dev]; obj++)
{
ret = (KLibraryStatus)k3lGetDeviceConfig(dev, ksoLink + obj, &(_link_config[dev][obj]), sizeof(_link_config[dev][obj]));
if (ret != ksSuccess)
throw start_failed(STG(FMT("k3lGetDeviceConfig(dev=%d,link=%d): %s") % dev % obj % Verbose::status(ret)));
if (k3lGetDeviceConfig(dev, ksoLink + obj, &(_link_config[dev][obj]),
sizeof(_link_config[dev][obj])) != ksSuccess)
throw start_failed("k3lGetDeviceConfig(link)");
}
}
}
void K3LAPI::fini(void)
void K3LAPIBase::fini(void)
{
for (unsigned int dev = 0; dev < _device_count; dev++)
{
@ -290,9 +282,9 @@ void K3LAPI::fini(void)
if (_link_count) { delete[] _link_count; _link_count = NULL; }
}
int32 K3LAPI::get_dsp(int32 dev, K3LAPI::DspType type)
int32 K3LAPIBase::get_dsp(KDeviceType devtype, K3LAPI::DspType type) const
{
switch (device_type(dev))
switch (devtype)
{
case kdtFXO:
case kdtFXOVoIP:
@ -311,3 +303,7 @@ int32 K3LAPI::get_dsp(int32 dev, K3LAPI::DspType type)
}
}
int32 K3LAPIBase::get_dsp(const K3LAPIBase::GenericTarget & tgt, K3LAPI::DspType type) const
{
return get_dsp(_device_type[tgt.device], type);
}

View File

@ -40,6 +40,9 @@
*/
#include <string>
#include <stdexcept>
#include <format.hpp>
#include <k3l.h>
@ -59,15 +62,110 @@
#ifndef _K3LAPI_HPP_
#define _K3LAPI_HPP_
struct K3LAPI
struct K3LAPITraits
{
struct invalid_device;
struct invalid_channel;
struct invalid_link;
struct invalid_target: public std::runtime_error
{
friend class invalid_device;
friend class invalid_channel;
friend class invalid_link;
const int32 device, object;
protected:
invalid_target(int32 _device, int32 _object, const std::string & msg)
: std::runtime_error(msg), device(_device), object(_object) {};
};
struct invalid_device: public invalid_target
{
invalid_device(int32 _device)
: invalid_target(_device, -1, STG(FMT("invalid device number '%d'") % _device)) {};
};
struct invalid_channel: public invalid_target
{
invalid_channel(int32 _device, int32 _channel)
: invalid_target(_device, _channel, STG(FMT("invalid channel number '%d' on device '%d'") % _channel % _device)) {};
};
struct invalid_link: public invalid_target
{
invalid_link(int32 _device, int32 _link)
: invalid_target(_device, _link, STG(FMT("invalid link number '%d' on device '%d'") % _link % _device)) {};
};
};
struct K3LAPIBase
{
/* High level checked object identifier. */
struct GenericTarget
{
typedef enum { DEVICE, CHANNEL, MIXER, LINK } Type;
GenericTarget(const K3LAPIBase & k3lapi, Type _type, int32 _device, int32 _object)
: type(_type), device((unsigned int)_device), object((unsigned int)_object)
{
switch (_type)
{
case DEVICE:
if (!k3lapi.valid_device(_device))
throw K3LAPITraits::invalid_device(_device);
break;
case CHANNEL:
case MIXER:
if (!k3lapi.valid_channel(_device, _object))
throw K3LAPITraits::invalid_channel(_device, _object);
break;
case LINK:
if (!k3lapi.valid_link(_device, _object))
throw K3LAPITraits::invalid_link(_device, _object);
break;
}
};
const Type type;
const unsigned int device;
const unsigned int object;
};
/*
struct LinkTarget : public GenericTarget
{
LinkTarget(const K3LAPIBase & k3lapi, int32 _device, int32 _object)
: GenericTarget(k3lapi, GenericTarget::LINK, _device, _object) {};
};
struct ChannelTarget : public GenericTarget
{
ChannelTarget(const K3LAPIBase & k3lapi, int32 _device, int32 _object)
: GenericTarget(k3lapi, GenericTarget::CHANNEL, _device, _object) {};
};
*/
template < GenericTarget::Type T >
struct Target: public GenericTarget
{
Target(const K3LAPIBase & k3lapi, int32 _device, int32 _object)
: GenericTarget(k3lapi, T, _device, _object) {};
// operator const GenericTarget&() const { return static_cast<const GenericTarget &>(*this); };
};
/* exceptions */
struct start_failed
struct start_failed: public std::runtime_error
{
start_failed(const char * _msg) : msg(_msg) {};
start_failed(std::string _msg) : msg(_msg) {};
std::string msg;
start_failed(const char * msg)
: std::runtime_error(msg) {};
};
struct failed_command
@ -91,30 +189,6 @@ struct K3LAPI
int32 rc;
};
struct invalid_device
{
invalid_device(int32 _device)
: device(_device) {};
int32 device;
};
struct invalid_channel
{
invalid_channel(int32 _device, int32 _channel)
: device(_device), channel(_channel) {};
int32 device, channel;
};
struct invalid_link
{
invalid_link(unsigned int _device, unsigned int _link)
: device(_device), link(_link) {};
int32 device, link;
};
struct get_param_failed
{
get_param_failed(std::string _name, int32 _rc)
@ -124,6 +198,8 @@ struct K3LAPI
KLibraryStatus rc;
};
/* typedefs essenciais */
typedef K3L_DEVICE_CONFIG device_conf_type;
typedef K3L_CHANNEL_CONFIG channel_conf_type;
typedef K3L_CHANNEL_CONFIG * channel_ptr_conf_type;
@ -132,8 +208,8 @@ struct K3LAPI
/* constructors/destructors */
K3LAPI(bool has_exceptions = false);
virtual ~K3LAPI() {};
K3LAPIBase();
virtual ~K3LAPIBase() {};
/* (init|final)ialize the whole thing! */
@ -142,239 +218,106 @@ struct K3LAPI
/* verificacao de intervalos */
inline bool valid_device(int32 dev)
inline bool valid_device(int32 dev) const
{
return (dev >= 0 && dev < ((int32)_device_count));
}
inline bool valid_channel(int32 dev, int32 obj)
inline bool valid_channel(int32 dev, int32 obj) const
{
return (valid_device(dev) && obj >= 0 && obj < ((int32)_channel_count[dev]));
}
inline bool valid_link(int32 dev, int32 obj)
inline bool valid_link(int32 dev, int32 obj) const
{
return (valid_device(dev) && obj >= 0 && obj < ((int32)_link_count[dev]));
}
/*!
\brief High level object identifier
Since Khomp works with an object concept, this is used to map the
object id with its proper type.
*/
struct target
{
/*! The types a target can have */
typedef enum { DEVICE, CHANNEL, MIXER, LINK } target_type;
target(K3LAPI & k3lapi, target_type type_init, int32 device_value, int32 object_value)
: type(type_init),
device((unsigned short)device_value),
object((unsigned short)object_value)
{
switch (type_init)
{
case DEVICE:
if (!k3lapi.valid_device(device_value))
throw invalid_device(device_value);
break;
case CHANNEL:
case MIXER:
if (!k3lapi.valid_channel(device_value, object_value))
throw invalid_channel(device_value, object_value);
break;
case LINK:
if (!k3lapi.valid_link(device_value, object_value))
throw invalid_link(device_value, object_value);
break;
}
};
const target_type type;
const unsigned short device;
const unsigned short object;
};
/* envio de comandos para placa (geral) */
void raw_command(int32 dev, int32 dsp, std::string & str);
void raw_command(int32 dev, int32 dsp, const char * cmds, int32 size);
void raw_command(int32 dev, int32 dsp, std::string & str) const;
void raw_command(int32 dev, int32 dsp, const char * cmds, int32 size) const;
/* obter dados 'cacheados' (geral) */
inline unsigned int device_count(void)
inline unsigned int device_count(void) const
{
return _device_count;
}
/* envio de comandos para placa (sem identificadores) */
void mixer(int32 dev, int32 obj, byte track, KMixerSource src, int32 index);
void mixerRecord(int32 dev, int32 obj, byte track, KMixerSource src, int32 index);
void mixerCTbus(int32 dev, int32 obj, byte track, KMixerSource src, int32 index);
void mixer(int32 dev, int32 obj, byte track, KMixerSource src, int32 index) const;
void mixerRecord(int32 dev, KDeviceType type, int32 obj, byte track, KMixerSource src, int32 index) const;
void mixerCTbus(int32 dev, int32 obj, byte track, KMixerSource src, int32 index) const;
void command (int32 dev, int32 obj, int32 code, std::string & str);
void command (int32 dev, int32 obj, int32 code, const char * parms = NULL);
void command (int32 dev, int32 obj, int32 code, std::string & str) const;
void command (int32 dev, int32 obj, int32 code, const char * parms = NULL) const;
/* obter dados 'cacheados' (sem identificadores) */
inline unsigned int channel_count(int32 dev)
{
if (!valid_device(dev))
{
if (_has_exceptions)
throw invalid_device(dev);
else
return 0;
}
return _channel_count[dev];
}
inline unsigned int link_count(int32 dev)
{
if (!valid_device(dev))
{
if (_has_exceptions)
throw invalid_device(dev);
else
return 0;
}
return _link_count[dev];
}
inline uint32 channel_stats(int32 dev, int32 obj, uint32 index)
{
if (!valid_channel(dev, obj))
{
if (_has_exceptions)
throw invalid_channel(dev, obj);
else
return 0;
}
uint32 res_value = (uint32)-1;
stt_code stt_res = ksFail;
#if K3L_AT_LEAST(2,1,0)
stt_res = k3lGetChannelStats(dev, obj, index, &res_value);
#endif
if(stt_res != ksSuccess)
{
return (uint32)-1;
}
return res_value;
}
KDeviceType device_type(int32 dev)
{
if (!valid_device(dev))
{
if (_has_exceptions)
throw invalid_device(dev);
else
return kdtDevTypeCount;
}
return _device_type[dev];
}
K3L_DEVICE_CONFIG & device_config(int32 dev)
{
if (!valid_device(dev))
throw invalid_device(dev);
return _device_config[dev];
}
K3L_CHANNEL_CONFIG & channel_config(int32 dev, int32 obj)
{
if (!valid_channel(dev, obj))
throw invalid_channel(dev, obj);
return _channel_config[dev][obj];
}
K3L_LINK_CONFIG & link_config(int32 dev, int32 obj)
{
if (!valid_link(dev, obj))
throw invalid_channel(dev, obj);
return _link_config[dev][obj];
}
/* envio de comandos para placa (com identificadores) */
void mixer(target & tgt, byte track, KMixerSource src, int32 index)
void mixer(const GenericTarget & tgt, byte track, KMixerSource src, int32 index) const
{
mixer((int32)tgt.device, (int32)tgt.object, track, src, index);
mixer(tgt.device, tgt.object, track, src, index);
}
void mixerRecord(target & tgt, byte track, KMixerSource src, int32 index)
void mixerRecord(const GenericTarget & tgt, byte track, KMixerSource src, int32 index) const
{
mixerRecord((int32)tgt.device, (int32)tgt.object, track, src, index);
mixerRecord((int32)tgt.device, _device_type[tgt.device], (int32)tgt.object, track, src, index);
}
void mixerCTbus(target & tgt, byte track, KMixerSource src, int32 index)
void mixerCTbus(const GenericTarget & tgt, byte track, KMixerSource src, int32 index) const
{
mixerCTbus((int32)tgt.device, (int32)tgt.object, track, src, index);
}
void command (target & tgt, int32 code, std::string & str)
void command(const GenericTarget & tgt, int32 code, std::string & str) const
{
command((int32)tgt.device, (int32)tgt.object, code, str);
};
void command (target & tgt, int32 code, const char * parms = NULL)
void command(const GenericTarget & tgt, int32 code, const char * parms = NULL) const
{
command((int32)tgt.device, (int32)tgt.object, code, parms);
};
/* obter dados 'cacheados' (com indentificadores) */
inline unsigned int channel_count(target & tgt)
inline unsigned int channel_count(const GenericTarget & tgt) const
{
return _channel_count[tgt.device];
}
inline unsigned int link_count(target & tgt)
inline unsigned int link_count(const GenericTarget & tgt) const
{
return _link_count[tgt.device];
}
KDeviceType device_type(target & tgt)
KDeviceType device_type(const GenericTarget & tgt) const
{
return _device_type[tgt.device];
}
K3L_DEVICE_CONFIG & device_config(target & tgt)
const K3L_DEVICE_CONFIG & device_config(const GenericTarget & tgt) const
{
return _device_config[tgt.device];
}
K3L_CHANNEL_CONFIG & channel_config(target & tgt)
const K3L_CHANNEL_CONFIG & channel_config(const Target<GenericTarget::CHANNEL> & tgt) const
{
return _channel_config[tgt.device][tgt.object];
}
K3L_LINK_CONFIG & link_config(target & tgt)
const K3L_LINK_CONFIG & link_config(const Target<GenericTarget::LINK> & tgt) const
{
return _link_config[tgt.device][tgt.object];
}
/* pega valores em strings de eventos */
KLibraryStatus get_param(K3L_EVENT *ev, const char *name, std::string &res);
std::string get_param(K3L_EVENT *ev, const char *name);
KLibraryStatus get_param(K3L_EVENT *ev, const char *name, std::string &res) const;
std::string get_param(K3L_EVENT *ev, const char *name) const;
/* inicializa valores em cache */
@ -389,12 +332,12 @@ struct K3LAPI
DSP_SIGNALING,
};
int32 get_dsp(int32, DspType);
int32 get_dsp(KDeviceType, DspType) const;
int32 get_dsp(const GenericTarget &, DspType) const;
protected:
const bool _has_exceptions;
unsigned int _device_count;
unsigned int * _channel_count;
unsigned int * _link_count;
@ -405,4 +348,145 @@ struct K3LAPI
KDeviceType * _device_type;
};
/* exceptions */
template < bool E = false >
struct K3LAPIException
{
void invalid_device(const int32 device) const
{
/* NOTHING */
}
void invalid_channel(const int32 device, const int32 channel) const
{
/* NOTHING */
}
void invalid_link(const int32 device, const int32 link) const
{
/* NOTHING */
}
};
template < >
struct K3LAPIException < true >
{
void invalid_device(const int32 device) const
{
throw K3LAPITraits::invalid_device(device);
}
void invalid_channel(const int32 device, const int32 channel) const
{
throw K3LAPITraits::invalid_channel(device, channel);
}
void invalid_link(const int32 device, const int32 link) const
{
throw K3LAPITraits::invalid_link(device, link);
}
};
template < bool E = false >
struct K3LAPITemplate: public K3LAPIBase, protected K3LAPIException < E >
{
using K3LAPIBase::device_config;
using K3LAPIBase::channel_config;
using K3LAPIBase::link_config;
using K3LAPIBase::device_type;
using K3LAPIBase::get_dsp;
using K3LAPIBase::mixerRecord;
/* obter dados 'cacheados' (sem identificadores) */
inline unsigned int channel_count(int32 dev) const
{
if (!valid_device(dev))
{
K3LAPIException< E >::invalid_device(dev);
return 0;
}
return _channel_count[dev];
}
inline unsigned int link_count(int32 dev) const
{
if (!valid_device(dev))
{
K3LAPIException< E >::invalid_device(dev);
return 0;
}
return _link_count[dev];
}
inline uint32 channel_stats(int32 dev, int32 obj, uint32 index) const
{
if (!valid_channel(dev, obj))
{
K3LAPIException< E >::invalid_channel(dev, obj);
return 0u;
}
uint32 res_value = 0u;
#if K3L_AT_LEAST(2,1,0)
if (k3lGetChannelStats(dev, obj, index, &res_value) != ksSuccess)
return 0u;
return res_value;
#endif
}
KDeviceType device_type(int32 dev) const
{
if (!valid_device(dev))
{
K3LAPIException< E >::invalid_device(dev);
return kdtDevTypeCount;
}
return _device_type[dev];
}
const K3L_DEVICE_CONFIG & device_config(int32 dev) const
{
if (!valid_device(dev))
throw K3LAPITraits::invalid_device(dev);
return _device_config[dev];
}
const K3L_CHANNEL_CONFIG & channel_config(int32 dev, int32 obj) const
{
if (!valid_channel(dev, obj))
throw K3LAPITraits::invalid_channel(dev, obj);
return _channel_config[dev][obj];
}
const K3L_LINK_CONFIG & link_config(int32 dev, int32 obj) const
{
if (!valid_link(dev, obj))
throw K3LAPITraits::invalid_link(dev, obj);
return _link_config[dev][obj];
}
int32 get_dsp(int32 dev, DspType type) const
{
return get_dsp(device_type(dev), type);
}
void mixerRecord(int32 dev, int32 obj, byte track, KMixerSource src, int32 index) const
{
mixerRecord(dev, device_type(dev), obj, track, src, index);
}
};
typedef K3LAPITemplate<> K3LAPI;
#endif /* _K3LAPI_HPP_ */

View File

@ -46,7 +46,8 @@ std::string K3LUtil::channelStatus(int32 dev, int32 channel,
{
try
{
K3L_CHANNEL_CONFIG & config = _k3lapi.channel_config(dev, channel);
const K3L_CHANNEL_CONFIG & config = _k3lapi.channel_config(dev, channel);
K3L_CHANNEL_STATUS status;
KLibraryStatus ret = (KLibraryStatus) k3lGetDeviceStatus (dev,
@ -60,7 +61,7 @@ std::string K3LUtil::channelStatus(int32 dev, int32 channel,
: "Unknown (fail)");
}
}
catch(K3LAPI::invalid_channel & e)
catch(K3LAPITraits::invalid_channel & e)
{
return (fmt == Verbose::EXACT ? "<unknown[fail]>" : "Unknown (fail)");
}
@ -83,64 +84,35 @@ std::string K3LUtil::callStatus(int32 dev, int32 channel,
}
std::string K3LUtil::linkStatus(int32 dev, int32 link,
Verbose::Presentation fmt, KSignaling sig)
Verbose::Presentation fmt, KSignaling signaling, bool simpleStatus)
{
try
{
if (sig == ksigInactive)
if (signaling == ksigInactive)
{
K3L_LINK_CONFIG & config = _k3lapi.link_config(dev, link);
sig = config.Signaling;
const K3L_LINK_CONFIG & config = _k3lapi.link_config(dev, link);
signaling = config.Signaling;
}
K3L_LINK_STATUS status;
K3L_LINK_STATUS status;
KLibraryStatus ret = (KLibraryStatus) k3lGetDeviceStatus (dev,
link + ksoLink, &status, sizeof(status));
switch (ret)
{
case ksSuccess: return Verbose::linkStatus(sig, status.E1, fmt);
case ksSuccess: return Verbose::linkStatus(signaling, status.E1, fmt, simpleStatus);
default: return (fmt == Verbose::EXACT ?
"<unknown[failure]>" : "Unknown (failure)");
}
}
catch(K3LAPI::invalid_channel & e)
catch(K3LAPITraits::invalid_channel & e)
{
return (fmt == Verbose::EXACT ? "<unknown[failure]>"
: "Unknown (failure)");
}
}
std::string K3LUtil::getLinkStatus(int32 dev, int32 link,
Verbose::Presentation fmt)
{
switch (_k3lapi.device_type(dev))
{
#if K3L_AT_LEAST(1,6,0)
case kdtFXS:
case kdtFXSSpx:
return linkStatus(dev, link, fmt, ksigAnalogTerminal);
#if K3L_AT_LEAST(2,1,0)
case kdtE1FXSSpx:
if (link == 1)
return linkStatus(dev, link, fmt, ksigAnalogTerminal);
#endif
#endif
default:
break;
}
K3L_LINK_CONFIG & conf = _k3lapi.link_config(dev, link);
std::string res = linkStatus(dev, link, fmt);
if (conf.ReceivingClock & 0x01)
res += (fmt == Verbose::EXACT ? ",sync" : " (sync)");
return res;
}
unsigned int K3LUtil::physicalLinkCount(int32 dev, bool count_virtual)
{
@ -199,7 +171,7 @@ unsigned int K3LUtil::physicalLinkCount(int32 dev, bool count_virtual)
break;
}
}
catch(K3LAPI::invalid_device & e)
catch(K3LAPITraits::invalid_device & e)
{
return 0;
}

View File

@ -64,10 +64,8 @@ struct K3LUtil
std::string linkStatus(int32, int32,
Verbose::Presentation fmt = Verbose::HUMAN,
KSignaling sig = ksigInactive);
std::string getLinkStatus(int32, int32,
Verbose::Presentation fmt = Verbose::HUMAN);
KSignaling sig = ksigInactive,
bool simpleStatus = false);
unsigned int physicalLinkCount(int32 dev, bool count_virtual = false);

View File

@ -55,6 +55,7 @@
#if defined(COMMONS_LIBRARY_USING_ASTERISK)
extern "C"
{
#include <asterisk.h>
#include <asterisk/localtime.h>
}
#elif defined(COMMONS_LIBRARY_USING_CALLWEAVER)
@ -443,35 +444,17 @@ struct Logger
localtime_r (&tv, &lt);
#endif
out_msg += STG(FMT("[%04d-%02d-%02d %02d:%02d:%02d] ")
% (lt.tm_year + 1900) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour
% lt.tm_min % lt.tm_sec);
#elif defined(COMMONS_LIBRARY_USING_CALLWEAVER)
#elif defined(COMMONS_LIBRARY_USING_CALLWEAVER) || defined(COMMONS_LIBRARY_USING_FREESWITCH)
time_t tv;
struct tm lt;
time (&tv);
localtime_r (&tv, &lt);
out_msg += STG(FMT("[%04d-%02d-%02d %02d:%02d:%02d] ")
% (lt.tm_year + 1900) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour
% lt.tm_min % lt.tm_sec);
#elif defined(COMMONS_LIBRARY_USING_FREESWITCH)
time_t tv;
struct tm lt;
time (&tv);
localtime_r (&tv, &lt);
out_msg += STG(FMT("[%04d-%02d-%02d %02d:%02d:%02d] ")
% (lt.tm_year + 1900) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour
% lt.tm_min % lt.tm_sec);
#endif
out_msg += STG(FMT("[%02d-%02d-%02d %02d:%02d:%02d] ")
% (lt.tm_year % 100) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour
% lt.tm_min % lt.tm_sec);
}
if (opt._flags[Option::DATETIMEMS])
@ -497,16 +480,16 @@ struct Logger
#endif
#if ASTERISK_AT_LEAST(1,6,0)
out_msg += STG(FMT("[%04d-%02d-%02d %02d:%02d:%02d:%04d] ")
% (lt.tm_year + 1900) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour % lt.tm_min
out_msg += STG(FMT("[%02d-%02d-%02d %02d:%02d:%02d:%04d] ")
% (lt.tm_year % 100) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour % lt.tm_min
% lt.tm_sec % (tv.tv_usec / 1000));
#else
out_msg += STG(FMT("[%04d-%02d-%02d %02d:%02d:%02d:%04d] ")
% (lt.tm_year + 1900) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour % lt.tm_min
out_msg += STG(FMT("[%02d-%02d-%02d %02d:%02d:%02d:%04d] ")
% (lt.tm_year % 100) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour % lt.tm_min
% lt.tm_sec % (tv * 1000));
#endif
#elif defined(COMMONS_LIBRARY_USING_CALLWEAVER)
#elif defined(COMMONS_LIBRARY_USING_CALLWEAVER) || defined(COMMONS_LIBRARY_USING_FREESWITCH)
time_t tv;
struct tm lt;
@ -514,22 +497,9 @@ struct Logger
localtime_r (&tv, &lt);
out_msg += STG(FMT("[%04d-%02d-%02d %02d:%02d:%02d:%04d] ")
% (lt.tm_year + 1900) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour % lt.tm_min
out_msg += STG(FMT("[%02d-%02d-%02d %02d:%02d:%02d:%04d] ")
% (lt.tm_year % 100) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour % lt.tm_min
% lt.tm_sec % (tv * 1000));
#elif defined(COMMONS_LIBRARY_USING_FREESWITCH)
time_t tv;
struct tm lt;
time (&tv);
localtime_r (&tv, &lt);
out_msg += STG(FMT("[%04d-%02d-%02d %02d:%02d:%02d:%04d] ")
% (lt.tm_year + 1900) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour % lt.tm_min
% lt.tm_sec % (tv * 1000));
#endif
}
@ -538,7 +508,7 @@ struct Logger
if (opt._flags[Option::THREADID])
{
#if defined (COMMONS_LIBRARY_USING_ASTERISK) || defined(COMMONS_LIBRARY_USING_CALLWEAVER) || defined(COMMONS_LIBRARY_USING_FREESWITCH)
out_msg += STG(FMT("t=%08p ") % ((void*)pthread_self()));
out_msg += STG(FMT("%08x ") % ((unsigned long)pthread_self()));
#endif
}

View File

@ -45,6 +45,11 @@
#ifndef _REFCOUNTER_HPP_
#define _REFCOUNTER_HPP_
#define COUNTER_CLASS(...) ReferenceCounter< __VA_ARGS__ >
#define COUNTER_SUPER(...) public COUNTER_CLASS( __VA_ARGS__ )
#define COUNTER_REFER(o, ...) COUNTER_CLASS( __VA_ARGS__ )(static_cast< const COUNTER_CLASS( __VA_ARGS__ ) & >(o))
// DEPRECATED DECLARATIONS ///
#define NEW_REFCOUNTER(...) public ReferenceCounter< __VA_ARGS__ >
#define INC_REFCOUNTER(o, ...) ReferenceCounter< __VA_ARGS__ >(static_cast< const ReferenceCounter < __VA_ARGS__ > & >(o))
@ -179,13 +184,13 @@ struct ReferenceCounter
};
template < typename T >
struct ReferenceContainer: NEW_REFCOUNTER(ReferenceContainer< T >)
struct ReferenceContainer: COUNTER_SUPER(ReferenceContainer< T >)
{
/* type */
typedef T Type;
/* shorthand */
typedef ReferenceCounter < ReferenceContainer< Type > > Counter;
typedef COUNTER_CLASS(ReferenceContainer< Type >) Counter;
// TODO: make this a generic exception someday
struct NotFound {};
@ -249,7 +254,7 @@ struct ReferenceContainer: NEW_REFCOUNTER(ReferenceContainer< T >)
};
// return value (pointer)!
Type * operator()(void)
Type * operator()(void) const
{
return _reference_value;
};

View File

@ -74,7 +74,7 @@ void Regex::Expression::initialize(void)
_errorstate = regcomp(&_comp_regex, _expression, _flags);
}
std::string Regex::Expression::regerror_as_string(void)
std::string Regex::Expression::regerror_as_string(void) const
{
unsigned int count = regerror(_errorstate, &_comp_regex, 0, 0) + 1;
@ -95,6 +95,7 @@ void Regex::Match::initialize(void)
{
_subcounter = (_expression.subcount() + 2); // 0 + N.. + invalid
_submatches = new regmatch_t[_subcounter];
_subcaching = new std::string[_subcounter];
_have_match = (regexec(_expression.repr(), _basestring.c_str(),
_subcounter, _submatches, _flags) == 0);
}
@ -117,7 +118,7 @@ std::string Regex::Match::replace(Regex::ReplaceMap & map)
try
{
if (_submatches[0].rm_so != 0 && (map.find(0) != map.end()))
return _basestring.replace(_submatches[0].rm_so, _submatches[0].rm_eo - _submatches[0].rm_so, map.find(0)->second);
return buffer.replace(_submatches[0].rm_so, _submatches[0].rm_eo - _submatches[0].rm_so, map.find(0)->second);
for (unsigned int n = 1; (_submatches[n].rm_so != -1) && (n < _subcounter); n++)
{

View File

@ -111,12 +111,12 @@ struct Regex
}
}
bool valid(void) { return (_errorstate == 0); }
bool valid(void) const { return (_errorstate == 0); }
unsigned int subcount(void) { return _subcounter; }
const regex_t * repr(void) { return &_comp_regex; }
unsigned int subcount(void) const { return _subcounter; }
const regex_t * repr(void) const { return &_comp_regex; }
std::string error(void)
std::string error(void) const
{
switch (_errorstate)
{
@ -127,31 +127,33 @@ struct Regex
}
private:
void initialize(void);
std::string regerror_as_string(void);
std::string regerror_as_string(void) const;
private:
void initialize(void);
protected:
const char * _expression;
bool _alloced;
const bool _alloced;
unsigned int _subcounter;
int _errorstate;
regex_t _comp_regex;
unsigned int _flags;
const unsigned int _flags;
};
struct Match: NEW_REFCOUNTER(Match)
struct Match: COUNTER_SUPER(Match)
{
Match(const char * basestring, Expression & expression, unsigned int flags = 0)
Match(const char * basestring, const Expression & expression, unsigned int flags = 0)
: _basestring(basestring), _expression(expression), _subcounter(0), _submatches(0),
_have_match(false), _flags(flags)
{
initialize();
}
Match(std::string & basestring, Expression & expression, unsigned int flags = 0)
Match(const std::string & basestring, const Expression & expression, unsigned int flags = 0)
: _basestring(basestring), _expression(expression), _subcounter(0), _submatches(0),
_have_match(false), _flags(flags)
{
@ -159,7 +161,7 @@ struct Regex
}
Match(const Match & o)
: INC_REFCOUNTER(o, Match),
: COUNTER_REFER(o, Match),
_basestring(o._basestring), _expression(o._expression),
_subcounter(o._subcounter), _submatches(o._submatches),
_have_match(o._have_match), _flags(o._flags)
@ -169,6 +171,10 @@ struct Regex
void unreference()
{
delete[] _submatches;
delete[] _subcaching;
_submatches = 0;
_subcaching = 0;
}
bool matched(void)
@ -184,34 +190,23 @@ struct Regex
return false;
}
std::string submatch(int number)
const std::string & submatch(int number)
{
if (!matched(number))
return "";
return _subcaching[_subcounter - 1 /* invalid, always empty! */ ];
return _basestring.substr(_submatches[number].rm_so,
_submatches[number].rm_eo - _submatches[number].rm_so);
}
/**
* \brief gets a map with all matches
* \return std::map<int,std::string> with all matches
* \note index 0 in map, is the complete string
* \author Eduardo Nunes Pereira
*
* If fails the empty map is returned
*/
std::map<int, std::string> obtain_match_map()
{
int match_counter = 0;
std::map<int,std::string> tmp_map;
while(matched(match_counter))
if (_subcaching[number].empty())
{
tmp_map.insert(std::make_pair(match_counter,submatch(match_counter)));
match_counter++;
_subcaching[number].assign(_basestring, _submatches[number].rm_so,
_submatches[number].rm_eo - _submatches[number].rm_so);
}
return tmp_map;
return _subcaching[number];
}
const std::string & operator[](int number)
{
return submatch(number);
}
/**
@ -226,25 +221,21 @@ struct Regex
std::string replace(ReplaceMap &);
std::string replace(std::string, unsigned int index = REP_BASE);
std::string operator[](int number)
{
return submatch(number);
}
// NOTE: there is already a way to get subcount defined on EXPRESSION class!
private:
void initialize(void);
protected:
std::string _basestring;
Expression & _expression;
const std::string _basestring;
const Expression & _expression;
unsigned int _subcounter;
regmatch_t * _submatches;
std::string * _subcaching;
bool _have_match;
unsigned int _flags;
const unsigned int _flags;
};
};

View File

@ -0,0 +1,485 @@
/*
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2009 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
*/
#include <ringbuffer.hpp>
// #include <stdio.h>
/* Documentation of the formula used in the buffer arithmetic.
*
* [0|1|2|3|4|5|6|7] => size=8
* | |
* reader |
* writer
*
* => writer has places [5,6,7,0,1] to write (5 places).
*
* => 8 - (4-2+1) = 8 - (2+1) = 8 - 3 = 5
*
* > writer goes 1 up, amount goes 1 down.
* > reader goes 1 up, amount goes 1 up.
* > size goes 1 down, amount goes 1 down.
*
*/
/********** BUFFER FUNCTIONS **********/
/* writes everything or nothing */
bool Ringbuffer_traits::traits_provide(char * buffer, const char * value, unsigned int amount, bool do_not_overwrite)
{
/* avoid using different values */
Buffer_table cache = _pointers;
bool need_overwrite = false;
if (amount > free_blocks(cache))
{
if (do_not_overwrite)
return false;
/* if we are allowed to overwrite, just the buffer size matters for us */
if (amount >= _size)
return false;
/* we need to change reader pointer below... */
need_overwrite = true;
}
const unsigned int wr = cache.writer.complete;
const unsigned int wp = cache.writer.complete - 1;
/* should we go around the buffer for writing? */
if ((wr + amount) > _size)
{
// fprintf(stderr, "%p> first if matched\n", this);
if (need_overwrite)
{
do
{
Buffer_pointer extra(cache.reader);
extra.complete = ((wr + amount) % _size); // (extra.complete + amount) % _size;
// extra.complete = (extra.complete + amount) % _size;
if (update(cache.reader, extra))
break;
}
while (true);
}
unsigned int wr1 = _size - wr + 1; /* writer is already 1 position after */
unsigned int wr2 = amount - wr1;
// fprintf(stderr, "%p> partial write: (%d/%d) %d/%d [%d/%d]\n", this, wr1, wr2, amount, _size, reader, writer);
/* two partial writes (one at the end, another at the beginning) */
memcpy((void *) &(buffer[wp]), (const void *) (value), _block * wr1);
memcpy((void *) (buffer), (const void *) &(value[wr1]), _block * wr2);
}
else
{
// fprintf(stderr, "%p> second if matched\n", this);
if (need_overwrite)
{
do
{
Buffer_pointer extra(cache.reader);
extra.complete = ((wr + amount) % _size); // (extra.complete + amount) % _size;
if (update(cache.reader, extra))
break;
}
while (true);
}
// fprintf(stderr, "%p> full write: a=%d/s=%d [r=%d/w=%d]\n", this, amount, _size, reader, writer);
/* we are talking about buffers here, man! */
memcpy((void *) &(buffer[wp]), (const void *) value, _block * amount);
}
_pointers.writer.complete = ((wp + amount) % _size) + 1;
_pointers.writer.partial = 1;
// if (need_overwrite)
// fprintf(stdout, "%p> write end: w=%d/r=%d\n", this, _pointers.writer.complete, _pointers.reader.complete);
return true;
}
/* returns the number of itens that have been read */
unsigned int Ringbuffer_traits::traits_consume(const char * buffer, char * value, unsigned int amount, bool atomic_mode)
{
/* avoid using different values */
Buffer_table cache = _pointers;
const unsigned int available = used_blocks(cache);
if (atomic_mode && amount > available)
return false;
const unsigned int rd = _pointers.reader.complete;
unsigned int total = std::min(amount, available);
/* should we go around the buffer for reading? */
if ((rd + total) >= _size)
{
unsigned int rd1 = _size - rd;
unsigned int rd2 = total - rd1;
// fprintf(stderr, "%p> partial read: (%d/%d) %d/%d [%d/%d]\n", this, rd1, rd2, total, _size, reader, writer);
/* two partial consumes (one at the end, another at the beginning) */
memcpy((void *) (value), (const void *) &(buffer[rd]), _block * rd1);
memcpy((void *) &(value[rd1]), (const void *) (buffer), _block * rd2);
}
else
{
// fprintf(stderr, "%p> full read: %d/%d [%d/%d]\n", this, total, _size, reader, writer);
/* we are talking about buffers here, man! */
memcpy((void *) value, (const void *) &(buffer[rd]), _block * total);
}
do
{
/* jump the reader forward */
Buffer_pointer index((cache.reader.complete + total) % _size, 0);
if (update(cache.reader, index))
break;
}
while (true);
// fprintf(stderr, "%p> read end: %d [block=%d]\n", this, reader, _block);
return total;
}
/********** TWO-PHASE BUFFER FUNCTIONS ***********/
/* returns the number of itens that have been read */
unsigned int Ringbuffer_traits::traits_consume_begins(const char * buffer, char * value, unsigned int amount, bool atomic_mode)
{
/* avoid using different values */
Buffer_table cache = _pointers;
const unsigned int available = used_blocks(cache);
if (amount > available)
{
if (atomic_mode)
return false;
}
const unsigned int rd = _pointers.reader.complete;
unsigned int total = std::min(amount, available);
/* should we go around the buffer for reading? */
if ((rd + total) >= _size)
{
unsigned int rd1 = _size - rd;
unsigned int rd2 = total - rd1;
// fprintf(stderr, "%p> partial read: (%d/%d) %d/%d [%d/%d]\n", this, rd1, rd2, total, _size, reader, writer);
/* two partial consumes (one at the end, another at the beginning) */
memcpy((void *) (value), (const void *) &(buffer[rd]), _block * rd1);
memcpy((void *) &(value[rd1]), (const void *) (buffer), _block * rd2);
}
else
{
// fprintf(stderr, "%p> full read: %d/%d [%d/%d]\n", this, total, _size, reader, writer);
/* we are talking about buffers here, man! */
memcpy((void *) value, (const void *) &(buffer[rd]), _block * total);
}
return total;
}
bool Ringbuffer_traits::traits_consume_commit(unsigned int amount)
{
if (amount == 0)
return true;
/* avoid using different values */
Buffer_table cache = _pointers;
const unsigned int available = used_blocks(cache);
/* cannot commit more than available! */
if (amount > available)
return false;
unsigned int total = std::min(amount, available);
do
{
/* jump the reader forward */
Buffer_pointer index((cache.reader.complete + total) % _size, 0);
if (update(cache.reader, index))
break;
}
while (true);
// fprintf(stderr, "%p> read end: %d [block=%d]\n", this, reader, _block);
return true;
}
/********** PARTIAL BUFFER FUNCTIONS (bytes) ***********/
/* writes everything or nothing */
bool Ringbuffer_traits::traits_provide_partial(char * buffer, const char * value, unsigned int amount)
{
/* avoid using different values */
Buffer_table cache = _pointers;
const unsigned int memsize = (_size * _block);
if (amount > (free_blocks(cache) * _block))
return false;
const unsigned int wr = ((cache.writer.complete - 1) * _block) + cache.writer.partial;
const unsigned int wp = wr - 1;
/* should we go around the buffer for writing? */
if ((wr + amount) > memsize)
{
// fprintf(stderr, "%p> first if matched\n", this);
unsigned int wr1 = memsize - wr + 1; /* writer is already 1 position after */
unsigned int wr2 = amount - wr1;
// fprintf(stderr, "%p> partial write: (%d/%d) %d/%d [%d/%d]\n", this, wr1, wr2, amount, _size, reader, writer);
/* two partial writes (one at the end, another at the beginning) */
memcpy((void *) &(buffer[wp]), (const void *) (value), wr1);
memcpy((void *) (buffer), (const void *) &(value[wr1]), wr2);
}
else
{
// fprintf(stderr, "%p> second if matched\n", this);
// fprintf(stderr, "%p> full write: a=%d/s=%d [r=%d/w=%d]\n", this, amount, _size, reader, writer);
/* we are talking about buffers here, man! */
memcpy((void *) &(buffer[wp]), (const void *) value, amount);
}
const unsigned int new_wp = (wp + amount) % memsize;
_pointers.writer.complete = (unsigned int)(floor((double)new_wp / (double)_block) + 1);
_pointers.writer.partial = (new_wp % _block) + 1;
// if (need_overwrite)
// fprintf(stdout, "%p> write end: w=%d/r=%d\n", this, _pointers.writer.complete, _pointers.reader.complete);
return true;
}
/* returns the number of bytes that have been read */
unsigned int Ringbuffer_traits::traits_consume_partial(const char * buffer, char * value, unsigned int amount)
{
/* avoid using different values */
Buffer_table cache = _pointers;
const unsigned int available = used_blocks(cache) * _block;
const unsigned int rd = (_pointers.reader.complete * _block) + _pointers.reader.partial;
const unsigned int memsize = _size * _block;
unsigned int total = std::min(amount, available);
/* should we go around the buffer for reading? */
if ((rd + total) >= _size)
{
unsigned int rd1 = memsize - rd;
unsigned int rd2 = total - rd1;
// fprintf(stderr, "%p> partial read: (%d/%d) %d/%d [%d/%d]\n", this, rd1, rd2, total, _size, reader, writer);
/* two partial consumes (one at the end, another at the beginning) */
memcpy((void *) (value), (const void *) &(buffer[rd]), rd1);
memcpy((void *) &(value[rd1]), (const void *) (buffer), rd2);
}
else
{
// fprintf(stderr, "%p> full read: %d/%d [%d/%d]\n", this, total, _size, reader, writer);
/* we are talking about buffers here, man! */
memcpy((void *) value, (const void *) &(buffer[rd]), total);
}
do
{
const unsigned int new_rd = (((cache.reader.complete * _block) + cache.reader.partial) + total) % memsize;
/* jump the reader forward */
Buffer_pointer index((unsigned int)floor((double)new_rd / (double)_block), (unsigned short)(new_rd % _block));
if (update(cache.reader, index))
break;
}
while (true);
// fprintf(stderr, "%p> read end: %d [block=%d]\n", this, reader, _block);
return total;
}
/********** IO FUNCTIONS **********/
/* returns the number of items written to from buffer to stream */
unsigned int Ringbuffer_traits::traits_put(const char * buffer, std::ostream &fd, unsigned int amount)
{
/* avoid using different values */
Buffer_table cache = _pointers;
const unsigned int available = used_blocks(cache);
if (amount > available)
return false;
const unsigned int wr = _pointers.writer.complete;
const unsigned int rd = _pointers.reader.complete;
unsigned int total = std::min(amount, available);
/* should we go around the buffer for reading? */
if ((rd + total) >= _size)
{
unsigned int rd1 = _size - rd;
unsigned int rd2 = total - rd1;
// fprintf(stderr, "%p> partial read: (%d/%d) %d/%d [%d/%d]\n", this, rd1, rd2, total, _size, reader, writer);
/* two partial consumes (one at the end, another at the beginning) */
fd.write((const char *) &(buffer[rd]), _block * rd1);
fd.write((const char *) (buffer), _block * rd2);
}
else
{
// fprintf(stderr, "%p> full read: %d/%d [%d/%d]\n", this, total, _size, reader, writer);
fd.write((const char *) &(buffer[rd]), _block * total);
}
do
{
/* jump the reader forward */
Buffer_pointer index((cache.reader.complete + total) % _size, 0);
if (update(cache.reader, index))
break;
}
while (true);
// fprintf(stderr, "%p> read end: %d [block=%d]\n", this, reader, _block);
return total;
}
/* returns number of items read from stream to buffer */
unsigned int Ringbuffer_traits::traits_get(char * buffer, std::istream &fd, unsigned int amount)
{
/* avoid using different values */
Buffer_table cache = _pointers;
if (amount > free_blocks(cache))
return false;
const unsigned int wr = cache.writer.complete;
const unsigned int wp = cache.writer.complete - 1;
unsigned int real_amount = 0;
/* should we go around the buffer for writing? */
if ((wr + amount) > _size)
{
// fprintf(stderr, "%p> first if matched\n", this);
unsigned int wr1 = _size - wr + 1; /* writer is already 1 position after */
unsigned int wr2 = amount - wr1;
// fprintf(stderr, "%p> partial write: (%d/%d) %d/%d [%d/%d]\n", this, wr1, wr2, amount, _size, reader, writer);
/* two partial writes (one at the end, another at the beginning) */
unsigned int char_amount = 0;
/* one partial write on the buffer (at the end) */
fd.read((char *) &(buffer[wp]), _block * wr1);
char_amount += fd.gcount();
if (fd.gcount() == (int)(_block * wr1))
{
/* another partial write on the buffer (at the beginning) */
fd.read((char *) (buffer), _block * wr2);
char_amount += fd.gcount();
}
real_amount = char_amount / _block;
}
else
{
// fprintf(stderr, "%p> second if matched\n", this);
// fprintf(stderr, "%p> full write: a=%d/s=%d [r=%d/w=%d]\n", this, amount, _size, reader, writer);
/* we are talking about buffers here, man! */
fd.read((char *) &(buffer[wp]), _block * amount);
real_amount = fd.gcount() / _block;
}
_pointers.writer.complete = ((wp + amount) % _size) + 1;
_pointers.writer.partial = 1;
// fprintf(stdout, "%p> write end: %d\n", this, _pointers.writer.complete);
return real_amount;
}

View File

@ -46,6 +46,12 @@
Also, it works only for single-reader + single-writer, since it does not depends
on external mutex functions.
NOTE: for single element provide/consume, this abstraction has standard C++ semantics.
for multiple and partial element provide/consume, memcpy is used - thus complex C++
objects which need correct copy constructor semantics should not copied this way.
*/
#include <string.h>
@ -61,7 +67,7 @@
struct Buffer_pointer
{
Buffer_pointer(unsigned int _complete = 0u, unsigned short _partial = 0u)
Buffer_pointer(unsigned int _complete, unsigned short _partial)
: complete(_complete), partial(_partial)
{};
@ -134,6 +140,10 @@ __attribute__((packed));
struct Ringbuffer_traits
{
struct BufferFull {};
struct BufferEmpty {};
protected:
Ringbuffer_traits(unsigned int block, unsigned int size)
: _block(block), _size(size)
{};
@ -155,6 +165,28 @@ struct Ringbuffer_traits
return Atomic::doCAS(&(_pointers.reader), &cache, update);
}
inline unsigned int free_blocks(const Buffer_table & cache) const
{
const unsigned int r = cache.reader.complete;
const unsigned int w = cache.writer.complete;
if (r >= w)
return (r - w);
return _size - (w - r);
}
inline unsigned int used_blocks(const Buffer_table & cache) const
{
const unsigned int r = cache.reader.complete;
const unsigned int w = cache.writer.complete;
if (r >= w)
return (_size - (r - w)) - 1;
return (w - r) - 1;
}
protected:
const unsigned int _block;
const unsigned int _size;
@ -163,11 +195,8 @@ struct Ringbuffer_traits
};
template <typename T>
struct Ringbuffer: protected Ringbuffer_traits, public NonCopyable
struct Ringbuffer: public Ringbuffer_traits, public NonCopyable
{
struct BufferFull {};
struct BufferEmpty {};
Ringbuffer(unsigned int size)
: Ringbuffer_traits(sizeof(T), size)
{
@ -189,15 +218,17 @@ struct Ringbuffer: protected Ringbuffer_traits, public NonCopyable
}
/***** GENERIC RANGE/INDEX CALCULATION FUNCTIONS *****/
bool may_write(Buffer_table & cache)
protected:
inline bool may_write(const Buffer_table & cache) const
{
const unsigned int r = cache.reader.complete;
const unsigned int w = cache.writer.complete;
return (((r - w) != 1) && (!(r == 0 && w == _size)));
return (((r - w) != 0) && (!(r == 0 && w == _size)));
}
bool may_read(Buffer_table & cache)
inline bool may_read(const Buffer_table & cache) const
{
if ((cache.writer.complete - cache.reader.complete) == 1)
return false;
@ -205,7 +236,7 @@ struct Ringbuffer: protected Ringbuffer_traits, public NonCopyable
return true;
}
unsigned int writer_next(Buffer_pointer & cache, Buffer_pointer & index)
inline unsigned int writer_next(const Buffer_pointer & cache, Buffer_pointer & index) const
{
unsigned int dest = cache.complete - 1,
temp = cache.complete + 1;
@ -218,7 +249,7 @@ struct Ringbuffer: protected Ringbuffer_traits, public NonCopyable
return dest;
};
void reader_next(Buffer_pointer & cache, Buffer_pointer & index)
inline void reader_next(const Buffer_pointer & cache, Buffer_pointer & index) const
{
unsigned int temp = cache.complete + 1;
@ -230,6 +261,7 @@ struct Ringbuffer: protected Ringbuffer_traits, public NonCopyable
/***** BUFFER FUNCTIONS *****/
public:
bool provide(const T & value)
{
Buffer_table cache = _pointers;
@ -280,9 +312,9 @@ struct Ringbuffer: protected Ringbuffer_traits, public NonCopyable
}
/* writes everything or nothing */
inline bool provide(const T * value, unsigned int amount, bool skip_overwrite = true)
inline bool provide(const T * value, unsigned int amount, bool do_not_overwrite = true)
{
return traits_provide((char *)_buffer, (const char *) value, amount, skip_overwrite);
return traits_provide((char *)_buffer, (const char *) value, amount, do_not_overwrite);
}
/* returns the number of items that have been read (atomic_mode == true means 'all or nothing') */
@ -337,7 +369,7 @@ struct Ringbuffer: protected Ringbuffer_traits, public NonCopyable
// fprintf(stderr, "%p> write: %d/%d [%d/%d]\n", this, _pointers.reader, _pointers.writer, _pointers.reader_partial, _pointers.writer_partial);
}
T & consumer_start(void)
const T & consumer_start(void)
{
Buffer_table cache = _pointers;
@ -391,13 +423,13 @@ struct Ringbuffer: protected Ringbuffer_traits, public NonCopyable
/* returns the number of items written to from buffer to stream */
inline unsigned int put(std::ostream &fd, unsigned int amount)
{
return traits_put((char *)_buffer, fd, amount);
return traits_put((const char *)_buffer, fd, amount);
}
/* returns number of items read from stream to buffer */
inline unsigned int get(std::istream &fd, unsigned int amount)
{
return traits_get((const char *)_buffer, fd, amount);
return traits_get((char *)_buffer, fd, amount);
}
void clear()

View File

@ -55,7 +55,7 @@
* implement the "unreference()" method for releasing resources. */
template < typename Implementor >
struct SimpleLockCommon: NEW_REFCOUNTER( SimpleLockCommon < Implementor > )
struct SimpleLockCommon: COUNTER_SUPER( SimpleLockCommon < Implementor > )
{
friend class ReferenceCounter < SimpleLockCommon < Implementor > >;
@ -71,7 +71,7 @@ struct SimpleLockCommon: NEW_REFCOUNTER( SimpleLockCommon < Implementor > )
{};
SimpleLockCommon(const SimpleLockCommon & o)
: INC_REFCOUNTER(o, SimpleLockCommon)
: COUNTER_REFER(o, SimpleLockCommon)
{};
virtual ~SimpleLockCommon()

View File

@ -141,6 +141,38 @@ unsigned int Strings::tokenize(const std::string & str, Strings::vector_type & t
return (cur_token - 1);
}
long Strings::tolong(const std::string & str, int base)
{
return tolong(str.c_str(), base);
}
unsigned long Strings::toulong(const std::string & str, int base)
{
return toulong(str.c_str(), base);
}
unsigned long long Strings::toulonglong(const std::string & str, int base)
{
return toulonglong(str.c_str(), base);
}
double Strings::todouble(const std::string & str)
{
return todouble(str.c_str());
}
long Strings::tolong(const char * str, int base)
{
char *str_end = 0;
unsigned long value = strtol(str, &str_end, base);
if (str_end && *str_end == 0)
return value;
throw invalid_value(str);
}
bool Strings::toboolean(std::string str)
{
std::string tmp(str);
@ -153,11 +185,11 @@ bool Strings::toboolean(std::string str)
throw invalid_value(str);
}
long Strings::tolong(std::string str, int base)
unsigned long Strings::toulong(const char * str, int base)
{
char *str_end = 0;
unsigned long value = strtol(str.c_str(), &str_end, base);
unsigned long value = strtoul(str, &str_end, base);
if (str_end && *str_end == 0)
return value;
@ -165,26 +197,14 @@ long Strings::tolong(std::string str, int base)
throw invalid_value(str);
}
unsigned long Strings::toulong(std::string str, int base)
{
char *str_end = 0;
unsigned long value = strtoul(str.c_str(), &str_end, base);
if (str_end && *str_end == 0)
return value;
throw invalid_value(str);
}
unsigned long long Strings::toulonglong(std::string str, int base)
unsigned long long Strings::toulonglong(const char * str, int base)
{
#if defined(_WINDOWS) || defined(_Windows) || defined(_WIN32) || defined(WIN32)
throw not_implemented();
#else
char *str_end = 0;
unsigned long long value = strtoull(str.c_str(), &str_end, base);
unsigned long long value = strtoull(str, &str_end, base);
if (str_end && *str_end == 0)
return value;
@ -193,11 +213,11 @@ unsigned long long Strings::toulonglong(std::string str, int base)
#endif
}
double Strings::todouble(std::string str)
double Strings::todouble(const char * str)
{
char *str_end = 0;
double value = strtod(str.c_str(), &str_end);
double value = strtod(str, &str_end);
if (str_end && *str_end == 0)
return value;

View File

@ -68,6 +68,8 @@ struct Strings
bool empty() { return _list.empty(); };
const list_type & list() { return _list; };
protected:
list_type _list;
};
@ -75,8 +77,8 @@ struct Strings
public:
struct invalid_value
{
invalid_value(const char * value): _value(value) {};
invalid_value(std::string value): _value(value) {};
invalid_value(const char * value): _value(value) {};
invalid_value(const std::string & value): _value(value) {};
std::string & value() { return _value; }
@ -92,10 +94,15 @@ struct Strings
static bool toboolean(std::string);
static std::string fromboolean(bool);
static long tolong(std::string, int base = 10);
static unsigned long toulong(std::string, int base = 10);
static unsigned long long toulonglong(std::string, int base = 10);
static double todouble(std::string);
static long tolong(const std::string &, int base = 10);
static unsigned long toulong(const std::string &, int base = 10);
static unsigned long long toulonglong(const std::string &, int base = 10);
static double todouble(const std::string &);
static long tolong(const char *, int base = 10);
static unsigned long toulong(const char *, int base = 10);
static unsigned long long toulonglong(const char *, int base = 10);
static double todouble(const char *);
static std::string lower(std::string);
static std::string hexadecimal(std::string);

View File

@ -1,7 +1,7 @@
/*
/*
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2009 Khomp Ind. & Com.
Copyright (C) 2007-2009 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/
@ -23,40 +23,40 @@
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.
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
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "saved_condition.hpp"
bool SavedCondition::wait(unsigned int msec)
{
bool ret = true;
bool ret = true;
switch_mutex_lock(_mutex);
if (!_signaled)
{
{
/* msec * 1000 = The amount of time in microseconds to wait. */
if (switch_thread_cond_timedwait(_condition, _mutex, (switch_interval_time_t)msec * 1000) != 0)
ret = false;
}
if (switch_thread_cond_timedwait(_condition, _mutex, (switch_interval_time_t)msec * 1000) != 0)
ret = false;
}
_signaled = false;
switch_mutex_unlock(_mutex);
switch_mutex_unlock(_mutex);
return ret;
return ret;
}

View File

@ -1,7 +1,7 @@
/*
/*
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2009 Khomp Ind. & Com.
Copyright (C) 2007-2009 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/
@ -23,20 +23,20 @@
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.
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
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _SAVED_CONDITION_
@ -104,7 +104,7 @@ struct SavedCondition : public SavedConditionCommon// : public RefCounter < Save
if (!_signaled)
switch_thread_cond_wait(_condition, _mutex);
_signaled = false;
switch_mutex_unlock(_mutex);

View File

@ -1,7 +1,7 @@
/*
/*
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2009 Khomp Ind. & Com.
Copyright (C) 2007-2009 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/
@ -23,20 +23,20 @@
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.
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
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _SIMPLE_LOCK_HPP_
@ -72,7 +72,7 @@ struct SimpleLockBasic: public SimpleLockCommon < Implementor >
{
/* do nothing */
};
void unreference()
{
switch_mutex_destroy(_mutex);

View File

@ -1,7 +1,7 @@
/*
/*
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2009 Khomp Ind. & Com.
Copyright (C) 2007-2009 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/
@ -23,20 +23,20 @@
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.
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
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _THREAD_HPP_
@ -66,7 +66,7 @@ struct Thread : ThreadCommon
T _data;
A _arg;
};
template<typename T, typename R>
struct ThreadData < T, R, void > : ThreadDataCommon
{
@ -79,7 +79,7 @@ struct Thread : ThreadCommon
T _data;
};
template<typename T, typename A>
struct ThreadData < T, void, A > : ThreadDataCommon
{
@ -111,7 +111,7 @@ struct Thread : ThreadCommon
};
template<typename T>
Thread(T obj, switch_memory_pool_t *pool=NULL) :
Thread(T obj, switch_memory_pool_t *pool=NULL) :
_thread_info(new ThreadData<T, typename DecomposeFunction<T>::Return, void>(obj)),
_pool(pool),
_can_delete_pool(false)
@ -134,7 +134,7 @@ struct Thread : ThreadCommon
}
switch_threadattr_stacksize_set(
(switch_threadattr_t *)_thread_info->_attribute,
(switch_threadattr_t *)_thread_info->_attribute,
SWITCH_THREAD_STACKSIZE);
if(!priority())
@ -143,9 +143,9 @@ struct Thread : ThreadCommon
}
}
template<typename T, typename A>
Thread(T obj, A arg, switch_memory_pool_t *pool=NULL) :
Thread(T obj, A arg, switch_memory_pool_t *pool=NULL) :
_thread_info(new ThreadData<T, typename DecomposeFunction<T>::Return, A>(obj, arg)),
_pool(pool),
_can_delete_pool(false)
@ -168,7 +168,7 @@ struct Thread : ThreadCommon
}
switch_threadattr_stacksize_set(
(switch_threadattr_t *)_thread_info->_attribute,
(switch_threadattr_t *)_thread_info->_attribute,
SWITCH_THREAD_STACKSIZE);
if(!priority())
@ -178,11 +178,11 @@ struct Thread : ThreadCommon
}
~Thread()
~Thread()
{
if(_thread_info)
delete _thread_info;
if (_can_delete_pool)
switch_core_destroy_memory_pool(&_pool);
}
@ -202,10 +202,10 @@ struct Thread : ThreadCommon
if(!_pool || !_thread_info->_attribute)
return false;
switch_thread_create((switch_thread_t**)&_thread_info->_self,
(switch_threadattr_t *)_thread_info->_attribute,
run,
_thread_info,
switch_thread_create((switch_thread_t**)&_thread_info->_self,
(switch_threadattr_t *)_thread_info->_attribute,
run,
_thread_info,
_pool);
if(!_thread_info->_self)
@ -223,13 +223,13 @@ struct Thread : ThreadCommon
*
* SWITCH_DECLARE(switch_status_t) switch_thread_join(switch_status_t *retval, switch_thread_t *thd);
*/
if(!_thread_info->_self)
return -2;
int retval = 0;
if(switch_thread_join((switch_status_t*)&retval,
if(switch_thread_join((switch_status_t*)&retval,
(switch_thread_t *)_thread_info->_self) != 0)
return -1;
@ -267,7 +267,7 @@ private:
{
#ifndef WIN32
struct sched_param param;
struct apr_threadattr_t *myattr = (struct apr_threadattr_t *)_thread_info->_attribute;
if (pthread_attr_setschedpolicy(
@ -307,13 +307,13 @@ protected:
static void *SWITCH_THREAD_FUNC run(BaseThreadType *thread, void * obj)
{
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
// "Starting new Thread\n");
ThreadDataCommon * data = (ThreadDataCommon *)obj;
int retval = data->run();
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
// "Stopping new Thread = %d\n", retval);
((Thread *)(data->_thread))->exit(retval);

View File

@ -42,11 +42,14 @@
#ifndef _TAGGED_UNION_HPP_
#define _TAGGED_UNION_HPP_
#include <stdexcept>
#include <iostream>
#include <unistd.h>
#include <typeinfo>
#include <stdexcept>
#include <iostream>
#include <format.hpp>
namespace Tagged
{
struct EmptyUnion
@ -69,7 +72,7 @@ namespace Tagged
~EmptyUnion() { _adjusted = false; };
bool operator==(const EmptyUnion & o)
bool operator==(const EmptyUnion & o) const
{
return true;
};
@ -80,24 +83,24 @@ namespace Tagged
void setup(void) { _adjusted = true; };
protected:
bool value_set(void) { return false; };
bool value_get(void) { return false; };
bool value_set(void) const { return false; };
bool value_get(void) const { return false; };
bool value_check(void) { return false; };
bool value_check(void) const { return false; };
template < typename S >
bool value_visit(S & visitor, typename S::ReturnType & ret)
bool value_visit(S & visitor, typename S::ReturnType & ret) const
{
return false;
};
template < typename S >
bool value_visit_void(S & visitor)
bool value_visit_void(S & visitor) const
{
return false;
};
bool adjusted() { return _adjusted; };
bool adjusted() const { return _adjusted; };
private:
bool _adjusted;
@ -114,7 +117,7 @@ namespace Tagged
// constructor with initializer
template < typename U >
Union( U value )
Union(U value)
: _value(0)
{
set(value);
@ -123,7 +126,7 @@ namespace Tagged
// copy constructor
Union(const Union & o)
: E(static_cast<const E&>(o)),
_value( (o._value ? new const V(*(o._value)) : 0) )
_value( (o._value ? new V(*(o._value)) : 0) )
{};
// copy assignment operator
@ -137,7 +140,7 @@ namespace Tagged
if (o._value)
{
_value = new const V(*(o._value));
_value = new V(*(o._value));
}
E::operator=(static_cast<const E&>(o));
@ -163,18 +166,21 @@ namespace Tagged
}
template < typename U >
bool check(void)
bool check(void) const
{
return value_check(static_cast<const U * const>(0));
return value_check(static_cast< const U * const>(0));
};
template < typename U >
const U & get(void)
U & get(void) const
{
const U * res = 0;
U * res = 0;
if (!E::adjusted())
throw std::runtime_error("tagged union empty!");
if (!value_get(&res) || !res)
throw std::runtime_error("type mismatch");
throw std::runtime_error(STG(FMT("type mismatch when asked for '%s'") % typeid(U).name()));
return *res;
};
@ -190,7 +196,7 @@ namespace Tagged
};
template < typename S >
typename S::ReturnType visit(S visitor)
typename S::ReturnType visit(S visitor) const
{
typename S::ReturnType ret;
@ -201,7 +207,7 @@ namespace Tagged
};
template < typename S >
void visit_void(S visitor)
void visit_void(S visitor) const
{
if (!value_visit_void(visitor))
throw std::runtime_error("unable to visit empty value");
@ -219,7 +225,7 @@ namespace Tagged
};
// compare (equal) operator
bool operator==(const Union & o)
bool operator==(const Union & o) const
{
bool are_equal = false;
@ -236,7 +242,7 @@ namespace Tagged
};
// compare types
bool sameType(const Union & o)
bool sameType(const Union & o) const
{
if ((!(_value) && !(o._value)) || (_value && o._value))
return E::operator==(static_cast<const E&>(o));
@ -254,13 +260,13 @@ namespace Tagged
bool value_set(V val)
{
_value = new const V(val);
_value = new V(val);
E::setup();
return true;
};
bool value_get(const V ** val)
bool value_get(V ** val) const
{
if (!_value)
return false;
@ -269,14 +275,14 @@ namespace Tagged
return true;
}
bool value_check(const V * const junk)
bool value_check(const V * const junk) const
{
(void)junk;
return (_value != 0);
};
template < typename S >
bool value_visit(S & visitor, typename S::ReturnType & ret)
bool value_visit(S & visitor, typename S::ReturnType & ret) const
{
if (_value)
{
@ -288,7 +294,7 @@ namespace Tagged
};
template < typename S >
bool value_visit_void(S & visitor)
bool value_visit_void(S & visitor) const
{
if (_value)
{
@ -300,7 +306,7 @@ namespace Tagged
};
private:
const V * _value;
V * _value;
};
};

View File

@ -276,6 +276,20 @@ bool TimerTraits::traits_restart (TimerTraits::Index & idx, bool force)
return ret;
}
void TimerTraits::traits_setup(TimerTraits::Index * idx, unsigned int msecs, const void * func, void * data, unsigned int value)
{
_mutex.lock();
if (idx->valid)
{
(void)traits_del_unlocked(*idx);
}
*idx = traits_add_unlocked(msecs, func, data, value);
_mutex.unlock();
}
bool TimerTraits::traits_del_unlocked (TimerTraits::Index & idx)
{
bool ret = false;

View File

@ -125,6 +125,8 @@ struct TimerTraits
bool traits_del (Index & idx);
bool traits_del (const void * func, const void * data = 0, unsigned int value = 0);
void traits_setup(Index * idx, unsigned int msecs, const void * func, void * data = 0, unsigned int value = 0);
/* timer start/stop functions */
bool start(void);
bool stop(void);
@ -169,7 +171,7 @@ struct TimerTraits
};
template < typename F, typename D >
struct TimerTemplate: NEW_REFCOUNTER(TimerTemplate< F, D >)
struct TimerTemplate: COUNTER_SUPER(TimerTemplate< F, D >)
{
typedef TimerTraits::Index Index;
typedef TimerTraits::Control Control;
@ -179,7 +181,7 @@ struct TimerTemplate: NEW_REFCOUNTER(TimerTemplate< F, D >)
{};
TimerTemplate(const TimerTemplate< F, D > & o)
: INC_REFCOUNTER(o, TimerTemplate< F, D >),
: COUNTER_REFER(o, TimerTemplate< F, D >),
_timer(o._timer)
{};
@ -192,6 +194,11 @@ struct TimerTemplate: NEW_REFCOUNTER(TimerTemplate< F, D >)
bool start() { return _timer->start(); }
bool stop() { return _timer->stop(); }
inline void setup(Index * idx, unsigned int msecs, F * func, D data = 0, unsigned int value = 0)
{
_timer->traits_setup(idx, msecs, (const void *)func, (void *)(data), value);
}
inline Index add(unsigned int msecs, F * func, D data = 0, unsigned int value = 0)
{
return _timer->traits_add(msecs, (const void *)func, (void *)(data), value);

View File

@ -55,15 +55,33 @@
/*** Used for checking information on classes and stuff.. ***/
template< typename T >
class IsClass
struct IsClass
{
protected:
template< typename X > static char ( &A( void(X::*)() ) )[1];
template< typename X > static char ( &A( X ) )[2];
template < typename X > static char ( &A( void(X::*)() ) )[1];
template < typename X > static char ( &A( X ) )[2];
public:
static bool const Result = sizeof( A< T >(0) ) == 1;
};
template < typename T >
struct IsConst
{
static bool const Result = false;
};
template < typename T >
struct IsConst< const T >
{
static bool const Result = true;
};
template < typename T >
struct IsConst< T const * >
{
static bool const Result = true;
};
/*** Used for template metaprogramming ***/
template < bool Value, typename Then, typename Else >

View File

@ -11,7 +11,7 @@
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
"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
@ -41,87 +41,84 @@
#include <refcounter.hpp>
#include <typeinfo>
#ifndef _VARIABLE_HPP_
#define _VARIABLE_HPP_
#ifndef _VARIANT_H_
#define _VARIANT_H_
/* this is internal, should not be used by the user */
struct NoArgumentDefined {};
template < typename UserReturnType, typename UserArgumentType = NoArgumentDefined >
struct VariantBaseType
template < typename R >
struct VariableBaseTable
{
typedef UserReturnType ReturnType;
typedef UserArgumentType ArgumentType;
virtual ~VariantBaseType() {};
virtual int which() = 0;
virtual ReturnType visit(void) { return ReturnType(); };
virtual ReturnType visit(ArgumentType) { return ReturnType(); };
R value;
};
template < typename BaseType = VariantBaseType < void > >
struct Variant: NEW_REFCOUNTER(Variant < BaseType >)
struct EmptyVariable {};
template < typename R >
struct Variable
{
typedef typename BaseType::ReturnType ReturnType;
typedef typename BaseType::ArgumentType ArgumentType;
protected:
typedef VariableBaseTable< R > BaseType;
struct InvalidType {};
typedef const BaseType * ConstObjType;
typedef BaseType * ObjType;
typedef R BaseType::* VarType;
Variant(BaseType * value, bool is_owner = false)
: _value(value), _is_owner(is_owner) {};
public:
template < typename ConstructorObjType >
Variable(R ConstructorObjType::* v)
: _adjusted(true),
_variable(reinterpret_cast<const VarType>(v))
{};
Variant(const Variant & v)
: INC_REFCOUNTER(v, Variant < BaseType >),
_value(v._value), _is_owner(v._is_owner) {};
Variable()
: _adjusted(false)
{};
virtual ~Variant() {};
void unreference()
template < typename MemberType >
void operator=(const MemberType v)
{
if (_is_owner && _value)
{
delete _value;
_value = 0;
}
};
template < typename ValueType >
ValueType & get(void)
{
try
{
ValueType & ret = dynamic_cast < ValueType & > (*_value);
return ret;
}
catch (std::bad_cast & e)
{
throw InvalidType();
}
};
int which()
{
return _value->which();
_adjusted = true;
_variable = reinterpret_cast<const VarType>(v);
}
ReturnType visit(void)
template < typename Type >
R & operator()(Type * obj) const
{
return _value->visit();
if (!_adjusted)
throw EmptyVariable();
return (reinterpret_cast< ObjType >(obj))->*(_variable);
}
ReturnType visit(ArgumentType arg)
template < typename Type >
R & operator()(Type & obj) const
{
return _value->visit(arg);
if (!_adjusted)
throw EmptyVariable();
return (reinterpret_cast< ObjType >(&obj))->*(_variable);
}
protected:
BaseType * _value;
bool _is_owner;
template < typename Type >
const R & operator()(const Type * obj) const
{
if (!_adjusted)
throw EmptyVariable();
return (reinterpret_cast< ConstObjType >(obj))->*(_variable);
}
template < typename Type >
const R & operator()(const Type & obj) const
{
if (!_adjusted)
throw EmptyVariable();
return (reinterpret_cast< ConstObjType >(&obj))->*(_variable);
}
protected:
bool _adjusted;
VarType _variable;
};
#endif /* _VARIANT_H_ */
#endif /* _VARIABLE_HPP_ */

View File

@ -0,0 +1,303 @@
/*
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2009 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 _VERBOSE_HPP_
#define _VERBOSE_HPP_
#include <string>
#include <sstream>
#include <map>
#include <k3l.h>
// k3lApiMajorVersion
#ifndef CM_PING
# include <k3lVersion.h>
# include <KTools.h>
#endif
#include <types.hpp>
#include <k3lapi.hpp>
#include <format.hpp>
#include <verbose_traits.hpp>
struct Verbose
{
typedef enum
{
R2_COUNTRY_BRA = 1,
R2_COUNTRY_ARG = 2,
R2_COUNTRY_CHI = 3,
R2_COUNTRY_MEX = 4,
R2_COUNTRY_URY = 5,
R2_COUNTRY_VEN = 6
}
R2CountryType;
typedef enum
{
HUMAN,
EXACT
}
Presentation;
/* dynamic (object) stuff */
Verbose(const K3LAPI & api)
: _api(api) {};
#if K3L_AT_LEAST(2,0,0)
std::string event(const int32, const K3L_EVENT * const,
const R2CountryType r2_country = R2_COUNTRY_BRA,
const Presentation fmt = HUMAN) const;
#else
std::string event(const int32, const K3L_EVENT * const,
const Presentation fmt = HUMAN) const;
#endif
std::string channelStatus(const int32, const int32, const int32,
const Presentation fmt = HUMAN) const;
/* end of dynamic (object) stuff */
protected:
const K3LAPI & _api;
/* used internally */
struct internal_not_found {};
public:
/* static (class) stuff */
static std::string echoLocation(const KEchoLocation, const Presentation fmt = HUMAN);
static std::string echoCancellerConfig(const KEchoCancellerConfig, const Presentation fmt = HUMAN);
#if K3L_AT_LEAST(2,0,0)
static std::string event(const KSignaling, const int32, const K3L_EVENT * const,
const R2CountryType = R2_COUNTRY_BRA, Presentation fmt = HUMAN);
#else
static std::string event(const KSignaling, const int32, const K3L_EVENT * const,
const Presentation fmt = HUMAN);
#endif
#if K3L_AT_LEAST(2,0,0)
static std::string command(const int32, const K3L_COMMAND * const,
const R2CountryType = R2_COUNTRY_BRA,
const Presentation fmt = HUMAN);
static std::string command(const int32, const int32, const int32, const char * const,
const R2CountryType = R2_COUNTRY_BRA,
const Presentation fmt = HUMAN);
#else
static std::string command(const int32, const K3L_COMMAND * const,
const Presentation fmt = HUMAN);
static std::string command(const int32, const int32, const int32, const char * const,
const Presentation fmt = HUMAN);
#endif
static std::string deviceName(const KDeviceType, const int32, const int32 count = 0, const Presentation fmt = HUMAN);
static std::string deviceName(const KDeviceType, const int32, const Presentation fmt);
static std::string deviceType(const KDeviceType, const int32 count = 0, const Presentation fmt = HUMAN);
static std::string deviceType(const KDeviceType, const Presentation fmt);
static std::string deviceModel(const KDeviceType, const int32, const int32 count = 0, const Presentation fmt = HUMAN);
static std::string deviceModel(const KDeviceType, const int32, const Presentation fmt);
static std::string channelFeatures(const int32, const Presentation fmt = HUMAN);
static std::string signaling(const KSignaling, const Presentation fmt = HUMAN);
static std::string systemObject(const KSystemObject, const Presentation fmt = HUMAN);
static std::string mixerTone(const KMixerTone, const Presentation fmt = HUMAN);
static std::string mixerSource(const KMixerSource, const Presentation fmt = HUMAN);
static std::string seizeFail(const KSeizeFail, const Presentation fmt = HUMAN);
#if K3L_AT_LEAST(2,0,0)
static std::string callFail(const KSignaling, const R2CountryType, const int32, const Presentation fmt = HUMAN);
#else
static std::string callFail(const KSignaling, const int32, const Presentation fmt = HUMAN);
#endif
static std::string channelFail(const KSignaling, const int32, const Presentation fmt = HUMAN);
static std::string internalFail(const KInternalFail, const Presentation fmt = HUMAN);
static std::string linkErrorCounter(const KLinkErrorCounter, const Presentation fmt = HUMAN);
static std::string linkStatus(const KSignaling, const int32, const Presentation fmt = HUMAN, const bool simpleStatus = false);
static std::string channelStatus(const KSignaling, const int32, const Presentation fmt = HUMAN);
static std::string callStatus(const KCallStatus, const Presentation fmt = HUMAN);
static std::string status(const KLibraryStatus, const Presentation fmt = HUMAN);
#if K3L_AT_LEAST(2,0,0)
static std::string signGroupB(const KSignGroupB, const R2CountryType contry = R2_COUNTRY_BRA,
Presentation fmt = HUMAN);
#else
static std::string signGroupB(const KSignGroupB, const Presentation fmt = HUMAN);
#endif
#if K3L_AT_LEAST(2,0,0)
static std::string signGroupII(const KSignGroupII, const R2CountryType contry = R2_COUNTRY_BRA,
Presentation fmt = HUMAN);
#else
static std::string signGroupII(const KSignGroupII, const Presentation fmt = HUMAN);
#endif
static std::string h100configIndex(const KH100ConfigIndex, const Presentation fmt = HUMAN);
static std::string eventName(const int32 value)
{
return VerboseTraits::eventName((VerboseTraits::Event)value);
};
static std::string commandName(const int32 value)
{
return VerboseTraits::commandName((VerboseTraits::Command)value);
};
#if K3L_AT_LEAST(1,5,0)
static std::string sipFailures(const KSIP_Failures, const Presentation fmt = HUMAN);
#endif
#if K3L_AT_LEAST(1,5,1)
static std::string isdnCause(const KQ931Cause, const Presentation fmt = HUMAN);
#endif
#if K3L_AT_LEAST(1,5,2)
static std::string isdnDebug(const int32, const Presentation fmt = HUMAN);
#endif
#if K3L_AT_LEAST(1,6,0)
static std::string callStartInfo(const KCallStartInfo, const Presentation fmt = HUMAN);
static std::string gsmCallCause(const KGsmCallCause, const Presentation fmt = HUMAN);
static std::string gsmMobileCause(const KGsmMobileCause, const Presentation fmt = HUMAN);
static std::string gsmSmsCause(const KGsmSmsCause, const Presentation fmt = HUMAN);
static std::string q931ProgressIndication(const KQ931ProgressIndication,
Presentation fmt = HUMAN);
#endif
#if K3L_AT_LEAST(2,1,0)
static std::string faxResult(const KFaxResult code, const Presentation fmt = HUMAN);
static std::string faxFileErrorCause(const KFaxFileErrorCause code, const Presentation fmt = HUMAN);
#endif
/* end of static (class) stuff */
private:
static std::string internal_deviceType(const KDeviceType, const int32);
static std::string internal_deviceModel(const KDeviceType, const int32, const int32);
#if K3L_AT_LEAST(1,5,0)
static std::string internal_sipFailures(const KSIP_Failures, const Presentation fmt = HUMAN);
#endif
#if K3L_AT_LEAST(1,5,1)
static std::string internal_isdnCause(const KQ931Cause, const Presentation fmt = HUMAN);
#endif
#if K3L_AT_LEAST(2,0,0)
static std::string internal_signGroupB(const KSignGroupB, const R2CountryType contry, const Presentation fmt = HUMAN);
static std::string internal_signGroupII(const KSignGroupII, const R2CountryType contry, const Presentation fmt = HUMAN);
#else
static std::string internal_signGroupB(const KSignGroupB, const Presentation fmt = HUMAN);
static std::string internal_signGroupII(const KSignGroupII, const Presentation fmt = HUMAN);
#endif
#if K3L_AT_LEAST(1,6,0)
static std::string internal_gsmCallCause(const KGsmCallCause, const Presentation fmt = HUMAN);
static std::string internal_gsmMobileCause(const KGsmMobileCause, const Presentation fmt = HUMAN);
static std::string internal_gsmSmsCause(const KGsmSmsCause, const Presentation fmt = HUMAN);
static std::string internal_q931ProgressIndication(const KQ931ProgressIndication, const Presentation fmt = HUMAN);
#endif
private:
enum Type
{
DEVICE,
CHANNEL,
PLAYER,
MIXER,
LINK,
NONE
};
struct Target
{
Target(Type _type)
: type(_type), device(-1), object(-1)
{};
Target(Type _type, int32 _device)
: type(_type), device(_device), object(-1)
{};
Target(Type _type, int32 _device, int32 _object)
: type(_type), device(_device), object(_object)
{};
const Type type;
const int32 device;
const int32 object;
};
static void generate(std::string &, const std::string &, const Target, const std::string &);
static std::string show(std::string &, const std::string &, const Target, const std::string &);
static std::string show(std::string &, const std::string &, const Target);
template < typename ReturnType >
static ReturnType presentation(const Presentation fmt, ReturnType str_exact, ReturnType str_human)
{
switch (fmt)
{
case HUMAN: return str_human;
case EXACT: return str_exact;
};
return str_exact;
}
};
#endif /* _VERBOSE_HPP_ */

View File

@ -1,710 +0,0 @@
/*
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2009 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
*/
#include <config_options.hpp>
ConfigOption::ConfigOption(std::string name, const ConfigOption::StringType & value, const ConfigOption::StringType defvalue, string_allowed_type allowed, bool list_me)
: _my_name(name), _value_data(new StringData(const_cast<StringType &>(value), defvalue, allowed), true),
_list_me(list_me), _values(NULL), _loaded(false)
{};
ConfigOption::ConfigOption(std::string name, const ConfigOption::StringType & value, const ConfigOption::StringType defvalue, bool list_me)
: _my_name(name), _value_data(new StringData(const_cast<StringType &>(value), defvalue, string_allowed_type()), true),
_list_me(list_me), _values(NULL), _loaded(false)
{};
ConfigOption::ConfigOption(std::string name, const ConfigOption::SignedIntType & value, const ConfigOption::SignedIntType defvalue,
ConfigOption::SignedIntType min, ConfigOption::SignedIntType max, ConfigOption::SignedIntType step, bool list_me)
: _my_name(name), _value_data(new SignedIntData(const_cast<SignedIntType &>(value), defvalue, Range<SignedIntType>(min, max, step)), true),
_list_me(list_me), _values(NULL), _loaded(false)
{};
ConfigOption::ConfigOption(std::string name, const ConfigOption::UnsignedIntType & value, const ConfigOption::UnsignedIntType defvalue,
ConfigOption::UnsignedIntType min, ConfigOption::UnsignedIntType max, ConfigOption::UnsignedIntType step, bool list_me)
: _my_name(name), _value_data(new UnsignedIntData(const_cast<UnsignedIntType &>(value), defvalue, Range<UnsignedIntType>(min, max, step)), true),
_list_me(list_me), _values(NULL), _loaded(false)
{};
ConfigOption::ConfigOption(std::string name, const ConfigOption::BooleanType & value, const ConfigOption::BooleanType defvalue, bool list_me)
: _my_name(name), _value_data(new BooleanData(const_cast<BooleanType &>(value), defvalue), true),
_list_me(list_me), _values(NULL), _loaded(false)
{};
ConfigOption::ConfigOption(std::string name, ConfigOption::FunctionType fun, std::string defvalue, string_allowed_type allowed, bool list_me)
: _my_name(name), _value_data(new FunctionData(fun, defvalue, allowed), true),
_list_me(list_me), _values(NULL), _loaded(false)
{};
ConfigOption::ConfigOption(std::string name, ConfigOption::FunctionType fun, std::string defvalue, bool list_me)
: _my_name(name), _value_data(new FunctionData(fun, defvalue, string_allowed_type()), true),
_list_me(list_me), _values(NULL), _loaded(false)
{};
ConfigOption::ConfigOption(const ConfigOption & o)
: _my_name(o._my_name), _value_data(o._value_data),
_list_me(o._list_me), _values(o._values), _loaded(o._loaded)
{};
ConfigOption::~ConfigOption(void)
{
if (_values)
{
for (unsigned int i = 0; _values[i] != NULL; i++)
delete _values[i];
delete[] _values;
_values = NULL;
}
};
void ConfigOption::set(ConfigOption::StringType value)
{
switch (_value_data.which())
{
case ID_STRING:
{
try
{
StringData & tmp = _value_data.get<StringData>();
if (tmp.string_allowed.empty())
{
tmp.string_val = value;
_loaded = true;
}
else
{
if (tmp.string_allowed.find(value) != tmp.string_allowed.end())
{
tmp.string_val = value;
_loaded = true;
return;
}
std::string allowed_string;
for (string_allowed_type::iterator i = tmp.string_allowed.begin(); i != tmp.string_allowed.end(); i++)
{
allowed_string += " '";
allowed_string += (*i);
allowed_string += "'";
}
throw ConfigProcessFailure(STG(FMT("value '%s' not allowed for option '%s' (allowed values:%s)")
% value % _my_name % allowed_string));
}
break;
}
catch(ValueType::InvalidType & e)
{
throw;
}
}
case ID_FUN:
{
try
{
FunctionData & tmp = _value_data.get<FunctionData>();
tmp.fun_val(value);
_loaded = true;
break;
}
catch(ValueType::InvalidType & e)
{
throw;
}
}
default:
{
throw ConfigProcessFailure(STG(FMT("option '%s' is not of type string, nor function defined") % _my_name));
}
}
}
void ConfigOption::set(ConfigOption::SignedIntType value)
{
try
{
SignedIntData & tmp = _value_data.get<SignedIntData>();
if (value < tmp.sint_Range.minimum)
throw ConfigProcessFailure(STG(FMT("value '%d' out-of-Range for option '%s' (too low)") % value % _my_name));
if (value > tmp.sint_Range.maximum)
throw ConfigProcessFailure(STG(FMT("value '%d' out-of-Range for option '%s' (too high)") % value % _my_name));
if (((value - tmp.sint_Range.minimum) % tmp.sint_Range.step) != 0)
throw ConfigProcessFailure(STG(FMT("value '%d' out-of-Range for option '%s' (outside allowed step)") % value % _my_name));
tmp.sint_val = value;
_loaded = true;
}
catch(ValueType::InvalidType & e)
{
throw;
}
}
void ConfigOption::set(ConfigOption::UnsignedIntType value)
{
try
{
UnsignedIntData & tmp = _value_data.get<UnsignedIntData>();
if (value < tmp.uint_Range.minimum)
throw ConfigProcessFailure(STG(FMT("value '%d' out-of-Range for option '%s' (too low)") % value % _my_name));
if (value > tmp.uint_Range.maximum)
throw ConfigProcessFailure(STG(FMT("value '%d' out-of-Range for option '%s' (too high)") % value % _my_name));
if (((value - tmp.uint_Range.minimum) % tmp.uint_Range.step) != 0)
throw ConfigProcessFailure(STG(FMT("value '%d' out-of-Range for option '%s' (outside allowed step)") % value % _my_name));
tmp.uint_val = value;
_loaded = true;
}
catch(ValueType::InvalidType & e)
{
throw;
}
}
void ConfigOption::set(ConfigOption::BooleanType value)
{
try
{
BooleanData & tmp = _value_data.get<BooleanData>();
tmp.bool_val = value;
_loaded = true;
}
catch(ValueType::InvalidType & e)
{
throw;
}
}
std::string & ConfigOption::name(void) { return _my_name; };
ConfigOption::value_id_type ConfigOption::type(void)
{
return (value_id_type) _value_data.which();
};
const char ** ConfigOption::values(void)
{
if (_values != NULL)
return _values;
switch ((value_id_type) _value_data.which())
{
case ConfigOption::ID_BOOL:
{
_values = new const char*[3];
_values[0] = strdup("yes");
_values[1] = strdup("no");
_values[2] = NULL;
return _values;
}
case ConfigOption::ID_SINT:
{
try
{
SignedIntData & tmp = _value_data.get<SignedIntData>();
unsigned int count = ((tmp.sint_Range.maximum - tmp.sint_Range.minimum) / tmp.sint_Range.step) + 1;
unsigned int index = 0;
_values = new const char*[count + 1];
for (SignedIntType i = tmp.sint_Range.minimum; i <= tmp.sint_Range.maximum; i += tmp.sint_Range.step, index++)
_values[index] = strdup(STG(FMT("%d") % i).c_str());
_values[index] = NULL;
return _values;
}
catch(ValueType::InvalidType & e)
{
throw;
}
}
case ConfigOption::ID_UINT:
{
try
{
UnsignedIntData & tmp = _value_data.get<UnsignedIntData>();
unsigned int count = ((tmp.uint_Range.maximum - tmp.uint_Range.minimum) / tmp.uint_Range.step) + 1;
unsigned int index = 0;
_values = new const char*[count + 1];
for (UnsignedIntType i = tmp.uint_Range.minimum; i <= tmp.uint_Range.maximum; i += tmp.uint_Range.step, index++)
_values[index] = strdup(STG(FMT("%d") % i).c_str());
_values[index] = NULL;
return _values;
}
catch(ValueType::InvalidType & e)
{
throw;
}
}
case ConfigOption::ID_STRING:
{
try
{
StringData & tmp = _value_data.get<StringData>();
_values = new const char*[ tmp.string_allowed.size() + 1 ];
unsigned int index = 0;
for (string_allowed_type::iterator i = tmp.string_allowed.begin(); i != tmp.string_allowed.end(); i++, index++)
_values[index] = strdup((*i).c_str());
_values[index] = NULL;
return _values;
}
catch(ValueType::InvalidType & e)
{
throw;
}
}
case ConfigOption::ID_FUN:
{
try
{
FunctionData & tmp = _value_data.get<FunctionData>();
_values = new const char*[ tmp.fun_allowed.size() + 1 ];
unsigned int index = 0;
for (string_allowed_type::iterator i = tmp.fun_allowed.begin(); i != tmp.fun_allowed.end(); i++, index++)
_values[index] = strdup((*i).c_str());
_values[index] = NULL;
return _values;
}
catch(ValueType::InvalidType & e)
{
throw;
}
}
default:
throw ConfigProcessFailure(STG(FMT("unknown type identifier '%d'") % _value_data.which()));
}
};
void ConfigOption::reset(void)
{
_loaded = false;
};
void ConfigOption::commit(void)
{
if (_loaded)
return;
switch ((value_id_type) _value_data.which())
{
case ConfigOption::ID_BOOL:
{
try
{
BooleanData & tmp = _value_data.get<BooleanData>();
tmp.bool_val = tmp.bool_default;
}
catch(ValueType::InvalidType & e)
{
throw;
}
break;
}
case ConfigOption::ID_SINT:
{
try
{
SignedIntData & tmp = _value_data.get<SignedIntData>();
tmp.sint_val = tmp.sint_default;
}
catch(ValueType::InvalidType & e)
{
throw;
}
break;
}
case ConfigOption::ID_UINT:
{
try
{
UnsignedIntData & tmp = _value_data.get<UnsignedIntData>();
tmp.uint_val = tmp.uint_default;
}
catch(ValueType::InvalidType & e)
{
throw;
}
break;
}
case ConfigOption::ID_STRING:
{
try
{
StringData & tmp = _value_data.get<StringData>();
tmp.string_val = tmp.string_default;
}
catch(ValueType::InvalidType & e)
{
throw;
}
break;
}
case ConfigOption::ID_FUN:
{
try
{
FunctionData & tmp = _value_data.get<FunctionData>();
tmp.fun_val(tmp.fun_default);
}
catch(ValueType::InvalidType & e)
{
throw;
}
break;
}
default:
throw ConfigProcessFailure(STG(FMT("unknown type identifier '%d'") % _value_data.which()));
}
_loaded = true;
};
void ConfigOption::copy_from(ConfigOption & src)
{
if (src._value_data.which() != _value_data.which())
throw ConfigProcessFailure(STG(FMT("unable to copy options, source type differs from destination.")));
if (!src._loaded)
return;
switch ((value_id_type) _value_data.which())
{
case ConfigOption::ID_BOOL:
{
try
{
BooleanData & stmp = src._value_data.get<BooleanData>();
BooleanData & dtmp = _value_data.get<BooleanData>();
/* do not copy references, but values.. */
bool tmpval = stmp.bool_val;
dtmp.bool_val = tmpval;
}
catch(ValueType::InvalidType & e)
{
throw;
}
break;
}
case ConfigOption::ID_SINT:
{
try
{
SignedIntData & stmp = src._value_data.get<SignedIntData>();
SignedIntData & dtmp = _value_data.get<SignedIntData>();
/* do not copy references, but values.. */
int tmpval = stmp.sint_val;
dtmp.sint_val = tmpval;
}
catch(ValueType::InvalidType & e)
{
throw;
}
break;
}
case ConfigOption::ID_UINT:
{
try
{
UnsignedIntData & stmp = src._value_data.get<UnsignedIntData>();
UnsignedIntData & dtmp = _value_data.get<UnsignedIntData>();
/* do not copy references, but values.. */
unsigned int tmpval = stmp.uint_val;
dtmp.uint_val = tmpval;
}
catch(ValueType::InvalidType & e)
{
throw;
}
break;
}
case ConfigOption::ID_STRING:
{
try
{
StringData & stmp = src._value_data.get<StringData>();
StringData & dtmp = _value_data.get<StringData>();
/* do not copy references, but values.. */
std::string tmpval = stmp.string_val;
dtmp.string_val = tmpval;
}
catch(ValueType::InvalidType & e)
{
throw;
}
break;
}
case ConfigOption::ID_FUN:
{
/* TO IMPLEMENT (NEEDS ANOTHER METHOD ON FUNCTION FOR GETTING VALUE) */
// FunctionData & tmp = boost::get<FunctionData>(_value_data);
//
// if (!tmp.loaded)
// {
// tmp.fun_val(tmp.fun_default);
// tmp.loaded = true;
// }
break;
}
default:
throw ConfigProcessFailure(STG(FMT("unknown type identifier '%d'") % _value_data.which()));
}
_loaded = true;
};
/*********************************/
bool ConfigOptions::add(ConfigOption option)
{
//option_map_type::iterator iter2 = _map.begin();
//boost::tie(iter2, ok2)
std::pair<option_map_type::iterator, bool> ret = _map.insert(option_pair_type(option.name(), option));
return ret.second;
}
bool ConfigOptions::synonym(std::string equiv_opt, std::string main_opt)
{
//syn_option_map_type::iterator iter = _syn_map.begin();
//boost::tie(iter, ok)
std::pair<syn_option_map_type::iterator, bool> ret = _syn_map.insert(syn_option_pair_type(equiv_opt, main_opt));
return ret.second;
}
ConfigOptions::string_set ConfigOptions::options(void)
{
string_set res;
for (option_map_type::iterator i = _map.begin(); i != _map.end(); i++)
res.insert((*i).first);
return res;
}
void ConfigOptions::process(const char * name, const char * value)
{
option_map_type::iterator iter = find_option(name);
if (iter == _map.end())
throw ConfigProcessFailure(STG(FMT("unknown option '%s'") % name));
try
{
switch ((*iter).second.type())
{
case ConfigOption::ID_SINT:
set<ConfigOption::SignedIntType>((*iter).first, Strings::toulong(value));
return;
case ConfigOption::ID_UINT:
set<ConfigOption::UnsignedIntType>((*iter).first, Strings::tolong(value));
return;
case ConfigOption::ID_BOOL:
set<ConfigOption::BooleanType>((*iter).first, Strings::toboolean(value));
return;
case ConfigOption::ID_STRING:
case ConfigOption::ID_FUN:
set<ConfigOption::StringType>((*iter).first, std::string(value));
return;
default:
throw ConfigProcessFailure(STG(FMT("unknown type identifier '%d'") % (*iter).second.type()));
}
}
catch (Strings::invalid_value & e)
{
throw ConfigProcessFailure(STG(FMT("invalid value '%s' for option '%s'") % value % name));
}
}
const char ** ConfigOptions::values(const char * name)
{
option_map_type::iterator iter = find_option(name);
if (iter == _map.end())
throw ConfigProcessFailure(STG(FMT("unknown option '%s'") % name));
return (*iter).second.values();
}
const char ** ConfigOptions::values(void)
{
if (_values != NULL)
return _values;
unsigned int count = 0;
for (option_map_type::iterator i = _map.begin(); i != _map.end(); i++)
if ((*i).second.list_me())
++count;
_values = new const char*[ count + 1 ];
unsigned int index = 0;
for (option_map_type::iterator i = _map.begin(); i != _map.end(); i++)
{
if ((*i).second.list_me())
{
_values[index] = strdup((*i).first.c_str());
++index;
}
}
_values[index] = NULL;
return _values;
}
void ConfigOptions::reset(void)
{
for (option_map_type::iterator i = _map.begin(); i != _map.end(); i++)
(*i).second.reset();
}
ConfigOptions::messages_type ConfigOptions::commit(void)
{
messages_type msgs;
for (option_map_type::iterator i = _map.begin(); i != _map.end(); i++)
{
try
{
(*i).second.commit();
}
catch (ConfigProcessFailure & e)
{
msgs.push_back(e.msg);
}
}
return msgs;
}
bool ConfigOptions::loaded(std::string name)
{
option_map_type::iterator iter = find_option(name);
if (iter == _map.end())
return false;
return iter->second.loaded();
}
void ConfigOptions::copy_from(ConfigOptions & source, std::string name)
{
option_map_type::iterator iter_src = source.find_option(name);
option_map_type::iterator iter_dst = find_option(name);
if (iter_src == source._map.end())
throw ConfigProcessFailure(STG(FMT("unknown option '%s' on source") % name));
if (iter_dst == _map.end())
throw ConfigProcessFailure(STG(FMT("unknown option '%s' on destination") % name));
iter_dst->second.copy_from(iter_src->second);
}
ConfigOptions::option_map_type::iterator ConfigOptions::find_option(std::string name)
{
syn_option_map_type::iterator syn_iter = _syn_map.find(name);
if (syn_iter != _syn_map.end())
name = syn_iter->second;
option_map_type::iterator iter = _map.find(name);
return iter;
}

View File

@ -1,286 +0,0 @@
/*
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2009 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
*/
#include <set>
#include <map>
#include <vector>
#include <strings.hpp>
#include <function.hpp>
#include <variant.hpp>
#include <format.hpp>
#ifndef _CONFIG_OPTIONS_HPP_
#define _CONFIG_OPTIONS_HPP_
struct ConfigProcessFailure
{
ConfigProcessFailure(std::string _msg): msg(_msg) {};
std::string msg;
};
struct ConfigOption
{
typedef int SignedIntType;
typedef unsigned int UnsignedIntType;
typedef bool BooleanType;
typedef std::string StringType;
typedef Function::Function1 < void, std::string > FunctionType;
typedef std::set < StringType > string_allowed_type;
/* this should reflect 'variant.which()'! */
typedef enum
{
ID_SINT = 0,
ID_UINT = 1,
ID_BOOL = 2,
ID_STRING = 3,
ID_FUN = 4,
}
value_id_type;
template < typename number_type >
struct Range
{
Range(number_type _minimum, number_type _maximum, number_type _step)
: minimum(_minimum), maximum(_maximum), step(_step) {};
number_type minimum, maximum, step;
};
struct SignedIntData : public VariantBaseType < void >
{
SignedIntData(SignedIntType & _sint_val, SignedIntType _sint_default, Range< SignedIntType > _sint_Range)
: sint_val(_sint_val), sint_default(_sint_default), sint_Range(_sint_Range) {};
int which()
{
return ID_SINT;
}
SignedIntType & sint_val;
SignedIntType sint_default;
Range<SignedIntType> sint_Range;
};
struct UnsignedIntData : public VariantBaseType < void >
{
UnsignedIntData(UnsignedIntType & _uint_val, UnsignedIntType _uint_default, Range< UnsignedIntType > _uint_Range)
: uint_val(_uint_val), uint_default(_uint_default), uint_Range(_uint_Range) {};
int which()
{
return ID_UINT;
}
UnsignedIntType & uint_val;
UnsignedIntType uint_default;
Range<UnsignedIntType> uint_Range;
};
struct BooleanData : public VariantBaseType < void >
{
BooleanData(BooleanType & _bool_val, BooleanType _bool_default)
: bool_val(_bool_val), bool_default(_bool_default) {};
int which()
{
return ID_BOOL;
}
BooleanType & bool_val;
BooleanType bool_default;
};
struct StringData : public VariantBaseType < void >
{
StringData(std::string & _string_val, std::string _string_default, string_allowed_type _string_allowed)
: string_val(_string_val), string_default(_string_default), string_allowed(_string_allowed) {};
int which()
{
return ID_STRING;
}
std::string & string_val;
std::string string_default;
string_allowed_type string_allowed;
};
struct FunctionData : public VariantBaseType < void >
{
FunctionData(FunctionType _fun_val, std::string _fun_default, string_allowed_type _fun_allowed)
: fun_val(_fun_val), fun_default(_fun_default), fun_allowed(_fun_allowed) {};
int which()
{
return ID_FUN;
}
FunctionType fun_val;
std::string fun_default;
string_allowed_type fun_allowed;
};
typedef Variant < VariantBaseType < void > > ValueType;
ConfigOption(std::string, const StringType &, const StringType, string_allowed_type allowed, bool list_me = true);
ConfigOption(std::string, const StringType &, const StringType = "", bool list_me = true);
ConfigOption(std::string, const SignedIntType &, const SignedIntType = 0, SignedIntType min = -INT_MAX, SignedIntType max = INT_MAX, SignedIntType step = 1, bool list_me = true);
ConfigOption(std::string, const UnsignedIntType &, const UnsignedIntType = 0, UnsignedIntType min = 0, UnsignedIntType max = UINT_MAX, UnsignedIntType step = 1, bool list_me = true);
ConfigOption(std::string, const BooleanType &, const BooleanType = false, bool list_me = true);
ConfigOption(std::string, FunctionType, std::string defvalue, string_allowed_type allowed, bool list_me = true);
ConfigOption(std::string, FunctionType, std::string defvalue = "", bool list_me = true);
ConfigOption(const ConfigOption & o);
~ConfigOption(void);
void set(StringType value);
void set(SignedIntType value);
void set(UnsignedIntType value);
void set(BooleanType value);
BooleanType get_bool(){ return _value_data.get<BooleanData>().bool_val; }
std::string get_str(){ return _value_data.get<StringData>().string_val; }
SignedIntType get_sint(){ return _value_data.get<SignedIntData>().sint_val; }
UnsignedIntType get_uint(){ return _value_data.get<UnsignedIntData>().uint_val; }
std::string & name(void);
value_id_type type(void);
const char ** values(void);
void reset(void);
void commit(void);
bool list_me(void) { return _list_me; };
bool loaded(void) { return _loaded; };
void copy_from(ConfigOption &);
protected:
std::string _my_name;
ValueType _value_data;
bool _list_me;
const char ** _values;
bool _loaded;
};
struct ConfigOptions
{
typedef std::vector < std::string > messages_type;
ConfigOptions(void): _values(NULL) {};
typedef std::set < std::string > string_set;
typedef std::map < std::string, ConfigOption > option_map_type;
typedef std::pair < std::string, ConfigOption > option_pair_type;
typedef std::map < std::string, std::string > syn_option_map_type;
typedef std::pair < std::string, std::string > syn_option_pair_type;
bool add(ConfigOption option);
/* only valid in "process" (for backwards compatibility config files) */
bool synonym(std::string, std::string);
template <typename ValueType>
void set(std::string name, ValueType value)
{
option_map_type::iterator iter = _map.find(name);
if (iter == _map.end())
throw ConfigProcessFailure(STG(FMT("unknown option: %s") % name));
(*iter).second.set(value);
}
std::string get(std::string name)
{
option_map_type::iterator iter = _map.find(name);
if (iter == _map.end())
throw ConfigProcessFailure(STG(FMT("unknown option: %s") % name));
switch((*iter).second.type())
{
case ConfigOption::ID_BOOL: return (*iter).second.get_bool() ? "yes" : "no";
case ConfigOption::ID_STRING: return (*iter).second.get_str();
case ConfigOption::ID_UINT: return STG(FMT("%d") % (*iter).second.get_uint());
case ConfigOption::ID_SINT: return STG(FMT("%d") % (*iter).second.get_sint());
case ConfigOption::ID_FUN: return "";
}
}
string_set options(void);
void process(const char *, const char *); /* process option from file */
void reset(void); /* reset loaded opts */
messages_type commit(void); /* set defaults */
const char ** values(const char *); /* option value */
const char ** values(void); /* values from options */
bool loaded(std::string); /* return if config was loaded */
void copy_from(ConfigOptions &, std::string);
protected:
option_map_type::iterator find_option(std::string);
protected:
option_map_type _map;
syn_option_map_type _syn_map;
const char ** _values;
};
#endif /* _CONFIG_OPTIONS_HPP_ */

View File

@ -1,241 +0,0 @@
/*
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2009 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
*/
#include <errno.h>
#include <configurator/configfile.hpp>
#if _MSC_VER >= 1400
#undef close
#endif
void Configfile::ignore(std::string str)
{
_ignores.insert(str);
};
bool Configfile::select(Section **ptr, std::string str)
{
/* default section == this! */
*ptr = this;
/* always success by default */
return true;
};
bool Configfile::adjust(Section * section, std::string & opt, std::string & val)
{
return section->load(opt, val);
};
bool Configfile::deserialize(std::ifstream& fd)
{
Section * section = NULL;
/* default selection! */
if (!select(&section))
{
_errors.push_back("default selection has failed!");
return false;
}
size_t count = 0;
while (fd.good())
{
std::string str;
/* read one line! */
std::getline(fd, str);
size_t lst = str.size() - 1;
if (str.size() >= 1 && str[lst] == '\r') //cuida das quebras de linha do tipo \r\n
{
str.erase(lst,1);
--lst;
}
/* empty line! */
if (str.size() == 0)
continue;
/* comment! */
if (str[0] == '#')
continue;
++count;
if (str[0] == '[' && str[lst] == ']')
{
str.erase(0,1); --lst;
str.erase(lst,1); --lst;
if (!select(&section, str))
{
_errors.push_back(STG(FMT("erroneous section '%s'") % str));
/* ignore this section */
section = NULL;
continue;
}
}
else
{
std::string::size_type pos = str.find('=');
if (pos == std::string::npos)
{
_errors.push_back(STG(FMT("erroneous separator '%s'") % str));
continue;
};
if (section == NULL)
{
_errors.push_back(STG(FMT("no section for option '%s'") % str));
continue;
}
std::string opt(str.substr(0,pos));
std::string val(str.substr(pos+1));
if (_ignores.find(opt) != _ignores.end())
continue;
if (val == "@") val = "";
if (adjust(section, opt, val))
continue;
_errors.push_back(STG(FMT("option '%s' does "
"not exist or '%s' is not a valid value (at section '%s')")
% opt % val % section->name()));
}
}
// retorna 'true' se arquivo tinha alguma coisa valida.
return (count != 0);
}
bool Configfile::obtain()
{
std::ifstream fd(_filename.c_str());
if (!fd.is_open())
{
_errors.push_back(STG(FMT("unable to open file '%s': %s")
% _filename % strerror(errno)));
return false;
};
if (!deserialize(fd))
{
fd.close();
return false;
}
fd.close();
return true;
};
void Configfile::recurse(std::ofstream& fd, Section * section)
{
typedef Section::SectionMap::iterator section_iter;
typedef Section::OptionMap::iterator option_iter;
for (option_iter i = section->option_begin(); i != section->option_end(); i++)
{
std::string res;
if ((*i).second.store(res))
{
if (res == "") res = "@";
fd << (*i).first << "=" << res << std::endl;
}
}
if (!section->recursive())
return;
for (section_iter j = section->section_begin(); j != section->section_end(); j++)
recurse(fd, (*j).second);
}
bool Configfile::serialize(std::ofstream& fd)
{
recurse(fd, this);
return true;
}
bool Configfile::provide()
{
std::string tmp(_filename);
tmp += ".new";
std::ofstream fd(tmp.c_str());
if (!fd.good())
{
_errors.push_back(STG(FMT("unable to open file '%s': %s")
% tmp % strerror(errno)));
return false;
}
if (!serialize(fd))
{
fd.close();
return false;
}
fd.close();
if (rename(tmp.c_str(), _filename.c_str()) != 0)
{
_errors.push_back(STG(FMT("unable to replace config file '%s': %s")
% _filename % strerror(errno)));
return false;
}
return true;
}
#if _MSC_VER >= 1400
#define close _close
#endif

View File

@ -1,185 +0,0 @@
/*
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2009 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
*/
#include <configurator/option.hpp>
bool Option::equals(std::string & value)
{
switch (_restriction.numeral())
{
case Restriction::N_UNIQUE:
{
Restriction::Value my_value;
if (!_restriction.get(Restriction::F_USER, my_value))
return false;
return (my_value == value);
}
case Restriction::N_MULTIPLE:
{
Restriction::Vector my_values;
if (!_restriction.get(Restriction::F_USER, my_values))
return false;
for (Restriction::Vector::iterator i = my_values.begin(); i != my_values.end(); i++)
{
if ((*i) == value)
return true;
}
return false;
}
}
return false;
}
bool Option::load(std::string & value)
{
bool ret = _restriction.set(Restriction::F_FILE, value);
if (ret) _modified = false;
return ret;
}
bool Option::change(std::string & value)
{
bool ret = _restriction.set(Restriction::F_FILE, value);
if (ret) _modified = true;
return ret;
}
bool Option::store(std::string & value)
{
switch (_restriction.numeral())
{
case Restriction::N_UNIQUE:
return _restriction.get(Restriction::F_FILE, value);
case Restriction::N_MULTIPLE:
{
Restriction::Vector values;
if (!_restriction.get(Restriction::F_FILE, values))
return false;
Strings::Merger strs;
for (Restriction::Vector::iterator i = values.begin(); i != values.end(); i++)
strs.add(*i);
value = strs.merge(",");
return true;
}
default:
return false;
}
}
Option::Flags Option::set(const char * value)
{
std::string str_value(value);
return set(str_value);
}
Option::Flags Option::set(Restriction::Value & value)
{
Restriction::Value last_value, curr_value;
Flags flags;
bool ret1 = _restriction.get(Restriction::F_USER, last_value);
if (!_restriction.set(Restriction::F_USER, value))
return flags;
flags[F_ADJUSTED] = true;
bool ret2 = _restriction.get(Restriction::F_USER, curr_value);
if (!ret1 || (ret2 && (last_value != curr_value)))
{
flags[F_MODIFIED] = true;
_modified = true;
}
return flags;
}
Option::Flags Option::set(Restriction::Vector & values)
{
Restriction::Vector last_values, curr_values;
Flags flags;
bool ret1 = _restriction.get(Restriction::F_USER, last_values);
if (!_restriction.set(Restriction::F_USER, values))
return flags;
flags[F_ADJUSTED] = true;
bool ret2 = _restriction.get(Restriction::F_USER, curr_values);
if (!ret1 || (ret2 && (last_values != curr_values)))
{
flags[F_MODIFIED] = true;
_modified = true;
}
return flags;
}
bool Option::get(Restriction::Value & value)
{
return _restriction.get(Restriction::F_USER, value);
}
bool Option::get(Restriction::Vector & values)
{
return _restriction.get(Restriction::F_USER, values);
}

View File

@ -1,353 +0,0 @@
/*
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2009 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
*/
#include <math.h>
#include <string.h>
#include <iostream>
#include <strings.hpp>
#include <configurator/restriction.hpp>
/* internal helper! */
bool Restriction::equalNumber(const double a, const double b)
{
char tmp1[64];
char tmp2[64];
snprintf(tmp1, sizeof(tmp1), "%.3f", a);
snprintf(tmp2, sizeof(tmp2), "%.3f", b);
if (strncmp(tmp1, tmp2, sizeof(tmp1)))
return false;
return true;
}
/* process value to our internal representation */
bool Restriction::process(Restriction::Format fmt,
const Restriction::Value & value, Restriction::Value & final)
{
switch (_bounds)
{
case B_RANGE:
{
if (_kind != K_NUMBER)
return false;
std::string tmpvalue;
Restriction::Value::const_iterator itr = value.begin();
Restriction::Value::const_iterator end = value.end();
tmpvalue.reserve(value.size());
// f*cking dot/comma notation!
for (; itr != end; ++itr)
tmpvalue += ((*itr) != ',' ? (*itr) : '.');
try
{
double newvalue = Strings::todouble(tmpvalue);
if (newvalue < _init && newvalue > _fini)
return false;
double res = (newvalue - _init) / _step;
if (!equalNumber(res, rint(res)))
return false;
final = value;
return true;
}
catch (...)
{
return false;
}
}
case B_LIST:
for (List::iterator i = _list.begin(); i != _list.end(); i++)
{
Value & tmp = (*i);
if (tmp == value)
{
final = value;
return true;
}
}
return false;
case B_MAPS:
switch (fmt)
{
case F_USER:
{
Map::iterator i = _map_from_usr.find(std::string(value));
if (i == _map_from_usr.end())
return false;
Value & tmp = (*i).second;
final = tmp;
return true;
}
case F_FILE:
{
Map::iterator i = _map_from_cfg.find(std::string(value));
if (i == _map_from_cfg.end())
return false;
final = value;
return true;
}
default:
break;
}
return false;
case B_FREE:
final = value;
return true;
default:
break;
}
return false;
}
/* unprocess the value (outputs the external representation) */
bool Restriction::unprocess(Restriction::Format fmt,
const Restriction::Value & value, Restriction::Value & final)
{
switch (_bounds)
{
case B_MAPS:
switch (fmt)
{
case F_USER:
{
Map::iterator i = _map_from_cfg.find(std::string(value));
if (i == _map_from_cfg.end())
return false;
final = (*i).second;
return true;
}
default:
break;
}
default:
final = value;
return true;
}
}
/***************************** *****************************/
bool Restriction::get(Restriction::Format fmt, Restriction::Value & value)
{
if (_numeral != N_UNIQUE)
return false;
if (!unprocess(fmt, _value._unique, value))
return false;
return true;
}
bool Restriction::get(Restriction::Format fmt, Restriction::Vector & values)
{
if (_numeral != N_MULTIPLE)
return false;
List & my_values = _value._multiple;
for (List::iterator i = my_values.begin(); i != my_values.end(); i++)
{
Value & value = (*i);
Value final;
if (!unprocess(fmt, value, final))
return false;
values.push_back(final);
};
return true;
}
/***************************** *****************************/
bool Restriction::set(Restriction::Format fmt, Restriction::Value &value)
{
switch (_numeral)
{
case N_UNIQUE:
{
Value final;
if (!process(fmt, value, final))
return false;
_value._unique = final;
return true;
}
case N_MULTIPLE:
{
if (value == "@" || value == "#" || value == "")
{
_value._multiple.clear();
return true;
}
Strings::vector_type values;
Strings::tokenize(value, values, ",");
return set(fmt, values);
}
default:
return false;
}
}
bool Restriction::set(Restriction::Format fmt, Restriction::Vector & values)
{
if (_numeral != N_MULTIPLE)
return false;
if (values.empty())
{
_value._multiple.clear();
}
else
{
/* list needed to store temporary values */
List finals;
for (Vector::iterator i = values.begin(); i != values.end(); i++)
{
Value & value = (*i);
Value final;
if (!process(fmt, value, final))
return false;
finals.push_back(final);
}
List & lst = _value._multiple;
/* need to clear values set before */
lst.clear();
for (List::iterator i = finals.begin(); i != finals.end(); i++)
{
Value value = (*i);
lst.push_back(value);
}
};
return true;
}
/***************************** *****************************/
void Restriction::allowed(Restriction::Vector &vals)
{
switch (_bounds)
{
case B_FREE:
return;
case B_LIST:
for (List::iterator i = _list.begin(); i != _list.end(); i++)
vals.push_back((*i));
break;
case B_MAPS:
for (Map::iterator i = _map_from_usr.begin(); i != _map_from_usr.end(); i++)
vals.push_back((*i).first);
break;
case B_RANGE:
{
if (_kind != K_NUMBER)
return;
// is there any fraction?
bool has_fraction = (!equalNumber(_init, rint(_init))) || (!equalNumber(_fini, rint(_fini))) || (!equalNumber(_step, rint(_step)));
const char * format = (has_fraction ? "%.2f" : "%02.0f");
for (double i = _init; i <= _fini; i += _step)
{
char tmp[32];
snprintf(tmp, sizeof(tmp), format, i);
vals.push_back(std::string(tmp));
}
break;
}
default:
break;
}
}
void Restriction::init_class()
{
_value._unique.clear();
_value._multiple.clear();
}

View File

@ -1,321 +0,0 @@
/*
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2009 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
*/
#include <stdarg.h>
#include <string>
#include <list>
#include <vector>
#include <map>
#ifndef _CONFIG_RESTRICTION_HPP_
#define _CONFIG_RESTRICTION_HPP_
struct Restriction
{
/* generic types */
enum Format
{
F_USER,
F_FILE
};
enum Kind
{
// K_INTEGER,
// K_FLOAT,
K_STRING,
K_NUMBER // = K_INTEGER // compatibility
};
enum Bounds
{
B_FREE,
B_RANGE,
B_LIST,
B_MAPS
};
enum Numeral
{
N_UNIQUE,
N_MULTIPLE
};
typedef std::string Value;
/* types used for data input */
struct Pair
{
const char *pretty;
const char *value;
};
typedef std::pair < Value, Value > PairMap;
typedef std::list < PairMap > ListMap;
/* types used internally */
typedef std::map < Value, Value > Map;
typedef std::vector < Value > Vector;
typedef std::list < Value > List;
typedef std::pair < Value, Value > MapPair;
struct Generic
{
Value _unique;
List _multiple;
};
Restriction(Kind kind, Numeral num)
: _kind(kind), _bounds(B_FREE), _numeral(num), _unit(""),
_init(-1), _fini(-1), _step(-1)
{
init_class();
}
/*
Restriction(Kind kind, Numeral num,
int init, int fini, int step = 1)
: _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(unit),
_iinit(init), _ifini(fini), _istep(step),
_finit(-1), _ffini(-1), _fstep(-1)
{
init_class();
}
Restriction(Kind kind, Numeral num,
const char *unit, int init, int fini, int step = 1)
: _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(unit),
_iinit(init), _ifini(fini), _istep(step),
_finit(-1), _ffini(-1), _fstep(-1)
{
init_class();
}
Restriction(Kind kind, Numeral num,
std::string unit, int init, int fini, int step = 1)
: _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(unit),
_iinit(init), _ifini(fini), _istep(step),
_finit(-1), _ffini(-1), _fstep(-1)
{
init_class();
}
Restriction(Kind kind, Numeral num,
float init, float fini, float step = 1)
: _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(unit),
_iinit(-1), _ifini(-1), _istep(-1)
_finit(init), _ffini(fini), _fstep(step),
{
init_class();
}
Restriction(Kind kind, Numeral num,
const char *unit, float init, float fini, float step = 1.0)
: _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(unit),
_iinit(-1), _ifini(-1), _istep(-1)
_finit(init), _ffini(fini), _fstep(step),
{
init_class();
}
Restriction(Kind kind, Numeral num,
std::string unit, float init, float fini, float step = 1.0)
: _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(unit),
_iinit(-1), _ifini(-1), _istep(-1)
_finit(init), _ffini(fini), _fstep(step),
{
init_class();
}
*/
Restriction(Kind kind, Numeral num,
double init, double fini, double step = 1)
: _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(""),
_init(init), _fini(fini), _step(step)
{
init_class();
}
Restriction(Kind kind, Numeral num,
const char *unit, double init, double fini, double step = 1.0)
: _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(unit),
_init(init), _fini(fini), _step(step)
{
init_class();
}
Restriction(Kind kind, Numeral num,
std::string unit, double init, double fini, double step = 1.0)
: _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(unit),
_init(init), _fini(fini), _step(step)
{
init_class();
}
Restriction(Kind kind, Numeral num,
const char *first, ...)
: _kind(kind), _bounds(B_LIST), _numeral(num), _unit(""),
_init(-1), _fini(-1), _step(-1)
{
_list.push_back(std::string(first));
va_list ap;
va_start(ap, first);
while (true)
{
const char *arg = va_arg(ap, const char *);
if (arg == NULL) break;
_list.push_back(std::string(arg));
}
init_class();
}
Restriction(Kind kind, const char *unit, Numeral num,
const char *first, ...)
: _kind(kind), _bounds(B_LIST), _numeral(num), _unit(unit),
_init(-1), _fini(-1), _step(-1)
{
_list.push_back(std::string(first));
va_list ap;
va_start(ap, first);
while (true)
{
const char *arg = va_arg(ap, const char *);
if (arg == NULL) break;
_list.push_back(std::string(arg));
}
init_class();
}
Restriction(Kind kind, Numeral num,
const struct Pair first, ...)
: _kind(kind), _bounds(B_MAPS), _numeral(num), _unit(""),
_init(-1), _fini(-1), _step(-1)
{
_map_from_usr.insert(MapPair(Value(first.pretty), Value(first.value)));
_map_from_cfg.insert(MapPair(Value(first.value), Value(first.pretty)));
va_list ap;
va_start(ap, first);
while (true)
{
Pair arg = va_arg(ap, Pair);
if (arg.pretty == NULL) break;
_map_from_usr.insert(MapPair(Value(arg.pretty), Value(arg.value)));
_map_from_cfg.insert(MapPair(Value(arg.value), Value(arg.pretty)));
}
init_class();
}
Restriction(Kind kind, Numeral num, List list)
: _kind(kind), _bounds(B_LIST), _numeral(num), _unit(""),
_init(-1), _fini(-1), _step(-1), _list(list)
{
init_class();
}
Restriction(Kind kind, Numeral num, ListMap map)
: _kind(kind), _bounds(B_MAPS), _numeral(num), _unit(""),
_init(-1), _fini(-1), _step(-1)
{
for (ListMap::iterator i = map.begin(); i != map.end(); i++)
{
_map_from_usr.insert(MapPair(Value((*i).first), Value((*i).second)));
_map_from_cfg.insert(MapPair(Value((*i).second), Value((*i).first)));
}
init_class();
}
Kind kind() { return _kind; };
Bounds bounds() { return _bounds; };
Numeral numeral() { return _numeral; };
Value unit() { return _unit; };
bool set(Format, Vector &);
bool set(Format, Value &);
bool get(Format, Vector &);
bool get(Format, Value &);
void allowed(Vector &);
private:
bool process(Format, const Value &, Value &);
bool unprocess(Format, const Value &, Value &);
void init_class();
bool equalNumber(const double, const double);
protected:
Kind _kind;
Bounds _bounds;
Numeral _numeral;
Value _unit;
double _init, _fini, _step;
Map _map_from_usr,
_map_from_cfg;
List _list;
Generic _value;
};
#endif /* _CONFIG_RESTRICTION_HPP_ */

View File

@ -1,226 +0,0 @@
/*
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2009 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
*/
#include <string>
#include <vector>
#include <map>
#include <algorithm>
#include <iostream>
#include <configurator/option.hpp>
#ifndef _CONFIG_SECTION_HPP_
#define _CONFIG_SECTION_HPP_
struct Section
{
typedef std::map < std::string, Option > OptionMap;
typedef std::vector< Option * > OptionVector;
typedef std::map < std::string, Section * > SectionMap;
typedef std::vector < Section * > SectionVector;
struct not_found {}; /* exception */
// protected:
Section(std::string name, std::string desc, bool recursive = true)
: _name(name), _description(desc), _recursive(recursive) {};
void add(Option o)
{
_options.insert(std::pair<std::string,Option>(o.name(), o));
};
void del(std::string name)
{
_options.erase(name);
};
void add(Section *s)
{
_sections.insert(std::pair<std::string,Section*>(s->name(), s));
};
public:
const std::string & name() { return _name; };
const std::string & description() { return _description; };
const bool & recursive() { return _recursive; };
OptionMap::iterator option_begin() { return _options.begin(); };
OptionMap::iterator option_end() { return _options.end(); };
SectionMap::iterator section_begin() { return _sections.begin(); };
SectionMap::iterator section_end() { return _sections.end(); };
/**/
Option * option_find(const char *, bool recurse = false);
Section * section_find(const char *, bool recurse = false);
Option * option_find(std::string &, bool recurse = false);
Section * section_find(std::string &, bool recurse = false);
/**/
void options(OptionVector &);
void sections(SectionVector &);
/**/
template <typename F>
bool search_and_apply(std::string &key, std::string &value, F f)
{
OptionMap::iterator i = _options.find(key);
if (i != _options.end())
return f((*i).second);
if (!_recursive)
return false;
return (find_if(_sections.begin(), _sections.end(), f) != _sections.end());
}
private:
struct key_value
{
key_value(std::string &k, std::string &v): _k(k), _v(v) {};
std::string & _k, & _v;
};
struct load_section: protected key_value
{
load_section(std::string &k, std::string &v): key_value(k,v) {};
bool operator()(Option &o) { return o.load(_v); };
bool operator()(SectionMap::value_type &v) { return v.second->load(_k,_v); };
};
struct change_section: protected key_value
{
change_section(std::string &k, std::string &v): key_value(k,v) {};
bool operator()(Option &o) { return o.change(_v); };
bool operator()(SectionMap::value_type &v) { return v.second->change(_k,_v); };
};
struct store_section: protected key_value
{
store_section(std::string &k, std::string &v): key_value(k,v) {};
bool operator()(Option &o) { return o.store(_v); };
bool operator()(SectionMap::value_type &v) { return v.second->store(_k,_v); };
};
struct set_section: protected key_value
{
set_section(std::string &k, std::string &v): key_value(k,v) {};
bool operator()(Option &o) { return (o.set(_v))[Option::F_ADJUSTED]; };
bool operator()(SectionMap::value_type &v) { return v.second->set(_k,_v); };
};
struct get_section: protected key_value
{
get_section(std::string &k, std::string &v): key_value(k,v) {};
bool operator()(Option &o) { return o.get(_v); };
bool operator()(SectionMap::value_type &v) { return v.second->get(_k,_v); };
};
struct modified_section
{
bool operator()(OptionMap::value_type &v) { return v.second.modified(); };
bool operator()(SectionMap::value_type &v) { return v.second->modified(); };
};
public:
bool load(const char * key, std::string value)
{
std::string skey(key);
return search_and_apply(skey, value, load_section(skey, value));
}
bool load(std::string &key, std::string &value)
{
return search_and_apply(key, value, load_section(key, value));
}
bool change(std::string &key, std::string &value)
{
return search_and_apply(key, value, change_section(key, value));
}
bool store(std::string &key, std::string &value)
{
return search_and_apply(key, value, store_section(key, value));
}
bool set(std::string &key, std::string &value)
{
return search_and_apply(key, value, set_section(key, value));
}
bool get(std::string &key, std::string &value)
{
return search_and_apply(key, value, get_section(key, value));
}
bool modified()
{
return ((find_if(_options.begin(), _options.end(), modified_section()) != _options.end()) ||
(find_if(_sections.begin(), _sections.end(), modified_section()) != _sections.end()));
}
private:
Section() {};
protected:
std::string _name;
std::string _description;
OptionMap _options;
SectionMap _sections;
bool _recursive;
};
#endif /* _CONFIG_SECTION_HPP_ */

View File

@ -1,575 +0,0 @@
/*
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2009 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
*/
#include <ringbuffer.hpp>
/********** BUFFER FUNCTIONS **********/
/* writes everything or nothing */
bool Ringbuffer_traits::traits_provide(char * buffer, const char * value, unsigned int amount, bool skip_overwrite)
{
/* avoid using different values */
Buffer_table cache = _pointers;
const unsigned int reader = cache.reader.complete;
const unsigned int writer = cache.writer.complete;
const unsigned int dest = cache.writer.complete - 1;
const bool reader_less = cache.reader.complete < cache.writer.complete;
if (amount >= _size)
return false;
bool ret = true;
/* should we go around the buffer for writing? */
if (((writer + amount) > _size) && (reader_less || !skip_overwrite))
{
/* Documentation of the formula used in the 'if' below.
*
* [0|1|2|3|4|5|6|7] => size=8
* | |
* reader |
* writer
*
* => writer has places [5,6,7,0,1] to write (5 places).
*
* => 8 - (4-2+1) = 8 - (2+1) = 8 - 3 = 5
*
* > writer goes 1 up, amount goes 1 down.
* > reader goes 1 up, amount goes 1 up.
* > size goes 1 down, amount goes 1 down.
*
*/
if ((_size - (writer - reader + 1)) <= amount)
{
if (skip_overwrite)
return false;
do
{
Buffer_pointer extra(cache.reader);
extra.complete = (extra.complete + amount) % _size;
if (update(cache.reader, extra))
break;
}
while (true);
ret = false;
}
unsigned int wr1 = _size - writer + 1; /* writer is already 1 position after */
unsigned int wr2 = amount - wr1;
// fprintf(stderr, "%p> partial write: (%d/%d) %d/%d [%d/%d]\n", this, wr1, wr2, amount, _size, reader, writer);
/* two partial writes (one at the end, another at the beginning) */
memcpy((void *) &(buffer[dest]), (const void *) (value), _block * wr1);
memcpy((void *) (buffer), (const void *) &(value[wr1]), _block * wr2);
}
else
{
if (!reader_less && ((reader - writer) <= amount))
{
if (skip_overwrite)
return false;
do
{
Buffer_pointer extra(cache.reader);
extra.complete = (extra.complete + amount) % _size;
if (update(cache.reader, extra))
break;
}
while (true);
ret = false;
}
// fprintf(stderr, "%p> full write: a=%d/s=%d [r=%d/w=%d]\n", this, amount, _size, reader, writer);
/* we are talking about buffers here, man! */
memcpy((void *) &(buffer[dest]), (const void *) value, _block * amount);
}
_pointers.writer.complete = ((dest + amount) % _size) + 1;
_pointers.writer.partial = 1;
// fprintf(stderr, "%p> write end: %d [block=%d]\n", this, writer, _block);
return ret;
}
/* returns the number of itens that have been read */
unsigned int Ringbuffer_traits::traits_consume(const char * buffer, char * value, unsigned int amount, bool atomic_mode)
{
/* avoid using different values */
Buffer_table cache = _pointers;
const unsigned int writer = _pointers.writer.complete;
const unsigned int reader = _pointers.reader.complete;
const bool writer_less = writer < reader;
unsigned int total = 0;
/* should we go around the buffer for reading? */
if (writer_less && (reader + amount >= _size))
{
total = std::min(_size - (reader - writer + 1), amount);
if ((total == 0) || (atomic_mode && (total < amount)))
return 0;
unsigned int rd1 = _size - reader;
unsigned int rd2 = total - rd1;
// fprintf(stderr, "%p> partial read: (%d/%d) %d/%d [%d/%d]\n", this, rd1, rd2, total, _size, reader, writer);
/* two partial consumes (one at the end, another at the beginning) */
memcpy((void *) (value), (const void *) &(buffer[reader]), _block * rd1);
memcpy((void *) &(value[rd1]), (const void *) (buffer), _block * rd2);
}
else
{
total = std::min((!writer_less ? writer - (reader + 1) : amount), amount);
if ((total == 0) || (atomic_mode && (total < amount)))
return 0;
// fprintf(stderr, "%p> full read: %d/%d [%d/%d]\n", this, total, _size, reader, writer);
/* we are talking about buffers here, man! */
memcpy((void *) value, (const void *) &(buffer[reader]), _block * total);
}
do
{
/* jump the reader forward */
Buffer_pointer index((cache.reader.complete + total) % _size);
if (update(cache.reader, index))
break;
}
while (true);
// fprintf(stderr, "%p> read end: %d [block=%d]\n", this, reader, _block);
return total;
}
/********** TWO-PHASE BUFFER FUNCTIONS ***********/
/* returns the number of itens that have been read */
unsigned int Ringbuffer_traits::traits_consume_begins(const char * buffer, char * value, unsigned int amount, bool atomic_mode)
{
Buffer_table cache = _pointers;
/* avoid using different values */
const unsigned int reader = cache.reader.complete;
const unsigned int writer = cache.writer.complete;
const bool writer_less = writer < reader;
unsigned int total = 0;
/* should we go around the buffer for reading? */
if (writer_less && (reader + amount >= _size))
{
total = std::min(_size - (reader - writer + 1), amount);
if ((total == 0) || (atomic_mode && (total < amount)))
return 0;
unsigned int rd1 = _size - reader;
unsigned int rd2 = total - rd1;
// fprintf(stderr, "%p> partial read: (%d/%d) %d/%d [%d/%d]\n", this, rd1, rd2, total, _size, reader, writer);
/* two partial consumes (one at the end, another at the beginning) */
memcpy((void *) (value), (const void *) &(buffer[reader]), _block * rd1);
memcpy((void *) &(value[rd1]), (const void *) (buffer), _block * rd2);
}
else
{
total = std::min((!writer_less ? writer - (reader + 1) : amount), amount);
if ((total == 0) || (atomic_mode && (total < amount)))
return 0;
// fprintf(stderr, "%p> full read: %d/%d [%d/%d]\n", this, total, _size, reader, writer);
/* we are talking about buffers here, man! */
memcpy((void *) value, (const void *) &(buffer[reader]), _block * total);
}
// fprintf(stderr, "%p> read end: %d [%d]\n", this, _reader, _reader_partial);
return total;
}
bool Ringbuffer_traits::traits_consume_commit(unsigned int amount)
{
/* avoid using different values */
Buffer_table cache = _pointers;
const unsigned int writer = cache.writer.complete;
const unsigned int reader = cache.reader.complete;
const bool writer_less = writer < reader;
unsigned int total = 0;
/* should we go around the buffer for reading? */
if (writer_less && (reader + amount >= _size))
{
total = std::min(_size - (reader - writer + 1), amount);
if (total < amount)
return false;
// fprintf(stderr, "%p> partial read: (%d/%d) %d/%d [%d/%d]\n", this, rd1, rd2, total, _size, reader, writer);
}
else
{
total = std::min((!writer_less ? writer - (reader + 1) : amount), amount);
if (total < amount)
return false;
// fprintf(stderr, "%p> full read: %d/%d [%d/%d]\n", this, total, _size, reader, writer);
}
do
{
/* jump the reader forward */
Buffer_pointer index(cache.reader);
index.complete = (index.complete + total) % _size;
if (update(cache.reader, index))
break;
}
while (true);
// fprintf(stderr, "%p> read end: %d [%d]\n", this, _reader, _reader_partial);
return true;
}
/********** PARTIAL BUFFER FUNCTIONS (bytes) ***********/
/* writes everything or nothing */
bool Ringbuffer_traits::traits_provide_partial(char * buffer, const char * value, unsigned int amount)
{
/* avoid using different values */
Buffer_table cache = _pointers;
const unsigned int reader = (cache.reader.complete * _block) + cache.reader.partial;
const unsigned int writer = ((cache.writer.complete - 1) * _block) + cache.writer.partial;
const unsigned int size = _size * _block;
const unsigned int dest = writer - 1;
// fprintf(stderr, "%p> provide partial: %d/%d [%d/%d]\n", this, reader, writer, amount, size);
const bool reader_less = reader < writer;
/* should we go around the buffer for writing? */
if (reader_less && ((writer + amount) > size))
{
/* Documentation of the formula used in the 'if' below.
*
* [0|1|2|3|4|5|6|7] => size=8
* | |
* reader |
* writer
*
* => writer has places [5,6,7,0,1] to write (5 places).
*
* => 8 - (4-2+1) = 8 - (2+1) = 8 - 3 = 5
*
* > writer goes 1 up, amount goes 1 down.
* > reader goes 1 up, amount goes 1 up.
* > size goes 1 down, amount goes 1 down.
*
*/
if ((size - (writer - reader + 1)) <= amount)
return false;
unsigned int wr1 = size - writer + 1; /* writer is already 1 position after */
unsigned int wr2 = amount - wr1;
// fprintf(stderr, "%p> p partial write: (%d/%d) %d/%d [%d/%d]\n", this, wr1, wr2, amount, size, reader, writer);
/* two partial writes (one at the end, another at the beginning) */
memcpy((void *) &(buffer[dest]), (const void *) (value), wr1);
memcpy((void *) (buffer), (const void *) &(value[wr1]), wr2);
}
else
{
if (!reader_less && ((reader - writer) <= amount))
return false;
// fprintf(stderr, "%p> p full write: %d/%d [r=%d/w=%d]\n", this, amount, size, reader, writer);
/* we are talking about buffers here, man! */
memcpy((void *) &(buffer[dest]), (const void *) value, amount);
}
unsigned int new_writer = ((dest + amount) % size) + 1;
/* update "full length position" */
_pointers.writer.complete = (unsigned int)floor((double) new_writer / (double)_block)+1;
_pointers.writer.partial = (unsigned short)(new_writer % _block);
// fprintf(stderr, "%p> p write end: %d [block=%d]\n", this, new_writer, _block);
return true;
}
/* returns the number of bytes that have been read */
unsigned int Ringbuffer_traits::traits_consume_partial(const char * buffer, char * value, unsigned int amount)
{
/* avoid using different values */
Buffer_table cache = _pointers;
const unsigned int writer = ((cache.writer.complete - 1) * _block) + cache.writer.partial;
const unsigned int reader = (cache.reader.complete * _block) + cache.reader.partial;
const unsigned int size = _size * _block;
// fprintf(stderr, "%p> consume partial: %d/%d [%d/%d]\n", this, reader, writer, amount, size);
const bool writer_less = writer < reader;
unsigned int total = 0;
/* should we go around the buffer for reading? */
if (writer_less && (reader + amount >= size))
{
total = std::min(size - (reader - writer + 1), amount);
if (total == 0)
return 0;
unsigned int rd1 = size - reader;
unsigned int rd2 = total - rd1;
// fprintf(stderr, "%p> p partial read: (%d/%d) %d/%d [%d/%d]\n", this, rd1, rd2, total, size, reader, writer);
/* two partial consumes (one at the end, another at the beginning) */
memcpy((void *) (value), (const void *) &(buffer[reader]), rd1);
memcpy((void *) &(value[rd1]), (const void *) (buffer), rd2);
}
else
{
total = std::min((writer_less ? amount : writer - (reader + 1)), amount);
if (total == 0)
return 0;
// fprintf(stderr, "%p> p full read: %d/%d [r=%d/w=%d]\n", this, total, size, reader, writer);
/* we are talking about buffers here, man! */
memcpy((void *) value, (const void *) &(buffer[reader]), total);
}
do
{
unsigned int new_reader = (((cache.reader.complete * _block) + cache.reader.partial) + total) % size;
/* jump the reader forward */
Buffer_pointer index((unsigned int)floor((double)new_reader / (double)_block),
(unsigned short)(new_reader % _block));
if (update(cache.reader, index))
{
// fprintf(stderr, "%p> p read end: %d [block=%d]\n", this, new_reader, _block);
break;
}
}
while (true);
return total;
}
/********** IO FUNCTIONS **********/
/* returns the number of items written to from buffer to stream */
unsigned int Ringbuffer_traits::traits_put(const char * buffer, std::ostream &fd, unsigned int amount)
{
/* avoid using different values */
Buffer_table cache = _pointers;
const unsigned int reader = cache.reader.complete;
const unsigned int writer = cache.writer.complete;
const bool writer_less = writer < reader;
unsigned int total = 0;
/* should we go around the buffer for reading? */
if (writer_less && (reader + amount >= _size))
{
total = std::min(_size - (reader - writer + 1), amount);
if (total == 0)
return 0;
unsigned int rd1 = _size - reader;
unsigned int rd2 = total - rd1;
// fprintf(stderr, "%p> partial read: (%d/%d) %d/%d [%d/%d]\n", this, rd1, rd2, total, _size, reader, writer);
/* two partial consumes (one at the end, another at the beginning) */
fd.write((const char *) &(buffer[reader]), _block * rd1);
fd.write((const char *) (buffer), _block * rd2);
}
else
{
total = std::min((!writer_less ? writer - (reader + 1) : amount), amount);
if (total == 0)
return 0;
// fprintf(stderr, "%p> full read: %d/%d [%d/%d]\n", this, total, _size, reader, writer);
/* we are talking about buffers here, man! */
fd.write((const char *) &(buffer[reader]), _block * total);
}
do
{
/* jump the reader forward */
Buffer_pointer index(cache.reader);
index.complete = (index.complete + total) % _size;
if (update(cache.reader, index))
break;
}
while (true);
return total;
}
/* returns number of items read from stream to buffer */
unsigned int Ringbuffer_traits::traits_get(char * buffer, std::istream &fd, unsigned int amount)
{
/* avoid using different values */
Buffer_table cache = _pointers;
const unsigned int reader = cache.reader.complete;
const unsigned int writer = cache.writer.complete;
const unsigned int dest = writer - 1;
const bool reader_less = reader < writer;
unsigned int real_amount = 0;
/* should we go around the buffer for writing? */
if (reader_less && ((writer + amount) > _size))
{
/* Documentation of the formula used in the 'if' below.
*
* [0|1|2|3|4|5|6|7] => size=8
* | |
* reader |
* writer
*
* => writer has places [5,6,7,0,1] to write (5 places).
*
* => 8 - (4-2+1) = 8 - (2+1) = 8 - 3 = 5
*
* > writer goes 1 up, amount goes 1 down.
* > reader goes 1 up, amount goes 1 up.
* > size goes 1 down, amount goes 1 down.
*
*/
if ((_size - (writer - reader + 1)) <= amount)
return false;
unsigned int wr1 = _size - writer + 1; /* writer is already 1 position after */
unsigned int wr2 = amount - wr1;
// fprintf(stderr, "%p> partial write: (%d/%d) %d/%d [%d/%d]\n", this, wr1, wr2, amount, _size, reader, writer);
unsigned int char_amount = 0;
/* one partial write on the buffer (at the end) */
fd.read((char *) &(buffer[dest]), _block * wr1);
char_amount += fd.gcount();
if (fd.gcount() == (int)(_block * wr1))
{
/* another partial write on the buffer (at the beginning) */
fd.read((char *) (buffer), _block * wr2);
char_amount += fd.gcount();
}
real_amount = char_amount / _block;
}
else
{
if (!reader_less && ((reader - writer) <= amount))
return false;
// fprintf(stderr, "%p> full write: %d/%d [%d/%d]\n", this, amount, _size, reader, writer);
/* we are talking about buffers here, man! */
fd.read((char *) &(buffer[dest]), _block * amount);
real_amount = fd.gcount() / _block;
}
_pointers.writer.complete = ((dest + real_amount) % _size) + 1;
_pointers.writer.partial = 1;
return real_amount;
}

View File

@ -0,0 +1,183 @@
#!/bin/sh
cut_defines ()
{
cut -b9- | cut -f1 | cut -d' ' -f1
}
list_commands ()
{
egrep -h 'define.+CM_' "$@" | cut_defines
}
list_events ()
{
# list and remove deprecations
egrep -h 'define.+EV_' "$@" | cut_defines | \
grep -v 'EV_CALL_PROGRESS\|EV_FAX_MESSAGE_CONFIRMATION'
}
make_enumeration_one_by_one ()
{
while read line
do
local size=$[50 - $(expr length "${line}")]
echo -n " K_${line}"
for ((i=0;i<size;i++))
do
echo -n " "
done
echo "= ${line},"
done
}
make_enumeration ()
{
local name="$1"; shift
local func="$1"; shift
echo " typedef enum"
echo " {"
"${func}" "$@" | make_enumeration_one_by_one
echo " }"
echo " ${name};"
}
make_switch_case_one_by_one ()
{
while read line
do
local size=$[50 - $(expr length "${line}")]
echo -n " case K_${line}:"
for ((i=0;i<size;i++))
do
echo -n " "
done
echo "return \"${line}\";"
done
}
make_switch_case ()
{
local type="$1"; shift
local name="$1"; shift
local func="$1"; shift
echo "std::string VerboseTraits::${name}Name(const ${type} value)"
echo "{"
echo " switch(value)"
echo " {"
"${func}" "$@" | make_switch_case_one_by_one
echo " }"
echo " return STG(FMT(\"${name}=%d\") % ((int)value));"
echo "}"
}
make_license ()
{
echo '/*'
echo ' KHOMP generic endpoint/channel library.'
echo ' Copyright (C) 2007-2010 Khomp Ind. & Com.'
echo ''
echo ' The contents of this file are subject to the Mozilla Public License Version 1.1'
echo ' (the "License"); you may not use this file except in compliance with the'
echo ' License. You may obtain a copy of the License at http://www.mozilla.org/MPL/'
echo ''
echo ' Software distributed under the License is distributed on an "AS IS" basis,'
echo ' WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for'
echo ' the specific language governing rights and limitations under the License.'
echo ''
echo ' Alternatively, the contents of this file may be used under the terms of the'
echo ' "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which'
echo ' case the provisions of "LGPL License" are applicable instead of those above.'
echo ''
echo ' If you wish to allow use of your version of this file only under the terms of'
echo ' the LGPL License and not to allow others to use your version of this file under'
echo ' the MPL, indicate your decision by deleting the provisions above and replace them'
echo ' with the notice and other provisions required by the LGPL License. If you do not'
echo ' delete the provisions above, a recipient may use your version of this file under'
echo ' either the MPL or the LGPL License.'
echo ''
echo ' The LGPL header follows below:'
echo ''
echo ' This library is free software; you can redistribute it and/or'
echo ' modify it under the terms of the GNU Lesser General Public'
echo ' License as published by the Free Software Foundation; either'
echo ' version 2.1 of the License, or (at your option) any later version.'
echo ''
echo ' This library is distributed in the hope that it will be useful,'
echo ' but WITHOUT ANY WARRANTY; without even the implied warranty of'
echo ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU'
echo ' Lesser General Public License for more details.'
echo ''
echo ' You should have received a copy of the GNU Lesser General Public License'
echo ' along with this library; if not, write to the Free Software Foundation, Inc.,'
echo ' 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA'
echo ''
echo '*/'
echo "/* ****************************************************************************** */"
echo "/* ******************* AUTO GENERATED FILE - DO NOT EDIT! *********************** */"
echo "/* ****************************************************************************** */"
echo
}
make_header ()
{
make_license
echo "#ifndef _VERBOSE_TRAITS_H_"
echo "#define _VERBOSE_TRAITS_H_"
echo
echo "#include <string>"
echo
echo "#include <format.hpp>"
echo
echo "#include <k3l.h>"
echo
echo "struct VerboseTraits"
echo "{"
make_enumeration "Command" list_commands "$@" || return 1
echo
make_enumeration "Event" list_events "$@" || return 1
echo
echo " static std::string eventName(const Event);"
echo " static std::string commandName(const Command);"
echo "};"
echo
echo "#endif /* _VERBOSE_TRAITS_H_ */"
}
make_source ()
{
make_license
echo "#include <verbose_traits.hpp>"
echo
make_switch_case "Event" "event" list_events "$@" || return 1
echo
make_switch_case "Command" "command" list_commands "$@" || return 1
}
make_run ()
{
local destdir="$1"; shift
if [ ! -d "${destdir}" ]
then
echo "ERROR: First argument is not a directory!"
return 1
fi
make_header "$@" > "${destdir}/verbose_traits.hpp"
make_source "$@" > "${destdir}/verbose_traits.cpp"
}
make_run "$@"

View File

@ -1,505 +0,0 @@
/*
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2009 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
*/
#include <string>
#include <sstream>
#include <map>
#include <k3l.h>
// k3lApiMajorVersion
#ifndef CM_PING
# include <k3lVersion.h>
# include <KTools.h>
#endif
#include <types.hpp>
#include <k3lapi.hpp>
#include <format.hpp>
#ifndef _VERBOSE_HPP_
#define _VERBOSE_HPP_
struct Verbose
{
typedef enum
{
K_CM_SEIZE = CM_SEIZE,
K_CM_SYNC_SEIZE = CM_SYNC_SEIZE,
#if K3L_AT_LEAST(1,6,0)
K_CM_SIP_REGISTER = CM_SIP_REGISTER,
#endif
K_CM_DIAL_DTMF = CM_DIAL_DTMF,
K_CM_DISCONNECT = CM_DISCONNECT,
K_CM_CONNECT = CM_CONNECT,
K_CM_PRE_CONNECT = CM_PRE_CONNECT,
K_CM_CAS_CHANGE_LINE_STT = CM_CAS_CHANGE_LINE_STT,
K_CM_CAS_SEND_MFC = CM_CAS_SEND_MFC,
K_CM_SET_FORWARD_CHANNEL = CM_SET_FORWARD_CHANNEL,
K_CM_CAS_SET_MFC_DETECT_MODE = CM_CAS_SET_MFC_DETECT_MODE,
K_CM_DROP_COLLECT_CALL = CM_DROP_COLLECT_CALL,
K_CM_MAKE_CALL = CM_MAKE_CALL,
K_CM_RINGBACK = CM_RINGBACK,
K_CM_USER_INFORMATION = CM_USER_INFORMATION,
#if !K3L_AT_LEAST(2,2,0)
K_CM_VOIP_SEIZE = CM_VOIP_SEIZE, //deprecated
#endif
K_CM_LOCK_INCOMING = CM_LOCK_INCOMING,
K_CM_UNLOCK_INCOMING = CM_UNLOCK_INCOMING,
K_CM_LOCK_OUTGOING = CM_LOCK_OUTGOING,
K_CM_UNLOCK_OUTGOING = CM_UNLOCK_OUTGOING,
K_CM_START_SEND_FAIL = CM_START_SEND_FAIL,
K_CM_STOP_SEND_FAIL = CM_STOP_SEND_FAIL,
K_CM_END_OF_NUMBER = CM_END_OF_NUMBER,
#if K3L_AT_LEAST(1,6,0)
K_CM_SS_TRANSFER = CM_SS_TRANSFER,
K_CM_GET_SMS = CM_GET_SMS,
K_CM_PREPARE_SMS = CM_PREPARE_SMS,
K_CM_SEND_SMS = CM_SEND_SMS,
#endif
#if K3L_HAS_MPTY_SUPPORT
K_CM_HOLD_SWITCH = CM_HOLD_SWITCH,
K_CM_MPTY_CONF = CM_MPTY_CONF,
K_CM_MPTY_SPLIT = CM_MPTY_SPLIT,
#endif
K_CM_ENABLE_DTMF_SUPPRESSION = CM_ENABLE_DTMF_SUPPRESSION,
K_CM_DISABLE_DTMF_SUPPRESSION = CM_DISABLE_DTMF_SUPPRESSION,
K_CM_ENABLE_AUDIO_EVENTS = CM_ENABLE_AUDIO_EVENTS,
K_CM_DISABLE_AUDIO_EVENTS = CM_DISABLE_AUDIO_EVENTS,
K_CM_ENABLE_CALL_PROGRESS = CM_ENABLE_CALL_PROGRESS,
K_CM_DISABLE_CALL_PROGRESS = CM_DISABLE_CALL_PROGRESS,
K_CM_FLASH = CM_FLASH,
K_CM_ENABLE_PULSE_DETECTION = CM_ENABLE_PULSE_DETECTION,
K_CM_DISABLE_PULSE_DETECTION = CM_DISABLE_PULSE_DETECTION,
K_CM_ENABLE_ECHO_CANCELLER = CM_ENABLE_ECHO_CANCELLER,
K_CM_DISABLE_ECHO_CANCELLER = CM_DISABLE_ECHO_CANCELLER,
K_CM_ENABLE_AGC = CM_ENABLE_AGC,
K_CM_DISABLE_AGC = CM_DISABLE_AGC,
K_CM_ENABLE_HIGH_IMP_EVENTS = CM_ENABLE_HIGH_IMP_EVENTS,
K_CM_DISABLE_HIGH_IMP_EVENTS = CM_DISABLE_HIGH_IMP_EVENTS,
#if K3L_AT_LEAST(1,6,0)
K_CM_ENABLE_CALL_ANSWER_INFO = CM_ENABLE_CALL_ANSWER_INFO,
K_CM_DISABLE_CALL_ANSWER_INFO = CM_DISABLE_CALL_ANSWER_INFO,
#endif
K_CM_RESET_LINK = CM_RESET_LINK,
#if K3L_AT_LEAST(1,6,0)
K_CM_CLEAR_LINK_ERROR_COUNTER = CM_CLEAR_LINK_ERROR_COUNTER,
#endif
K_CM_SEND_DTMF = CM_SEND_DTMF,
K_CM_STOP_AUDIO = CM_STOP_AUDIO,
K_CM_HARD_RESET = CM_HARD_RESET,
K_CM_SEND_TO_CTBUS = CM_SEND_TO_CTBUS,
K_CM_RECV_FROM_CTBUS = CM_RECV_FROM_CTBUS,
K_CM_SETUP_H100 = CM_SETUP_H100,
K_CM_MIXER = CM_MIXER,
K_CM_CLEAR_MIXER = CM_CLEAR_MIXER,
K_CM_PLAY_FROM_FILE = CM_PLAY_FROM_FILE,
K_CM_RECORD_TO_FILE = CM_RECORD_TO_FILE,
K_CM_PLAY_FROM_STREAM = CM_PLAY_FROM_STREAM,
K_CM_INTERNAL_PLAY = CM_INTERNAL_PLAY,
K_CM_STOP_PLAY = CM_STOP_PLAY,
K_CM_STOP_RECORD = CM_STOP_RECORD,
K_CM_PAUSE_PLAY = CM_PAUSE_PLAY,
K_CM_PAUSE_RECORD = CM_PAUSE_RECORD,
K_CM_RESUME_PLAY = CM_RESUME_PLAY,
K_CM_RESUME_RECORD = CM_RESUME_RECORD,
K_CM_INCREASE_VOLUME = CM_INCREASE_VOLUME,
K_CM_DECREASE_VOLUME = CM_DECREASE_VOLUME,
K_CM_LISTEN = CM_LISTEN,
K_CM_STOP_LISTEN = CM_STOP_LISTEN,
K_CM_PREPARE_FOR_LISTEN = CM_PREPARE_FOR_LISTEN,
K_CM_PLAY_SOUND_CARD = CM_PLAY_SOUND_CARD,
K_CM_STOP_SOUND_CARD = CM_STOP_SOUND_CARD,
K_CM_MIXER_CTBUS = CM_MIXER_CTBUS,
K_CM_PLAY_FROM_STREAM_EX = CM_PLAY_FROM_STREAM_EX,
K_CM_INTERNAL_PLAY_EX = CM_INTERNAL_PLAY_EX,
K_CM_ENABLE_PLAYER_AGC = CM_ENABLE_PLAYER_AGC,
K_CM_DISABLE_PLAYER_AGC = CM_DISABLE_PLAYER_AGC,
K_CM_START_STREAM_BUFFER = CM_START_STREAM_BUFFER,
K_CM_ADD_STREAM_BUFFER = CM_ADD_STREAM_BUFFER,
K_CM_STOP_STREAM_BUFFER = CM_STOP_STREAM_BUFFER,
K_CM_SEND_BEEP = CM_SEND_BEEP,
K_CM_SEND_BEEP_CONF = CM_SEND_BEEP_CONF,
K_CM_ADD_TO_CONF = CM_ADD_TO_CONF,
K_CM_REMOVE_FROM_CONF = CM_REMOVE_FROM_CONF,
K_CM_RECORD_TO_FILE_EX = CM_RECORD_TO_FILE_EX,
K_CM_SET_VOLUME = CM_SET_VOLUME,
K_CM_SET_LINE_CONDITION = CM_SET_LINE_CONDITION,
K_CM_SEND_LINE_CONDITION = CM_SEND_LINE_CONDITION,
K_CM_SET_CALLER_CATEGORY = CM_SET_CALLER_CATEGORY,
K_CM_DIAL_MFC = CM_DIAL_MFC,
#if !K3L_AT_LEAST(2,0,0)
K_CM_VOIP_START_DEBUG = CM_VOIP_START_DEBUG,
K_CM_VOIP_STOP_DEBUG = CM_VOIP_STOP_DEBUG,
K_CM_VOIP_DUMP_STAT = CM_VOIP_DUMP_STAT,
K_CM_ISDN_DEBUG = CM_ISDN_DEBUG,
K_CM_PING = CM_PING,
K_CM_LOG_REQUEST = CM_LOG_REQUEST,
K_CM_LOG_CREATE_DISPATCHER = CM_LOG_CREATE_DISPATCHER,
K_CM_LOG_DESTROY_DISPATCHER = CM_LOG_DESTROY_DISPATCHER,
#endif
#if K3L_AT_LEAST(1,6,0)
K_CM_START_CADENCE = CM_START_CADENCE,
K_CM_STOP_CADENCE = CM_STOP_CADENCE,
K_CM_CHECK_NEW_SMS = CM_CHECK_NEW_SMS,
K_CM_SEND_TO_MODEM = CM_SEND_TO_MODEM,
#endif
#if K3L_AT_LEAST(2,1,0)
K_CM_START_FAX_TX = CM_START_FAX_TX,
K_CM_STOP_FAX_TX = CM_STOP_FAX_TX,
K_CM_ADD_FAX_FILE = CM_ADD_FAX_FILE,
K_CM_ADD_FAX_PAGE_BREAK = CM_ADD_FAX_PAGE_BREAK,
K_CM_START_FAX_RX = CM_START_FAX_RX,
K_CM_STOP_FAX_RX = CM_STOP_FAX_RX,
K_CM_SIM_CARD_SELECT = CM_SIM_CARD_SELECT,
#endif
#if K3L_AT_LEAST(2,1,0)
K_CM_NOTIFY_WATCHDOG = CM_NOTIFY_WATCHDOG,
K_CM_STOP_WATCHDOG = CM_STOP_WATCHDOG,
K_CM_WATCHDOG_COUNT = CM_WATCHDOG_COUNT,
K_CM_START_WATCHDOG = CM_START_WATCHDOG,
#endif
}
kcommand;
typedef enum
{
K_EV_CHANNEL_FREE = EV_CHANNEL_FREE,
K_EV_CONNECT = EV_CONNECT,
K_EV_DISCONNECT = EV_DISCONNECT,
K_EV_CALL_SUCCESS = EV_CALL_SUCCESS,
K_EV_CALL_FAIL = EV_CALL_FAIL,
K_EV_NO_ANSWER = EV_NO_ANSWER,
K_EV_BILLING_PULSE = EV_BILLING_PULSE,
K_EV_SEIZE_SUCCESS = EV_SEIZE_SUCCESS,
K_EV_SEIZE_FAIL = EV_SEIZE_FAIL,
K_EV_SEIZURE_START = EV_SEIZURE_START,
K_EV_CAS_LINE_STT_CHANGED = EV_CAS_LINE_STT_CHANGED,
K_EV_CAS_MFC_RECV = EV_CAS_MFC_RECV,
K_EV_NEW_CALL = EV_NEW_CALL,
K_EV_USER_INFORMATION = EV_USER_INFORMATION,
K_EV_DIALED_DIGIT = EV_DIALED_DIGIT,
#if K3L_AT_LEAST(1,6,0)
K_EV_SIP_REGISTER_INFO = EV_SIP_REGISTER_INFO,
K_EV_RING_DETECTED = EV_RING_DETECTED,
#endif
K_EV_CALL_HOLD_START = EV_CALL_HOLD_START,
K_EV_CALL_HOLD_STOP = EV_CALL_HOLD_STOP,
#if K3L_AT_LEAST(1,6,0)
K_EV_SS_TRANSFER_FAIL = EV_SS_TRANSFER_FAIL,
K_EV_FLASH = EV_FLASH,
#endif
K_EV_DTMF_DETECTED = EV_DTMF_DETECTED,
K_EV_DTMF_SEND_FINISH = EV_DTMF_SEND_FINISH,
K_EV_AUDIO_STATUS = EV_AUDIO_STATUS,
K_EV_CADENCE_RECOGNIZED = EV_CADENCE_RECOGNIZED,
K_EV_END_OF_STREAM = EV_END_OF_STREAM,
K_EV_PULSE_DETECTED = EV_PULSE_DETECTED,
K_EV_POLARITY_REVERSAL = EV_POLARITY_REVERSAL,
#if K3L_AT_LEAST(1,6,0)
K_EV_ISDN_PROGRESS_INDICATOR = EV_ISDN_PROGRESS_INDICATOR,
K_EV_CALL_ANSWER_INFO = EV_CALL_ANSWER_INFO,
K_EV_COLLECT_CALL = EV_COLLECT_CALL,
K_EV_SIP_DTMF_DETECTED = EV_SIP_DTMF_DETECTED,
K_EV_RECV_FROM_MODEM = EV_RECV_FROM_MODEM,
K_EV_NEW_SMS = EV_NEW_SMS,
K_EV_SMS_INFO = EV_SMS_INFO,
K_EV_SMS_DATA = EV_SMS_DATA,
K_EV_SMS_SEND_RESULT = EV_SMS_SEND_RESULT,
#endif
#if K3L_HAS_MPTY_SUPPORT
K_EV_CALL_MPTY_START = EV_CALL_MPTY_START,
K_EV_CALL_MPTY_STOP = EV_CALL_MPTY_STOP,
K_EV_GSM_COMMAND_STATUS = EV_GSM_COMMAND_STATUS,
#endif
K_EV_CHANNEL_FAIL = EV_CHANNEL_FAIL,
K_EV_REFERENCE_FAIL = EV_REFERENCE_FAIL,
K_EV_INTERNAL_FAIL = EV_INTERNAL_FAIL,
K_EV_HARDWARE_FAIL = EV_HARDWARE_FAIL,
K_EV_LINK_STATUS = EV_LINK_STATUS,
#if K3L_AT_LEAST(1,6,0)
K_EV_PHYSICAL_LINK_UP = EV_PHYSICAL_LINK_UP,
K_EV_PHYSICAL_LINK_DOWN = EV_PHYSICAL_LINK_DOWN,
#endif
K_EV_CLIENT_RECONNECT = EV_CLIENT_RECONNECT,
K_EV_VOIP_SEIZURE = EV_VOIP_SEIZURE,
K_EV_SEIZURE = EV_SEIZURE,
#if K3L_AT_LEAST(2,1,0)
K_EV_FAX_CHANNEL_FREE = EV_FAX_CHANNEL_FREE,
K_EV_FAX_FILE_SENT = EV_FAX_FILE_SENT,
K_EV_FAX_FILE_FAIL = EV_FAX_FILE_FAIL,
K_EV_FAX_MESSAGE_CONFIRMATION = EV_FAX_MESSAGE_CONFIRMATION,
K_EV_FAX_TX_TIMEOUT = EV_FAX_TX_TIMEOUT,
K_EV_FAX_PAGE_CONFIRMATION = EV_FAX_PAGE_CONFIRMATION,
K_EV_FAX_REMOTE_INFO = EV_FAX_REMOTE_INFO,
#endif
#if K3L_AT_LEAST(2,1,0)
K_EV_WATCHDOG_COUNT = EV_WATCHDOG_COUNT,
#endif
#if !K3L_AT_LEAST(2,0,0)
K_EV_PONG = EV_PONG,
#endif
}
kevent;
typedef enum
{
R2_COUNTRY_ARG = 1,
R2_COUNTRY_BRA = 2,
R2_COUNTRY_CHI = 3,
R2_COUNTRY_MEX = 4,
R2_COUNTRY_URY = 5,
R2_COUNTRY_VEN = 6
}
R2CountryType;
typedef enum
{
HUMAN,
EXACT
}
Presentation;
/* dynamic (object) stuff */
Verbose(K3LAPI & api): _api(api) {};
#if K3L_AT_LEAST(2,0,0)
std::string event(int32, K3L_EVENT*, R2CountryType r2_country = R2_COUNTRY_BRA,
Presentation fmt = HUMAN);
#else
std::string event(int32, K3L_EVENT*, Presentation fmt = HUMAN);
#endif
std::string channelStatus(int32, int32, int32, Presentation fmt = HUMAN);
/* end of dynamic (object) stuff */
protected:
K3LAPI & _api;
/* used internally */
struct internal_not_found {};
public:
/* static (class) stuff */
static std::string echoLocation(KEchoLocation, Presentation fmt = HUMAN);
static std::string echoCancellerConfig(KEchoCancellerConfig, Presentation fmt = HUMAN);
#if K3L_AT_LEAST(2,0,0)
static std::string event(KSignaling, int32, K3L_EVENT*, R2CountryType = R2_COUNTRY_BRA,
Presentation fmt = HUMAN);
#else
static std::string event(KSignaling, int32, K3L_EVENT*, Presentation fmt = HUMAN);
#endif
#if K3L_AT_LEAST(2,0,0)
static std::string command(int32, K3L_COMMAND*, R2CountryType = R2_COUNTRY_BRA,
Presentation fmt = HUMAN);
static std::string command(int32, int32, int32, const char *, R2CountryType = R2_COUNTRY_BRA,
Presentation fmt = HUMAN);
#else
static std::string command(int32, K3L_COMMAND*, Presentation fmt = HUMAN);
static std::string command(int32, int32, int32, const char *, Presentation fmt = HUMAN);
#endif
static std::string deviceName(KDeviceType, int32, Presentation fmt = HUMAN);
static std::string deviceType(KDeviceType, Presentation fmt = HUMAN);
static std::string deviceModel(KDeviceType, int32, Presentation fmt = HUMAN);
static std::string channelFeatures(int32, Presentation fmt = HUMAN);
static std::string signaling(KSignaling, Presentation fmt = HUMAN);
static std::string systemObject(KSystemObject, Presentation fmt = HUMAN);
static std::string mixerTone(KMixerTone, Presentation fmt = HUMAN);
static std::string mixerSource(KMixerSource, Presentation fmt = HUMAN);
static std::string seizeFail(KSeizeFail, Presentation fmt = HUMAN);
#if K3L_AT_LEAST(2,0,0)
static std::string callFail(KSignaling, R2CountryType, int32, Presentation fmt = HUMAN);
#else
static std::string callFail(KSignaling, int32, Presentation fmt = HUMAN);
#endif
static std::string channelFail(KSignaling, int32, Presentation fmt = HUMAN);
static std::string internalFail(KInternalFail, Presentation fmt = HUMAN);
static std::string linkErrorCounter(KLinkErrorCounter, Presentation fmt = HUMAN);
static std::string linkStatus(KSignaling, int32, Presentation fmt = HUMAN);
static std::string channelStatus(KSignaling, int32, Presentation fmt = HUMAN);
static std::string callStatus(KCallStatus, Presentation fmt = HUMAN);
static std::string status(KLibraryStatus, Presentation fmt = HUMAN);
#if K3L_AT_LEAST(2,0,0)
static std::string signGroupB(KSignGroupB, R2CountryType contry = R2_COUNTRY_BRA,
Presentation fmt = HUMAN);
#else
static std::string signGroupB(KSignGroupB, Presentation fmt = HUMAN);
#endif
#if K3L_AT_LEAST(2,0,0)
static std::string signGroupII(KSignGroupII, R2CountryType contry = R2_COUNTRY_BRA,
Presentation fmt = HUMAN);
#else
static std::string signGroupII(KSignGroupII, Presentation fmt = HUMAN);
#endif
static std::string h100configIndex(KH100ConfigIndex, Presentation fmt = HUMAN);
static std::string eventName(int32);
static std::string commandName(int32);
#if K3L_AT_LEAST(1,5,0)
static std::string sipFailures(KSIP_Failures, Presentation fmt = HUMAN);
#endif
#if K3L_AT_LEAST(1,5,1)
static std::string isdnCause(KQ931Cause, Presentation fmt = HUMAN);
#endif
#if K3L_AT_LEAST(1,5,2)
static std::string isdnDebug(int32, Presentation fmt = HUMAN);
#endif
#if K3L_AT_LEAST(1,6,0)
static std::string callStartInfo(KCallStartInfo, Presentation fmt = HUMAN);
static std::string gsmCallCause(KGsmCallCause, Presentation fmt = HUMAN);
static std::string gsmMobileCause(KGsmMobileCause, Presentation fmt = HUMAN);
static std::string gsmSmsCause(KGsmSmsCause, Presentation fmt = HUMAN);
static std::string q931ProgressIndication(KQ931ProgressIndication,
Presentation fmt = HUMAN);
#endif
#if K3L_AT_LEAST(2,1,0)
static std::string faxResult(KFaxResult code, Presentation fmt = HUMAN);
static std::string faxFileErrorCause(KFaxFileErrorCause code, Presentation fmt = HUMAN);
#endif
/* end of static (class) stuff */
private:
static std::string internal_deviceType(KDeviceType);
static std::string internal_deviceModel(KDeviceType, int32);
#if K3L_AT_LEAST(1,5,0)
static std::string internal_sipFailures(KSIP_Failures, Presentation fmt = HUMAN);
#endif
#if K3L_AT_LEAST(1,5,1)
static std::string internal_isdnCause(KQ931Cause, Presentation fmt = HUMAN);
#endif
#if K3L_AT_LEAST(2,0,0)
static std::string internal_signGroupB(KSignGroupB, R2CountryType contry, Presentation fmt = HUMAN);
static std::string internal_signGroupII(KSignGroupII, R2CountryType contry, Presentation fmt = HUMAN);
#else
static std::string internal_signGroupB(KSignGroupB, Presentation fmt = HUMAN);
static std::string internal_signGroupII(KSignGroupII, Presentation fmt = HUMAN);
#endif
#if K3L_AT_LEAST(1,6,0)
static std::string internal_gsmCallCause(KGsmCallCause, Presentation fmt = HUMAN);
static std::string internal_gsmMobileCause(KGsmMobileCause, Presentation fmt = HUMAN);
static std::string internal_gsmSmsCause(KGsmSmsCause, Presentation fmt = HUMAN);
static std::string internal_q931ProgressIndication(KQ931ProgressIndication, Presentation fmt = HUMAN);
#endif
private:
enum Type
{
DEVICE,
CHANNEL,
PLAYER,
MIXER,
LINK,
NONE
};
struct Target
{
Target(Type _type)
: type(_type), device(-1), object(-1)
{};
Target(Type _type, int32 _device)
: type(_type), device(_device), object(-1)
{};
Target(Type _type, int32 _device, int32 _object)
: type(_type), device(_device), object(_object)
{};
Type type;
int32 device;
int32 object;
};
static void generate(std::string &, std::string &, Target, std::string &);
static std::string show(std::string &, std::string, Target, std::string &);
static std::string show(std::string &, std::string, Target);
template < typename ReturnType >
static ReturnType presentation(Presentation fmt, ReturnType str_exact, ReturnType str_human)
{
switch (fmt)
{
case HUMAN: return str_human;
case EXACT: return str_exact;
};
return str_exact;
}
};
#endif /* _VERBOSE_HPP_ */

View File

@ -37,17 +37,22 @@
</li><li><b>context-fxs</b>: Contexto de entrada para placas FXS (o padrão é "khomp-DD-CC", onde "DD" será substituído, no momento da ligação, pelo número do dispositivo, "CC" pelo número do canal, e "SSSS" pelo número serial do dispositivo);
</li><li><b>context-gsm-call</b> (ou "context-gsm"): Contexto de entrada para ligações GSM (o padrão é "khomp-DD-CC", onde "DD" será substituído no momento da ligação pelo número do dispositivo, "CC" pelo número do canal, e "SSSS" pelo número serial do dispositivo);
</li><li><b>context-gsm-sms</b>: Contexto de entrada para SMSs (o padrão é "khomp-sms-DD-CC", onde "DD" será substituído pelo número de dispositivo, "CC" pelo número do canal, e "SSSS" pelo número serial do dispositivo);
</li><li><b>context-pr</b>: Contexto de entrada para ligações em placas KPR (o padrão é "khomp-DD-CC", onde "DD" será substituído, no momento da ligação, pelo número do dispositivo, "CC" pelo número do canal);
</li><li><b>context-pr</b>: Contexto de entrada para ligações em placas KPR (o padrão é "khomp-DD-CC", onde "DD" será substituído, no momento da ligação, pelo número do dispositivo, "CC" pelo número do canal);
</li><li><b>delay-ringback-co</b>: Define o tempo de <i>delay</i> para ativar a geração de tom de controle de chamada (<i>ringback</i>) pelo Endpoint da Khomp quando há uma indicação de <i>ringback</i>, e não há áudio sendo enviado por quem indicou a situação de controle da chamada;
</li><li><b>delay-ringback-pbx</b>: Define o tempo de <i>delay</i> para ativar a geração de controle de chamada (<i>ringback</i>) pelo Endpoint da Khomp quando há uma indicação de <i>ringback</i>, e o áudio de controle enviado não possui nenhum tom (ou seja, está em silêncio);
</li><li><b>disconnect-delay</b>: Define o tempo em milissegundos para realizar o processamento de um evento de desconexão, para ignorar situações onde outros equipamentos realizam o duplo atendimento para derrubar chamadas a cobrar;
</li><li><b>drop-collect-call</b>: Ativa ("yes") ou desativa ("no") o derrubamento de chamadas à cobrar. Caso ativo, todas as chamadas à cobrar serão derrubadas não importando o que foi ajustado na variável KDropCollectCall (o valor padrão é "no");
</li><li><b>echo-canceller</b>: Ativa ("yes") ou desativa ("no") o cancelamento de eco automático pelo Endpoint;
</li><li><b>flash-to-digits</b>: Define os dígitos para serem enviados quando o FLASH é detectado na FXS;
</li><li><b>fxo-send-pre-audio</b>: Quando ativada ("yes") libera canal de áudio sainte antes da conexão da chamada em placas KFXO (o valor padrão é "yes");
</li><li><b>fxs-digit-timeout</b>: Define o <i>timeout</i>, em segundos, entre dígitos na FXS;
</li><li><b>fxs-global-orig</b>: Número inicial para numeração seqüencial de ramais das placas <b>KFXS</b> que não estiverem listadas na seção <b>&lt;fxs-branches&gt;</b> (a numeração segue ordem crescente por número da placa e número do canal físico) (o padrão é "0");
</li><li><b>fxs-co-dialtone</b>: Seqüências de números, separados por vírgula, que disparam um tom contínuo (de central pública) em ramais FXS (ex: "0,99" faz com que, ao discar "0" ou "99", o usuário receba o tom de linha contínuo) (o padrão é vazio);
</li><li><b>fxs-bina</b>: Quando ativada ("yes"), ligações para ramais FXS enviarão os dígitos correspondentes ao telefone de origem em sinalização BINA DTMF (o valor padrão é "no");
</li><li><b>ignore-letter-dtmfs</b>: Define se o canal deve ignorar DTMFs incomuns detectados pela placa (A, B, C e D). Entretanto, se você necessita passar esses dígitos pela placa, você deve ajustar esta opção para "no" (o valor padrão é "yes");
</li><li><b>input-volume</b>: Define o volume de entrada das ligações, varia de -10 a +10&nbsp;;
</li><li><b>kommuter-activation</b>: Define se a ativação de dispositivos kommuter encontrados no sistema será feita de forma automática ("auto"), ou de forma manual ("manual") pelo usuário, através do comando "khomp kommuter on/off";
</li><li><b>kommuter-timeout</b>: Define o <i>timeout</i> (em segundos) com que os kommuters serão inicializados. Se chegarem a este <i>timeout</i> sem receberem notificação do channel, os dispositivos irão comutar para o estado "desligado". O valor mínimo é "0" , onde os links permanecerão sempre comutados no estado "ligado", e o valor máximo é "255";
</li><li><b>language</b>: Define idioma para ligações nas placas Khomp;
</li><li><b>log-to-console</b>: Define mensagens de log que devem ser impressas na console;
</li><li><b>log-to-disk</b>: Define mensagens de log que devem ser salvar em disco;
</li><li><b>out-of-band-dtmfs</b>: Ativa ("yes") ou desativa ("no") a supressão DTMF e o envio destes out-of-band;
@ -55,12 +60,9 @@
</li><li><b>pulse-forwarding</b>: Ativa ("yes") ou desativa ("no") a detecção de pulsos e a conversão dos mesmos em DTMFs;
</li><li><b>r2-preconnect-wait</b>: Define o tempo de espera do envio da sinalização de ringback, no protocolo R2/MFC, para iniciar o envio de áudio de silêncio. Apenas utilizado quando "r2-strict-behaviour" estiver ajustado para "no";
</li><li><b>r2-strict-behaviour</b>: Ativa ("yes") ou desativa ("no") o comportamento da sinalização R2/MFC conforme a norma define. O padrão é "no", e pode ser alterado para "yes" caso seja necessário receber/enviar dados precisos da sinalização do protocolo (condição de B, por exemplo);
</li><li><b>ringback-delay-co</b>: Define o tempo de <i>delay</i> para ativar a geração de tom de controle de chamada (<i>ringback</i>) pelo Endpoint da Khomp quando há uma indicação de <i>ringback</i>, e não há áudio sendo enviado por quem indicou a situação de controle da chamada;
</li><li><b>ringback-delay-pbx</b>: Define o tempo de <i>delay</i> para ativar a geração de controle de chamada (<i>ringback</i>) pelo Endpoint da Khomp quando há uma indicação de <i>ringback</i>, e o áudio de controle enviado não possui nenhum tom (ou seja, está em silêncio);
</li><li><b>suppression-delay</b>: Ativa ("yes") ou desativa ("no") o delay necessário para supressão DTMF. Se desativado ("no"), também desativa supressão de DTMFs;
</li><li><b>trace</b>: Define opções de depuração. Não deve ser utilizado em produção a não ser que estritamente necessário;
</li><li><b>user-transfer-digits</b>: Define uma seqüência de dígitos DTMF para iniciar a transferencia entre o FreeSWITCH&reg; e um outro PABX (utilizando sinalização de usuário, como QSig ou FXO FLASH);
</li><li><b>flash-to-digits</b>: Define os dígitos para serem enviados quando o FLASH é detectado na FXS;
</li></ul>
<p><br />
</p>
@ -117,15 +119,13 @@
<ul><li>context;
</li><li>input-volume;
</li><li>output-volume;
</li><li>accountcode;
</li><li>calleridnum;
</li><li>calleridname;
</li><li>mailbox;
</li><li>flash-to-digits.
</li></ul>
<p>Cada opção é separada uma da outra por um pipe "|" ou uma barra "/" e definidas após dois pontos ":", exemplo:
</p>
<pre> &lt;param name="200" value="language:en|context:master-branch" /&gt;
<pre> &lt;param name="200" value="input-volume:1|context:master-branch" /&gt;
</pre>
<p>Para maiores informações sobre a sintaxe e exemplos, favor consultar o arquivo de configuração.
</p><p><br />

View File

@ -18,7 +18,7 @@
<p>This step is carried out in a semi-automated way using the <b>khompwizard</b> program, a wizard that configures the basic parameters of the system boards. This wizard initializes the configuration files using information from the user when they are needed, initializing the standard settings to default values.
</p><p>Typically, this program runs automatically after installation of the system. However, you may need to run it manually if an update is being performed, or if new cards were added to the system after installing new drivers.
</p><p><br />
If you need to set advanced parameters of the board and/or signaling, the program <b>k3lconfig</b> allows you to access all the available settings for each installed card. For more information about this program, check the <b><a href="http://169.254.1.3/kdevwiki/wikidocs/index.php?title=K3lconfig_-_User%27s_Guide&amp;action=edit&amp;redlink=1" class="new" title="K3lconfig - User&#39;s Guide (página não existe)">k3lconfig User's Guide</a></b>. For solving synchronization issues, check the <a href="#_Troubleshooting" title="">Troubleshooting</a> section for manual configuration of the boards.
If you need to set advanced parameters of the board and/or signaling, the program <b>k3lconfig</b> allows you to access all the available settings for each installed card. For more information about this program, check the <b><a href="http://169.254.1.3/kdevwiki/wikidocs/index.php?title=K3lconfig_-_User%27s_Guide&amp;action=edit&amp;redlink=1" class="new" title="K3lconfig - User&#39;s Guide (página não existe)">k3lconfig User's Guide</a></b>. For solving synchronization issues, check the <a href="#Troubleshooting" title="">Troubleshooting</a> section for manual configuration of the boards.
<br />
</p>
<a name="Endpoint_Configuration" id="Endpoint_Configuration"></a><h2> <span class="mw-headline"> Endpoint Configuration </span></h2>
@ -39,16 +39,21 @@ If you need to set advanced parameters of the board and/or signaling, the progra
</li><li><b>context-gsm-call</b> (or <b>context-gsm</b>): Context of entry for GSM boards (the default is "khomp-CC-DD", where "DD" will be replaced at the time of connection by the device number, "CC" by channel number, and "SSSS" by the device serial number);
</li><li><b>context-gsm-sms</b>: Context for incoming SMSs (the default is "khomp-sms-CC-DD", where "DD" will be replaced by the number of device, "CC" by channel number and "SSSS" by the device's serial number);
</li><li><b>context-pr</b>: Context for incoming connections on boards KPR (default is "khomp-CC-DD", where "DD" will be replaced at the time of connection by the device number, "CC "by channel number);
</li><li><b>delay-ringback-co</b>: Sets the delay to enable the generation of call control tone (ringback) by the Endpoint Khomp when there is an ringback indication from signaling and there is no audio being sent by the channel which indicated the situation (local option);
</li><li><b>delay-ringback-pbx</b>: Sets the delay to enable the generation of call control tone (ringback) by the Endpoint Khomp when there is an ringback indication, and the audio has no tone (silence) (local option);
</li><li><b>disconnect-delay</b>: Sets the time in milliseconds to perform processing a disconnect event, to ignore situations where other equipment performing the double service to overthrow collect calls (local option);
</li><li><b>drop-collect-call</b>: Enables/Disables the action of dropping collect calls. If enabled, all collect calls will be dropped no matter what KDropCollectCall is set to (the default value is "no");
</li><li><b>echo-canceller</b> (former 'echocanceller): Active ("yes") or disables ("no") echo cancellation automatic Endpoint (local option);
</li><li><b>flash-to-digits</b>: Defines the digits to be sent when the FLASH is detected on FXS channels;
</li><li><b>fxo-send-pre-audio</b>: When enabled ("yes") releases audio channel before the outgoing call connection boards KFXO (the default value is "yes");
</li><li><b>fxs-digit-timeout</b>: Defines the timeout, in seconds, between digits of a FXS board's extension;
</li><li><b>fxs-global-orig</b>: Start number for sequencial branch numbering in FXS cards that are not listed in the <b>[fxs-branches]</b> section (the numbering follows ascending order from board number and physical channel number) (default is "0");
</li><li><b>fxs-co-dialtone</b>: Sequences of numbers, separated by commas, which fires a continuous tone (of central office) in FXS branches (eg: "0,99" means that, when you dial "0" or "99", the user will hear a continuous dial tone) (default is empty);
</li><li><b>fxs-bina</b>: When enabled ("yes"), calls to FXS lines will send digits corresponding to the source phone identification using BINA DTMF signaling (the default value is "no") (local option);
</li><li><b>ignore-letter-dtmfs</b>: Defines if the channel should ignore some uncommon DTMF digits detected by the board (A, B, C and D). However, if you need to pass those digits througth the board, you may need to set this option to 'no' (the default value is "yes");
</li><li><b>input-volume</b>: Sets the volume gain for incoming audio (entering the board), from -10 to +10 (local option);
</li><li><b>kommuter-activation</b>: Sets whether to activate devices kommuter found in the system will be done automatically ("auto") by the channel, or manually ("manual") by the user through the command "khomp kommuter on/off"
</li><li><b>kommuter-timeout</b>: Sets the timeout (in seconds) for initializing the kommuter devices. If this timeout is reached without receiving notification of the channel, the devices will switch back to "off" condition. The minimum value is "0", where the links will always remain switched "on", and the maximum is "255";
</li><li><b>language</b>: Set language to Khomp channel calls (local option);
</li><li><b>log-to-console</b>: Set log messages to be printed on the console;
</li><li><b>log-to-disk</b> (old "log"): Set log messages to be saved to disk;
</li><li><b>out-of-band-DTMF</b> (former <b>dtmfsuppression</b>): Activate ("yes") or disables ("no") the removal and DTMF sending these out-of-band (local option);
@ -56,12 +61,9 @@ If you need to set advanced parameters of the board and/or signaling, the progra
</li><li><b>pulse-forwarding</b> (former 'pulsedetection): Active ("yes") or disables ("no") for the detection of pulses and converting them into DTMF (local option);
</li><li><b>r2-preconnect-wait</b> (former 'r2preconnectwait): Sets the timeout sending the ringback signaling, protocol R2/MFC to start sending audio silence. Only used when "r2-strict-Behavior" is set to "no" (local option);
</li><li><b>r2-strict-Behaviour</b>: Enable ("yes") or disables ("no") the behavior of signaling R2/MFC as the standard sets. The default is "no", and can be changed to "yes" if needed to receive / send data precise signaling protocol (condition B, for example) (local option);
</li><li><b>ringback-delay-co</b>: Sets the delay to enable the generation of call control tone (ringback) by the Endpoint Khomp when there is an ringback indication from signaling and there is no audio being sent by the channel which indicated the situation (local option);
</li><li><b>ringback-delay-pbx</b>: Sets the delay to enable the generation of call control tone (ringback) by the Endpoint Khomp when there is an ringback indication, and the audio has no tone (silence) (local option);
</li><li><b>suppression-delay</b> (former <b>suppressiondelay</b>): Activate ("yes") or disables ("no") the delay necessary to suppress DTMF. If disabled ("no"), also disables suppression of DTMF (local option);
</li><li><b>trace</b>: Set debugging options. Should not be used in production unless absolutely necessary;
</li><li><b>user-transfer-digits</b>: Defines a sequence of DTMF digits to initiate the transfer between FreeSWITCH&reg; and another PBX (using user signaling, like QSig or FXO FLASH).
</li><li><b>flash-to-digits</b>: Defines the digits to be sent when the FLASH is detected on FXS channels..
</li><li><b>user-transfer-digits</b>: Defines a sequence of DTMF digits to initiate the transfer between FreeSWITCH&reg; and another PBX (using user signaling, like QSig or FXO FLASH);
</li></ul>
<p><br />
</p>
@ -121,15 +123,13 @@ For details, please refer to the configuration file for examples.
<ul><li>context;
</li><li>input-volume;
</li><li>output-volume;
</li><li>accountcode;
</li><li>calleridnum;
</li><li>calleridname;
</li><li>mailbox;
</li><li>flash-to-digits.
</li></ul>
<p>Each option is separated from each other by a pipe "|" or a slash "/" and defined after the colon ":". Example:
</p>
<pre>&lt;param name="200" value="language:en|context:master-branch" /&gt;
<pre>&lt;param name="200" value="input-volume:1|context:master-branch" /&gt;
</pre>
<p>For more information on the syntax and examples, please refer to the configuration file.
</p><p>For more information visit the configuration file '<b>khomp.conf.xml'</b>.

View File

@ -0,0 +1,26 @@
<include>
<!-- ########################### FXS Context ############################### -->
<context name="khomp-fxs-00">
<extension name="main">
<condition field="destination_number" expression="^(\d{4})$">
<action application="set" data="called_party_callgroup=1"/>
<action application="db" data="insert/last_dial/${called_party_callgroup}/${uuid}"/>
<action application="bridge" data="khomp/r$1"/>
</condition>
</extension>
<extension name="intercept">
<condition field="destination_number" expression="^55$">
<action application="answer"/>
<action application="set" data="intercept_unbridged_only=true"/>
<action application="intercept" data="${db(select/last_dial/1)}"/>
</condition>
</extension>
</context>
<!-- ####################################################################### -->
</include>

View File

@ -0,0 +1,43 @@
<include>
<!-- ########################### FXS Context ############################### -->
<context name="khomp-fxs-00">
<extension name="main">
<condition field="destination_number" expression="^(\d{4})$">
<action application="set" data="continue_on_fail=true"/>
<action application="set" data="dialed_extension=$1"/>
<action application="export" data="dialed_extension=$1"/>
<action application="bind_meta_app" data="1 b s execute_extension::attented_xfer XML khomp-features"/>
<action application="set" data="transfer_ringback=$${hold_music}"/>
<action application="set" data="call_timeout=10"/>
<action application="set" data="hangup_after_bridge=true"/>
<action application="bridge" data="khomp/r$1"/>
<action application="bridge" data="sofia/external/$1@169.1.1.1"/>
<action application="hangup"/>
</condition>
</extension>
</context>
<!-- ####################################################################### -->
<!-- ########################## Features ################################### -->
<context name="khomp-features">
<extension name="attented_xfer">
<condition field="destination_number" expression="^attented_xfer$">
<action application="set" data="continue_on_fail=true"/>
<action application="set" data="ringback=${us-ring}"/>
<action application="read" data="3 4 misc/8000/transfer1.wav attxfer_callthis 30000 #"/>
<action application="set" data="origination_cancel_key=#" />
<action application="att_xfer" data="khomp/r${attxfer_callthis}"/>
<action application="att_xfer" data="sofia/external/${attxfer_callthis}@169.1.1.1" />
</condition>
</extension>
</context>
<!-- ####################################################################### -->
</include>

View File

@ -268,7 +268,7 @@ struct Transfer
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);
_idx_xfer_dial = Board::board(_pvt->target().device)->_timers.add(Opt::_options._transferdigittimeout(), &userXferTimer, _pvt, TM_VAL_CALL);
}
else
{
@ -280,7 +280,7 @@ struct Transfer
}
}
catch (K3LAPI::invalid_device & err)
catch (K3LAPITraits::invalid_device & err)
{
LOG(ERROR, PVT_FMT(_pvt->target(), "Unable to get device: %d!") % err.device);
}
@ -506,7 +506,7 @@ struct Transfer<T, false>
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);
_idx_xfer_dial = Board::board(_pvt->target().device)->_timers.add(Opt::_options._transferdigittimeout(), &userXferTimer, _pvt, TM_VAL_CALL);
}
else
{
@ -530,7 +530,7 @@ struct Transfer<T, false>
}
}
catch (K3LAPI::invalid_device & err)
catch (K3LAPITraits::invalid_device & err)
{
LOG(ERROR, PVT_FMT(_pvt->target(), "Unable to get device: %d!") % err.device);
}
@ -735,6 +735,9 @@ struct Transfer<T, false>
};
/*************************** SMS **********************************************/
#define ESL_SMS_RECEIVED "khomp::sms_received"
#define ESL_SMS_SENT "khomp::sms_sent"
struct SMS : public Application
{
typedef std::list< switch_core_session_t *> OwnersList;
@ -889,6 +892,78 @@ struct SMS : public Application
bool _conf;
};
static struct _SMSEvent : public ESL
{
_SMSEvent() : ESL("khomp::sms")
{
if(_events)
{
_events->push_back(ESL_SMS_RECEIVED);
_events->push_back(ESL_SMS_SENT);
}
}
~_SMSEvent()
{
if(_events)
{
//Remove two from vector
_events->pop_back();
_events->pop_back();
}
}
bool operator()(Board::KhompPvt * pvt, ReceiveData & data)
{
switch_event_t *event = create(ESL_SMS_RECEIVED);
if(!event)
{
LOG(ERROR, "Cannot create SMS ESL");
return false;
}
add(event, pvt->target());
add(event, "Type", data._type);
add(event, "From", data._from);
add(event, "Date", data._date);
add(event, "Size", data._size);
add(event, "Coding", data._coding);
add(event, "Serial", data._serial);
add(event, "Id", data._id);
add(event, "Page", data._page);
add(event, "Pages", data._pages);
add(event, "Sc_date", data._sc_date);
add(event, "Status", data._status);
add(event, "Body", data._body);
return fire(&event);
}
bool operator()(Board::KhompPvt * pvt, SendData & data)
{
switch_event_t *event = create(ESL_SMS_SENT);
if(!event)
{
LOG(ERROR, "Cannot create SMS ESL");
return false;
}
add(event, pvt->target());
add(event, "Dest", data._dest);
add(event, "Body", data._body);
add(event, "Confirmation?", (data._conf ? "Yes" : "No"));
return fire(&event);
}
} SMSEvent;
struct Request
{
/* "empty" constructor */

View File

@ -99,12 +99,52 @@ struct Command
std::string usage; /* usage of the command, a help */
};
struct CommandXMLOutput : public Command
{
void createRoot(const char *name)
{
root = switch_xml_new(name);
}
void insertXML(switch_xml_t xml)
{
switch_xml_insert(xml,root,0);
}
void clearRoot()
{
if(root)
{
switch_xml_free(root);
root = NULL;
}
}
void printXMLOutput(switch_stream_handle_t *stream)
{
K::Logger::Logg2(C_CLI,stream,switch_xml_toxml(root,SWITCH_FALSE));
}
CommandXMLOutput() : root(NULL) {};
switch_xml_t root; /* for commands that ouput as xml */
};
struct Cli
{
/* Useful definitions --------------------------------------------------- */
typedef switch_status_t (APIFunc)(const char*, switch_core_session_t*, switch_stream_handle_t*);
typedef std::vector<Command*> Commands;
/* Define the output types form commands */
typedef enum
{
VERBOSE = 1,
CONCISE,
DETAILED,
XML
} OutputType;
/* register our commands, but you must create the command function */
static void registerCommands(APIFunc func,switch_loadable_module_interface_t **mod_int);
@ -145,27 +185,31 @@ struct Cli
/* The Commands --------------------------------------------------------- */
/* khomp summary */
static struct _KhompSummary : public Command
static struct _KhompSummary : public CommandXMLOutput
{
_KhompSummary(bool on_cli_term = true):
_on_cli_term(on_cli_term)
CommandXMLOutput(),
_on_cli_term(on_cli_term),
xdevs(NULL)
{
complete_name = "summary";
options.push_back("verbose");
options.push_back("concise");
options.push_back("xml");
brief = "Print system info.";
usage = \
"Prints detailed info about the system like API version and \n" \
"boards characteristics like DSPs version.\n\n" \
"Usage: khomp summary [concise]";
"Usage: khomp summary [concise|verbose|xml]";
_commands.push_back(this);
};
bool execute(int argc, char *argv[]);
bool _on_cli_term; /* indicates if message is sent to fs_cli */
bool _on_cli_term; /* indicates if message is sent to fs_cli */
switch_xml_t xdevs; /* support xml needed to help the interation */
} KhompSummary;
/* khomp show calls */
@ -239,21 +283,22 @@ struct Cli
} KhompChannelsUnblock;
/* khomp show statistics */
static struct _KhompShowStatistics : public Command
static struct _KhompShowStatistics : public CommandXMLOutput
{
_KhompShowStatistics()
_KhompShowStatistics() : CommandXMLOutput(), xdevs(NULL)
{
complete_name = "show statistics";
options.push_back("verbose");
options.push_back("detailed");
options.push_back("xml");
brief = "Shows statistics of the channels.";
usage = \
"Shows statistics of the channels, like number of calls incoming \n" \
"and outgoing, status, status time.\n\n" \
"Usage: khomp show statistics [{verbose [<board> [<channel>]]} | \n" \
"Usage: khomp show statistics [{{verbose|xml} [<board> [<channel>]]} | \n" \
" {detailed <board> <channel>}]\n" \
"\tboard -- Number of the board (start from 0).\n" \
"\tchannel -- Number of the channel (start from 0).\n" \
@ -274,20 +319,22 @@ struct Cli
bool execute(int argc, char *argv[]);
/* support functions */
void cliStatistics(unsigned int device);
void cliDetailedStatistics(unsigned int device, unsigned int channel);
void cliStatistics(unsigned int device, OutputType output_type);
void cliDetailedStatistics(unsigned int device, unsigned int channel, OutputType output_type);
switch_xml_t xdevs; /* support xml needed to help the interation */
} KhompShowStatistics;
/* khomp show channels */
static struct _KhompShowChannels: public Command
static struct _KhompShowChannels: public CommandXMLOutput
{
_KhompShowChannels()
_KhompShowChannels() : CommandXMLOutput(), xdev(NULL)
{
complete_name = "show channels";
options.push_back("verbose");
options.push_back("concise");
options.push_back("xml");
brief = "Show all channels status.";
usage = \
@ -295,34 +342,40 @@ struct Cli
"khomp API point of view.\n\n" \
"Usage: \n" \
"khomp show channels [{<board> [<channel>]} | \n" \
"{{concise|verbose} [<board> [<channel>]]}]\n" \
"{{concise|verbose|xml} [<board> [<channel>]]}]\n" \
"\tboard -- Number of the board (start from 0).\n" \
"e.g. khomp show channels - List status of all channels of all boards.\n" \
"e.g. khomp show channels concise 0 - List status of all channels of \n" \
" board 0 in a concise way.";
" board 0 in a concise way.\n" \
"e.g. khomp show channels xml 0 - List status of all channels of \n" \
" board 0 in a xml structure.";
_commands.push_back(this);
};
/* support function for _KhompShowChannels */
void showChannel(unsigned int device, bool concise, unsigned int channel);
void showChannels(unsigned int device, bool concise);
void showChannel(unsigned int device, unsigned int channel, OutputType output_type = Cli::VERBOSE);
void showChannels(unsigned int device, OutputType output_type = Cli::VERBOSE);
bool execute(int argc, char *argv[]);
switch_xml_t xdev; /* support xml needed to help the interation */
} KhompShowChannels;
/* khomp show links */
static struct _KhompShowLinks: public Command
static struct _KhompShowLinks: public CommandXMLOutput
{
_KhompShowLinks()
_KhompShowLinks() : CommandXMLOutput(), xdev(NULL)
{
complete_name = "show links";
options.push_back("verbose");
options.push_back("concise");
options.push_back("xml");
options.push_back("errors");
options.push_back("errors verbose");
options.push_back("errors concise");
options.push_back("errors xml");
brief = "Show E1 link(s) status/errors counters in a concise \n" \
"way or not.";
@ -332,8 +385,9 @@ struct Cli
"status/the error counters of each link on the board. It prints in \n" \
"a concise way for parsing facilities.\n\n" \
"Usage: \n" \
"khomp show links [[errors] [{<board>} | {{concise|verbose} [<board>]}]]\n" \
"khomp show links [[errors] [{<board>} | {{concise|verbose|xml} [<board>]}]]\n"\
"e.g. khomp show links - Show all links of all boards.\n" \
"e.g. khomp show links xml - Show all links of all boards in xml.\n" \
"e.g. khomp show links errors - Show error counters of all links of \n" \
" all boards.\n" \
"e.g. khomp show links errors 0 - Show error counters of all links of \n" \
@ -343,10 +397,12 @@ struct Cli
};
/* support function for _KhompShowLinks */
void showLinks(unsigned int device, bool concise);
void showErrors(unsigned int device, bool concise);
void showLinks(unsigned int device, OutputType output_type = Cli::VERBOSE);
void showErrors(unsigned int device, OutputType output_type = Cli::VERBOSE);
std::string getLinkStatus(int dev, int obj, Verbose::Presentation fmt);
bool execute(int argc, char *argv[]);
switch_xml_t xdev; /* support xml needed to help the interation */
} KhompShowLinks;
/* khomp clear links */
@ -653,24 +709,41 @@ struct Cli
{
complete_name = "get";
options.push_back("dialplan");
options.push_back("echo-canceller");
options.push_back("auto-gain-control");
options.push_back("out-of-band-dtmfs");
options.push_back("suppression-delay");
options.push_back("auto-fax-adjustment");
options.push_back("fax-adjustment-timeout");
options.push_back("pulse-forwarding");
options.push_back("r2-strict-behaviour");
options.push_back("r2-preconnect-wait");
options.push_back("native-bridge");
options.push_back("suppression-delay");
options.push_back("context-fxo");
options.push_back("context-fxo-alt");
options.push_back("context-fxs");
options.push_back("context-fxs-alt");
options.push_back("context-gsm-call");
options.push_back("context-gsm-call-alt");
options.push_back("context-gsm-sms");
options.push_back("context-digital");
options.push_back("context-fxs");
options.push_back("context-fxo");
options.push_back("context-gsm-call");
options.push_back("context-gsm-sms");
options.push_back("context-pr");
options.push_back("log-to-console");
options.push_back("log-to-disk");
options.push_back("trace");
options.push_back("output-volume");
options.push_back("input-volume");
options.push_back("fxs-global-orig");
options.push_back("fxs-co-dialtone");
options.push_back("fxs-bina");
options.push_back("disconnect-delay");
options.push_back("delay-ringback-co");
options.push_back("delay-ringback-pbx");
options.push_back("ignore-letter-dtmfs");
options.push_back("fxo-send-pre-audio");
options.push_back("fxs-digit-timeout");
options.push_back("drop-collect-call");
options.push_back("kommuter-activation");
options.push_back("kommuter-timeout");
options.push_back("user-transfer-digits");
options.push_back("flash-to-digits");
brief = "Get configuration options in the Khomp channel.";
@ -678,36 +751,37 @@ struct Cli
"Usage: khomp get <option>\n" \
"<option> -- Shown below, with a short description each.\n\n" \
"Option Description\n" \
"dialplan Gets the Name of the dialplan module in use.\n" \
"echo-canceller Gets the echo cancellation procedures if they are \n" \
" avaliable.\n" \
" avaliable.\n" \
"auto-gain-control Gets the AGC procedures if they are avaliable.\n" \
"out-of-band-dtmfs Gets DTMFs to be sent out-of-band (using ast_frames) \n" \
" instead of in-band (audio).\n" \
" instead of in-band (audio).\n" \
"suppression-delay Enable/disable the internal buffer for DTMF \n" \
" suppression.\n" \
"auto-fax-adjustment Gets the automatic adjustment for FAX (mainly, \n" \
" disables the echo canceller).\n" \
" disables the echo canceller).\n" \
//"fax-adjustment-timeout"
"pulse-forwarding Gets the forwarding of detected pulses as DTMF tones.\n" \
"r2-strict-behaviour Gets the R2 protocol behavior while answering lines.\n" \
"r2-preconnect-wait Sets the R2 protocol delay to pre-connect after \n" \
" sending ringback signal.\n" \
"native-bridge Enable/disable the native bridge mode for the channel.\n"\
"suppression-delay Enable/disable the internal buffer for DTMF \n" \
" suppression.\n" \
"context-fxo Context (may be a template) for receiving FXO calls.\n" \
"context-fxo-alt Alternative context (may be a template) for \n" \
" receiving FXO calls.\n" \
"context-fxs Context (may be a template) for receiving FXS calls.\n" \
"context-fxs-alt Alternative context (may be a template) for \n" \
" receiving FXS calls.\n" \
"context-gsm-call Context (may be a template) for receiving GSM calls.\n" \
"context-gsm-call-alt Alternative context (may be a template) for \n" \
" receiving GSM calls.\n" \
"context-gsm-sms Context (may be a template) for receiving GSM \n" \
" messages.\n" \
"r2-preconnect-wait Gets the R2 protocol delay to pre-connect after \n" \
" sending ringback signal.\n" \
"context-digital Context (may be a template) for receiving digital \n" \
" (E1) calls.\n" \
" (E1) calls.\n" \
"context-fxs Context (may be a template) for receiving FXS calls.\n" \
"context-fxo Context (may be a template) for receiving FXO calls.\n" \
"context-gsm-call Context (may be a template) for receiving GSM calls.\n" \
"context-gsm-sms Context (may be a template) for receiving GSM \n" \
" messages.\n" \
"context-pr Context (may be a template) for receiving calls on \n" \
" Passive Record boards.\n" \
"log-to-console Gets the logging of messages to console.\n" \
"log-to-disk Gets the logging of messages to disk.\n" \
"trace Gets the low level tracing.\n" \
"output-volume Gets the volume multiplier to be applied by the \n" \
" board over the output audio.\n" \
" board over the output audio.\n" \
"input-volume Gets the volume multiplier to be applied by the \n" \
" board over the input audio.\n\n" \
" board over the input audio.\n\n" \
"FOR ALL COMMANDS, CHECK THE DOCUMENTATION.";
_commands.push_back(this);
@ -723,24 +797,42 @@ struct Cli
{
complete_name = "set";
options.push_back("dialplan");
options.push_back("echo-canceller");
options.push_back("auto-gain-control");
options.push_back("out-of-band-dtmfs");
options.push_back("suppression-delay");
options.push_back("auto-fax-adjustment");
options.push_back("fax-adjustment-timeout");
options.push_back("pulse-forwarding");
options.push_back("r2-strict-behaviour");
options.push_back("r2-preconnect-wait");
options.push_back("native-bridge");
options.push_back("suppression-delay");
options.push_back("context-fxo");
options.push_back("context-fxo-alt");
options.push_back("context-fxs");
options.push_back("context-fxs-alt");
options.push_back("context-gsm-call");
options.push_back("context-gsm-call-alt");
options.push_back("context-gsm-sms");
options.push_back("context-digital");
options.push_back("context-fxs");
options.push_back("context-fxo");
options.push_back("context-gsm-call");
options.push_back("context-gsm-sms");
options.push_back("context-pr");
options.push_back("log-to-console");
options.push_back("log-to-disk");
options.push_back("trace");
options.push_back("output-volume");
options.push_back("input-volume");
options.push_back("fxs-global-orig");
options.push_back("fxs-co-dialtone");
options.push_back("fxs-bina");
options.push_back("disconnect-delay");
options.push_back("delay-ringback-co");
options.push_back("delay-ringback-pbx");
options.push_back("ignore-letter-dtmfs");
options.push_back("fxo-send-pre-audio");
options.push_back("fxs-digit-timeout");
options.push_back("drop-collect-call");
options.push_back("kommuter-activation");
options.push_back("kommuter-timeout");
options.push_back("user-transfer-digits");
options.push_back("flash-to-digits");
brief = "Ajust configuration options in the Khomp channel.";
usage = \
@ -749,36 +841,36 @@ struct Cli
"\t<value> -- Depends on the option. Check the documentation for \n" \
"\t more info.\n\n" \
"Option Description\n" \
"dialplan Sets the Name of the dialplan module in use.\n" \
"echo-canceller Sets the echo cancellation procedures if they are \n" \
" avaliable.\n" \
" avaliable.\n" \
"auto-gain-control Sets the AGC procedures if they are avaliable.\n" \
"out-of-band-dtmfs Sets DTMFs to be sent out-of-band (using ast_frames) \n" \
" instead of in-band (audio).\n" \
" instead of in-band (audio).\n" \
"suppression-delay Enable/disable the internal buffer for DTMF \n" \
" suppression.\n" \
"auto-fax-adjustment Sets the automatic adjustment for FAX (mainly, \n" \
" disables the echo canceller).\n" \
" disables the echo canceller).\n" \
"pulse-forwarding Sets the forwarding of detected pulses as DTMF tones.\n" \
"r2-strict-behaviour Sets the R2 protocol behavior while answering lines.\n" \
"r2-preconnect-wait Sets the R2 protocol delay to pre-connect after \n" \
" sending ringback signal.\n" \
"native-bridge Enable/disable the native bridge mode for the channel.\n"\
"suppression-delay Enable/disable the internal buffer for DTMF \n" \
" suppression.\n" \
"context-fxo Context (may be a template) for receiving FXO calls.\n" \
"context-fxo-alt Alternative context (may be a template) for \n" \
" receiving FXO calls.\n" \
"context-fxs Context (may be a template) for receiving FXS calls.\n" \
"context-fxs-alt Alternative context (may be a template) for \n" \
" receiving FXS calls.\n" \
"context-gsm-call Context (may be a template) for receiving GSM calls.\n" \
"context-gsm-call-alt Alternative context (may be a template) for \n" \
" receiving GSM calls.\n" \
"context-gsm-sms Context (may be a template) for receiving GSM \n" \
" messages.\n" \
" sending ringback signal.\n" \
"context-digital Context (may be a template) for receiving digital \n" \
" (E1) calls.\n" \
" (E1) calls.\n" \
"context-fxs Context (may be a template) for receiving FXS calls.\n" \
"context-fxo Context (may be a template) for receiving FXO calls.\n" \
"context-gsm-call Context (may be a template) for receiving GSM calls.\n" \
"context-gsm-sms Context (may be a template) for receiving GSM \n" \
" messages.\n" \
"context-pr Context (may be a template) for receiving calls on \n" \
" Passive Record boards.\n" \
"log-to-console Sets the logging of messages to console.\n" \
"log-to-disk Sets the logging of messages to disk.\n" \
"trace Sets the low level tracing.\n" \
"output-volume Sets the volume multiplier to be applied by the \n" \
" board over the output audio.\n" \
" board over the output audio.\n" \
"input-volume Sets the volume multiplier to be applied by the \n" \
" board over the input audio.\n\n" \
" board over the input audio.\n\n" \
"FOR ALL COMMANDS, CHECK THE DOCUMENTATION.";
_commands.push_back(this);

View File

@ -58,10 +58,10 @@
"%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
FMT("%s (d=%02d,c=%03d) " msg) % __SWITCH_FUNC__ % tgt.device % tgt.object
#define PVT_MSG(tgt,msg) \
"%s (d=%02hu,c=%03hu) " msg, __SWITCH_FUNC__, tgt.device, tgt.object
"%s (d=%02d,c=%03d) " msg, __SWITCH_FUNC__, tgt.device, tgt.object
#define D(x) ( FMT( "%s: " x ) % __func__ )

View File

@ -97,7 +97,7 @@ struct FrameStorage
template < int S >
struct FrameManager: protected FrameStorage
{
typedef char Packet[ S ];
typedef const char Packet[ S ];
typedef Ringbuffer < Packet > AudioBuffer;

View File

@ -98,7 +98,9 @@ struct Globals
static Mutex khomp_alloc_mutex;
/* Config options class */
static ConfigOptions options;
static Config::Options options;
static const Regex::Expression regex_allocation;
/* FreeSWITCH Articular Ligaments */
static switch_endpoint_interface_t * khomp_endpoint_interface;

View File

@ -221,6 +221,37 @@ struct KhompPvt
return strBuffer;
}
switch_xml_t getDetailedXML()
{
/* very very important yet! */
idle();
std::string str_incoming_time = timeToString(_total_time_incoming);
std::string str_outgoing_time = timeToString(_total_time_outgoing);
std::string str_idle_time = timeToString(_total_idle_time);
/* total */
switch_xml_t xtotal = switch_xml_new("total");
/* total/incoming_time */
switch_xml_t xin_time = switch_xml_add_child_d(xtotal,"incoming_time",0);
switch_xml_set_txt_d(xin_time, str_incoming_time.c_str());
/* total/outgoing_time */
switch_xml_t xout_time = switch_xml_add_child_d(xtotal,"outgoing_time",0);
switch_xml_set_txt_d(xout_time, str_outgoing_time.c_str());
/* total/idle_time */
switch_xml_t xidle_time = switch_xml_add_child_d(xtotal,"idle_time",0);
switch_xml_set_txt_d(xidle_time, str_idle_time.c_str());
/* total/channel_fails */
switch_xml_t xchannel_fails = switch_xml_add_child_d(xtotal,"channel_fails",0);
switch_xml_set_txt_d(xchannel_fails, STR(FMT("%d") % _channel_fails));
return xtotal;
}
void clear()
{
time(&_base_time);
@ -373,7 +404,7 @@ struct KhompPvt
public:
/* KhompPvt constructor */
KhompPvt(K3LAPI::target & target);
KhompPvt(K3LAPIBase::GenericTarget & target);
/* KhompPvt destructor */
virtual ~KhompPvt()
@ -388,8 +419,14 @@ public:
_pvt(pvt) {}
std::string getDetailedRates();
switch_xml_t getDetailedRatesXML();
std::string getDetailed();
switch_xml_t getDetailedXML();
std::string getRow();
switch_xml_t getNode();
void clear()
{
@ -569,6 +606,7 @@ public:
/* statistics functions */
virtual std::string getStatistics(Statistics::Type type);
virtual switch_xml_t getStatisticsXML(Statistics::Type type);
virtual void clearStatistics()
{
_pvt_statistics->clear();
@ -649,7 +687,7 @@ public:
return pvt_locked;
}
K3LAPI::target & target()
K3LAPIBase::GenericTarget & target()
{
return _target;
}
@ -996,18 +1034,20 @@ public:
{
DBG(FUNC,PVT_FMT(_target,"c"));
/*
if(!_group_context.empty())
{
contexts.insert(contexts.begin(), _group_context);
//contexts.push_back(_group_context);
}
*/
for (MatchExtension::ContextListType::iterator i = contexts.begin(); i != contexts.end(); i++)
replaceTemplate((*i), "DD", _target.device);
BEGIN_CONTEXT
{
K3L_DEVICE_CONFIG & dev_cfg = Globals::k3lapi.device_config(_target.device);
const K3L_DEVICE_CONFIG & dev_cfg = Globals::k3lapi.device_config(_target);
for (MatchExtension::ContextListType::iterator i = contexts.begin(); i != contexts.end(); i++)
replaceTemplate((*i), "SSSS", atoi(dev_cfg.SerialNumber));
@ -1048,7 +1088,7 @@ public:
Call * call() { return _call; }
K3LAPI::target _target; /*!< The device/channel pair to bind this pvt to */
K3LAPIBase::GenericTarget _target; /*!< The device/channel pair to bind this pvt to */
ChanLockType _mutex; /*!< Used for *our* internal locking */
Call *_call;
switch_core_session_t *_session; /*!< The session to which this pvt is associated with */
@ -1066,6 +1106,10 @@ public:
std::string _group_context;
PvtStatistics *_pvt_statistics;
std::string _mohclass;
std::string _language;
std::string _accountcode;
};
/******************************************************************************/
@ -1115,7 +1159,7 @@ public:
}
catch (...)
{
throw K3LAPI::invalid_channel(_device_id, obj);
throw K3LAPITraits::invalid_channel(_device_id, obj);
}
}
@ -1141,7 +1185,7 @@ public:
{
ret = channel(obj)->eventHandler(e);
}
catch (K3LAPI::invalid_channel & invalid)
catch (K3LAPITraits::invalid_channel & invalid)
{
LOG(ERROR, OBJ_FMT(_device_id,obj,"(Generic Board) r (invalid channel on event '%s')")
% Verbose::eventName(e->Code).c_str());
@ -1191,7 +1235,7 @@ public:
\return KhompPvt to be used on the call.
*/
static KhompPvt * find_channel(char* allocation_string, switch_core_session_t * new_session, switch_call_cause_t * cause);
static void khomp_add_event_board_data(const K3LAPI::target target, switch_event_t *event);
static void khomp_add_event_board_data(const K3LAPIBase::GenericTarget target, switch_event_t *event);
static Board * board(int dev)
{
@ -1208,7 +1252,7 @@ public:
}
catch(...)
{
throw K3LAPI::invalid_device(dev);
throw K3LAPITraits::invalid_device(dev);
}
}
@ -1223,11 +1267,11 @@ public:
}
catch(...)
{
throw K3LAPI::invalid_channel(device, object);
throw K3LAPITraits::invalid_channel(device, object);
}
}
static KhompPvt * get(K3LAPI::target & target)
static KhompPvt * get(K3LAPIBase::GenericTarget & target)
{
//if (!Globals::k3lapi.valid_channel(target.device, target.object))
// throw K3LAPI::invalid_channel(target.device, target.object);
@ -1252,7 +1296,7 @@ public:
{
stats = Globals::k3lapi.channel_stats(device, object, index);
}
catch(K3LAPI::invalid_channel & err)
catch(K3LAPITraits::invalid_channel & err)
{
//K::logger::logg(C_WARNING, B(dev,channel, "Command get_stats has failed with error '%s'.") %
// Verbose::status((KLibraryStatus) stt_res));

View File

@ -114,7 +114,7 @@ struct KhompPvtFXO: public KhompPvt
_call_info_report = false;
_call_info_drop = 0;
_user_xfer_digits = Opt::_user_xfer;
_user_xfer_digits = Opt::_options._user_xfer_digits();
_user_xfer_buffer.clear();
_digits_buffer.clear();
@ -141,7 +141,7 @@ struct KhompPvtFXO: public KhompPvt
//ChanTimer::Index _idx_disconnect;
};
/******************************************************************************/
KhompPvtFXO(K3LAPI::target & target) : KhompPvt(target)
KhompPvtFXO(K3LAPIBase::GenericTarget & target) : KhompPvt(target)
{
_fax = new Fax(this);
_transfer = new Transfer<CallFXO>(this);
@ -323,7 +323,7 @@ struct KhompPvtFXO: public KhompPvt
for (unsigned obj = 0; obj < Globals::k3lapi.channel_count(_device_id); obj++)
{
K3LAPI::target tgt(Globals::k3lapi, K3LAPI::target::CHANNEL, _device_id, obj);
K3LAPIBase::GenericTarget tgt(Globals::k3lapi, K3LAPIBase::GenericTarget::CHANNEL, _device_id, obj);
KhompPvt * pvt;
switch(Globals::k3lapi.channel_config(_device_id, obj).Signaling)

View File

@ -115,7 +115,7 @@ struct KhompPvtGSM: public KhompPvt
};
/******************************************************************************/
KhompPvtGSM(K3LAPI::target & target) : KhompPvt(target)
KhompPvtGSM(K3LAPIBase::GenericTarget & target) : KhompPvt(target)
{
_sms = new SMS(this);
command(KHOMP_LOG, CM_ENABLE_CALL_ANSWER_INFO);
@ -278,7 +278,7 @@ struct KhompPvtGSM: public KhompPvt
for (unsigned obj = 0; obj < Globals::k3lapi.channel_count(_device_id); obj++)
{
K3LAPI::target tgt(Globals::k3lapi, K3LAPI::target::CHANNEL, _device_id, obj);
K3LAPIBase::GenericTarget tgt(Globals::k3lapi, K3LAPIBase::GenericTarget::CHANNEL, _device_id, obj);
KhompPvt * pvt;
switch(Globals::k3lapi.channel_config(_device_id, obj).Signaling)

View File

@ -122,7 +122,7 @@ struct KhompPvtE1: public KhompPvt
};
/******************************************************************************/
KhompPvtE1(K3LAPI::target & target) : KhompPvt(target)
KhompPvtE1(K3LAPIBase::GenericTarget & target) : KhompPvt(target)
{
_fax = new Fax(this);
command(KHOMP_LOG,CM_ENABLE_CALL_ANSWER_INFO);
@ -219,7 +219,7 @@ struct KhompPvtE1: public KhompPvt
{
Board::board(_target.device)->_timers.del(callE1()->_idx_disconnect);
}
catch (K3LAPI::invalid_device & err)
catch (K3LAPITraits::invalid_device & err)
{
LOG(ERROR, PVT_FMT(target(), "Unable to get device: %d!") % err.device);
}
@ -310,7 +310,7 @@ struct KhompPvtISDN: public KhompPvtE1
_uui_information.clear();
_isdn_cause = -1;
_user_xfer_digits = Opt::_user_xfer;
_user_xfer_digits = Opt::_options._user_xfer_digits();
_user_xfer_buffer.clear();
_digits_buffer.clear();
_qsig_number.clear();
@ -332,7 +332,7 @@ struct KhompPvtISDN: public KhompPvtE1
};
/******************************************************************************/
KhompPvtISDN(K3LAPI::target & target) : KhompPvtE1(target)
KhompPvtISDN(K3LAPIBase::GenericTarget & target) : KhompPvtE1(target)
{
_transfer = new Transfer<CallISDN, false>(this);
}
@ -496,7 +496,7 @@ struct KhompPvtR2: public KhompPvtE1
std::string _incoming_exten;
};
/******************************************************************************/
KhompPvtR2(K3LAPI::target & target) : KhompPvtE1(target)
KhompPvtR2(K3LAPIBase::GenericTarget & target) : KhompPvtE1(target)
{
K3L_E1600A_FW_CONFIG dspAcfg;
@ -672,7 +672,7 @@ struct KhompPvtFlash: public KhompPvtR2
bool clear()
{
_user_xfer_digits = Opt::_user_xfer;
_user_xfer_digits = Opt::_options._user_xfer_digits();
_user_xfer_buffer.clear();
_digits_buffer.clear();
@ -686,7 +686,7 @@ struct KhompPvtFlash: public KhompPvtR2
};
/******************************************************************************/
KhompPvtFlash(K3LAPI::target & target) : KhompPvtR2(target)
KhompPvtFlash(K3LAPIBase::GenericTarget & target) : KhompPvtR2(target)
{
_transfer = new Transfer<CallFlash>(this);
}
@ -796,7 +796,7 @@ struct KhompPvtFXS: public KhompPvt
}
else if (name == "ring_cadence")
{
Opt::CadencesMapType::iterator i = Opt::_cadences.find(value);
CadencesMapType::iterator i = Opt::_cadences.find(value);
if (i != Opt::_cadences.end())
{
@ -858,11 +858,11 @@ struct KhompPvtFXS: public KhompPvt
};
/******************************************************************************/
KhompPvtFXS(K3LAPI::target & target) : KhompPvt(target)
KhompPvtFXS(K3LAPIBase::GenericTarget & target) : KhompPvt(target)
{
//command(KHOMP_LOG,CM_ENABLE_CALL_ANSWER_INFO);
/* sequence numbers on FXS */
static Opt::OrigToNseqMapType fxs_nseq = generateNseqMap();
static OrigToNseqMapType fxs_nseq = generateNseqMap();
load(fxs_nseq);
}
@ -926,7 +926,7 @@ struct KhompPvtFXS: public KhompPvt
}
bool setupConnection();
void load(Opt::OrigToNseqMapType & fxs_nseq);
void load(OrigToNseqMapType & fxs_nseq);
void loadOptions();
bool parseBranchOptions(std::string options_str);
bool alloc();
@ -991,13 +991,10 @@ struct KhompPvtFXS: public KhompPvt
std::string _context;
int _input_volume;
int _output_volume;
std::string _mohclass;
std::string _language;
std::string _accountcode;
std::string _mailbox;
std::string _flash;
static Opt::OrigToNseqMapType generateNseqMap();
static OrigToNseqMapType generateNseqMap();
static void dialTimer(KhompPvt * pvt);
static void transferTimer(KhompPvt * pvt);
@ -1044,7 +1041,7 @@ struct KhompPvtFXS: public KhompPvt
for (unsigned obj = 0; obj < Globals::k3lapi.channel_count(_device_id); obj++)
{
K3LAPI::target tgt(Globals::k3lapi, K3LAPI::target::CHANNEL, _device_id, obj);
K3LAPIBase::GenericTarget tgt(Globals::k3lapi, K3LAPIBase::GenericTarget::CHANNEL, _device_id, obj);
KhompPvt * pvt;
switch(Globals::k3lapi.channel_config(_device_id, obj).Signaling)

View File

@ -81,7 +81,7 @@ struct KhompPvtPassive: public KhompPvt
};
*/
/******************************************************************************/
KhompPvtPassive(K3LAPI::target & target) : KhompPvt(target)
KhompPvtPassive(K3LAPIBase::GenericTarget & target) : KhompPvt(target)
{
}
@ -150,7 +150,7 @@ struct KhompPvtPassive: public KhompPvt
/********************************** HI Channel ********************************/
struct KhompPvtHI: public KhompPvtPassive
{
KhompPvtHI(K3LAPI::target & target) : KhompPvtPassive(target)
KhompPvtHI(K3LAPIBase::GenericTarget & target) : KhompPvtPassive(target)
{
}
@ -189,7 +189,7 @@ struct KhompPvtHI: public KhompPvtPassive
/********************************* KPR Channel ********************************/
struct KhompPvtKPR: public KhompPvtPassive
{
KhompPvtKPR(K3LAPI::target & target) : KhompPvtPassive(target)
KhompPvtKPR(K3LAPIBase::GenericTarget & target) : KhompPvtPassive(target)
{
}
@ -243,7 +243,7 @@ struct KhompPvtKPR: public KhompPvtPassive
for (unsigned obj = 0; obj < Globals::k3lapi.channel_count(_device_id); obj++)
{
K3LAPI::target tgt(Globals::k3lapi, K3LAPI::target::CHANNEL, _device_id, obj);
K3LAPIBase::GenericTarget tgt(Globals::k3lapi, K3LAPIBase::GenericTarget::CHANNEL, _device_id, obj);
KhompPvt * pvt;
switch(Globals::k3lapi.channel_config(_device_id, obj).Signaling)

View File

@ -47,9 +47,32 @@
#include <string>
#include <map>
#include <vector>
#include <config_options.hpp>
#include "switch.h"
#include "utils.h"
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;
struct CadenceType
{
CadenceType(void)
@ -67,182 +90,171 @@ struct CadenceType
unsigned int ring_ext_s;
};
struct CSpan {
std::string _dialplan;
std::string _context;
std::string _dialstring;
typedef std::pair < std::string, CadenceType > CadencesPairType;
typedef std::map < std::string, CadenceType > CadencesMapType;
struct Options
{
Config::Value< bool > _debug;
Config::Value< std::string > _dialplan;
Config::Value< std::string > _context;
Config::Value< bool > _echo_canceller;
Config::Value< bool > _auto_gain_control;
Config::Value< bool > _out_of_band_dtmfs;
Config::Value< bool > _suppression_delay;
Config::Value< bool > _pulse_forwarding;
Config::Value< bool > _native_bridge;
Config::Value< bool > _recording;
Config::Value< bool > _has_ctbus;
Config::Value< bool > _fxs_bina;
Config::Value< bool > _fxo_send_pre_audio;
Config::Value< bool > _drop_collect_call;
Config::Value< bool > _ignore_letter_dtmfs;
Config::Value< bool > _optimize_audio_path;
Config::Value< bool > _auto_fax_adjustment;
Config::Value< unsigned int > _fax_adjustment_timeout;
Config::Value< bool > _r2_strict_behaviour;
Config::Value< unsigned int > _r2_preconnect_wait;
Config::Value< unsigned int > _fxs_digit_timeout;
Config::Value< unsigned int > _transferdigittimeout;
Config::Value< std::string > _flash;
Config::Value< std::string > _blindxfer;
Config::Value< std::string > _atxfer;
Config::Value< unsigned int > _ringback_co_delay;
Config::Value< unsigned int > _ringback_pbx_delay;
Config::Value< unsigned int > _disconnect_delay;
Config::Value< int > _input_volume;
Config::Value< int > _output_volume;
struct CentralOfficeDialtone : public Config::FunctionValue
{
void operator ()(const Config::StringType &);
const DestVectorType & operator()(void) const { return _value; };
void clear(void)
{
_value.clear();
}
protected:
DestVectorType _value;
} _fxs_co_dialtone;
struct LogDiskOption : public Config::FunctionValue
{
void operator ()(const Config::StringType &);
} _log_disk_option;
/*
struct CallGroupOption: public Config::FunctionValue
{
void operator ()(const Config::StringType &);
const std::string operator()(void) const { return _groups; };
protected:
std::string _groups;
} _callgroup;
struct PickupGroupOption: public Config::FunctionValue
{
void operator ()(const Config::StringType &);
const std::string operator()(void) const { return _groups; };
protected:
std::string _groups;
} _pickupgroup; // or intercept
*/
struct LogConsoleOption : public Config::FunctionValue
{
void operator ()(const Config::StringType &);
} _log_console_option;
struct LogTraceOption : public Config::FunctionValue
{
void operator ()(const Config::StringType &);
} _log_trace_option;
struct RecordPrefixOption: public Config::FunctionValue
{
void operator ()(const Config::StringType &);
const std::string & operator()(void) const { return _value; };
protected:
std::string _value;
} _record_prefix;
Config::Value< std::string > _user_xfer_digits;
Config::Value< std::string > _fxs_global_orig_base;
Config::Value< std::string > _global_mohclass;
Config::Value< std::string > _global_language;
Config::Value< std::string > _context_gsm_call;
Config::Value< std::string > _context2_gsm_call;
Config::Value< std::string > _context_gsm_sms;
Config::Value< std::string > _context_fxo;
Config::Value< std::string > _context2_fxo;
Config::Value< std::string > _context_fxs;
Config::Value< std::string > _context2_fxs;
Config::Value< std::string > _context_digital;
Config::Value< std::string > _context_pr;
Config::Value< std::string > _callgroup;
Config::Value< std::string > _pickupgroup; /* or intercept */
Config::Value< std::string > _accountcode;
Config::Value< unsigned int > _kommuter_timeout;
Config::Value< std::string > _kommuter_activation;
Config::Value< unsigned int > _audio_packet_size;
};
struct Opt
{
typedef std::pair < std::string, CadenceType > CadencesPairType;
typedef std::map < std::string, CadenceType > CadencesMapType;
/* here we load [cadences] */
static CadencesMapType _cadences;
typedef std::map < std::string, std::string > OrigToDestMapType;
typedef std::pair < std::string, std::string > OrigToDestPairType;
typedef std::vector < std::string > DestVectorType;
/* here we load [groups] */
static GroupToDestMapType _groups;
typedef std::map < unsigned int, std::string > BoardToOrigMapType;
typedef std::pair < unsigned int, std::string > BoardToOrigPairType;
/* here we load [fxs-hotlines] */
static OrigToDestMapType _fxs_hotline;
typedef std::map < std::string, unsigned int > OrigToNseqMapType;
typedef std::pair < std::string, unsigned int > OrigToNseqPairType;
/* here we load [fxs-branches] */
static BoardToOrigMapType _fxs_orig_base;
typedef std::pair < unsigned int,unsigned int > ObjectIdType;
typedef std::pair < std::string, ObjectIdType > BranchToObjectPairType;
typedef std::map < std::string, ObjectIdType > BranchToObjectMapType;
/* here we load [fxs-options] */
static BranchToOptMapType _branch_options;
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;
/* here we load ... hannnn */
static BranchToObjectMapType _fxs_branch_map;
typedef std::pair < std::string, CSpan > SpanPairType;
typedef enum
{
GFLAG_MY_CODEC_PREFS = (1 << 0)
}
GFLAGS;
static Options _options;
/* Member functions */
static void initialize(void);
static void obtain(void);
static void commit(void);
static void printConfiguration(switch_stream_handle_t*);
protected:
//TODO: reload options at reloadxml ?
static void reload(void);
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 _flash;
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);
};
};

View File

@ -1 +1 @@
#define MOD_KHOMP_VERSION "1.0 - (rev: 5841)"
#define MOD_KHOMP_VERSION "1.0 - (rev: 5891)"

View File

@ -63,15 +63,8 @@ typedef enum
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. --

View File

@ -687,7 +687,97 @@ struct Statistics
virtual std::string getDetailed() { return ""; }
virtual void clear() {}
};
/******************************************************************************/
/****************************** ESL - Events **********************************/
struct ESL
{
typedef std::vector <std::string> VectorEvents;
ESL(std::string type);
~ESL();
switch_event_t * create(const std::string type)
{
switch_event_t *event;
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, type.c_str()) != SWITCH_STATUS_SUCCESS)
{
return NULL;
}
return event;
}
switch_event_t * create()
{
return create(_type);
}
bool add(switch_event_t *event, const std::string key,
const std::string value) const
{
if(!event) return false;
switch_status_t res = switch_event_add_header_string(event,
SWITCH_STACK_BOTTOM,
key.c_str(),
value.c_str());
return (res == SWITCH_STATUS_SUCCESS ? true : false);
}
bool add(switch_event_t *event, K3LAPIBase::GenericTarget & target)
{
bool ok = add(event, "Device", STR(FMT("%d") % target.device));
if(!ok)
return ok;
std::string type;
switch(target.type)
{
case K3LAPIBase::GenericTarget::CHANNEL:
type = "Channel";
break;
case K3LAPIBase::GenericTarget::MIXER:
type = "Mixer";
break;
case K3LAPIBase::GenericTarget::LINK:
type = "Link";
break;
default:
type = "Other";
break;
}
return add(event, type, STR(FMT("%d") % target.object));
}
bool fire(switch_event_t **event) const
{
if(!event || !*event) return false;
switch_status_t res = switch_event_fire(event);
*event = NULL;
return (res == SWITCH_STATUS_SUCCESS ? true : false);
}
static bool registerEvents();
static bool unregisterEvents();
protected:
const std::string _type;
static VectorEvents * _events;
};
/******************************************************************************/
/******************************************************************************/
#endif /* _UTILS_H_ */

View File

@ -269,22 +269,22 @@ switch_status_t khompExecute(switch_core_session_t *session)
switch_status_t khompHangup(switch_core_session_t *session)
{
DBG(FUNC, D("c"));
Board::KhompPvt *tech_pvt = NULL;
if(!session)
{
LOG(ERROR, D("r (Session is NULL)"));
return SWITCH_STATUS_SUCCESS;
LOG(ERROR, D("cr (Session is NULL)"));
return SWITCH_STATUS_FALSE;
}
tech_pvt = static_cast<Board::KhompPvt*>(switch_core_session_get_private(session));
if(!tech_pvt)
{
DBG(FUNC, D("r (pvt is NULL)"));
LOG(ERROR, D("cr (pvt is NULL)"));
return SWITCH_STATUS_FALSE;
}
DBG(FUNC, PVT_FMT(tech_pvt->target(), "c"));
try
{
@ -312,13 +312,13 @@ switch_status_t khompHangup(switch_core_session_t *session)
LOG(ERROR, PVT_FMT(tech_pvt->target(), "r (unable to lock: %s!)") % err._msg.c_str());
return SWITCH_STATUS_FALSE;
}
catch (K3LAPI::invalid_device & err)
catch (K3LAPITraits::invalid_device & err)
{
LOG(ERROR, PVT_FMT(tech_pvt->target(), "r (unable to get device: %d!)") % err.device);
return SWITCH_STATUS_FALSE;
}
DBG(FUNC, D("r"))
DBG(FUNC, PVT_FMT(tech_pvt->target(), "r"))
return SWITCH_STATUS_SUCCESS;
}
@ -331,12 +331,10 @@ switch_status_t khompPRHangup(switch_core_session_t *session)
switch_status_t khompDestroy(switch_core_session_t *session)
{
DBG(FUNC, D("c"))
if(!session)
{
DBG(FUNC, D("r (session is null)"))
return SWITCH_STATUS_SUCCESS;
LOG(ERROR, D("cr (session is null)"))
return SWITCH_STATUS_FALSE;
}
Board::KhompPvt *tech_pvt = NULL;
@ -345,24 +343,36 @@ switch_status_t khompDestroy(switch_core_session_t *session)
if(!tech_pvt)
{
DBG(FUNC, D("r (pvt is null)"))
LOG(ERROR, D("cr (pvt is null)"))
return SWITCH_STATUS_FALSE;
}
try
{
ScopedPvtLock lock(tech_pvt);
switch_core_session_set_private(session, NULL);
tech_pvt->destroyAll();
}
catch (ScopedLockFailed & err)
DBG(FUNC, PVT_FMT(tech_pvt->target(), "c"))
do
{
DBG(FUNC, PVT_FMT(tech_pvt->target(), "r (unable to lock: %s!)") % err._msg.c_str());
try
{
ScopedPvtLock lock(tech_pvt);
switch_core_session_set_private(session, NULL);
tech_pvt->destroyAll();
DBG(FUNC, PVT_FMT(tech_pvt->target(), "r"));
return SWITCH_STATUS_SUCCESS;
}
catch (ScopedLockFailed & err)
{
LOG(ERROR, PVT_FMT(tech_pvt->target(), "unable to lock: %s!: try again...") % err._msg.c_str());
}
}
while(true);
DBG(FUNC, PVT_FMT(tech_pvt->target(), "r (unable to lock!)"));
DBG(FUNC, D("r"))
return SWITCH_STATUS_SUCCESS;
return SWITCH_STATUS_FALSE;
}
switch_status_t khompSMSDestroy(switch_core_session_t *session)
@ -372,7 +382,7 @@ switch_status_t khompSMSDestroy(switch_core_session_t *session)
if(!session)
{
DBG(FUNC, D("r (session is null)"))
return SWITCH_STATUS_SUCCESS;
return SWITCH_STATUS_FALSE;
}
/*
Board::KhompPvt *tech_pvt = NULL;
@ -569,7 +579,7 @@ switch_status_t khompWrite(switch_core_session_t *session, switch_frame_t *frame
{
Board::board(tech_pvt->target().device)->_timers.del(tech_pvt->call()->_idx_co_ring);
}
catch (K3LAPI::invalid_device & err)
catch (K3LAPITraits::invalid_device & err)
{
LOG(ERROR, PVT_FMT(tech_pvt->target(), "Unable to get device: %d!") % err.device);
}
@ -666,7 +676,7 @@ switch_status_t khompAnswer(switch_core_session_t *session)
}
catch (K3LAPI::invalid_device & err)
catch (K3LAPITraits::invalid_device & err)
{
LOG(ERROR, D("unable to get device: %d!") % err.device);
return SWITCH_STATUS_FALSE;
@ -826,7 +836,7 @@ switch_call_cause_t khompCall
}
Board::KhompPvt *tech_pvt;
int cause = (int)SWITCH_CAUSE_SUCCESS;
int cause = (int)SWITCH_CAUSE_NONE;
try
{
@ -882,7 +892,7 @@ switch_call_cause_t khompCall
{
if(err._fail == ScopedLockFailed::ALLOC_FAILED)
{
LOG(ERROR, PVT_FMT(tech_pvt->target(), "unable to global alloc lock"));
LOG(ERROR, D("unable to global alloc lock: %s!") % err._msg.c_str());
}
else
{
@ -1295,7 +1305,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_khomp_load)
}
/* apply global volume now */
if(Opt::_input_volume != 0 || Opt::_output_volume != 0)
if(Opt::_options._input_volume() != 0 || Opt::_options._output_volume() != 0)
Board::applyGlobalVolume();
Opt::commit();
@ -1320,6 +1330,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_khomp_load)
/* Register cli commands */
Cli::registerCommands(apiKhomp,module_interface);
ESL::registerEvents();
/* Add applications */
SWITCH_ADD_APP(Globals::khomp_app_inteface, "KLog", "KLog", "KLog log every string to khomp log system", klogFunction, "<value>", SAF_SUPPORT_NOMEDIA);
@ -1352,6 +1364,9 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_khomp_shutdown)
Board::kommuter.stop();
Cli::unregisterCommands();
ESL::unregisterEvents();
/* Finnish him! */
DBG(FUNC, "Unloading mod_khomp...")
@ -1412,7 +1427,7 @@ extern "C" void Kstdcall khompAudioListener (int32 deviceid, int32 objectid, byt
try
{
//If NULL get throws K3LAPI::invalid_channel exception.
//If NULL get throws K3LAPITraits::invalid_channel exception.
Board::KhompPvt * pvt = Board::get(deviceid, objectid);
/* add listener audio to the read buffer */
@ -1485,7 +1500,7 @@ extern "C" void Kstdcall khompAudioListener (int32 deviceid, int32 objectid, byt
}
}
catch (K3LAPI::invalid_channel & err)
catch (K3LAPITraits::invalid_channel & err)
{
LOG(ERROR, OBJ_FMT(deviceid, objectid, "Invalid channel..."));
return;

View File

@ -44,6 +44,7 @@
#include "applications.h"
#include "lock.h"
bool Fax::adjustForFax()
{
/* Don't worry, let the man work */
@ -379,18 +380,20 @@ bool Fax::addFaxFile(const char * filename, bool last)
}
/******************************************************************************/
SMS::_SMSEvent SMS::SMSEvent;
bool SMS::justAlloc(unsigned int count)
{
/* incoming contexts */
MatchExtension::ContextListType contexts;
contexts.push_back(Opt::_context_gsm_sms);
contexts.push_back(Opt::_options._context_gsm_sms());
/* temporary variables */
std::string context;
std::string exten("s");
K3L_DEVICE_CONFIG & dev_cfg = Globals::k3lapi.device_config(_pvt->_target.device);
const K3L_DEVICE_CONFIG & dev_cfg = Globals::k3lapi.device_config(_pvt->_target);
for (MatchExtension::ContextListType::iterator i = contexts.begin(); i != contexts.end(); i++)
{
@ -438,7 +441,7 @@ bool SMS::justAlloc(unsigned int count)
switch_caller_profile_t *caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session),
"Khomp_SMS", //username
Opt::_dialplan.c_str(), //dialplan
Opt::_options._dialplan().c_str(), //dialplan
NULL, //caller_id_name
_got_sms._from.c_str(), //caller_id_number
NULL, //network_addr
@ -465,7 +468,7 @@ bool SMS::justAlloc(unsigned int count)
return false;
}
std::string name = STG(FMT("Khomp_SMS/%hu/%hu")
std::string name = STG(FMT("Khomp_SMS/%d/%d")
% _pvt->target().device
% _pvt->target().object);
@ -744,6 +747,8 @@ bool SMS::onSMSData(K3L_EVENT *e)
{
_got_sms._body = (const char *)(e->Params ? e->Params : "");
SMSEvent(_pvt, _got_sms);
if(!justStart())
{
if(_got_sms._type != "broadcast")
@ -945,6 +950,8 @@ int SMS::smsThread(void * sms_ptr)
if (sms->_result == kgccNone)
{
sms->SMSEvent(pvt, sms->_send_sms);
/* stats update if sent! */
sms->statistics<SMSStatistics>()->incrementOutgoing();
}

File diff suppressed because it is too large Load Diff

View File

@ -52,7 +52,9 @@ Globals::GlobalTimer * Globals::global_timer = NULL;
Globals::Mutex Globals::khomp_alloc_mutex;
ConfigOptions Globals::options;
Config::Options Globals::options;
const Regex::Expression Globals::regex_allocation("(((([bB])[ ]*([0-9]+))|(([sS])[ ]*([0-9]+)))[ ]*(([cClL])[ ]*([0-9]+)[ ]*([-][ ]*([0-9]+))?)?)|(([rR])[ ]*([0-9]+)[ ]*([-][ ]*([0-9]+))?)", Regex::E_EXTENDED);
switch_endpoint_interface_t * Globals::khomp_endpoint_interface = NULL;
switch_endpoint_interface_t * Globals::khomp_sms_endpoint_interface = NULL;

View File

@ -54,7 +54,7 @@ char Board::_cng_buffer[Globals::cng_buffer_size];
Kommuter Board::kommuter;
Board::KhompPvt::KhompPvt(K3LAPI::target & target) :
Board::KhompPvt::KhompPvt(K3LAPIBase::GenericTarget & target) :
_target(target),
_mutex(Globals::module_pool),
_session(NULL),
@ -66,6 +66,10 @@ Board::KhompPvt::KhompPvt(K3LAPI::target & target) :
_write_codec.implementation = NULL;
_pvt_statistics = new PvtStatistics(this);
_mohclass = Opt::_options._global_mohclass();
_language = Opt::_options._global_language();
_accountcode = Opt::_options._accountcode();
}
bool Board::initializeK3L(void)
@ -82,7 +86,7 @@ bool Board::initializeK3L(void)
}
catch (K3LAPI::start_failed & e)
{
LOG(ERROR,FMT("loading K3L API failed: %s") % e.msg);
LOG(ERROR,FMT("loading K3L API failed: %s") % e.what());
return false;
}
@ -236,7 +240,7 @@ void Board::initializeChannels(void)
for (unsigned obj = 0; obj < Globals::k3lapi.channel_count(_device_id); obj++)
{
K3LAPI::target tgt(Globals::k3lapi, K3LAPI::target::CHANNEL, _device_id, obj);
K3LAPIBase::GenericTarget tgt(Globals::k3lapi, K3LAPIBase::GenericTarget::CHANNEL, _device_id, obj);
KhompPvt * pvt;
@ -328,7 +332,25 @@ bool Board::initialize(void)
{
initializeCngBuffer();
initializeBoards();
try
{
initializeBoards();
}
catch(K3LAPITraits::invalid_device & err)
{
LOG(ERROR, FMT("Invalid device at initialize boards: %s") % err.what());
return false;
}
catch(K3LAPITraits::invalid_channel & err)
{
LOG(ERROR, FMT("Invalid channel at initialize boards: %s") % err.what());
return false;
}
catch(K3LAPITraits::invalid_link & err)
{
LOG(ERROR, FMT("Invalid link at initialize boards: %s") % err.what());
return false;
}
return true;
}
@ -340,7 +362,7 @@ bool Board::finalize(void)
return finalizeK3L();
}
void Board::khomp_add_event_board_data(const K3LAPI::target target, switch_event_t *event)
void Board::khomp_add_event_board_data(const K3LAPIBase::GenericTarget target, switch_event_t *event)
{
//if (!event) {
@ -349,7 +371,7 @@ void Board::khomp_add_event_board_data(const K3LAPI::target target, switch_event
try
{
if (target.type == K3LAPI::target::CHANNEL)
if (target.type == K3LAPIBase::GenericTarget::CHANNEL)
{
switch_core_session_t * s = get(target.device, target.object)->session();
switch_channel_event_set_data(Board::KhompPvt::getFSChannel(s), event);
@ -358,7 +380,7 @@ void Board::khomp_add_event_board_data(const K3LAPI::target target, switch_event
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Khomp-DeviceId", "%u", target.device);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Khomp-Object", "%u", target.object);
}
catch(K3LAPI::invalid_channel & err)
catch(K3LAPITraits::invalid_channel & err)
{
LOG(ERROR, PVT_FMT(target, "Invalid channel"));
}
@ -385,6 +407,23 @@ std::string Board::KhompPvt::getStatistics(Statistics::Type type)
}
}
switch_xml_t Board::KhompPvt::getStatisticsXML(Statistics::Type type)
{
switch(type)
{
case Statistics::DETAILED:
{
return _pvt_statistics->getDetailedXML();
}
case Statistics::ROW:
{
return _pvt_statistics->getNode();
}
default:
return NULL;
}
}
std::string Board::KhompPvt::PvtStatistics::getDetailedRates()
{
/* skip inactive channels */
@ -429,6 +468,49 @@ std::string Board::KhompPvt::PvtStatistics::getDetailedRates()
return strBuffer;
}
switch_xml_t Board::KhompPvt::PvtStatistics::getDetailedRatesXML()
{
switch_xml_t xrates = switch_xml_new("rates");
/* this values come from kserver */
unsigned int call_incoming = Globals::k3lapi.channel_stats(
_pvt->target().device, _pvt->target().object, kcsiInbound);
unsigned int call_outgoing = Globals::k3lapi.channel_stats(
_pvt->target().device, _pvt->target().object, kcsiOutbound);
float occupation_rate = 100.0;
if (_pvt->call()->statistics()->_total_idle_time > 0)
{
occupation_rate = 100 * (
_pvt->call()->statistics()->_total_time_incoming +
_pvt->call()->statistics()->_total_time_outgoing
) / (
_pvt->call()->statistics()->_total_idle_time +
_pvt->call()->statistics()->_total_time_incoming +
_pvt->call()->statistics()->_total_time_outgoing);
}
switch_xml_t xoccupation = switch_xml_add_child_d(xrates,"oucpation",0);
switch_xml_set_txt_d(xoccupation,STR(FMT("%d") % occupation_rate));
if (call_incoming > 0)
{
std::string str_calls_incoming_mean = timeToString ( (time_t) (_pvt->call()->statistics()->_total_time_incoming / call_incoming) );
switch_xml_t xmean_in = switch_xml_add_child_d(xrates,"incoming",0);
switch_xml_set_txt_d(xmean_in,str_calls_incoming_mean.c_str());
}
if (call_outgoing > 0)
{
std::string str_calls_outgoing_mean = timeToString ( (time_t) (_pvt->call()->statistics()->_total_time_outgoing / call_outgoing) );
switch_xml_t xmean_out = switch_xml_add_child_d(xrates,"outgoing",0);
switch_xml_set_txt_d(xmean_out,str_calls_outgoing_mean.c_str());
}
return xrates;
}
std::string Board::KhompPvt::PvtStatistics::getDetailed()
{
/* skip inactive channels */
@ -456,6 +538,34 @@ std::string Board::KhompPvt::PvtStatistics::getDetailed()
return strBuffer;
}
switch_xml_t Board::KhompPvt::PvtStatistics::getDetailedXML()
{
switch_xml_t xch = _pvt->call()->statistics()->getDetailedXML();
/* this values come from kserver */
unsigned int call_incoming = Globals::k3lapi.channel_stats(
_pvt->target().device, _pvt->target().object, kcsiInbound);
unsigned int call_outgoing = Globals::k3lapi.channel_stats(
_pvt->target().device, _pvt->target().object, kcsiOutbound);
unsigned int call_fails = Globals::k3lapi.channel_stats(
_pvt->target().device, _pvt->target().object, kcsiOutFailed);
/* total/call_incoming */
switch_xml_t xin_calls = switch_xml_add_child_d(xch,"calls_incoming",0);
switch_xml_set_txt_d(xin_calls,STR(FMT("%d") % call_incoming));
/* total/call_outgoing */
switch_xml_t xout_calls = switch_xml_add_child_d(xch,"calls_outgoing",0);
switch_xml_set_txt_d(xout_calls,STR(FMT("%d") % call_outgoing));
/* total/calls_failed */
switch_xml_t xfailed_calls = switch_xml_add_child_d(xch,"calls_failed",0);
switch_xml_set_txt_d(xfailed_calls,STR(FMT("%d") % call_fails));
return xch;
}
std::string Board::KhompPvt::PvtStatistics::getRow()
{
/* skip inactive channels */
@ -498,6 +608,71 @@ std::string Board::KhompPvt::PvtStatistics::getRow()
% string_time);
}
switch_xml_t Board::KhompPvt::PvtStatistics::getNode()
{
time_t action_time;
time (&action_time);
action_time -= _pvt->call()->statistics()->_base_time;
uint32 calls_incoming = Globals::k3lapi.channel_stats(
_pvt->target().device, _pvt->target().object, kcsiInbound);
uint32 calls_outgoing = Globals::k3lapi.channel_stats(
_pvt->target().device, _pvt->target().object, kcsiOutbound);
uint32 call_fails = Globals::k3lapi.channel_stats(
_pvt->target().device, _pvt->target().object, kcsiOutFailed);
std::string string_time = " n/a ";
std::string call_type = " none ";
if (_pvt->call()->_flags.check(Kflags::IS_INCOMING))
call_type = "incoming";
else if (_pvt->call()->_flags.check(Kflags::IS_OUTGOING))
call_type = "outgoing";
if (_pvt->owner())
{
string_time = timeToString(action_time);
}
/* device/channel */
switch_xml_t xchn = switch_xml_new("channel");
switch_xml_set_attr_d(xchn,"id",STR(FMT("%d") % _pvt->target().object));
/* device/channel/details */
switch_xml_t xdetails = switch_xml_add_child_d(xchn,"details",0);
/* device/channel/details/calls_incomming */
switch_xml_t xin_calls = switch_xml_add_child_d(xdetails,"calls_incoming",0);
switch_xml_set_txt_d(xin_calls,STR(FMT("%d") % calls_incoming));
/* device/channel/details/calls_outgoing */
switch_xml_t xout_calls = switch_xml_add_child_d(xdetails,"calls_incoming",0);
switch_xml_set_txt_d(xout_calls,STR(FMT("%d") % calls_outgoing));
/* device/channel/details/channel_fails */
switch_xml_t xchn_fails = switch_xml_add_child_d(xdetails,"channel_fails",0);
switch_xml_set_txt_d(xchn_fails,STR(FMT("%d") % _pvt->call()->statistics()->_channel_fails));
/* device/channel/details/calls_fails */
switch_xml_t xcall_fails = switch_xml_add_child_d(xdetails,"calls_fails",0);
switch_xml_set_txt_d(xcall_fails,STR(FMT("%d") % call_fails));
/* device/channel/details/state */
switch_xml_t xstate = switch_xml_add_child_d(xdetails,"state",0);
switch_xml_set_txt_d(xstate,_pvt->getStateString().c_str());
/* device/channel/details/call_type */
switch_xml_t xcall_type = switch_xml_add_child_d(xdetails,"call_type",0);
switch_xml_set_txt_d(xcall_type,call_type.c_str());
/* device/channel/details/time */
switch_xml_t xtime = switch_xml_add_child_d(xdetails,"time",0);
switch_xml_set_txt_d(xtime,string_time.c_str());
return xchn;
}
switch_status_t Board::KhompPvt::justAlloc(bool is_answering, switch_memory_pool_t **pool)
{
DBG(FUNC, PVT_FMT(target(), "c"));
@ -572,6 +747,20 @@ switch_status_t Board::KhompPvt::justAlloc(bool is_answering, switch_memory_pool
return SWITCH_STATUS_FALSE;
}
try
{
/* accounttcode for CDR identification */
setFSChannelVar(getFSChannel(),"accountcode",_accountcode.c_str());
/* language for IVR machine */
setFSChannelVar(getFSChannel(),"language",_language.c_str());
}
catch (Board::KhompPvt::InvalidSwitchChannel & err)
{
LOG(ERROR, PVT_FMT(target(), "(%s)") % err._msg.c_str() );
return SWITCH_STATUS_FALSE;
}
DBG(FUNC, PVT_FMT(target(), "r"));
return SWITCH_STATUS_SUCCESS;
}
@ -612,7 +801,7 @@ switch_status_t Board::KhompPvt::justStart(switch_caller_profile_t *profile)
% _call->_dest_addr % (contexts.size() >= 1 ? contexts[0] : "default"));
return SWITCH_STATUS_FALSE;
default:
DBG(FUNC, PVT_FMT(_target, "our: dialplan '%s', context '%s', exten '%s'") % Opt::_dialplan % context % exten);
DBG(FUNC, PVT_FMT(_target, "our: dialplan '%s', context '%s', exten '%s'") % Opt::_options._dialplan() % context % exten);
break;
}
@ -621,12 +810,12 @@ switch_status_t Board::KhompPvt::justStart(switch_caller_profile_t *profile)
else
{
exten = call()->_dest_addr;
DBG(FUNC, PVT_FMT(target(), "already found our: dialplan '%s', context '%s', exten '%s'") % Opt::_dialplan % call()->_incoming_context % exten);
DBG(FUNC, PVT_FMT(target(), "already found our: dialplan '%s', context '%s', exten '%s'") % Opt::_options._dialplan() % call()->_incoming_context % exten);
}
_caller_profile = switch_caller_profile_new(switch_core_session_get_pool(_session),
"Khomp", //username
Opt::_dialplan.c_str(), //dialplan
Opt::_options._dialplan().c_str(), //dialplan
NULL, //caller_id_name
_call->_orig_addr.c_str(), //caller_id_number
NULL, //network_addr
@ -645,7 +834,7 @@ switch_status_t Board::KhompPvt::justStart(switch_caller_profile_t *profile)
return SWITCH_STATUS_FALSE;
}
std::string name = STG(FMT("Khomp/%hu/%hu/%s")
std::string name = STG(FMT("Khomp/%d/%d/%s")
% target().device
% target().object
% _call->_dest_addr);
@ -672,7 +861,7 @@ switch_status_t Board::KhompPvt::justStart(switch_caller_profile_t *profile)
if(_call->_orig_addr.empty())
_call->_orig_addr = profile->caller_id_number;
switch_channel_set_name(channel, STG(FMT("Khomp/%hu/%hu/%s")
switch_channel_set_name(channel, STG(FMT("Khomp/%d/%d/%s")
% target().device
% target().object
% (!_call->_dest_addr.empty() ? _call->_dest_addr.c_str() : "")).c_str());
@ -772,7 +961,7 @@ bool Board::KhompPvt::indicateBusyUnlocked(int cause, bool sent_signaling)
Board::board(_target.device)->_timers.del(call()->_idx_pbx_ring);
Board::board(_target.device)->_timers.del(call()->_idx_co_ring);
}
catch (K3LAPI::invalid_device & err)
catch (K3LAPITraits::invalid_device & err)
{
LOG(ERROR, PVT_FMT(_target, "Unable to get device: %d!") % err.device);
}
@ -824,6 +1013,8 @@ void Board::KhompPvt::destroyAll()
switch_core_session_set_private(_session, NULL);
_session = NULL;
}
owner(NULL);
if(_caller_profile)
{
@ -854,8 +1045,6 @@ void Board::KhompPvt::destroyAll()
void Board::KhompPvt::doHangup()
{
owner(NULL);
try
{
switch_channel_t *channel = getFSChannel();
@ -903,7 +1092,7 @@ bool Board::KhompPvt::cleanup(CleanupType type)
Board::board(_target.device)->_timers.del(call()->_idx_pbx_ring);
Board::board(_target.device)->_timers.del(call()->_idx_co_ring);
}
catch (K3LAPI::invalid_device & err)
catch (K3LAPITraits::invalid_device & err)
{
LOG(ERROR, PVT_FMT(_target, "Unable to get device: %d!") % err.device);
}
@ -939,10 +1128,10 @@ bool Board::KhompPvt::cleanup(CleanupType type)
}
if(call()->_input_volume >= -10 && call()->_input_volume <= 10)
setVolume("input" , Opt::_input_volume);
setVolume("input" , Opt::_options._input_volume());
if(call()->_output_volume >= -10 && call()->_output_volume <= 10)
setVolume("output", Opt::_output_volume);
setVolume("output", Opt::_options._output_volume());
return _call->clear();
case CLN_SOFT:
@ -1037,7 +1226,7 @@ void Board::queueAddChannel(PriorityCallQueue &pqueue, unsigned int board, unsig
KhompPvt * pvt = get(board, object);
pqueue.insert(pvt);
}
catch(K3LAPI::invalid_channel & err)
catch(K3LAPITraits::invalid_channel & err)
{
//...
}
@ -1050,7 +1239,7 @@ Board::KhompPvt * Board::findFree(unsigned int board, unsigned int object, bool
KhompPvt * pvt = get(board, object);
return ((fully_available ? pvt->isFree() : pvt->isOK()) ? pvt : NULL);
}
catch(K3LAPI::invalid_channel & err)
catch(K3LAPITraits::invalid_channel & err)
{
}
return NULL;
@ -1066,10 +1255,10 @@ void Board::applyGlobalVolume(void)
{
try
{
Board::get(dev,obj)->setVolume("input", Opt::_input_volume);
Board::get(dev,obj)->setVolume("output",Opt::_output_volume);
Board::get(dev,obj)->setVolume("input", Opt::_options._input_volume());
Board::get(dev,obj)->setVolume("output",Opt::_options._output_volume());
}
catch(K3LAPI::invalid_channel & err)
catch(K3LAPITraits::invalid_channel & err)
{
DBG(FUNC, OBJ_FMT(dev, obj, "Channel not found"));
}
@ -1096,7 +1285,7 @@ bool Board::KhompPvt::startCadence(CadencesType type)
{
call()->_cadence = type;
Opt::CadencesMapType::iterator i = Opt::_cadences.find(tone);
CadencesMapType::iterator i = Opt::_cadences.find(tone);
std::string cmd_params;
if (i != Opt::_cadences.end())
@ -1220,9 +1409,10 @@ bool Board::KhompPvt::obtainRX(bool with_delay)
}
catch(K3LAPI::failed_raw_command & e)
{
LOG(ERROR, PVT_FMT(target(), "ERROR sending mixer record command!"));
LOG(ERROR, PVT_FMT(target(), "ERROR sending mixer command!"));
return false;
}
return true;
}
@ -1236,7 +1426,7 @@ bool Board::KhompPvt::obtainTX()
try
{
int dsp = Globals::k3lapi.get_dsp(_target.device, K3LAPI::DSP_AUDIO);
int dsp = Globals::k3lapi.get_dsp(_target, K3LAPI::DSP_AUDIO);
Globals::k3lapi.raw_command(_target.device, dsp, cmd1, sizeof(cmd1));
@ -1347,7 +1537,7 @@ bool Board::KhompPvt::dtmfSuppression(bool enable)
bool Board::KhompPvt::echoCancellation(bool enable)
{
K3L_DEVICE_CONFIG & devCfg = Globals::k3lapi.device_config(_target.device);
const K3L_DEVICE_CONFIG & devCfg = Globals::k3lapi.device_config(_target);
/* echo canceller should not be used for non-echo cancellable channels */
switch (devCfg.EchoConfig)
@ -1432,8 +1622,8 @@ bool Board::KhompPvt::setCollectCall()
const char * tmp_var = NULL;
// get option configuration value
confvalues.push_back(Opt::_drop_collect_call ? T_TRUE : T_FALSE);
DBG(FUNC, PVT_FMT(_target, "option drop collect call is '%s'") % (Opt::_drop_collect_call ? "yes" : "no"));
confvalues.push_back(Opt::_options._drop_collect_call() ? T_TRUE : T_FALSE);
DBG(FUNC, PVT_FMT(_target, "option drop collect call is '%s'") % (Opt::_options._drop_collect_call() ? "yes" : "no"));
// get global filter configuration value
tmp_var = switch_core_get_variable("KDropCollectCall");
@ -1622,7 +1812,7 @@ bool Board::KhompPvt::onAudioStatus(K3L_EVENT *e)
if (!call()->_flags.check(Kflags::CONNECTED))
{
obtainRX(Opt::_suppression_delay);
obtainRX(Opt::_options._suppression_delay());
//Marcar para o Freeswitch que jah tem audio passando
if (call()->_flags.check(Kflags::IS_OUTGOING))
@ -1660,7 +1850,7 @@ bool Board::KhompPvt::onAudioStatus(K3L_EVENT *e)
LOG(ERROR, PVT_FMT(target(), "r (%s)") % err._msg.c_str() );
return false;
}
catch (K3LAPI::invalid_device & err)
catch (K3LAPITraits::invalid_device & err)
{
LOG(ERROR, PVT_FMT(_target, "r (unable to get device: %d!)") % err.device);
return false;
@ -1679,7 +1869,7 @@ bool Board::KhompPvt::onCollectCall(K3L_EVENT *e)
//K::internal::ami_event(pvt, EVENT_FLAG_CALL, "CollectCall",
// STG(FMT("Channel: Khomp/B%dC%d\r\n") % pvt->boardid % pvt->objectid));
if (Opt::_drop_collect_call || _call->_flags.check(Kflags::DROP_COLLECT))
if (Opt::_options._drop_collect_call() || _call->_flags.check(Kflags::DROP_COLLECT))
{
/* disconnect! */
//TODO: SCE_HIDE !?
@ -1790,7 +1980,7 @@ bool Board::KhompPvt::onConnect(K3L_EVENT *e)
LOG(ERROR, PVT_FMT(target(), "r (%s)") % err._msg.c_str() );
return false;
}
catch (K3LAPI::invalid_device & err)
catch (K3LAPITraits::invalid_device & err)
{
LOG(ERROR, PVT_FMT(_target, "r (unable to get device: %d!)") % err.device);
return false;
@ -1896,7 +2086,7 @@ bool Board::KhompPvt::onDtmfDetected(K3L_EVENT *e)
return true;
}
if (Opt::_ignore_letter_dtmfs)
if (Opt::_options._ignore_letter_dtmfs())
{
switch (e->AddInfo)
{
@ -2105,7 +2295,7 @@ bool Board::KhompPvt::indicateRinging()
{
int ringback_value = RingbackDefs::RB_SEND_DEFAULT;
bool do_drop_call = Opt::_drop_collect_call
bool do_drop_call = Opt::_options._drop_collect_call()
|| call()->_flags.check(Kflags::DROP_COLLECT);
if (do_drop_call && call()->_collect_call)
@ -2128,7 +2318,7 @@ bool Board::KhompPvt::indicateRinging()
if (send_ringback)
{
call()->_flags.set(Kflags::GEN_CO_RING);
call()->_idx_co_ring = Board::board(_target.device)->_timers.add(Opt::_ringback_co_delay, &Board::KhompPvt::coRingGen,this);
call()->_idx_co_ring = Board::board(_target.device)->_timers.add(Opt::_options._ringback_co_delay(), &Board::KhompPvt::coRingGen,this);
/* start grabbing audio */
startListen();
@ -2145,7 +2335,7 @@ bool Board::KhompPvt::indicateRinging()
LOG(ERROR, PVT_FMT(_target, "r (unable to lock %s!)") % err._msg.c_str() );
return false;
}
catch (K3LAPI::invalid_device & err)
catch (K3LAPITraits::invalid_device & err)
{
LOG(ERROR, PVT_FMT(_target, "r (unable to get device: %d!)") % err.device);
return false;
@ -2333,7 +2523,7 @@ int Board::eventThread(void *void_evt)
% Globals::verbose.event(evt.obj(), evt.event()));
}
}
catch (K3LAPI::invalid_device & invalid)
catch (K3LAPITraits::invalid_device & invalid)
{
LOG(ERROR, D("invalid device on event '%s'")
% Verbose::eventName(evt.event()->Code).c_str());
@ -2378,7 +2568,7 @@ int Board::commandThread(void *void_evt)
LOG(ERROR, D("(d=%d) Error on command(%d)") % devid % cmd.code());
}
}
catch (K3LAPI::invalid_channel & invalid)
catch (K3LAPITraits::invalid_channel & invalid)
{
LOG(ERROR, OBJ_FMT(devid,cmd.obj(), "invalid device on command '%d'") % cmd.code());
}
@ -2418,7 +2608,7 @@ extern "C" int32 Kstdcall khompEventCallback(int32 obj, K3L_EVENT * e)
EventRequest e_req(obj, e);
Board::board(e->DeviceId)->chanEventHandler()->write(e_req);
}
catch (K3LAPI::invalid_device & err)
catch (K3LAPITraits::invalid_device & err)
{
LOG(ERROR, D("Unable to get device: %d!") % err.device);
return ksFail;

View File

@ -305,10 +305,11 @@ bool BoardFXO::KhompPvtFXO::onCallSuccess(K3L_EVENT *e)
if (call()->_pre_answer)
{
dtmfSuppression(Opt::_out_of_band_dtmfs && !call()->_flags.check(Kflags::FAX_DETECTED));
dtmfSuppression(Opt::_options._out_of_band_dtmfs() && !call()->_flags.check(Kflags::FAX_DETECTED));
startListen();
startStream();
switch_channel_mark_pre_answered(getFSChannel());
}
}
catch (ScopedLockFailed & err)
@ -316,6 +317,11 @@ bool BoardFXO::KhompPvtFXO::onCallSuccess(K3L_EVENT *e)
LOG(ERROR, PVT_FMT(_target, "(FXO) r (unable to lock %s!)") % err._msg.c_str() );
return false;
}
catch (Board::KhompPvt::InvalidSwitchChannel & err)
{
LOG(ERROR, PVT_FMT(target(), "(FXO) r (%s)") % err._msg.c_str() );
return false;
}
DBG(FUNC, PVT_FMT(_target, "(FXO) r"));
@ -355,16 +361,24 @@ bool BoardFXO::KhompPvtFXO::onAudioStatus(K3L_EVENT *e)
if(e->AddInfo == kmtFax)
{
DBG(FUNC, PVT_FMT(_target, "Fax detected"));
DBG(STRM, PVT_FMT(_target, "Fax detected"));
bool already_detected = call()->_flags.check(Kflags::FAX_DETECTED);
/* hadn't we did this already? */
bool already_detected = call()->_flags.check(Kflags::FAX_DETECTED);
time_t time_was = call()->_call_statistics->_base_time;
time_t time_now = time(NULL);
bool detection_timeout = (time_now > (time_was + (time_t) (Opt::_options._fax_adjustment_timeout())));
BEGIN_CONTEXT
{
if(already_detected)
break;
ScopedPvtLock lock(this);
/* already adjusted? do not adjust again. */
if (already_detected || detection_timeout)
break;
if (callFXO()->_call_info_drop != 0 || callFXO()->_call_info_report)
{
/* we did not detected fax yet, send answer info! */
@ -377,7 +391,7 @@ bool BoardFXO::KhompPvtFXO::onAudioStatus(K3L_EVENT *e)
}
}
if (Opt::_auto_fax_adjustment)
if (Opt::_options._auto_fax_adjustment())
{
DBG(FUNC, PVT_FMT(_target, "communication will be adjusted for fax!"));
_fax->adjustForFax();
@ -483,9 +497,9 @@ bool BoardFXO::KhompPvtFXO::onDtmfSendFinish(K3L_EVENT *e)
/* activate resources early... */
bool fax_detected = callFXO()->_flags.check(Kflags::FAX_DETECTED);
bool res_out_of_band_dtmf = Opt::_suppression_delay && Opt::_out_of_band_dtmfs && !fax_detected;
bool res_echo_cancellator = Opt::_echo_canceller && !fax_detected;
bool res_auto_gain_cntrol = Opt::_auto_gain_control && !fax_detected;
bool res_out_of_band_dtmf = Opt::_options._suppression_delay() && Opt::_options._out_of_band_dtmfs() && !fax_detected;
bool res_echo_cancellator = Opt::_options._echo_canceller() && !fax_detected;
bool res_auto_gain_cntrol = Opt::_options._auto_gain_control() && !fax_detected;
if (!call()->_flags.check(Kflags::KEEP_DTMF_SUPPRESSION))
dtmfSuppression(res_out_of_band_dtmf);
@ -497,7 +511,7 @@ bool BoardFXO::KhompPvtFXO::onDtmfSendFinish(K3L_EVENT *e)
autoGainControl(res_auto_gain_cntrol);
/* start sending audio if wanted so */
if (Opt::_fxo_send_pre_audio)
if (Opt::_options._fxo_send_pre_audio())
startStream();
//TODO: Verificar isso aqui
@ -624,13 +638,13 @@ bool BoardFXO::KhompPvtFXO::setupConnection()
bool fax_detected = callFXO()->_flags.check(Kflags::FAX_DETECTED) || (callFXO()->_var_fax_adjust == T_TRUE);
bool res_out_of_band_dtmf = (call()->_var_dtmf_state == T_UNKNOWN || fax_detected ?
Opt::_suppression_delay && Opt::_out_of_band_dtmfs && !fax_detected : (call()->_var_dtmf_state == T_TRUE));
Opt::_options._suppression_delay() && Opt::_options._out_of_band_dtmfs() && !fax_detected : (call()->_var_dtmf_state == T_TRUE));
bool res_echo_cancellator = (call()->_var_echo_state == T_UNKNOWN || fax_detected ?
Opt::_echo_canceller && !fax_detected : (call()->_var_echo_state == T_TRUE));
Opt::_options._echo_canceller() && !fax_detected : (call()->_var_echo_state == T_TRUE));
bool res_auto_gain_cntrol = (call()->_var_gain_state == T_UNKNOWN || fax_detected ?
Opt::_auto_gain_control && !fax_detected : (call()->_var_gain_state == T_TRUE));
Opt::_options._auto_gain_control() && !fax_detected : (call()->_var_gain_state == T_TRUE));
if (!call()->_flags.check(Kflags::REALLY_CONNECTED))
{
@ -739,8 +753,13 @@ bool BoardFXO::KhompPvtFXO::validContexts(
{
DBG(FUNC,PVT_FMT(_target,"(FXO) c"));
contexts.push_back(Opt::_context_fxo);
contexts.push_back(Opt::_context2_fxo);
if(!_group_context.empty())
{
contexts.push_back(_group_context);
}
contexts.push_back(Opt::_options._context_fxo());
contexts.push_back(Opt::_options._context2_fxo());
for (MatchExtension::ContextListType::iterator i = contexts.begin(); i != contexts.end(); i++)
{

View File

@ -115,10 +115,11 @@ bool BoardGSM::KhompPvtGSM::onCallSuccess(K3L_EVENT *e)
if (call()->_pre_answer)
{
dtmfSuppression(Opt::_out_of_band_dtmfs);
dtmfSuppression(Opt::_options._out_of_band_dtmfs());
startListen();
startStream();
switch_channel_mark_pre_answered(getFSChannel());
}
}
catch (ScopedLockFailed & err)
@ -126,6 +127,11 @@ bool BoardGSM::KhompPvtGSM::onCallSuccess(K3L_EVENT *e)
LOG(ERROR, PVT_FMT(_target, "(GSM) r (unable to lock %s!)") % err._msg.c_str() );
return false;
}
catch (Board::KhompPvt::InvalidSwitchChannel & err)
{
LOG(ERROR, PVT_FMT(target(), "(GSM) r (%s)") % err._msg.c_str() );
return false;
}
DBG(FUNC, PVT_FMT(_target, "(GSM) r"));
@ -401,14 +407,14 @@ bool BoardGSM::KhompPvtGSM::setupConnection()
}
bool res_out_of_band_dtmf = (call()->_var_dtmf_state == T_UNKNOWN ?
Opt::_suppression_delay && Opt::_out_of_band_dtmfs : (call()->_var_dtmf_state == T_TRUE));
Opt::_options._suppression_delay() && Opt::_options._out_of_band_dtmfs() : (call()->_var_dtmf_state == T_TRUE));
bool res_echo_cancellator = (call()->_var_echo_state == T_UNKNOWN ?
Opt::_echo_canceller : (call()->_var_echo_state == T_TRUE));
Opt::_options._echo_canceller() : (call()->_var_echo_state == T_TRUE));
bool res_auto_gain_cntrol = (call()->_var_gain_state == T_UNKNOWN ?
Opt::_auto_gain_control : (call()->_var_gain_state == T_TRUE));
Opt::_options._auto_gain_control() : (call()->_var_gain_state == T_TRUE));
if (!call()->_flags.check(Kflags::REALLY_CONNECTED))
@ -516,6 +522,11 @@ bool BoardGSM::KhompPvtGSM::validContexts(
{
DBG(FUNC,PVT_FMT(_target,"(GSM) c"));
if(!_group_context.empty())
{
contexts.push_back(_group_context);
}
if (!extra_context.empty())
{
if (!_group_context.empty())
@ -526,25 +537,25 @@ bool BoardGSM::KhompPvtGSM::validContexts(
contexts.push_back(pvt_context);
}
if (!Opt::_context_gsm_call.empty())
if (!Opt::_options._context_gsm_call().empty())
{
std::string context(Opt::_context_gsm_call);
std::string context(Opt::_options._context_gsm_call());
context += "-";
context += extra_context;
contexts.push_back(_group_context);
}
if (!Opt::_context2_gsm_call.empty())
if (!Opt::_options._context2_gsm_call().empty())
{
std::string context(Opt::_context2_gsm_call);
std::string context(Opt::_options._context2_gsm_call());
context += "-";
context += extra_context;
contexts.push_back(_group_context);
}
}
contexts.push_back(Opt::_context_gsm_call);
contexts.push_back(Opt::_context2_gsm_call);
contexts.push_back(Opt::_options._context_gsm_call());
contexts.push_back(Opt::_options._context2_gsm_call());
for (MatchExtension::ContextListType::iterator i = contexts.begin(); i != contexts.end(); i++)
replaceTemplate((*i), "CC", _target.object);

View File

@ -121,15 +121,16 @@ bool BoardE1::KhompPvtE1::onCallSuccess(K3L_EVENT *e)
if (call()->_pre_answer)
{
dtmfSuppression(Opt::_out_of_band_dtmfs && !call()->_flags.check(Kflags::FAX_DETECTED));
dtmfSuppression(Opt::_options._out_of_band_dtmfs()&& !call()->_flags.check(Kflags::FAX_DETECTED));
startListen();
startStream();
switch_channel_mark_pre_answered(getFSChannel());
}
else
{
call()->_flags.set(Kflags::GEN_PBX_RING);
call()->_idx_pbx_ring = Board::board(_target.device)->_timers.add(Opt::_ringback_pbx_delay,
call()->_idx_pbx_ring = Board::board(_target.device)->_timers.add(Opt::_options._ringback_pbx_delay(),
&Board::KhompPvt::pbxRingGen,this, TM_VAL_CALL);
}
@ -139,7 +140,7 @@ bool BoardE1::KhompPvtE1::onCallSuccess(K3L_EVENT *e)
LOG(ERROR, PVT_FMT(_target, "(E1) r (unable to lock %s!)") % err._msg.c_str() );
return false;
}
catch (K3LAPI::invalid_device & err)
catch (K3LAPITraits::invalid_device & err)
{
LOG(ERROR, PVT_FMT(_target, "(E1) r (unable to get device: %d!)") % err.device);
return false;
@ -152,7 +153,7 @@ bool BoardE1::KhompPvtE1::onCallSuccess(K3L_EVENT *e)
bool BoardE1::KhompPvtE1::onAudioStatus(K3L_EVENT *e)
{
//DBG(FUNC, PVT_FMT(_target, "(E1) c"));
DBG(STRM, PVT_FMT(_target, "(E1) c"));
try
{
@ -160,16 +161,27 @@ bool BoardE1::KhompPvtE1::onAudioStatus(K3L_EVENT *e)
if(e->AddInfo == kmtFax)
{
DBG(FUNC, PVT_FMT(_target, "Fax detected"));
DBG(STRM, PVT_FMT(_target, "Fax detected"));
/* hadn't we did this already? */
bool already_detected = call()->_flags.check(Kflags::FAX_DETECTED);
time_t time_was = call()->_call_statistics->_base_time;
time_t time_now = time(NULL);
bool detection_timeout = (time_now > (time_was + (time_t) (Opt::_options._fax_adjustment_timeout())));
DBG(STRM, PVT_FMT(_target, "is set? (%s) timeout? (%s)")
% (already_detected ? "true" : "false") % (detection_timeout ? "true" : "false"));
BEGIN_CONTEXT
{
if(already_detected)
break;
ScopedPvtLock lock(this);
/* already adjusted? do not adjust again. */
if (already_detected || detection_timeout)
break;
if (callE1()->_call_info_drop != 0 || callE1()->_call_info_report)
{
/* we did not detected fax yet, send answer info! */
@ -182,7 +194,7 @@ bool BoardE1::KhompPvtE1::onAudioStatus(K3L_EVENT *e)
}
}
if (Opt::_auto_fax_adjustment)
if (Opt::_options._auto_fax_adjustment())
{
DBG(FUNC, PVT_FMT(_target, "communication will be adjusted for fax!"));
_fax->adjustForFax();
@ -207,7 +219,7 @@ bool BoardE1::KhompPvtE1::onAudioStatus(K3L_EVENT *e)
bool ret = KhompPvt::onAudioStatus(e);
//DBG(FUNC, PVT_FMT(_target, "(E1) r"));
DBG(STRM, PVT_FMT(_target, "(E1) r"));
return ret;
}
@ -283,7 +295,7 @@ bool BoardE1::KhompPvtE1::onDisconnect(K3L_EVENT *e)
if (call()->_flags.check(Kflags::IS_OUTGOING) ||
call()->_flags.check(Kflags::IS_INCOMING))
{
if(Opt::_disconnect_delay == 0)
if(Opt::_options._disconnect_delay()== 0)
{
DBG(FUNC, PVT_FMT(_target, "queueing disconnecting outgoing channel!"));
command(KHOMP_LOG, CM_DISCONNECT);
@ -291,7 +303,7 @@ bool BoardE1::KhompPvtE1::onDisconnect(K3L_EVENT *e)
else
{
callE1()->_idx_disconnect = Board::board(_target.device)->_timers.add(
1000 * Opt::_disconnect_delay,&BoardE1::KhompPvtE1::delayedDisconnect,this);
1000 * Opt::_options._disconnect_delay(),&BoardE1::KhompPvtE1::delayedDisconnect,this);
}
}
else
@ -309,7 +321,7 @@ bool BoardE1::KhompPvtE1::onDisconnect(K3L_EVENT *e)
LOG(ERROR, PVT_FMT(_target, "(E1) r (unable to lock %s!)") % err._msg.c_str() );
return false;
}
catch (K3LAPI::invalid_device & err)
catch (K3LAPITraits::invalid_device & err)
{
LOG(ERROR, PVT_FMT(_target, "(E1) r (unable to get device: %d!)") % err.device);
return false;
@ -767,13 +779,13 @@ bool BoardE1::KhompPvtE1::setupConnection()
bool fax_detected = callE1()->_flags.check(Kflags::FAX_DETECTED) || (callE1()->_var_fax_adjust == T_TRUE);
bool res_out_of_band_dtmf = (call()->_var_dtmf_state == T_UNKNOWN || fax_detected ?
Opt::_suppression_delay && Opt::_out_of_band_dtmfs && !fax_detected : (call()->_var_dtmf_state == T_TRUE));
Opt::_options._suppression_delay()&& Opt::_options._out_of_band_dtmfs()&& !fax_detected : (call()->_var_dtmf_state == T_TRUE));
bool res_echo_cancellator = (call()->_var_echo_state == T_UNKNOWN || fax_detected ?
Opt::_echo_canceller && !fax_detected : (call()->_var_echo_state == T_TRUE));
Opt::_options._echo_canceller()&& !fax_detected : (call()->_var_echo_state == T_TRUE));
bool res_auto_gain_cntrol = (call()->_var_gain_state == T_UNKNOWN || fax_detected ?
Opt::_auto_gain_control && !fax_detected : (call()->_var_gain_state == T_TRUE));
Opt::_options._auto_gain_control()&& !fax_detected : (call()->_var_gain_state == T_TRUE));
if (!call()->_flags.check(Kflags::REALLY_CONNECTED))
{
@ -823,7 +835,12 @@ bool BoardE1::KhompPvtE1::validContexts(
{
DBG(FUNC,PVT_FMT(_target, "(E1) c"));
contexts.push_back(Opt::_context_digital);
if(!_group_context.empty())
{
contexts.push_back(_group_context);
}
contexts.push_back(Opt::_options._context_digital());
for (MatchExtension::ContextListType::iterator i = contexts.begin(); i != contexts.end(); i++)
{
@ -1122,7 +1139,7 @@ void BoardE1::KhompPvtR2::reportFailToReceive(int fail_code)
{
KhompPvt::reportFailToReceive(fail_code);
if (Opt::_r2_strict_behaviour && fail_code != -1)
if (Opt::_options._r2_strict_behaviour()&& fail_code != -1)
{
DBG(FUNC,PVT_FMT(_target, "sending a 'unknown number' message/audio"));
@ -1586,7 +1603,7 @@ bool BoardE1::KhompPvtR2::sendPreAudio(int rb_value)
DBG(FUNC,PVT_FMT(_target, "doing the R2 pre_connect wait..."));
/* wait some ms, just to be sure the command has been sent. */
usleep(Opt::_r2_preconnect_wait * 1000);
usleep(Opt::_options._r2_preconnect_wait()* 1000);
if (call()->_flags.check(Kflags::HAS_PRE_AUDIO))
{
@ -1654,7 +1671,7 @@ bool BoardE1::KhompPvtR2::indicateRinging()
{
int ringback_value = RingbackDefs::RB_SEND_DEFAULT;
bool do_drop_call = Opt::_drop_collect_call
bool do_drop_call = Opt::_options._drop_collect_call()
|| call()->_flags.check(Kflags::DROP_COLLECT);
if (do_drop_call && call()->_collect_call)
@ -1679,7 +1696,7 @@ bool BoardE1::KhompPvtR2::indicateRinging()
% condition_string);
}
if (Opt::_r2_strict_behaviour)
if (Opt::_options._r2_strict_behaviour())
{
/* send ringback too? */
send_ringback = sendPreAudio(ringback_value);
@ -1700,7 +1717,7 @@ bool BoardE1::KhompPvtR2::indicateRinging()
DBG(FUNC, PVT_FMT(_target, "Send ringback!"));
call()->_flags.set(Kflags::GEN_CO_RING);
call()->_idx_co_ring = Board::board(_target.device)->_timers.add(Opt::_ringback_co_delay, &Board::KhompPvt::coRingGen,this);
call()->_idx_co_ring = Board::board(_target.device)->_timers.add(Opt::_options._ringback_co_delay(), &Board::KhompPvt::coRingGen,this);
/* start grabbing audio */
startListen();
@ -1722,7 +1739,7 @@ bool BoardE1::KhompPvtR2::indicateRinging()
LOG(ERROR,PVT_FMT(_target, "(R2) r (%s)") % err._msg.c_str());
return false;
}
catch (K3LAPI::invalid_device & err)
catch (K3LAPITraits::invalid_device & err)
{
LOG(ERROR, PVT_FMT(_target, "(R2) r (unable to get device: %d!)") % err.device);
return false;
@ -1768,9 +1785,9 @@ bool BoardE1::KhompPvtR2::onNewCall(K3L_EVENT *e)
if(!ret)
return false;
if (!Opt::_r2_strict_behaviour)
if (!Opt::_options._r2_strict_behaviour())
{
bool do_drop_collect = Opt::_drop_collect_call;
bool do_drop_collect = Opt::_options._drop_collect_call();
const char* drop_str = getFSGlobalVar("KDropCollectCall");
if(checkTrueString(drop_str))
@ -1936,7 +1953,7 @@ bool BoardE1::KhompPvtR2::onNumberDetected(K3L_EVENT *e)
LOG(ERROR, PVT_FMT(target(), "unable to lock %s!") % err._msg.c_str() );
return false;
}
catch (K3LAPI::invalid_device & err)
catch (K3LAPITraits::invalid_device & err)
{
LOG(ERROR, PVT_FMT(_target, "unable to get device: %d!") % err.device);
return false;
@ -1973,32 +1990,32 @@ bool BoardE1::KhompPvtFlash::sendDtmf(std::string digit)
return ret;
}
Opt::OrigToNseqMapType BoardE1::KhompPvtFXS::generateNseqMap()
OrigToNseqMapType BoardE1::KhompPvtFXS::generateNseqMap()
{
Opt::OrigToNseqMapType fxs_nseq; /* sequence numbers on FXS */
OrigToNseqMapType fxs_nseq; /* sequence numbers on FXS */
fxs_nseq.insert(Opt::OrigToNseqPairType("", 0)); /* global sequence */
fxs_nseq.insert(OrigToNseqPairType("", 0)); /* global sequence */
for (Opt::BoardToOrigMapType::iterator i = Opt::_fxs_orig_base.begin(); i != Opt::_fxs_orig_base.end(); i++)
for (BoardToOrigMapType::iterator i = Opt::_fxs_orig_base.begin(); i != Opt::_fxs_orig_base.end(); i++)
{
fxs_nseq.insert(Opt::OrigToNseqPairType((*i).second, 0));
fxs_nseq.insert(OrigToNseqPairType((*i).second, 0));
}
return fxs_nseq;
}
void BoardE1::KhompPvtFXS::load(Opt::OrigToNseqMapType & fxs_nseq)
void BoardE1::KhompPvtFXS::load(OrigToNseqMapType & fxs_nseq)
{
Opt::BoardToOrigMapType::iterator it1 = Opt::_fxs_orig_base.find(_target.device);
Opt::OrigToNseqMapType::iterator it2;
BoardToOrigMapType::iterator it1 = Opt::_fxs_orig_base.find(_target.device);
OrigToNseqMapType::iterator it2;
std::string orig_base("invalid"); /* will have orig base */
if (it1 == Opt::_fxs_orig_base.end())
{
it2 = fxs_nseq.find("");
orig_base = Opt::_fxs_global_orig_base;
orig_base = Opt::_options._fxs_global_orig_base();
}
else
{
@ -2024,8 +2041,8 @@ void BoardE1::KhompPvtFXS::load(Opt::OrigToNseqMapType & fxs_nseq)
loadOptions();
/* makes a "reverse mapping" for Dial using 'r' identifiers */
Opt::_fxs_branch_map.insert(Opt::BranchToObjectPairType(_fxs_orig_addr,
Opt::ObjectIdType(_target.device, _target.object)));
Opt::_fxs_branch_map.insert(BranchToObjectPairType(_fxs_orig_addr,
ObjectIdType(_target.device, _target.object)));
/* increment sequence number */
++((*it2).second);
@ -2045,19 +2062,16 @@ void BoardE1::KhompPvtFXS::loadOptions()
/* Initialize fxs default options */
_calleridname.clear();
_amaflags = Opt::_amaflags;
_callgroup = Opt::_callgroup;
_pickupgroup = Opt::_pickupgroup;
//_amaflags = Opt::_amaflags;
_callgroup = Opt::_options._callgroup();
_pickupgroup = Opt::_options._pickupgroup();
_context.clear();
_input_volume = Opt::_input_volume;
_output_volume = Opt::_output_volume;
_mohclass = Opt::_global_mohclass;
_language = Opt::_global_language;
_accountcode = Opt::_accountcode;
_input_volume = Opt::_options._input_volume();
_output_volume = Opt::_options._output_volume();
_mailbox.clear();
_flash = Opt::_flash;
_flash = Opt::_options._flash();
Opt::BranchToOptMapType::iterator it3 = Opt::_branch_options.find(_fxs_orig_addr);
BranchToOptMapType::iterator it3 = Opt::_branch_options.find(_fxs_orig_addr);
if (it3 != Opt::_branch_options.end())
{
@ -2066,9 +2080,9 @@ void BoardE1::KhompPvtFXS::loadOptions()
//TODO: Implementar o setVolume para levar em consideracao que o
// padrao pode ser o da FXS
if (_input_volume != Opt::_input_volume)
if (_input_volume != Opt::_options._input_volume())
setVolume("input", _input_volume);
if (_output_volume != Opt::_output_volume)
if (_output_volume != Opt::_options._output_volume())
setVolume("output", _output_volume);
}
@ -2163,11 +2177,11 @@ bool BoardE1::KhompPvtFXS::parseBranchOptions(std::string options_str)
}
else if (opt_name == "calleridnum") // conscious ultra chuncho!
{
Opt::BranchToOptMapType::iterator it3 = Opt::_branch_options.find(_fxs_orig_addr);
BranchToOptMapType::iterator it3 = Opt::_branch_options.find(_fxs_orig_addr);
if (it3 != Opt::_branch_options.end())
{
Opt::_branch_options.insert(Opt::BranchToOptPairType(opt_value, it3->second));
Opt::_branch_options.insert(BranchToOptPairType(opt_value, it3->second));
Opt::_branch_options.erase(it3);
}
@ -2221,10 +2235,11 @@ bool BoardE1::KhompPvtFXS::alloc()
startStream();
/* do this procedures early (as audio is already being heard) */
dtmfSuppression(Opt::_out_of_band_dtmfs && !callFXS()->_flags.check(Kflags::FAX_DETECTED));
echoCancellation(Opt::_echo_canceller && !callFXS()->_flags.check(Kflags::FAX_DETECTED));
autoGainControl(Opt::_auto_gain_control && !callFXS()->_flags.check(Kflags::FAX_DETECTED));
dtmfSuppression(Opt::_options._out_of_band_dtmfs() && !callFXS()->_flags.check(Kflags::FAX_DETECTED));
echoCancellation(Opt::_options._echo_canceller() && !callFXS()->_flags.check(Kflags::FAX_DETECTED));
autoGainControl(Opt::_options._auto_gain_control() && !callFXS()->_flags.check(Kflags::FAX_DETECTED));
//TODO: NEED RECORD HERE !?
/* if it does not need context, probably it's a pickupcall and will
not pass throw setup_connection, so we start recording here*/
//if (!need_context && K::opt::recording && !pvt->is_recording)
@ -2234,7 +2249,6 @@ bool BoardE1::KhompPvtFXS::alloc()
return true;
}
bool BoardE1::KhompPvtFXS::onSeizureStart(K3L_EVENT *e)
{
DBG(FUNC, PVT_FMT(_target, "(FXS) c"));
@ -2260,13 +2274,13 @@ bool BoardE1::KhompPvtFXS::onSeizureStart(K3L_EVENT *e)
return false;
}
/* desabilita para evitar problemas de detecção de DTMF */
/* disable to avoid problems with DTMF detection */
echoCancellation(false);
autoGainControl(false);
call()->_orig_addr = _fxs_orig_addr;
Opt::OrigToDestMapType::iterator i = Opt::_fxs_hotline.find(_fxs_orig_addr);
OrigToDestMapType::iterator i = Opt::_fxs_hotline.find(_fxs_orig_addr);
if (i != Opt::_fxs_hotline.end())
{
@ -2285,7 +2299,6 @@ bool BoardE1::KhompPvtFXS::onSeizureStart(K3L_EVENT *e)
call()->_flags.clear(Kflags::FXS_DIAL_ONGOING);
call()->_flags.set(Kflags::FXS_OFFHOOK);
}
}
catch (ScopedLockFailed & err)
{
@ -2312,16 +2325,17 @@ bool BoardE1::KhompPvtFXS::onCallSuccess(K3L_EVENT *e)
if (call()->_pre_answer)
{
dtmfSuppression(Opt::_out_of_band_dtmfs);
dtmfSuppression(Opt::_options._out_of_band_dtmfs());
startListen();
startStream();
switch_channel_mark_pre_answered(getFSChannel());
}
else
{
call()->_flags.set(Kflags::GEN_PBX_RING);
call()->_idx_pbx_ring = Board::board(_target.device)->_timers.add(
Opt::_ringback_pbx_delay,
Opt::_options._ringback_pbx_delay(),
&Board::KhompPvt::pbxRingGen,
this,
TM_VAL_CALL);
@ -2333,11 +2347,16 @@ bool BoardE1::KhompPvtFXS::onCallSuccess(K3L_EVENT *e)
LOG(ERROR, PVT_FMT(_target, "(FXS) r (unable to lock %s!)") % err._msg.c_str() );
return false;
}
catch (K3LAPI::invalid_device & err)
catch (K3LAPITraits::invalid_device & err)
{
LOG(ERROR, PVT_FMT(_target, "(FXS) r (unable to get device: %d!)") % err.device);
return false;
}
catch (Board::KhompPvt::InvalidSwitchChannel & err)
{
LOG(ERROR, PVT_FMT(target(), "(FXS) r (%s)") % err._msg.c_str() );
return false;
}
DBG(FUNC, PVT_FMT(_target, "(FXS) r"));
@ -2536,7 +2555,7 @@ bool BoardE1::KhompPvtFXS::startTransfer()
startCadence(PLAY_PBX_TONE);
callFXS()->_idx_transfer = Board::board(_target.device)->_timers.add(Opt::_fxs_digit_timeout * 1000, &BoardE1::KhompPvtFXS::transferTimer, this, TM_VAL_CALL);
callFXS()->_idx_transfer = Board::board(_target.device)->_timers.add(Opt::_options._fxs_digit_timeout()* 1000, &BoardE1::KhompPvtFXS::transferTimer, this, TM_VAL_CALL);
}
catch(Board::KhompPvt::InvalidSwitchChannel & err)
@ -2545,7 +2564,7 @@ bool BoardE1::KhompPvtFXS::startTransfer()
LOG(ERROR, PVT_FMT(target(), "r (no valid partner %s!)") % err._msg.c_str());
return false;
}
catch (K3LAPI::invalid_device & err)
catch (K3LAPITraits::invalid_device & err)
{
LOG(ERROR, PVT_FMT(_target, "unable to get device: %d!") % err.device);
}
@ -2570,7 +2589,7 @@ bool BoardE1::KhompPvtFXS::stopTransfer()
{
Board::board(_target.device)->_timers.del(callFXS()->_idx_transfer);
}
catch (K3LAPI::invalid_device & err)
catch (K3LAPITraits::invalid_device & err)
{
LOG(ERROR, PVT_FMT(_target, "unable to get device: %d!") % err.device);
}
@ -2690,7 +2709,7 @@ bool BoardE1::KhompPvtFXS::transfer(std::string & context, bool blind)
{
Board::board(_target.device)->_timers.del(callFXS()->_idx_transfer);
}
catch (K3LAPI::invalid_device & err)
catch (K3LAPITraits::invalid_device & err)
{
LOG(ERROR, PVT_FMT(_target, "unable to get device: %d!") % err.device);
}
@ -2709,7 +2728,7 @@ bool BoardE1::KhompPvtFXS::transfer(std::string & context, bool blind)
if(blind)
{
DBG(FUNC, PVT_FMT(_target, "Blind Transfer"));
switch_ivr_session_transfer(peer_session, number.c_str(), Opt::_dialplan.c_str(), context.c_str());
switch_ivr_session_transfer(peer_session, number.c_str(), Opt::_options._dialplan().c_str(), context.c_str());
}
else
{
@ -2748,7 +2767,7 @@ bool BoardE1::KhompPvtFXS::transfer(std::string & context, bool blind)
switch_channel_set_variable(channel, SWITCH_PARK_AFTER_BRIDGE_VARIABLE, "true");
switch_core_event_hook_add_state_change(session(), xferHook);
switch_ivr_session_transfer(session(), number.c_str(), Opt::_dialplan.c_str(), context.c_str());
switch_ivr_session_transfer(session(), number.c_str(), Opt::_options._dialplan().c_str(), context.c_str());
DBG(FUNC, PVT_FMT(target(), "Generating ring"));
call()->_indication = INDICA_RING;
@ -2758,9 +2777,9 @@ bool BoardE1::KhompPvtFXS::transfer(std::string & context, bool blind)
/*
try
{
call()->_idx_co_ring = Board::board(_target.device)->_timers.add(Opt::_ringback_co_delay, &Board::KhompPvt::coRingGen,this);
call()->_idx_co_ring = Board::board(_target.device)->_timers.add(Opt::_options._ringback_co_delay(), &Board::KhompPvt::coRingGen,this);
}
catch (K3LAPI::invalid_device & err)
catch (K3LAPITraits::invalid_device & err)
{
LOG(ERROR, PVT_FMT(_target, "unable to get device: %d!") % err.device);
}
@ -2816,7 +2835,7 @@ bool BoardE1::KhompPvtFXS::onDtmfDetected(K3L_EVENT *e)
mixer(KHOMP_LOG, 1, kmsGenerator, kmtSilence);
callFXS()->_idx_dial = Board::board(_target.device)->_timers.add(Opt::_fxs_digit_timeout * 1000, &BoardE1::KhompPvtFXS::dialTimer, this, TM_VAL_CALL);
callFXS()->_idx_dial = Board::board(_target.device)->_timers.add(Opt::_options._fxs_digit_timeout()* 1000, &BoardE1::KhompPvtFXS::dialTimer, this, TM_VAL_CALL);
}
else
{
@ -2849,7 +2868,7 @@ bool BoardE1::KhompPvtFXS::onDtmfDetected(K3L_EVENT *e)
DBG(FUNC, PVT_FMT(target(), "match more..."));
/* can match, will match more, and it's an external call? */
for (Opt::DestVectorType::iterator i = Opt::_fxs_co_dialtone.begin(); i != Opt::_fxs_co_dialtone.end(); i++)
for (DestVectorType::const_iterator i = Opt::_options._fxs_co_dialtone().begin(); i != Opt::_options._fxs_co_dialtone().end(); i++)
{
if (callFXS()->_incoming_exten == (*i))
{
@ -2931,7 +2950,7 @@ bool BoardE1::KhompPvtFXS::onDtmfDetected(K3L_EVENT *e)
DBG(FUNC, PVT_FMT(target(), "match more..."));
/* can match, will match more, and it's an external call? */
for (Opt::DestVectorType::iterator i = Opt::_fxs_co_dialtone.begin(); i != Opt::_fxs_co_dialtone.end(); i++)
for (DestVectorType::const_iterator i = Opt::_options._fxs_co_dialtone().begin(); i != Opt::_options._fxs_co_dialtone().end(); i++)
{
if (callFXS()->_flash_transfer == (*i))
{
@ -2967,7 +2986,7 @@ bool BoardE1::KhompPvtFXS::onDtmfDetected(K3L_EVENT *e)
LOG(ERROR, PVT_FMT(_target, "(FXS) r (unable to lock %s!)") % err._msg.c_str() );
return false;
}
catch (K3LAPI::invalid_device & err)
catch (K3LAPITraits::invalid_device & err)
{
LOG(ERROR, PVT_FMT(_target, "(FXS) r (unable to get device: %d!)") % err.device);
return false;
@ -3080,7 +3099,7 @@ int BoardE1::KhompPvtFXS::makeCall(std::string params)
/* we always have audio */
call()->_flags.set(Kflags::HAS_PRE_AUDIO);
if (Opt::_fxs_bina && !call()->_orig_addr.empty())
if (Opt::_options._fxs_bina()&& !call()->_orig_addr.empty())
{
/* Sending Bina DTMF*/
callFXS()->_flags.set(Kflags::WAIT_SEND_DTMF);
@ -3165,6 +3184,11 @@ bool BoardE1::KhompPvtFXS::doChannelAnswer(CommandRequest &cmd)
LOG(ERROR,PVT_FMT(_target, "(FXS) r (unable to lock %s!)") % err._msg.c_str() );
return false;
}
catch (Board::KhompPvt::InvalidSwitchChannel & err)
{
LOG(ERROR, PVT_FMT(target(), "r (%s)") % err._msg.c_str() );
return false;
}
DBG(FUNC, PVT_FMT(_target, "(FXS) r"));
@ -3276,14 +3300,14 @@ bool BoardE1::KhompPvtFXS::setupConnection()
}
bool res_out_of_band_dtmf = (call()->_var_dtmf_state == T_UNKNOWN ?
Opt::_suppression_delay && Opt::_out_of_band_dtmfs : (call()->_var_dtmf_state == T_TRUE));
Opt::_options._suppression_delay() && Opt::_options._out_of_band_dtmfs(): (call()->_var_dtmf_state == T_TRUE));
bool res_echo_cancellator = (call()->_var_echo_state == T_UNKNOWN ?
Opt::_echo_canceller : (call()->_var_echo_state == T_TRUE));
Opt::_options._echo_canceller() : (call()->_var_echo_state == T_TRUE));
bool res_auto_gain_cntrol = (call()->_var_gain_state == T_UNKNOWN ?
Opt::_auto_gain_control : (call()->_var_gain_state == T_TRUE));
Opt::_options._auto_gain_control() : (call()->_var_gain_state == T_TRUE));
if (!call()->_flags.check(Kflags::REALLY_CONNECTED))
@ -3408,8 +3432,13 @@ bool BoardE1::KhompPvtFXS::validContexts(
if(!_context.empty())
contexts.push_back(_context);
contexts.push_back(Opt::_context_fxs);
contexts.push_back(Opt::_context2_fxs);
if(!_group_context.empty())
{
contexts.push_back(_group_context);
}
contexts.push_back(Opt::_options._context_fxs());
contexts.push_back(Opt::_options._context2_fxs());
for (MatchExtension::ContextListType::iterator i = contexts.begin(); i != contexts.end(); i++)
{

View File

@ -50,7 +50,12 @@ bool BoardPassive::KhompPvtPassive::validContexts(
{
DBG(FUNC,PVT_FMT(_target,"(Passive) c"));
contexts.push_back(Opt::_context_pr);
if(!_group_context.empty())
{
contexts.push_back(_group_context);
}
contexts.push_back(Opt::_options._context_pr());
for (MatchExtension::ContextListType::iterator i = contexts.begin(); i != contexts.end(); i++)
{

View File

@ -47,170 +47,109 @@
#include "logger.h"
#include "spec.h"
bool Opt::_debug;
std::string Opt::_dialplan;
std::string Opt::_context;
std::string Opt::_user_xfer;
std::map < std::string, CSpan > Opt::_spans;
Opt::GroupToDestMapType Opt::_groups;
Opt::CadencesMapType Opt::_cadences;
#include <function.hpp>
bool Opt::_echo_canceller;
bool Opt::_auto_gain_control;
bool Opt::_out_of_band_dtmfs;
bool Opt::_suppression_delay;
bool Opt::_pulse_forwarding;
bool Opt::_native_bridge;
bool Opt::_recording;
bool Opt::_has_ctbus;
bool Opt::_fxs_bina;
bool Opt::_fxo_send_pre_audio;
bool Opt::_drop_collect_call;
bool Opt::_ignore_letter_dtmfs;
bool Opt::_optimize_audio_path;
Options Opt::_options;
CadencesMapType Opt::_cadences;
GroupToDestMapType Opt::_groups;
OrigToDestMapType Opt::_fxs_hotline;
BoardToOrigMapType Opt::_fxs_orig_base;
BranchToOptMapType Opt::_branch_options;
BranchToObjectMapType Opt::_fxs_branch_map;
bool Opt::_auto_fax_adjustment;
unsigned int Opt::_fax_adjustment_timeout;
bool Opt::_r2_strict_behaviour;
unsigned int Opt::_r2_preconnect_wait;
unsigned int Opt::_fxs_digit_timeout;
unsigned int Opt::_transferdigittimeout;
std::string Opt::_flash;
std::string Opt::_atxfer;
std::string Opt::_blindxfer;
unsigned int Opt::_ringback_co_delay;
unsigned int Opt::_ringback_pbx_delay;
unsigned int Opt::_disconnect_delay;
int Opt::_input_volume;
int Opt::_output_volume;
Opt::DestVectorType Opt::_fxs_co_dialtone;
Opt::OrigToDestMapType Opt::_fxs_hotline;
std::string Opt::_fxs_global_orig_base;
Opt::BoardToOrigMapType Opt::_fxs_orig_base;
Opt::BranchToObjectMapType Opt::_fxs_branch_map;
Opt::BranchToOptMapType Opt::_branch_options;
std::string Opt::_global_mohclass;
std::string Opt::_global_language;
std::string Opt::_record_prefix;
std::string Opt::_context_gsm_call;
std::string Opt::_context2_gsm_call;
std::string Opt::_context_gsm_sms;
std::string Opt::_context_fxo;
std::string Opt::_context2_fxo;
std::string Opt::_context_fxs;
std::string Opt::_context2_fxs;
std::string Opt::_context_digital;
std::string Opt::_context_pr;
int Opt::_amaflags;
std::string Opt::_callgroup;
std::string Opt::_pickupgroup;
std::string Opt::_accountcode;
unsigned int Opt::_kommuter_timeout;
std::string Opt::_kommuter_activation;
unsigned int Opt::_audio_packet_size;
/* not beautiful, should think of something! */
#define FUNCTION_VALUE(x) reinterpret_cast< Config::FunctionValue Options::* >( x )
void Opt::initialize(void)
{
Globals::options.add(ConfigOption("debug", _debug, false));
Globals::options.add(ConfigOption("dialplan", _dialplan, "XML"));
Globals::options.add(ConfigOption("context", _context, "default"));
Globals::options.add(Config::Option("debug", &Options::_debug, false));
Globals::options.add(Config::Option("dialplan", &Options::_dialplan, "XML"));
Globals::options.add(Config::Option("context", &Options::_context, "default"));
Globals::options.add(ConfigOption("echo-canceller", _echo_canceller, true));
Globals::options.add(ConfigOption("auto-gain-control", _auto_gain_control, true));
Globals::options.add(ConfigOption("out-of-band-dtmfs", _out_of_band_dtmfs, true));
Globals::options.add(ConfigOption("suppression-delay", _suppression_delay, true));
Globals::options.add(ConfigOption("pulse-forwarding", _pulse_forwarding, false));
Globals::options.add(ConfigOption("native-bridge", _native_bridge, true));
Globals::options.add(ConfigOption("recording", _recording, true));
Globals::options.add(ConfigOption("has-ctbus", _has_ctbus, false));
Globals::options.add(ConfigOption("fxs-bina", _fxs_bina, true));
Globals::options.add(ConfigOption("fxo-send-pre-audio", _fxo_send_pre_audio, true));
Globals::options.add(ConfigOption("drop-collect-call", _drop_collect_call, false));
Globals::options.add(ConfigOption("ignore-letter-dtmfs", _ignore_letter_dtmfs, false));
Globals::options.add(ConfigOption("optimize-audio-path", _optimize_audio_path, false));
Globals::options.add(Config::Option("echo-canceller", &Options::_echo_canceller, true));
Globals::options.add(Config::Option("auto-gain-control", &Options::_auto_gain_control, true));
Globals::options.add(Config::Option("out-of-band-dtmfs", &Options::_out_of_band_dtmfs, true));
Globals::options.add(Config::Option("suppression-delay", &Options::_suppression_delay, true));
Globals::options.add(Config::Option("pulse-forwarding", &Options::_pulse_forwarding, false));
Globals::options.add(Config::Option("native-bridge", &Options::_native_bridge, true));
Globals::options.add(Config::Option("recording", &Options::_recording, true));
Globals::options.add(Config::Option("has-ctbus", &Options::_has_ctbus, false));
Globals::options.add(Config::Option("fxs-bina", &Options::_fxs_bina, true));
Globals::options.add(Config::Option("fxo-send-pre-audio", &Options::_fxo_send_pre_audio, true));
Globals::options.add(Config::Option("drop-collect-call", &Options::_drop_collect_call, false));
Globals::options.add(Config::Option("ignore-letter-dtmfs", &Options::_ignore_letter_dtmfs, true));
Globals::options.add(Config::Option("optimize-audio-path", &Options::_optimize_audio_path, false));
Globals::options.add(ConfigOption("auto-fax-adjustment", _auto_fax_adjustment, true));
Globals::options.add(ConfigOption("fax-adjustment-timeout", _fax_adjustment_timeout, 30u, 3u, 9999u));
Globals::options.add(Config::Option("auto-fax-adjustment", &Options::_auto_fax_adjustment, true));
Globals::options.add(Config::Option("fax-adjustment-timeout", &Options::_fax_adjustment_timeout, 30u, 3u, 9999u));
Globals::options.add(ConfigOption("r2-strict-behaviour", _r2_strict_behaviour, false));
Globals::options.add(ConfigOption("r2-preconnect-wait", _r2_preconnect_wait, 250u, 25u, 500u));
Globals::options.add(Config::Option("r2-strict-behaviour", &Options::_r2_strict_behaviour, false));
Globals::options.add(Config::Option("r2-preconnect-wait", &Options::_r2_preconnect_wait, 250u, 25u, 500u));
Globals::options.add(ConfigOption("fxs-digit-timeout", _fxs_digit_timeout, 7u, 1u, 30u));
Globals::options.add(Config::Option("fxs-digit-timeout", &Options::_fxs_digit_timeout, 7u, 1u, 30u));
Globals::options.add(Config::Option("transferdigittimeout", &Options::_transferdigittimeout, 3000u, 0u, 90000u));
Globals::options.add(ConfigOption("transferdigittimeout", _transferdigittimeout, 3000u, 0u, 90000u));
Globals::options.add(Config::Option("atxfer", &Options::_atxfer, ""));
Globals::options.add(Config::Option("blindxfer", &Options::_blindxfer, ""));
Globals::options.add(ConfigOption("flash-to-digits", _flash, "*1"));
Globals::options.add(Config::Option("flash-to-digits", &Options::_flash, "*1"));
Globals::options.add(ConfigOption("atxfer", _atxfer, ""));
Globals::options.add(ConfigOption("blindxfer", _blindxfer, ""));
Globals::options.add(ConfigOption("delay-ringback-co", _ringback_co_delay, 1500u, 0u, 999000u));
Globals::options.add(ConfigOption("delay-ringback-pbx", _ringback_pbx_delay, 2500u, 0u, 999000u));
Globals::options.add(Config::Option("delay-ringback-co", &Options::_ringback_co_delay, 1500u, 0u, 999000u));
Globals::options.add(Config::Option("delay-ringback-pbx", &Options::_ringback_pbx_delay, 2500u, 0u, 999000u));
Globals::options.add(ConfigOption("disconnect-delay", _disconnect_delay, 0u, 0u, 100000u));
Globals::options.add(Config::Option("disconnect-delay", &Options::_disconnect_delay, 0u, 0u, 100000u));
Globals::options.add(ConfigOption("input-volume", _input_volume, 0, -10, 10));
Globals::options.add(ConfigOption("output-volume", _output_volume, 0, -10, 10));
Globals::options.add(Config::Option("input-volume", &Options::_input_volume, 0, -10, 10));
Globals::options.add(Config::Option("output-volume", &Options::_output_volume, 0, -10, 10));
Globals::options.add(Config::Option("fxs-co-dialtone",
FUNCTION_VALUE(&Options::_fxs_co_dialtone), ""));
Globals::options.add(ConfigOption("fxs-co-dialtone", ProcessFXSCODialtone(), ""));
Globals::options.add(ConfigOption("fxs-global-orig", _fxs_global_orig_base, "0"));
Globals::options.add(Config::Option("log-to-disk",
FUNCTION_VALUE(&Options::_log_disk_option), "standard", false));
Globals::options.add(ConfigOption("language", _global_language, ""));
Globals::options.add(ConfigOption("mohclass", _global_mohclass, ""));
Globals::options.add(Config::Option("callgroup", &Options::_callgroup, "0"));
Globals::options.add(ConfigOption("record-prefix", ProcessRecordPrefix(), "/var/spool/freeswitch/monitor/"));
Globals::options.add(Config::Option("pickupgroup", &Options::_pickupgroup, "0"));
Globals::options.add(Config::Option("log-to-console",
FUNCTION_VALUE(&Options::_log_console_option), "standard", false));
Globals::options.add(ConfigOption("context-fxo", _context_fxo, "khomp-DD-CC"));
Globals::options.add(ConfigOption("context-fxo-alt", _context2_fxo, "khomp-DD"));
Globals::options.add(ConfigOption("context-fxs", _context_fxs, "khomp-DD-CC"));
Globals::options.add(ConfigOption("context-fxs-alt", _context2_fxs, "khomp-DD"));
Globals::options.add(ConfigOption("context-gsm-call", _context_gsm_call, "khomp-DD-CC"));
Globals::options.add(ConfigOption("context-gsm-call-alt", _context2_gsm_call, "khomp-DD"));
Globals::options.add(ConfigOption("context-gsm-sms", _context_gsm_sms, "khomp-sms-DD-CC"));
Globals::options.add(ConfigOption("context-digital", _context_digital, "khomp-DD-LL"));
Globals::options.add(ConfigOption("context-pr", _context_pr, "khomp-DD-CC"));
Globals::options.add(Config::Option("trace",
FUNCTION_VALUE(&Options::_log_trace_option), "", false));
Globals::options.add(ConfigOption("amaflags", ProcessAMAFlags(), "default"));
Globals::options.add(ConfigOption("callgroup", _callgroup, "0"));
Globals::options.add(ConfigOption("pickupgroup", _pickupgroup, "0"));
//Globals::options.add(ConfigOption("callgroup", ProcessCallGroup(), "0"));
//Globals::options.add(ConfigOption("pickupgroup", ProcessPickupGroup(), "0"));
Globals::options.add(Config::Option("record-prefix",
FUNCTION_VALUE(&Options::_record_prefix), "/var/spool/freeswitch/monitor/"));
Globals::options.add(Config::Option("fxs-global-orig", &Options::_fxs_global_orig_base, "0"));
Globals::options.add(ConfigOption("accountcode", _accountcode, ""));
Globals::options.add(Config::Option("language", &Options::_global_language, ""));
Globals::options.add(Config::Option("mohclass", &Options::_global_mohclass, ""));
ConfigOption::string_allowed_type kommuter_allowed;
kommuter_allowed.insert("auto");
kommuter_allowed.insert("manual");
Globals::options.add(Config::Option("context-fxo", &Options::_context_fxo, "khomp-DD-CC"));
Globals::options.add(Config::Option("context-fxo-alt", &Options::_context2_fxo, "khomp-DD"));
Globals::options.add(Config::Option("context-fxs", &Options::_context_fxs, "khomp-DD-CC"));
Globals::options.add(Config::Option("context-fxs-alt", &Options::_context2_fxs, "khomp-DD"));
Globals::options.add(Config::Option("context-gsm-call", &Options::_context_gsm_call, "khomp-DD-CC"));
Globals::options.add(Config::Option("context-gsm-call-alt", &Options::_context2_gsm_call, "khomp-DD"));
Globals::options.add(Config::Option("context-gsm-sms", &Options::_context_gsm_sms, "khomp-sms-DD-CC"));
Globals::options.add(Config::Option("context-digital", &Options::_context_digital, "khomp-DD-LL"));
Globals::options.add(Config::Option("context-pr", &Options::_context_pr, "khomp-DD-CC"));
Globals::options.add(ConfigOption("kommuter-activation", _kommuter_activation , "auto", kommuter_allowed));
Globals::options.add(ConfigOption("kommuter-timeout", _kommuter_timeout ,(unsigned int) 10 , (unsigned int) 0 , (unsigned int) 255));
Globals::options.add(Config::Option("accountcode", &Options::_accountcode, ""));
Globals::options.add(ConfigOption("audio-packet-length", _audio_packet_size,
Config::StringSet activation_strings;
activation_strings.insert("auto");
activation_strings.insert("manual");
Globals::options.add(Config::Option("kommuter-activation", &Options::_kommuter_activation , "auto", activation_strings));
Globals::options.add(Config::Option("kommuter-timeout", &Options::_kommuter_timeout ,(unsigned int) 10 , (unsigned int) 0 , (unsigned int) 255));
Globals::options.add(Config::Option("audio-packet-length", &Options::_audio_packet_size,
(unsigned int)KHOMP_READ_PACKET_SIZE, (unsigned int)KHOMP_MIN_READ_PACKET_SIZE, (unsigned int)KHOMP_MAX_READ_PACKET_SIZE, 8u));
Globals::options.add(ConfigOption("log-to-disk", ProcessLogOptions(O_GENERIC), "standard", false));
Globals::options.add(ConfigOption("log-to-console", ProcessLogOptions(O_CONSOLE), "standard", false));
Globals::options.add(ConfigOption("trace", ProcessTraceOptions(), "", false));
Globals::options.add(ConfigOption("user-transfer-digits", _user_xfer, ""));
Globals::options.add(Config::Option("user-transfer-digits", &Options::_user_xfer_digits, ""));
/* aliases */
Globals::options.synonym("context-gsm", "context-gsm-call");
Globals::options.synonym("context-gsm-alt", "context-gsm-call-alt");
@ -224,27 +163,34 @@ void Opt::initialize(void)
Globals::options.synonym("log", "log-to-disk");
Globals::options.synonym("volume", "output-volume");
Globals::options.synonym("disconnectdelay", "disconnect-delay");
}
void Opt::obtain(void)
{
/* everything should start clean! */
cleanConfiguration();
/* reset loaded options */
Globals::options.reset();
loadConfiguration("khomp.conf", NULL);
/* commit, loading defaults where needed */
ConfigOptions::messages_type msgs = Globals::options.commit();
/* config already full loaded at this point, so we can use our own log system... */
for (ConfigOptions::messages_type::iterator i = msgs.begin(); i != msgs.end(); i++)
try
{
DBG(FUNC,FMT("%s") % (*i).c_str());
/* everything should start clean! */
cleanConfiguration();
/* reset loaded options */
Globals::options.reset(&Opt::_options);
/* should be loaded *BEFORE* start_k3l */
loadConfiguration("khomp.conf", NULL);
/* commit, loading defaults where needed */
Config::Options::Messages msgs = Globals::options.commit(&Opt::_options);
/* config already full loaded at this point, so we can use our own log system... */
for (Config::Options::Messages::iterator i = msgs.begin(); i != msgs.end(); i++)
{
DBG(FUNC,FMT("%s") % (*i).c_str());
}
}
catch (std::runtime_error & e)
{
LOG(ERROR, FMT("unable to obtain general options: %s: procedure aborted!") % e.what());
}
}
void Opt::commit(void)
@ -283,8 +229,13 @@ void Opt::loadConfiguration(const char *file_name, const char **section, bool sh
{
switch_xml_t cfg, xml, settings;
if (!(xml = switch_xml_open_cfg(file_name, &cfg, NULL))) {
LOG(ERROR,FMT("Open of %s failed") % file_name);
if (!(xml = switch_xml_open_cfg(file_name, &cfg, NULL)))
{
if (show_errors)
{
LOG(ERROR,FMT("Open of %s failed") % file_name);
}
return;
}
@ -312,24 +263,10 @@ void Opt::loadConfiguration(const char *file_name, const char **section, bool sh
switch_xml_free(xml);
}
void Opt::printConfiguration(switch_stream_handle_t* stream)
{
for( std::map<std::string, CSpan>::iterator ii=_spans.begin(); ii!=_spans.end(); ++ii )
{
stream->write_function(stream,
"Span: %s.\nDialplan: %s.\nContext: %s.\nDialstring: %s.\n\n",
(*ii).first.c_str(),
(*ii).second._dialplan.c_str(),
(*ii).second._context.c_str(),
(*ii).second._dialstring.c_str());
}
}
void Opt::cleanConfiguration(void)
{
_fxs_orig_base.clear();
_fxs_hotline.clear();
_fxs_co_dialtone.clear();
_fxs_branch_map.clear();
_branch_options.clear();
@ -343,72 +280,56 @@ void Opt::cleanConfiguration(void)
_cadences.insert(CadencesPairType("vm-dialtone", CadenceType(1000,100,100,100)));
}
void Opt::ProcessFXSCODialtone::operator()(std::string options) // const
{
Strings::vector_type tokens;
Strings::tokenize(options, tokens, ",");
for (Strings::vector_type::iterator i = tokens.begin(); i != tokens.end(); i++)
_fxs_co_dialtone.push_back(*i);
}
void Opt::ProcessRecordPrefix::operator()(std::string path) // const
{
if (mkdir(path.c_str(), 493 /* 0755 */) < 0 && errno != EEXIST)
{
throw ConfigProcessFailure("the default recording directory could not be created.");
}
else
{
_record_prefix = path;
}
}
void Opt::ProcessAMAFlags::operator()(std::string options)
{
/*
//TODO: Do we need this ?
amaflags = ast_cdr_amaflags2int(options.c_str());
void Options::AmaflagOption::operator()(const Config::StringType & str)
{
//_value = Strings::tolong(str);
//if(_value < 0)
// throw Config::Failure(STG(FMT("invalid AMA flags: %s") % str));
}
if (amaflags < 0)
throw ConfigProcessFailure(STG(FMT("invalid AMA flags: %s") % options));
void Options::CallGroupOption::operator()(const Config::StringType & str)
{
_groups = str;
}
void Options::PickupGroupOption::operator()(const Config::StringType & str)
{
_groups = str;
}
*/
}
//TODO: Check this
void Opt::ProcessCallGroup::operator()(std::string options)
void Options::RecordPrefixOption::operator()(const Config::StringType & str)
{
// _callgroup = options.c_str();
if (mkdir(str.c_str(), 493 /* 0755 */) < 0 && errno != EEXIST)
throw Config::Failure("the default recording directory could not be created.");
_value = str;
}
//TODO: Check this
void Opt::ProcessPickupGroup::operator()(std::string options)
{
// _pickupgroup = options.c_str();
}
void Opt::ProcessLogOptions::operator()(std::string options)
{
switch (_output)
{
case O_GENERIC:
K::Logger::processLogDisk(NULL, options, false, true);
break;
case O_CONSOLE:
K::Logger::processLogConsole(NULL, options, false, true);
break;
default:
throw ConfigProcessFailure("attempt to process unknown log file configuration");
break;
}
}
void Opt::ProcessTraceOptions::operator()(std::string options)
void Options::CentralOfficeDialtone::operator()(const Config::StringType & str)
{
Strings::vector_type tokens;
Strings::tokenize(options, tokens, ",");
Strings::tokenize(str, tokens, ",");
for (Strings::vector_type::iterator i = tokens.begin(); i != tokens.end(); i++)
_value.push_back(*i);
}
void Options::LogDiskOption::operator()(const Config::StringType & str)
{
K::Logger::processLogDisk(NULL, str, false, true);
}
void Options::LogConsoleOption::operator()(const Config::StringType & str)
{
K::Logger::processLogConsole(NULL, str, false, true);
}
void Options::LogTraceOption::operator()(const Config::StringType & str)
{
Strings::vector_type tokens;
Strings::tokenize(str, tokens, ",");
bool enable_k3l_tracing = false;
bool enable_r2_tracing = false;
@ -418,17 +339,12 @@ void Opt::ProcessTraceOptions::operator()(std::string options)
{
std::string tok = Strings::trim(*i);
if (tok == "k3l")
/**/ if (tok == "k3l") enable_k3l_tracing = true;
else if (tok == "r2") enable_r2_tracing = true;
else if (tok == "rdsi") enable_rdsi_tracing = true;
else
{
enable_k3l_tracing = true;
}
else if (tok == "r2")
{
enable_r2_tracing = true;
}
else if (tok == "rdsi")
{
enable_rdsi_tracing = true;
LOG(ERROR, FMT("invalid string '%s' for option 'trace', ignoring...") % tok)
}
}
@ -485,12 +401,12 @@ switch_xml_t Opt::processSimpleXML(switch_xml_t &xml, const std::string& child_n
% var
% val);
Globals::options.process(var, val);
Globals::options.process(&Opt::_options, var, val);
}
catch (ConfigProcessFailure e)
catch (Config::Failure e)
{
LOG(ERROR,FMT("config processing error: %s. [%s=%s]")
% e.msg.c_str()
% e.what()
% var
% val);
@ -521,10 +437,10 @@ void Opt::processGroupXML(switch_xml_t &xml)
_groups.insert(GroupToDestPairType(var,val));
}
catch (ConfigProcessFailure e)
catch (Config::Failure e)
{
LOG(ERROR,FMT("config processing error: %s. [%s=%s]")
% e.msg.c_str()
% e.what()
% var
% val);
}
@ -575,10 +491,10 @@ void Opt::processCadenceXML(switch_xml_t &xml)
_cadences.insert(CadencesPairType(var, cadence));
}
}
catch (ConfigProcessFailure e)
catch (Config::Failure e)
{
LOG(ERROR,FMT("config processing error: %s. [%s=%s]")
% e.msg.c_str()
% e.what()
% var
% val);
@ -637,7 +553,7 @@ void Opt::processFXSBranchesXML(switch_xml_t &xml)
for (unsigned int device = 0; device < Globals::k3lapi.device_count(); device++)
{
K3L_DEVICE_CONFIG & conf = Globals::k3lapi.device_config(device);
const K3L_DEVICE_CONFIG & conf = Globals::k3lapi.device_config(device);
std::string str_serial(conf.SerialNumber);
@ -659,10 +575,10 @@ void Opt::processFXSBranchesXML(switch_xml_t &xml)
}
}
}
catch (ConfigProcessFailure e)
catch (Config::Failure e)
{
LOG(ERROR,FMT("config processing error: %s. [%s=%s]")
% e.msg.c_str()
% e.what()
% var
% val);
}
@ -702,10 +618,10 @@ void Opt::processFXSHotlines(switch_xml_t &xml)
_fxs_hotline.insert(OrigToDestPairType(var, val));
}
catch (ConfigProcessFailure e)
catch (Config::Failure e)
{
LOG(ERROR,FMT("config processing error: %s. [%s=%s]")
% e.msg.c_str()
% e.what()
% var
% val);
}
@ -758,10 +674,10 @@ void Opt::processFXSOptions(switch_xml_t &xml)
}
}
}
catch (ConfigProcessFailure e)
catch (Config::Failure e)
{
LOG(ERROR,FMT("config processing error: %s. [%s=%s]")
% e.msg.c_str()
% e.what()
% var
% val);
}

View File

@ -66,7 +66,7 @@ static SpecRetType processSpecAtom(std::string & atom, SpecFlagsType & flags, Sp
{
std::string group_name = allocstr.substr(1);
Opt::GroupToDestMapType::iterator it = Opt::_groups.find(group_name);
GroupToDestMapType::iterator it = Opt::_groups.find(group_name);
if (it == Opt::_groups.end())
{
@ -78,9 +78,9 @@ static SpecRetType processSpecAtom(std::string & atom, SpecFlagsType & flags, Sp
return processSpecAtoms(allocstr, flags, fun);
}
Regex::Expression e("(((([bB])[ ]*([0-9]+))|(([sS])[ ]*([0-9]+)))[ ]*(([cClL])[ ]*([0-9]+)[ ]*([-][ ]*([0-9]+))?)?)|(([rR])[ ]*([0-9]+)[ ]*([-][ ]*([0-9]+))?)", Regex::E_EXTENDED);
//Regex::Expression e("(((([bB])[ ]*([0-9]+))|(([sS])[ ]*([0-9]+)))[ ]*(([cClL])[ ]*([0-9]+)[ ]*([-][ ]*([0-9]+))?)?)|(([rR])[ ]*([0-9]+)[ ]*([-][ ]*([0-9]+))?)", Regex::E_EXTENDED);
Regex::Match what(allocstr, e);
Regex::Match what(allocstr, Globals::regex_allocation);
if (!what.matched())
{
@ -170,7 +170,7 @@ static SpecRetType processSpecAtom(std::string & atom, SpecFlagsType & flags, Sp
for (unsigned int i = branch_id; i <= branch2_id; i++)
{
std::string call_addr = BoardE1::KhompPvtFXS::padOrig(base_addr, i - branch_id);
Opt::BranchToObjectMapType::iterator i = Opt::_fxs_branch_map.find(call_addr);
BranchToObjectMapType::iterator i = Opt::_fxs_branch_map.find(call_addr);
if (i == Opt::_fxs_branch_map.end())
{
@ -188,7 +188,7 @@ static SpecRetType processSpecAtom(std::string & atom, SpecFlagsType & flags, Sp
{
std::string call_addr = BoardE1::KhompPvtFXS::padOrig(base_addr, i - branch_id);
Opt::BranchToObjectMapType::iterator i = Opt::_fxs_branch_map.find(call_addr);
BranchToObjectMapType::iterator i = Opt::_fxs_branch_map.find(call_addr);
if (i == Opt::_fxs_branch_map.end())
{
@ -205,7 +205,7 @@ static SpecRetType processSpecAtom(std::string & atom, SpecFlagsType & flags, Sp
{
DBG(FUNC, D("branch matched: %s") % base_addr);
Opt::BranchToObjectMapType::iterator i = Opt::_fxs_branch_map.find(base_addr);
BranchToObjectMapType::iterator i = Opt::_fxs_branch_map.find(base_addr);
if (i == Opt::_fxs_branch_map.end())
{
@ -440,7 +440,7 @@ struct funProcessCallChannelString
if (_all_fail)
_all_fail = (tmp ? !tmp->isOK() : true);
}
catch (K3LAPI::invalid_channel & err)
catch (K3LAPITraits::invalid_channel & err)
{
_all_fail = true;
}
@ -599,7 +599,7 @@ struct FunProcessGroupString
if (pvt) pvt->_group_context = _ctx;
}
catch (K3LAPI::invalid_channel & err)
catch (K3LAPITraits::invalid_channel & err)
{
}
@ -634,8 +634,13 @@ static bool processCallChannelString(std::string & str, Board::KhompPvt *& pvt,
pvt = proc.pvt(flags);
DBG(FUNC, D("pvt = %p") % pvt);
if (!pvt && cause && !(*cause))
*cause = SWITCH_CAUSE_INTERWORKING;
if (cause && !(*cause))
{
if (!pvt)
*cause = SWITCH_CAUSE_INTERWORKING;
else
*cause = SWITCH_CAUSE_SUCCESS;
}
ret = true;
break;
@ -663,9 +668,14 @@ bool processSMSChannelString(std::string & str, Board::KhompPvt *& pvt, int *cau
case SPR_CONTINUE:
pvt = proc.pvt(flags);
DBG(FUNC, FMT("pvt = %p") % pvt);
if (!pvt && cause && !(*cause))
*cause = SWITCH_CAUSE_INTERWORKING;
if (cause && !(*cause))
{
if (!pvt)
*cause = SWITCH_CAUSE_INTERWORKING;
else
*cause = SWITCH_CAUSE_SUCCESS;
}
return true;
}
@ -685,7 +695,7 @@ Board::KhompPvt * processDialString (const char *dial_charv, int *cause)
DBG(FUNC, FMT("processing dial string [%d] : '%s'") % dial_args.size() % dial_string);
if ((dial_args.size() < 1 && dial_args.size() > 3))
if ((dial_args.size() < 1 || dial_args.size() > 3))
{
LOG(ERROR, FMT("invalid dial string '%s': wrong number of separators ('/').") % dial_string);
return NULL;
@ -837,7 +847,7 @@ Board::KhompPvt * processSMSString (const char *sms_charv, int *cause)
void processGroupString()
{
for (Opt::GroupToDestMapType::iterator i = Opt::_groups.begin(); i != Opt::_groups.end(); i++)
for (GroupToDestMapType::iterator i = Opt::_groups.begin(); i != Opt::_groups.end(); i++)
{
const std::string & name = (*i).first;
std::string & opts = (*i).second;

View File

@ -44,7 +44,6 @@
#include <utils.h>
#include "khomp_pvt.h"
void Kflags::init()
{
_flags[CONNECTED]._name = "CONNECTED";
@ -461,7 +460,7 @@ bool Kommuter::stop()
}
/* stop all watches */
if (Opt::_kommuter_activation == "auto")
if (Opt::_options._kommuter_activation() == "auto")
{
for (int kommuter = 0 ; kommuter < _kommuter_count ; kommuter++)
{
@ -486,7 +485,7 @@ bool Kommuter::initialize(K3L_EVENT *e)
/* get total of kommuter devices */
_kommuter_count = e->AddInfo;
if(Opt::_kommuter_activation == "manual")
if(Opt::_options._kommuter_activation() == "manual")
{
if (_kommuter_count > 0)
{
@ -499,7 +498,7 @@ bool Kommuter::initialize(K3L_EVENT *e)
if (_kommuter_count > 0)
{
bool start_timer = false;
int timeout = Opt::_kommuter_timeout;
int timeout = Opt::_options._kommuter_timeout();
std::string param = STG(FMT("timeout=%d") % timeout);
@ -605,3 +604,74 @@ void Kommuter::wtdKickTimer(void *)
}
}
/************************************ ESLs **********************************/
ESL::VectorEvents * ESL::_events = NULL;
ESL::ESL(std::string type) : _type(type)
{
if(!_events)
_events = new VectorEvents();
// _events->push_back(_type);
}
ESL::~ESL()
{
if(!_events)
return;
//Remove one from vector
//_events->pop_back();
if(_events->size() == 0)
{
delete _events;
_events = NULL;
}
}
bool ESL::registerEvents()
{
bool ok = true;
DBG(FUNC, "Register ESLs");
if(!_events)
return true;
for(VectorEvents::const_iterator event = _events->begin(); event != _events->end(); event++)
{
if (switch_event_reserve_subclass((*(event)).c_str()) != SWITCH_STATUS_SUCCESS)
{
LOG(ERROR, FMT("Couldn't register subclass=\"%s\"") % *(event));
ok = false;
}
else
{
DBG(FUNC, FMT("Register subclass=\"%s\"") % *(event));
}
}
return ok;
}
bool ESL::unregisterEvents()
{
DBG(FUNC, "Unregister ESLs");
if(!_events)
return true;
for(VectorEvents::const_iterator event = _events->begin(); event != _events->end(); event++)
{
DBG(FUNC, FMT("Unregister subclass=\"%s\"") % *(event));
switch_event_free_subclass((*(event)).c_str());
}
return true;
}
/******************************************************************************/

View File

@ -60,7 +60,11 @@ Logfile::~Logfile()
/* nothing for now */
};
#if COMMONS_AT_LEAST(1,1)
bool Logfile::select(Section ** ptr, const std::string & str)
#else
bool Logfile::select(Section ** ptr, std::string str)
#endif
{
// default section, needed for API compliance.
if (str == "")

View File

@ -43,6 +43,7 @@
#include <stdexcept>
#pragma GCC visibility pop
#include <config_commons.hpp>
#include <format.hpp>
#include <configurator/configfile.hpp>
@ -57,7 +58,12 @@ struct Logfile: public Configfile
Logfile();
~Logfile();
#if COMMONS_AT_LEAST(1,1)
bool select(Section **, const std::string & str = "");
#else
bool select(Section **, std::string str = "");
#endif
bool serialize(std::ofstream &);
Section & root() { return _logoptions; };

View File

@ -53,10 +53,10 @@ then
clean "Need to be root\n"
fi
if [ "w$FREESWITCH_PATH" == "w" ]
then
clean "FreeSWITCH source PATH is needed: \n\tSet \"FREESWITCH_PATH=\"\n"
fi
#if [ "w$FREESWITCH_PATH" == "w" ]
#then
# clean "FreeSWITCH source PATH is needed: \n\tSet \"FREESWITCH_PATH=\"\n"
#fi
if ! which 'kserver' &> /dev/null
then
@ -85,9 +85,9 @@ then
clean "k3l version 2.1 must be installed: \n\tUninstall the old version of k3l and try again\n"
fi
make || clean "Error on compilation\n"
#make || clean "Error on compilation\n"
make install || clean "Error on installation\n"
#make install || clean "Error on installation\n"
echo "Successfully installed!"