Author: raulfragoso Date: Fri Jun 26 18:20:45 2009 New Revision: 13989 Log: Merge of changes from Khomp plus some minor changes in the code structure Added: freeswitch/trunk/contrib/mod/endpoints/mod_khomp/commons/config_options.cpp freeswitch/trunk/contrib/mod/endpoints/mod_khomp/commons/config_options.hpp freeswitch/trunk/contrib/mod/endpoints/mod_khomp/commons/format.cpp freeswitch/trunk/contrib/mod/endpoints/mod_khomp/commons/format.hpp freeswitch/trunk/contrib/mod/endpoints/mod_khomp/commons/k3lapi.hpp freeswitch/trunk/contrib/mod/endpoints/mod_khomp/commons/strings.cpp Modified: freeswitch/trunk/contrib/mod/endpoints/mod_khomp/Makefile freeswitch/trunk/contrib/mod/endpoints/mod_khomp/commons/k3lapi.cpp freeswitch/trunk/contrib/mod/endpoints/mod_khomp/mod_khomp.cpp Modified: freeswitch/trunk/contrib/mod/endpoints/mod_khomp/Makefile ============================================================================== --- freeswitch/trunk/contrib/mod/endpoints/mod_khomp/Makefile (original) +++ freeswitch/trunk/contrib/mod/endpoints/mod_khomp/Makefile Fri Jun 26 18:20:45 2009 @@ -1,6 +1,8 @@ MODNAME=mod_khomp -LOCAL_CFLAGS=-I./include -I./commons/include -lk3l -D_REENTRANT -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -DK3L_HOSTSYSTEM +VERBOSE=1 +LOCAL_CFLAGS=-I./include -I./commons -D_REENTRANT -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -DK3L_HOSTSYSTEM +LOCAL_LDFLAGS=-lk3l +LOCAL_OBJS= ./commons/k3lapi.o ./commons/config_options.o ./commons/format.o ./commons/strings.o +LOCAL_OBJS+= ./src/globals.o ./src/opt.o ./src/khomp_pvt.o -LOCAL_OBJS= ./commons/k3lapi.o - -include ../../../build/modmake.rules +include ../../../../build/modmake.rules Added: freeswitch/trunk/contrib/mod/endpoints/mod_khomp/commons/config_options.cpp ============================================================================== --- (empty file) +++ freeswitch/trunk/contrib/mod/endpoints/mod_khomp/commons/config_options.cpp Fri Jun 26 18:20:45 2009 @@ -0,0 +1,665 @@ +#include <config_options.hpp> + +config_option::config_option(std::string name, const config_option::string_type & value, const config_option::string_type defvalue, string_allowed_type allowed, bool list_me) +: _my_name(name), _value_data(new string_data_type(const_cast<string_type &>(value), defvalue, allowed)), + _list_me(list_me), _values(NULL), _loaded(false) +{}; + +config_option::config_option(std::string name, const config_option::string_type & value, const config_option::string_type defvalue, bool list_me) +: _my_name(name), _value_data(new string_data_type(const_cast<string_type &>(value), defvalue, string_allowed_type())), + _list_me(list_me), _values(NULL), _loaded(false) +{}; + +config_option::config_option(std::string name, const config_option::sint_type & value, const config_option::sint_type defvalue, + config_option::sint_type min, config_option::sint_type max, config_option::sint_type step, bool list_me) +: _my_name(name), _value_data(new sint_data_type(const_cast<sint_type &>(value), defvalue, range<sint_type>(min, max, step))), + _list_me(list_me), _values(NULL), _loaded(false) +{}; + +config_option::config_option(std::string name, const config_option::uint_type & value, const config_option::uint_type defvalue, + config_option::uint_type min, config_option::uint_type max, config_option::uint_type step, bool list_me) +: _my_name(name), _value_data(new uint_data_type(const_cast<uint_type &>(value), defvalue, range<uint_type>(min, max, step))), + _list_me(list_me), _values(NULL), _loaded(false) +{}; + +config_option::config_option(std::string name, const config_option::bool_type & value, const config_option::bool_type defvalue, bool list_me) +: _my_name(name), _value_data(new bool_data_type(const_cast<bool_type &>(value), defvalue)), + _list_me(list_me), _values(NULL), _loaded(false) +{}; + +config_option::config_option(std::string name, config_option::fun_type fun, std::string defvalue, string_allowed_type allowed, bool list_me) +: _my_name(name), _value_data(new fun_data_type(fun, defvalue, allowed)), + _list_me(list_me), _values(NULL), _loaded(false) +{}; + +config_option::config_option(std::string name, config_option::fun_type fun, std::string defvalue, bool list_me) +: _my_name(name), _value_data(new fun_data_type(fun, defvalue, string_allowed_type())), + _list_me(list_me), _values(NULL), _loaded(false) +{}; + +config_option::~config_option(void) +{ + if (_values) + { + for (unsigned int i = 0; _values[i] != NULL; i++) + delete _values[i]; + + delete[] _values; + } +}; + +void config_option::set(config_option::string_type value) +{ + switch (_value_data.which()) + { + case ID_STRING: + { + try + { + string_data_type & tmp = _value_data.get<string_data_type>(); + + + 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 config_process_failure(STG(FMT("value '%s' not allowed for option '%s' (allowed values:%s)") + % value % _my_name % allowed_string)); + } + break; + } + catch(value_type::InvalidType & e) + { + throw; + } + } + + case ID_FUN: + { + try + { + fun_data_type & tmp = _value_data.get<fun_data_type>(); + tmp.fun_val(value); + _loaded = true; + break; + } + catch(value_type::InvalidType & e) + { + throw; + } + + } + + default: + { + throw config_process_failure(STG(FMT("option '%s' is not of type string, nor function defined") % _my_name)); + } + } +} + +void config_option::set(config_option::sint_type value) +{ + try + { + sint_data_type & tmp = _value_data.get<sint_data_type>(); + + if (value < tmp.sint_range.minimum) + throw config_process_failure(STG(FMT("value '%d' out-of-range for option '%s' (too low)") % value % _my_name)); + + if (value > tmp.sint_range.maximum) + throw config_process_failure(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 config_process_failure(STG(FMT("value '%d' out-of-range for option '%s' (outside allowed step)") % value % _my_name)); + + tmp.sint_val = value; + _loaded = true; + } + catch(value_type::InvalidType & e) + { + throw; + } +} + +void config_option::set(config_option::uint_type value) +{ + try + { + uint_data_type & tmp = _value_data.get<uint_data_type>(); + + if (value < tmp.uint_range.minimum) + throw config_process_failure(STG(FMT("value '%d' out-of-range for option '%s' (too low)") % value % _my_name)); + + if (value > tmp.uint_range.maximum) + throw config_process_failure(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 config_process_failure(STG(FMT("value '%d' out-of-range for option '%s' (outside allowed step)") % value % _my_name)); + + tmp.uint_val = value; + _loaded = true; + } + catch(value_type::InvalidType & e) + { + throw; + } +} + +void config_option::set(config_option::bool_type value) +{ + try + { + bool_data_type & tmp = _value_data.get<bool_data_type>(); + tmp.bool_val = value; + _loaded = true; + } + catch(value_type::InvalidType & e) + { + throw; + } + +} + +std::string & config_option::name(void) { return _my_name; }; + +config_option::value_id_type config_option::type(void) +{ + return (value_id_type) _value_data.which(); +}; + +const char ** config_option::values(void) +{ + if (_values != NULL) + return _values; + + switch ((value_id_type) _value_data.which()) + { + case config_option::ID_BOOL: + { + _values = new const char*[3]; + + _values[0] = strdup("yes"); + _values[1] = strdup("no"); + _values[2] = NULL; + + return _values; + } + + case config_option::ID_SINT: + { + try + { + sint_data_type & tmp = _value_data.get<sint_data_type>(); + + + 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 (sint_type 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(value_type::InvalidType & e) + { + throw; + } + } + + case config_option::ID_UINT: + { + try + { + uint_data_type & tmp = _value_data.get<uint_data_type>(); + + 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 (uint_type 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(value_type::InvalidType & e) + { + throw; + } + } + + case config_option::ID_STRING: + { + try + { + string_data_type & tmp = _value_data.get<string_data_type>(); + + _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(value_type::InvalidType & e) + { + throw; + } + } + + case config_option::ID_FUN: + { + try + { + fun_data_type & tmp = _value_data.get<fun_data_type>(); + + _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(value_type::InvalidType & e) + { + throw; + } + + } + + default: + throw config_process_failure(STG(FMT("unknown type identifier '%d'") % _value_data.which())); + } +}; + +void config_option::reset(void) +{ + _loaded = false; +}; + +void config_option::commit(void) +{ + if (_loaded) + return; + + switch ((value_id_type) _value_data.which()) + { + case config_option::ID_BOOL: + { + try + { + bool_data_type & tmp = _value_data.get<bool_data_type>(); + tmp.bool_val = tmp.bool_default; + } + catch(value_type::InvalidType & e) + { + throw; + } + + break; + } + + case config_option::ID_SINT: + { + try + { + sint_data_type & tmp = _value_data.get<sint_data_type>(); + tmp.sint_val = tmp.sint_default; + } + catch(value_type::InvalidType & e) + { + throw; + } + break; + } + + case config_option::ID_UINT: + { + try + { + uint_data_type & tmp = _value_data.get<uint_data_type>(); + tmp.uint_val = tmp.uint_default; + } + catch(value_type::InvalidType & e) + { + throw; + } + break; + } + + case config_option::ID_STRING: + { + try + { + string_data_type & tmp = _value_data.get<string_data_type>(); + tmp.string_val = tmp.string_default; + } + catch(value_type::InvalidType & e) + { + throw; + } + break; + } + + case config_option::ID_FUN: + { + try + { + fun_data_type & tmp = _value_data.get<fun_data_type>(); + tmp.fun_val(tmp.fun_default); + } + catch(value_type::InvalidType & e) + { + throw; + } + break; + } + + default: + throw config_process_failure(STG(FMT("unknown type identifier '%d'") % _value_data.which())); + } + + _loaded = true; +}; + +void config_option::copy_from(config_option & src) +{ + if (src._value_data.which() != _value_data.which()) + throw config_process_failure(STG(FMT("unable to copy options, source type differs from destination."))); + + if (!src._loaded) + return; + + switch ((value_id_type) _value_data.which()) + { + case config_option::ID_BOOL: + { + try + { + bool_data_type & stmp = src._value_data.get<bool_data_type>(); + bool_data_type & dtmp = _value_data.get<bool_data_type>(); + /* do not copy references, but values.. */ + bool tmpval = stmp.bool_val; + dtmp.bool_val = tmpval; + } + catch(value_type::InvalidType & e) + { + throw; + } + + break; + } + + case config_option::ID_SINT: + { + try + { + sint_data_type & stmp = src._value_data.get<sint_data_type>(); + sint_data_type & dtmp = _value_data.get<sint_data_type>(); + /* do not copy references, but values.. */ + int tmpval = stmp.sint_val; + dtmp.sint_val = tmpval; + } + catch(value_type::InvalidType & e) + { + throw; + } + + break; + } + + case config_option::ID_UINT: + { + try + { + uint_data_type & stmp = src._value_data.get<uint_data_type>(); + uint_data_type & dtmp = _value_data.get<uint_data_type>(); + /* do not copy references, but values.. */ + unsigned int tmpval = stmp.uint_val; + dtmp.uint_val = tmpval; + } + catch(value_type::InvalidType & e) + { + throw; + } + + + break; + } + + case config_option::ID_STRING: + { + try + { + string_data_type & stmp = src._value_data.get<string_data_type>(); + string_data_type & dtmp = _value_data.get<string_data_type>(); + /* do not copy references, but values.. */ + std::string tmpval = stmp.string_val; + dtmp.string_val = tmpval; + } + catch(value_type::InvalidType & e) + { + throw; + } + + break; + } + + case config_option::ID_FUN: + { + /* TO IMPLEMENT (NEEDS ANOTHER METHOD ON FUNCTION FOR GETTING VALUE) */ + +// fun_data_type & tmp = boost::get<fun_data_type>(_value_data); +// +// if (!tmp.loaded) +// { +// tmp.fun_val(tmp.fun_default); +// tmp.loaded = true; +// } + break; + } + + default: + throw config_process_failure(STG(FMT("unknown type identifier '%d'") % _value_data.which())); + } + + _loaded = true; +}; + +/*********************************/ + +bool config_options::add(config_option 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 config_options::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; +} + +config_options::string_set config_options::options(void) +{ + string_set res; + + for (option_map_type::iterator i = _map.begin(); i != _map.end(); i++) + res.insert((*i).first); + + return res; +} + +void config_options::process(const char * name, const char * value) +{ + option_map_type::iterator iter = find_option(name); + + if (iter == _map.end()) + throw config_process_failure(STG(FMT("unknown option '%s'") % name)); + + try + { + switch ((*iter).second.type()) + { + case config_option::ID_SINT: + set<config_option::sint_type>((*iter).first, Strings::toulong(value)); + return; + case config_option::ID_UINT: + set<config_option::uint_type>((*iter).first, Strings::tolong(value)); + return; + case config_option::ID_BOOL: + set<config_option::bool_type>((*iter).first, Strings::toboolean(value)); + return; + case config_option::ID_STRING: + case config_option::ID_FUN: + set<config_option::string_type>((*iter).first, std::string(value)); + return; + default: + throw config_process_failure(STG(FMT("unknown type identifier '%d'") % (*iter).second.type())); + } + } + catch (Strings::invalid_value e) + { + throw config_process_failure(STG(FMT("invalid value '%s' for option '%s'") % value % name)); + } +} + +const char ** config_options::values(const char * name) +{ + option_map_type::iterator iter = find_option(name); + + if (iter == _map.end()) + throw config_process_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 (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 config_options::reset(void) +{ + for (option_map_type::iterator i = _map.begin(); i != _map.end(); i++) + (*i).second.reset(); +} + +config_options::messages_type config_options::commit(void) +{ + messages_type msgs; + + for (option_map_type::iterator i = _map.begin(); i != _map.end(); i++) + { + try + { + (*i).second.commit(); + } + catch (config_process_failure e) + { + msgs.push_back(e.msg); + } + } + + return msgs; +} + +bool config_options::loaded(std::string name) +{ + option_map_type::iterator iter = find_option(name); + + if (iter == _map.end()) + return false; + + return iter->second.loaded(); +} + +void config_options::copy_from(config_options & 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 config_process_failure(STG(FMT("unknown option '%s' on source") % name)); + + if (iter_dst == _map.end()) + throw config_process_failure(STG(FMT("unknown option '%s' on destination") % name)); + + iter_dst->second.copy_from(iter_src->second); +} + +config_options::option_map_type::iterator config_options::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; +} Added: freeswitch/trunk/contrib/mod/endpoints/mod_khomp/commons/config_options.hpp ============================================================================== --- (empty file) +++ freeswitch/trunk/contrib/mod/endpoints/mod_khomp/commons/config_options.hpp Fri Jun 26 18:20:45 2009 @@ -0,0 +1,281 @@ +#include <set> +#include <map> +#include <vector> + +#include <strings.hpp> + +#include <format.hpp> + +#ifndef INCLUDED_CONFIG_OPTIONS +#define INCLUDED_CONFIG_OPTIONS + +template < typename base_type > +struct Variant +{ + struct InvalidType {}; + + Variant(base_type * value) : _value(value) + { + _count = new int(1); + }; + + Variant(const Variant & v) : _value(v._value), _count(v._count) + { + + (*_count)++; + } + + ~Variant() + { + (*_count)--; + if (_value && !(*_count)) + { + delete _value; + delete _count; + } + }; + + template < typename return_type > + return_type & get(void) + { + try + { + return_type & ret = dynamic_cast < return_type & > (*_value); + return ret; + } + catch (std::bad_cast & e) + { + throw InvalidType(); + } + + }; + + int which() + { + return _value->which(); + } + + protected: + base_type * _value; + int *_count; +}; + +struct config_process_failure +{ + config_process_failure(std::string _msg): msg(_msg) {}; + std::string msg; +}; + +struct config_option +{ + typedef int sint_type; + typedef unsigned int uint_type; + typedef bool bool_type; + + typedef std::string string_type; + //typedef boost::function1<void, std::string> + typedef void (*fun_type)(std::string); + + typedef std::set < string_type > 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 BaseType + { + BaseType() {} + + virtual ~BaseType() {} + + virtual int which() = 0; + }; + + struct sint_data_type : public BaseType + { + sint_data_type(sint_type & _sint_val, sint_type _sint_default, range<sint_type> _sint_range) + : sint_val(_sint_val), sint_default(_sint_default), sint_range(_sint_range) {}; + + int which() + { + return ID_SINT; + } + + sint_type & sint_val; + sint_type sint_default; + range<sint_type> sint_range; + }; + + struct uint_data_type : public BaseType + { + uint_data_type(uint_type & _uint_val, uint_type _uint_default, range<uint_type> _uint_range) + : uint_val(_uint_val), uint_default(_uint_default), uint_range(_uint_range) {}; + + int which() + { + return ID_UINT; + } + + uint_type & uint_val; + uint_type uint_default; + range<uint_type> uint_range; + }; + + struct bool_data_type : public BaseType + { + bool_data_type(bool_type & _bool_val, bool_type _bool_default) + : bool_val(_bool_val), bool_default(_bool_default) {}; + + int which() + { + return ID_BOOL; + } + + bool_type & bool_val; + bool_type bool_default; + }; + + struct string_data_type : public BaseType + { + string_data_type(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 fun_data_type : public BaseType + { + fun_data_type(fun_type _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; + } + + fun_type fun_val; + std::string fun_default; + string_allowed_type fun_allowed; + }; + + + typedef Variant < BaseType > value_type; + //typedef boost::variant < sint_data_type , uint_data_type, bool_data_type, string_data_type, fun_data_type > value_type; + + config_option(std::string, const string_type &, const string_type, string_allowed_type allowed, bool list_me = true); + config_option(std::string, const string_type &, const string_type = "", bool list_me = true); + config_option(std::string, const sint_type &, const sint_type = 0, sint_type min = -INT_MAX, sint_type max = INT_MAX, sint_type step = 1, bool list_me = true); + config_option(std::string, const uint_type &, const uint_type = 0, uint_type min = 0, uint_type max = UINT_MAX, uint_type step = 1, bool list_me = true); + config_option(std::string, const bool_type &, const bool_type = false, bool list_me = true); + config_option(std::string, fun_type, std::string defvalue, string_allowed_type allowed, bool list_me = true); + config_option(std::string, fun_type, std::string defvalue = "", bool list_me = true); + + ~config_option(void); + + void set(string_type value); + + void set(sint_type value); + void set(uint_type value); + void set(bool_type value); + + 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(config_option &); + + protected: + std::string _my_name; + value_type _value_data; + + bool _list_me; + const char ** _values; + bool _loaded; +}; + +struct config_options +{ + typedef std::vector < std::string > messages_type; + + config_options(void): _values(NULL) {}; + + typedef std::set < std::string > string_set; + + typedef std::map < std::string, config_option > option_map_type; + typedef std::pair < std::string, config_option > 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(config_option option); + + /* only valid in "process" (for backwards compatibility config files) */ + bool synonym(std::string, std::string); + + template <typename value_type> + void set(std::string name, value_type value) + { + option_map_type::iterator iter = _map.find(name); + + if (iter == _map.end()) + throw config_process_failure(STG(FMT("unknown option: %s") % name)); + + (*iter).second.set(value); + } + + 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(config_options &, 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 /* INCLUDED_CONFIG_OPTIONS */ + Added: freeswitch/trunk/contrib/mod/endpoints/mod_khomp/commons/format.cpp ============================================================================== --- (empty file) +++ freeswitch/trunk/contrib/mod/endpoints/mod_khomp/commons/format.cpp Fri Jun 26 18:20:45 2009 @@ -0,0 +1,208 @@ +#include "format.hpp" + +const char * Format::INVALID_MSG = "** Invalid Format **"; + + +Format::Format(const char * fmt, bool exception) + : _valid(true), _exception(exception) +{ + std::string text; + std::string arg; + + const char * ptr = fmt; + + while(*ptr != '\0') + { + if (*ptr != '%') + { + text += *ptr; + ptr++; + continue; + } + else if(*(ptr+1) == '%') + { + text += *ptr; + ptr++; + text += *ptr; + ptr++; + continue; + } + + _args.push(new Argument(text, "text")); + + text.clear(); + + arg += *ptr; + + bool finished = false; + + ptr++; + + while(*ptr != '\0' && !finished) + { + + Argument * argument; + + switch (*ptr) + { + case ' ': + arg += *ptr; + _args.push(new Argument(arg, "text")); + arg.clear(); + finished = true; + break; + + case '%': + _args.push(new Argument(arg, "text")); + arg.clear(); + arg += *ptr; + break; + + case 'h': + arg += *ptr; + break; + + case 'l': + arg += *ptr; + break; + + case 'd': + case 'i': + arg += *ptr; + argument = new Argument(arg, typeid(int).name()); + argument->type(typeid(unsigned int).name()); + _args.push(argument); + argument = NULL; + arg.clear(); + finished = true; + break; + + case 'o': + case 'u': + case 'x': + case 'X': + arg += *ptr; + argument = new Argument(arg, typeid(unsigned int).name()); + argument->type(typeid(int).name()); + _args.push(argument); + argument = NULL; + arg.clear(); + finished = true; + break; + + case 'e': + case 'E': + case 'f': + case 'F': + case 'g': + case 'G': + case 'a': + case 'A': + arg += *ptr; + argument = new Argument(arg, typeid(double).name()); + argument->type(typeid(float).name()); + _args.push(argument); + argument = NULL; + arg.clear(); + finished = true; + break; + + case 'c': + arg += *ptr; + argument = new Argument(arg, typeid(char).name()); + argument->type(typeid(unsigned char).name()); + _args.push(argument); + argument = NULL; + arg.clear(); + finished = true; + break; + + case 's': + arg += *ptr; + argument = new Argument(arg, typeid(const char *).name()); + argument->type(typeid(char *).name()); + argument->type(typeid(const unsigned char *).name()); + argument->type(typeid(unsigned char *).name()); + _args.push(argument); + argument = NULL; + arg.clear(); + finished = true; + break; + + case 'p': + case 'C': + case 'S': + case 'n': + case 'm': + arg += *ptr; + _args.push(new Argument(arg, "")); + arg.clear(); + finished = true; + break; + default: + arg += *ptr; + break; + } + + ptr++; + + } + } + + if(!text.empty()) + _args.push(new Argument(text, "text")); + + if(!arg.empty()) + _args.push(new Argument(arg, "text")); + +} + +std::string Format::str() +{ + + if(!_valid) + { + if(_exception) + throw InvalidFormat(INVALID_MSG); + + _result.clear(); + _result += INVALID_MSG; + return _result; + } + + Argument * top; + bool text; + + do + { + text = false; + + if(_args.empty()) + return _result; + + top = _args.front(); + _args.pop(); + + if(top->compare("text")) + { + _result += top->fmts(); + text = true; + free(top); + } + + } + while(text); + + free(top); + + _valid = false; + + if(_exception) + throw InvalidFormat(INVALID_MSG); + + _result.clear(); + _result += INVALID_MSG; + return _result; +} + + Added: freeswitch/trunk/contrib/mod/endpoints/mod_khomp/commons/format.hpp ============================================================================== --- (empty file) +++ freeswitch/trunk/contrib/mod/endpoints/mod_khomp/commons/format.hpp Fri Jun 26 18:20:45 2009 @@ -0,0 +1,183 @@ +#ifndef _FORMAT_H_ +#define _FORMAT_H_ + +#include <string> +#include <queue> +#include <set> +#include <typeinfo> +#include <cstring> +#include <cstdlib> + +/* macros used for shortening lines and making the code clearer */ +#define STG(x) (x).str() +#define FMT(x) Format(x) + +struct Format +{ + static const char * INVALID_MSG; + + struct Argument + { + typedef std::set < std::string > StringSet; + + Argument(std::string init_fmts, std::string init_type) + : _fmts(init_fmts) + { + _types.insert(init_type); + }; + + void type(std::string t) + { + _types.insert(t); + } + + bool compare(const char * type) + { + for(StringSet::iterator it = _types.begin(); it != _types.end(); it++) + { + if(!strcmp(type, (*it).c_str())) + return true; + } + return false; + } + + std::string fmts() + { + return _fmts; + } + + protected: + std::string _fmts; + StringSet _types; + }; + + struct InvalidFormat + { + InvalidFormat(std::string msg) : _msg(msg) {} + + std::string _msg; + }; + + + typedef std::queue < Argument *> ArgumentsQueue; + + Format(const char * fmt, bool exception = false); + + std::string str(); + + template < typename Type > + Format & operator % ( Type value ) + { + Argument * top; + bool text; + + do + { + text = false; + + if(_args.empty()) { + _valid = false; + if(_exception) + throw InvalidFormat(INVALID_MSG); + return *this; + } + + top = _args.front(); + _args.pop(); + + if(top->compare("text")) + { + _result += top->fmts(); + text = true; + free(top); + } + + } + while(text); + + char tmp[1000]; + + if(top->compare("")) + { + snprintf(tmp, 1000, top->fmts().c_str(), value); + _result += tmp; + } + else if (top->compare(typeid(Type).name())) + { + snprintf(tmp, 1000, top->fmts().c_str(), value); + _result += tmp; + } + else + { + free(top); + _valid = false; + if(_exception) + throw InvalidFormat(INVALID_MSG); + return *this; + } + + free(top); + + return *this; + } + +Format & operator%( std::string & value ) +{ + Argument * top; + bool text; + + do + { + text = false; + + if(_args.empty()) { + _valid = false; + if(_exception) + throw InvalidFormat(INVALID_MSG); + return *this; + } + + top = _args.front(); + _args.pop(); + + if(top->compare("text")) + { + _result += top->fmts(); + text = true; + free(top); + } + + } + while(text); + + char tmp[1000]; + + if (top->compare(typeid(char *).name())) + { + snprintf(tmp, 1000, top->fmts().c_str(), value.c_str()); + _result += tmp; + } + else + { + free(top); + _valid = false; + if(_exception) + throw InvalidFormat(INVALID_MSG); + return *this; + } + + free(top); + + return *this; +} + +private: + bool _valid; + bool _exception; + std::string _result; + ArgumentsQueue _args; + +}; + +#endif /* _FORMAT_H_ */ + Modified: freeswitch/trunk/contrib/mod/endpoints/mod_khomp/commons/k3lapi.cpp ============================================================================== --- freeswitch/trunk/contrib/mod/endpoints/mod_khomp/commons/k3lapi.cpp (original) +++ freeswitch/trunk/contrib/mod/endpoints/mod_khomp/commons/k3lapi.cpp Fri Jun 26 18:20:45 2009 @@ -7,169 +7,165 @@ K3LAPI::~K3LAPI() { - _device_count = 0; - - if (_device_type) { delete[] _device_type; _device_type = NULL; } - if (_device_config) { delete[] _device_config; _device_config = NULL; } - if (_channel_config) { delete[] _channel_config; _channel_config = NULL; } - if (_link_config) { delete[] _link_config; _link_config = NULL; } - if (_channel_count) { delete[] _channel_count; _channel_count = NULL; } - if (_link_count) { delete[] _link_count; _link_count = NULL; } + _device_count = 0; + + if (_device_type) { delete[] _device_type; _device_type = NULL; } + if (_device_config) { delete[] _device_config; _device_config = NULL; } + if (_channel_config) { delete[] _channel_config; _channel_config = NULL; } + if (_link_config) { delete[] _link_config; _link_config = NULL; } + if (_channel_count) { delete[] _channel_count; _channel_count = NULL; } + if (_link_count) { delete[] _link_count; _link_count = NULL; } } /* initialize the whole thing! */ - + void K3LAPI::start(void) { - /* tie the used k3l to the compiled k3l version */ - char *ret = k3lStart(2, 0, 0); //k3lApiMajorVersion, k3lApiMinorVersion, 0); //k3lApiBuildVersion); - - if (ret && *ret) - throw start_failed(ret); - - /* call init automagically */ - init(); + /* tie the used k3l to the compiled k3l version */ + char *ret = k3lStart(2, 0, 0); //k3lApiBuildVersion); + + if (ret && *ret) + throw start_failed(ret); + + /* call init automagically */ + init(); } void K3LAPI::stop(void) { - k3lStop(); + k3lStop(); } /* envio de comandos para placa */ - + void K3LAPI::mixer(int32 dev, int32 obj, byte track, KMixerSource src, int32 index) { - KMixerCommand mix; + KMixerCommand mix; mix.Track = track; - mix.Source = src; + mix.Source = src; mix.SourceIndex = index; - command(dev, obj, CM_MIXER, (const char *) &mix); + command(dev, obj, CM_MIXER, (const char *) &mix); } void K3LAPI::mixerCTbus(int32 dev, int32 obj, byte track, KMixerSource src, int32 index) { - KMixerCommand mix; + KMixerCommand mix; mix.Track = track; - mix.Source = src; + mix.Source = src; mix.SourceIndex = index; - command(dev, obj, CM_MIXER_CTBUS, (const char *) &mix); + command(dev, obj, CM_MIXER_CTBUS, (const char *) &mix); } void K3LAPI::command(int32 dev, int32 obj, int32 code, std::string & str) { - command(dev, obj, code, str.c_str()); + command(dev, obj, code, str.c_str()); } void K3LAPI::command (int32 dev, int32 obj, int32 code, const char * parms) { K3L_COMMAND cmd; - cmd.Cmd = code; + cmd.Cmd = code; cmd.Object = obj; - cmd.Params = (byte *)parms; + cmd.Params = (byte *)parms; - int32 rc = k3lSendCommand(dev, &cmd); - - if (rc != ksSuccess) - throw failed_command(code, dev, obj, rc); + int32 rc = k3lSendCommand(dev, &cmd); + + if (rc != ksSuccess) + throw failed_command(code, dev, obj, rc); } void K3LAPI::raw_command(int32 dev, int32 dsp, std::string & str) { - raw_command(dev, dsp, str.data(), str.size()); + raw_command(dev, dsp, str.data(), str.size()); } void K3LAPI::raw_command(int32 dev, int32 dsp, const char * cmds, int32 size) { std::string str(cmds, size); - int32 rc = k3lSendRawCommand(dev, dsp, (void *)cmds, size); + int32 rc = k3lSendRawCommand(dev, dsp, (void *)cmds, size); - if (rc != ksSuccess) - throw failed_raw_command(dev, dsp, rc); + if (rc != ksSuccess) + throw failed_raw_command(dev, dsp, rc); } KLibraryStatus K3LAPI::get_param(K3L_EVENT *ev, const char *name, std::string &res) { - char tmp_param[256]; - memset((void*)tmp_param, 0, sizeof(tmp_param)); + char tmp_param[256]; + memset((void*)tmp_param, 0, sizeof(tmp_param)); - int32 rc = k3lGetEventParam (ev, (sbyte *)name, (sbyte *)tmp_param, sizeof(tmp_param)-1); - - if (rc != ksSuccess) - return (KLibraryStatus)rc; + int32 rc = k3lGetEventParam (ev, (sbyte *)name, (sbyte *)tmp_param, sizeof(tmp_param)-1); + + if (rc != ksSuccess) + return (KLibraryStatus)rc; - res.append(tmp_param, strlen(tmp_param)); - return ksSuccess; + res.append(tmp_param, strlen(tmp_param)); + return ksSuccess; } - + std::string K3LAPI::get_param(K3L_EVENT *ev, const char *name) { - std::string res; + std::string res; - KLibraryStatus rc = get_param(ev, name, res); + KLibraryStatus rc = get_param(ev, name, res); - if (rc != ksSuccess) - throw get_param_failed(name, rc); - - return res; + if (rc != ksSuccess) + throw get_param_failed(name, rc); + + return res; } void K3LAPI::init(void) { - if (_device_count != 0) return; + if (_device_count != 0) return; - _device_count = k3lGetDeviceCount(); + _device_count = k3lGetDeviceCount(); - _device_type = new KDeviceType[_device_count]; - _device_config = new device_conf_type[_device_count]; - _channel_config = new channel_ptr_conf_type[_device_count]; - _KChannel = new KChannel_ptr_t[_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]; - - for (unsigned int dev = 0; dev < _device_count; dev++) - { - _device_type[dev] = (KDeviceType) k3lGetDeviceType(dev); - - /* caches each device config */ - 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; - _link_count[dev] = _device_config[dev].LinkCount; - - /* caches each channel config */ - _channel_config[dev] = new channel_conf_type[_channel_count[dev]]; - _KChannel[dev] = new KChannel_t[_channel_count[dev]]; - - for (unsigned int obj = 0; obj < _channel_count[dev]; obj++) - { - 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 */ - _link_count[dev] = _device_config[dev].LinkCount; - - /* caches each link config */ - _link_config[dev] = new link_conf_type[_link_count[dev]]; - - for (unsigned int obj = 0; obj < _link_count[dev]; obj++) - { - if (k3lGetDeviceConfig(dev, ksoLink + obj, &(_link_config[dev][obj]), - sizeof(_link_config[dev][obj])) != ksSuccess) - throw start_failed("k3lGetDeviceConfig(link)"); - } - } + _device_type = new KDeviceType[_device_count]; + _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]; + + for (unsigned int dev = 0; dev < _device_count; dev++) + { + _device_type[dev] = (KDeviceType) k3lGetDeviceType(dev); + + /* caches each device config */ + 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; + _link_count[dev] = _device_config[dev].LinkCount; + + /* caches each channel config */ + _channel_config[dev] = new channel_conf_type[_channel_count[dev]]; + + for (unsigned int obj = 0; obj < _channel_count[dev]; obj++) + { + 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 */ + _link_count[dev] = _device_config[dev].LinkCount; + + /* caches each link config */ + _link_config[dev] = new link_conf_type[_link_count[dev]]; + + for (unsigned int obj = 0; obj < _link_count[dev]; obj++) + { + if (k3lGetDeviceConfig(dev, ksoLink + obj, &(_link_config[dev][obj]), + sizeof(_link_config[dev][obj])) != ksSuccess) + throw start_failed("k3lGetDeviceConfig(link)"); + } + } } Added: freeswitch/trunk/contrib/mod/endpoints/mod_khomp/commons/k3lapi.hpp ============================================================================== --- (empty file) +++ freeswitch/trunk/contrib/mod/endpoints/mod_khomp/commons/k3lapi.hpp Fri Jun 26 18:20:45 2009 @@ -0,0 +1,309 @@ +#include <string> + +#include <k3l.h> + +/* if using full k3l.h (for softpbx), version already defined. */ +#ifndef k3lApiMajorVersion +# include <k3lVersion.h> +#endif + +#ifdef __GNUC_PREREQ +#if __GNUC_PREREQ(4,3) +#include <cstring> +#endif +#endif + +#ifndef INCLUDED_K3LAPI_HPP +#define INCLUDED_K3LAPI_HPP + +struct K3LAPI +{ + /* exceptions */ + + struct start_failed + { + start_failed(const char * _msg) : msg(_msg) {}; + std::string msg; + }; + + struct failed_command + { + failed_command(int32 _code, unsigned short _dev, unsigned short _obj, int32 _rc) + : code(_code), dev(_dev), obj(_obj), rc(_rc) {}; + + int32 code; + unsigned short dev; + unsigned short obj; + int32 rc; + }; + + struct failed_raw_command + { + failed_raw_command(unsigned short _dev, unsigned short _dsp, int32 _rc) + : dev(_dev), dsp(_dsp), rc(_rc) {}; + + unsigned short dev; + unsigned short dsp; + int32 rc; + }; + + struct invalid_session + { + invalid_session(unsigned int _device, unsigned int _channel) + : device(_device), channel(_channel) {}; + + unsigned int device; + unsigned int channel; + }; + + 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) + : name(_name), rc((KLibraryStatus)_rc) {}; + + std::string name; + KLibraryStatus rc; + }; + + typedef K3L_DEVICE_CONFIG device_conf_type; + typedef K3L_CHANNEL_CONFIG channel_conf_type; + typedef K3L_CHANNEL_CONFIG * channel_ptr_conf_type; + typedef K3L_LINK_CONFIG link_conf_type; + typedef K3L_LINK_CONFIG * link_ptr_conf_type; + + /* constructors/destructors */ + + K3LAPI(); + ~K3LAPI(); + + /* (init|final)ialize the whole thing! */ + + void start(void); + void stop(void); + + /* verificacao de intervalos */ + + inline bool valid_device(int32 dev) + { + return (dev >= 0 && dev < ((int32)_device_count)); + } + + inline bool valid_channel(int32 dev, int32 obj) + { + return (valid_device(dev) && obj >= 0 && obj < ((int32)_channel_count[dev])); + } + + inline bool valid_link(int32 dev, int32 obj) + { + return (valid_device(dev) && obj >= 0 && obj < ((int32)_link_count[dev])); + } + + /* identificadores alto-nivel de objectos */ + struct target + { + 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)) + throw invalid_device(device); + break; + + case CHANNEL: + case MIXER: + if (!k3lapi.valid_channel(device, object)) + throw invalid_channel(device, object); + break; + + case LINK: + if (!k3lapi.valid_link(device, object)) + throw invalid_link(device, object); + break; + } + + }; + + target_type type; + + unsigned short device; + 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); + + /* obter dados 'cacheados' (geral) */ + + inline unsigned int device_count(void) + { + return _device_count; + } + + /* envio de comandos para placa (sem identificadores) */ + + void mixer(int32 dev, int32 obj, byte track, KMixerSource src, int32 index); + void mixerCTbus(int32 dev, int32 obj, byte track, KMixerSource src, int32 index); + + void command (int32 dev, int32 obj, int32 code, std::string & str); + void command (int32 dev, int32 obj, int32 code, const char * parms = NULL); + + /* obter dados 'cacheados' (sem identificadores) */ + + inline unsigned int channel_count(int32 dev) + { + if (!valid_device(dev)) + throw invalid_device(dev); + + return _channel_count[dev]; + } + + inline unsigned int link_count(int32 dev) + { + if (!valid_device(dev)) + throw invalid_device(dev); + + return _link_count[dev]; + } + + KDeviceType device_type(int32 dev) + { + if (!valid_device(dev)) + throw invalid_device(dev); + + 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_channel(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) + { + mixer((int32)tgt.device, (int32)tgt.object, track, src, index); + } + + void mixerCTbus(target & tgt, byte track, KMixerSource src, int32 index) + { + mixerCTbus((int32)tgt.device, (int32)tgt.object, track, src, index); + } + + void command (target & tgt, int32 code, std::string & str) + { + command((int32)tgt.device, (int32)tgt.object, code, str); + }; + + void command (target & tgt, int32 code, const char * parms = NULL) + { + command((int32)tgt.device, (int32)tgt.object, code, parms); + }; + + /* obter dados 'cacheados' (com indentificadores) */ + + inline unsigned int channel_count(target & tgt) + { + return _channel_count[tgt.device]; + } + + inline unsigned int link_count(target & tgt) + { + return _link_count[tgt.device]; + } + + KDeviceType device_type(target & tgt) + { + return _device_type[tgt.device]; + } + + + K3L_DEVICE_CONFIG & device_config(target & tgt) + { + return _device_config[tgt.device]; + } + + K3L_CHANNEL_CONFIG & channel_config(target & tgt) + { + return _channel_config[tgt.device][tgt.object]; + } + + K3L_LINK_CONFIG & link_config(target & tgt) + { + 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); + + /* inicializa valores em cache */ + + void init(void); + + protected: + + unsigned int _device_count; + unsigned int * _channel_count; + unsigned int * _link_count; + + device_conf_type * _device_config; + channel_ptr_conf_type * _channel_config; + link_ptr_conf_type * _link_config; + KDeviceType * _device_type; +}; + +#endif /* INCLUDED_K3LAPI_HPP */ Added: freeswitch/trunk/contrib/mod/endpoints/mod_khomp/commons/strings.cpp ============================================================================== --- (empty file) +++ freeswitch/trunk/contrib/mod/endpoints/mod_khomp/commons/strings.cpp Fri Jun 26 18:20:45 2009 @@ -0,0 +1,153 @@ +#include <strings.hpp> + +void Strings::Merger::add(std::string s) +{ + _list.push_back(s); +}; + +std::string Strings::Merger::merge(const std::string & sep) +{ + list_type::iterator i = _list.begin(); + + std::string res; + + if (i != _list.end()) + { + res += (*i); + ++i; + }; + + while (i != _list.end()) + { + res += sep; + res += (*i); + ++i; + } + + return res; +}; + +std::string Strings::Merger::merge(const char *sep) +{ + std::string ssep(sep); + return merge(ssep); +} + +void Strings::tokenize(const std::string & str, Strings::vector_type & tokens, + const std::string & delims, long int max_tokens) +{ + std::string::size_type init = str.find_first_not_of(delims, 0); + std::string::size_type fini = str.find_first_of(delims, init); + + long int cur_token = 1; + + while (std::string::npos != init) + { + if (std::string::npos != fini && cur_token < max_tokens) + { + tokens.push_back(str.substr(init, fini - init)); + ++cur_token; + } + else + { + tokens.push_back(str.substr(init, str.size() - init)); + break; + } + + init = str.find_first_not_of(delims, fini); + fini = str.find_first_of(delims, init); + } +} + +bool Strings::toboolean(std::string str) +{ + std::string tmp(str); + + Strings::lower(tmp); + + if ((tmp == "true") || (tmp == "yes")) return true; + if ((tmp == "false") || (tmp == "no")) return false; + + throw invalid_value(str); +} + +long Strings::tolong(std::string str, int base) +{ + char *str_end = 0; + + unsigned long value = strtol(str.c_str(), &str_end, base); + + if (str_end && *str_end == 0) + return value; + + 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) +{ +#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); + + if (str_end && *str_end == 0) + return value; + + throw invalid_value(str); +#endif +} + +std::string Strings::fromboolean(bool value) +{ + if (value) return "true"; + else return "false"; +} + +std::string Strings::lower(std::string str) +{ + std::string res; + + for (std::string::iterator i = str.begin(); i != str.end(); i++) + res += tolower((*i)); + + return res; +} + +std::string Strings::hexadecimal(std::string value) +{ + std::string result; + + for (std::string::iterator i = value.begin(); i != value.end(); i++) + { + if (i != value.begin()) + result += " "; + + result += STG(FMT("%2x") % (unsigned int)(*i)); + } + + return result; +} + +std::string Strings::trim(const std::string& str, const std::string& trim_chars) +{ + std::string result(str); + + result.erase( result.find_last_not_of( trim_chars ) + 1 ); + result.erase( 0, result.find_first_not_of( trim_chars ) ); + + return result; +} Modified: freeswitch/trunk/contrib/mod/endpoints/mod_khomp/mod_khomp.cpp ============================================================================== --- freeswitch/trunk/contrib/mod/endpoints/mod_khomp/mod_khomp.cpp (original) +++ freeswitch/trunk/contrib/mod/endpoints/mod_khomp/mod_khomp.cpp Fri Jun 26 18:20:45 2009 @@ -29,156 +29,144 @@ * mod_khomp.c -- Khomp board Endpoint Module * */ - + #define KHOMP_SYNTAX "khomp show [info|links|channels]" -/* Our includes */ -#include "k3lapi.hpp" +#include "mod_khomp.h" + +/* Handles callbacks and events from the boards */ +static int32 Kstdcall khomp_event_callback(int32 obj, K3L_EVENT * e); +static void Kstdcall khomp_audio_listener(int32 deviceid, int32 objectid, byte * read_buffer, int32 read_size); -extern "C" +typedef enum { - #include <switch.h> - #include "k3l.h" + TFLAG_IO = (1 << 0), + TFLAG_INBOUND = (1 << 1), + TFLAG_OUTBOUND = (1 << 2), + TFLAG_DTMF = (1 << 3), + TFLAG_VOICE = (1 << 4), + TFLAG_HANGUP = (1 << 5), + TFLAG_LINEAR = (1 << 6), + TFLAG_CODEC = (1 << 7), + TFLAG_BREAK = (1 << 8) } +TFLAGS; +/* Module management routines */ SWITCH_MODULE_LOAD_FUNCTION(mod_khomp_load); SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_khomp_shutdown); -//SWITCH_MODULE_RUNTIME_FUNCTION(mod_khomp_runtime); -SWITCH_MODULE_DEFINITION(mod_khomp, mod_khomp_load, mod_khomp_shutdown, NULL); //mod_khomp_runtime); +SWITCH_MODULE_DEFINITION(mod_khomp, mod_khomp_load, mod_khomp_shutdown, NULL); +/* State handlers for FreeSWITCH */ +static switch_status_t channel_on_init(switch_core_session_t *session); +static switch_status_t channel_on_routing(switch_core_session_t *session); +static switch_status_t channel_on_execute(switch_core_session_t *session); +static switch_status_t channel_on_hangup(switch_core_session_t *session); +static switch_status_t channel_on_exchange_media( + switch_core_session_t *session); +static switch_status_t channel_on_soft_execute(switch_core_session_t *session); -switch_endpoint_interface_t *khomp_endpoint_interface; -static switch_memory_pool_t *module_pool = NULL; -static int running = 1; - -static K3LAPI * k3l; - - -typedef enum { - TFLAG_IO = (1 << 0), - TFLAG_INBOUND = (1 << 1), - TFLAG_OUTBOUND = (1 << 2), - TFLAG_DTMF = (1 << 3), - TFLAG_VOICE = (1 << 4), - TFLAG_HANGUP = (1 << 5), - TFLAG_LINEAR = (1 << 6), - TFLAG_CODEC = (1 << 7), - TFLAG_BREAK = (1 << 8) -} TFLAGS; - -typedef enum { - GFLAG_MY_CODEC_PREFS = (1 << 0) -} GFLAGS; - - -static struct { - int debug; - char *ip; - int port; - char *dialplan; - char *codec_string; - char *codec_order[SWITCH_MAX_CODECS]; - int codec_order_last; - char *codec_rates_string; - char *codec_rates[SWITCH_MAX_CODECS]; - int codec_rates_last; - unsigned int flags; - int calls; - switch_mutex_t *mutex; -} globals; - -struct private_object { - unsigned int flags; - switch_codec_t read_codec; - switch_codec_t write_codec; - switch_frame_t read_frame; - unsigned char databuf[SWITCH_RECOMMENDED_BUFFER_SIZE]; - switch_core_session_t *session; - switch_caller_profile_t *caller_profile; - switch_mutex_t *mutex; - switch_mutex_t *flag_mutex; - //switch_thread_cond_t *cond; - unsigned int KDeviceId; // Represent de board we are making the call from - unsigned int KChannel; // Represent the channel we are making the call from +switch_state_handler_table_t khomp_state_handlers = { + /*.on_init */ channel_on_init, + /*.on_routing */ channel_on_routing, + /*.on_execute */ channel_on_execute, + /*.on_hangup */ channel_on_hangup, + /*.on_exchange_media */ channel_on_exchange_media, + /*.on_soft_execute */ channel_on_soft_execute }; -typedef struct private_object private_t; +/* Callbacks for FreeSWITCH */ +static switch_call_cause_t channel_outgoing_channel( + switch_core_session_t *session, + switch_event_t *var_event, + switch_caller_profile_t *outbound_profile, + switch_core_session_t **new_session, + switch_memory_pool_t **pool, + switch_originate_flag_t flags); +static switch_status_t channel_read_frame(switch_core_session_t *session, + switch_frame_t **frame, + switch_io_flag_t flags, + int stream_id); +static switch_status_t channel_write_frame(switch_core_session_t *session, + switch_frame_t *frame, + switch_io_flag_t flags, + int stream_id); +static switch_status_t channel_kill_channel(switch_core_session_t *session, + int sig); +static switch_status_t channel_send_dtmf(switch_core_session_t *session, + const switch_dtmf_t *dtmf); +static switch_status_t channel_receive_message(switch_core_session_t *session, + switch_core_session_message_t *msg); +static switch_status_t channel_receive_event(switch_core_session_t *session, + switch_event_t *event); -SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_dialplan, globals.dialplan); -SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_codec_string, globals.codec_string); -SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_codec_rates_string, globals.codec_rates_string); -SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_ip, globals.ip); +switch_io_routines_t khomp_io_routines = { + /*.outgoing_channel */ channel_outgoing_channel, + /*.read_frame */ channel_read_frame, + /*.write_frame */ channel_write_frame, + /*.kill_channel */ channel_kill_channel, + /*.send_dtmf */ channel_send_dtmf, + /*.receive_message */ channel_receive_message, + /*.receive_event */ channel_receive_event +}; /* Macros to define specific API functions */ SWITCH_STANDARD_API(khomp); - -static switch_status_t channel_on_init(switch_core_session_t *session); -static switch_status_t channel_on_hangup(switch_core_session_t *session); -static switch_status_t channel_on_routing(switch_core_session_t *session); -static switch_status_t channel_on_exchange_media(switch_core_session_t *session); -static switch_status_t channel_on_soft_execute(switch_core_session_t *session); -static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event, - switch_caller_profile_t *outbound_profile, - switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags); -static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id); -static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id); -static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig); - /* Helper function prototypes */ static void printSystemSummary(switch_stream_handle_t* stream); -static void printLinks(switch_stream_handle_t* stream, unsigned int device, unsigned int link); -static void printChannels(switch_stream_handle_t* stream, unsigned int device, unsigned int link); -/* Handles callbacks and events from the boards */ -static int32 Kstdcall khomp_event_callback(int32 obj, K3L_EVENT * e); -KLibraryStatus khomp_channel_from_event(unsigned int KDeviceId, unsigned int KChannel, K3L_EVENT * event); -/* Callback for receiving audio buffers from the boards */ -static void Kstdcall khomp_audio_listener (int32 deviceid, int32 mixer, byte * read_buffer, int32 read_size); +static void printLinks(switch_stream_handle_t* stream, unsigned int device, + unsigned int link); +static void printChannels(switch_stream_handle_t* stream, unsigned int device, + unsigned int link); /* Will init part of our private structure and setup all the read/write buffers */ -static switch_status_t tech_init(private_t *tech_pvt, switch_core_session_t *session) +static switch_status_t tech_init(KhompPvt *tech_pvt, switch_core_session_t *session) { - tech_pvt->read_frame.data = tech_pvt->databuf; - tech_pvt->read_frame.buflen = sizeof(tech_pvt->databuf); - switch_mutex_init(&tech_pvt->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session)); - switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session)); - switch_core_session_set_private(session, tech_pvt); - tech_pvt->session = session; - - if (switch_core_codec_init(&tech_pvt->read_codec, - "PCMA", - NULL, - 8000, - 20, - 1, - SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, - NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec?\n"); - return SWITCH_STATUS_GENERR; - } else { - if (switch_core_codec_init(&tech_pvt->write_codec, - "PCMA", - NULL, - 8000, - 20, - 1, - SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, - NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec?\n"); - switch_core_codec_destroy(&tech_pvt->read_codec); - return SWITCH_STATUS_GENERR; - } - } - - switch_core_session_set_read_codec(tech_pvt->session, &tech_pvt->read_codec); - switch_core_session_set_write_codec(tech_pvt->session, &tech_pvt->write_codec); - switch_set_flag_locked(tech_pvt, TFLAG_CODEC); - tech_pvt->read_frame.codec = &tech_pvt->read_codec; - switch_set_flag_locked(tech_pvt, TFLAG_IO); + tech_pvt->_read_frame.data = tech_pvt->_databuf; + tech_pvt->_read_frame.buflen = sizeof(tech_pvt->_databuf); + switch_mutex_init(&tech_pvt->_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session)); + + switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session)); + switch_core_session_set_private(session, tech_pvt); + tech_pvt->_session = session; + + if (switch_core_codec_init(&tech_pvt->_read_codec, + "PCMA", + NULL, + 8000, + 20, + 1, + SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, + NULL, switch_core_session_get_pool(tech_pvt->_session)) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec?\n"); + return SWITCH_STATUS_GENERR; + } else { + if (switch_core_codec_init(&tech_pvt->_write_codec, + "PCMA", + NULL, + 8000, + 20, + 1, + SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, + NULL, switch_core_session_get_pool(tech_pvt->_session)) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec?\n"); + switch_core_codec_destroy(&tech_pvt->_read_codec); + return SWITCH_STATUS_GENERR; + } + } - return SWITCH_STATUS_SUCCESS; + switch_core_session_set_read_codec(tech_pvt->_session, &tech_pvt->_read_codec); + switch_core_session_set_write_codec(tech_pvt->_session, &tech_pvt->_write_codec); + switch_set_flag_locked(tech_pvt, TFLAG_CODEC); + + tech_pvt->_read_frame.codec = &tech_pvt->_read_codec; + + switch_set_flag_locked(tech_pvt, TFLAG_IO); + + return SWITCH_STATUS_SUCCESS; } @@ -189,311 +177,299 @@ */ static switch_status_t channel_on_init(switch_core_session_t *session) { - switch_channel_t *channel; - private_t *tech_pvt = NULL; + KhompPvt * tech_pvt = static_cast< KhompPvt* >(switch_core_session_get_private(session)); + assert(tech_pvt != NULL); + + switch_channel_t *channel = switch_core_session_get_channel(session); + assert(channel != NULL); - tech_pvt = static_cast< private_t* >(switch_core_session_get_private(session)); - assert(tech_pvt != NULL); + switch_set_flag_locked(tech_pvt, TFLAG_IO); - channel = switch_core_session_get_channel(session); - assert(channel != NULL); - switch_set_flag_locked(tech_pvt, TFLAG_IO); - - /* Move channel's state machine to ROUTING. This means the call is trying - to get from the initial start where the call because, to the point - where a destination has been identified. If the channel is simply - left in the initial state, nothing will happen. */ - switch_channel_set_state(channel, CS_ROUTING); - switch_mutex_lock(globals.mutex); - globals.calls++; - switch_mutex_unlock(globals.mutex); + /* Move channel's state machine to ROUTING. This means the call is trying + to get from the initial start where the call because, to the point + where a destination has been identified. If the channel is simply + left in the initial state, nothing will happen. */ + switch_channel_set_state(channel, CS_ROUTING); - return SWITCH_STATUS_SUCCESS; + switch_mutex_lock(Globals::_mutex); + Globals::_calls++; + switch_mutex_unlock(Globals::_mutex); + + return SWITCH_STATUS_SUCCESS; } static switch_status_t channel_on_routing(switch_core_session_t *session) { - switch_channel_t *channel = NULL; - private_t *tech_pvt = NULL; + switch_channel_t *channel = NULL; + KhompPvt *tech_pvt = NULL; - channel = switch_core_session_get_channel(session); - assert(channel != NULL); + channel = switch_core_session_get_channel(session); + assert(channel != NULL); - tech_pvt = static_cast<private_t *>(switch_core_session_get_private(session)); - assert(tech_pvt != NULL); + tech_pvt = static_cast<KhompPvt *>(switch_core_session_get_private(session)); + assert(tech_pvt != NULL); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL ROUTING\n", switch_channel_get_name(channel)); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL ROUTING\n", switch_channel_get_name(channel)); - return SWITCH_STATUS_SUCCESS; + return SWITCH_STATUS_SUCCESS; } static switch_status_t channel_on_execute(switch_core_session_t *session) { - switch_channel_t *channel = NULL; - private_t *tech_pvt = NULL; + switch_channel_t *channel = NULL; + KhompPvt *tech_pvt = NULL; - channel = switch_core_session_get_channel(session); - assert(channel != NULL); + channel = switch_core_session_get_channel(session); + assert(channel != NULL); - tech_pvt = static_cast<private_t*>(switch_core_session_get_private(session)); - assert(tech_pvt != NULL); + tech_pvt = static_cast<KhompPvt*>(switch_core_session_get_private(session)); + assert(tech_pvt != NULL); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL EXECUTE\n", switch_channel_get_name(channel)); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL EXECUTE\n", switch_channel_get_name(channel)); - return SWITCH_STATUS_SUCCESS; + return SWITCH_STATUS_SUCCESS; } static switch_status_t channel_on_hangup(switch_core_session_t *session) { - switch_channel_t *channel = NULL; - private_t *tech_pvt = NULL; + switch_channel_t *channel = NULL; + KhompPvt *tech_pvt = NULL; - channel = switch_core_session_get_channel(session); - assert(channel != NULL); + channel = switch_core_session_get_channel(session); + assert(channel != NULL); - tech_pvt = static_cast<private_t*>(switch_core_session_get_private(session)); - assert(tech_pvt != NULL); + tech_pvt = static_cast<KhompPvt*>(switch_core_session_get_private(session)); + assert(tech_pvt != NULL); - switch_clear_flag_locked(tech_pvt, TFLAG_IO); - switch_clear_flag_locked(tech_pvt, TFLAG_VOICE); - //switch_thread_cond_signal(tech_pvt->cond); - - if (tech_pvt->read_codec.implementation) { - switch_core_codec_destroy(&tech_pvt->read_codec); - } - - if (tech_pvt->write_codec.implementation) { - switch_core_codec_destroy(&tech_pvt->write_codec); - } + switch_clear_flag_locked(tech_pvt, TFLAG_IO); + switch_clear_flag_locked(tech_pvt, TFLAG_VOICE); + //switch_thread_cond_signal(tech_pvt->_cond); - try { - k3l->command(tech_pvt->KDeviceId, tech_pvt->KChannel, CM_DISCONNECT, NULL); - } - catch(K3LAPI::failed_command & e) - { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "WE COULD NOT HANGUP THE CHANNEL! rc:%d\n", e.rc); - return SWITCH_STATUS_TERM; + if (tech_pvt->_read_codec.implementation) { + switch_core_codec_destroy(&tech_pvt->_read_codec); } + if (tech_pvt->_write_codec.implementation) { + switch_core_codec_destroy(&tech_pvt->_write_codec); + } - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s Originator Hangup.\n", switch_channel_get_name(channel)); - switch_mutex_lock(globals.mutex); - globals.calls--; - if (globals.calls < 0) { - globals.calls = 0; - } - switch_mutex_unlock(globals.mutex); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s Originator Hangup.\n", switch_channel_get_name(channel)); + switch_mutex_lock(Globals::_mutex); + Globals::_calls--; + if (Globals::_calls < 0) { + Globals::_calls = 0; + } + switch_mutex_unlock(Globals::_mutex); - return SWITCH_STATUS_SUCCESS; + return SWITCH_STATUS_SUCCESS; } static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig) { - switch_channel_t *channel = NULL; - private_t *tech_pvt = NULL; - - channel = switch_core_session_get_channel(session); - assert(channel != NULL); - - tech_pvt = static_cast<private_t*>(switch_core_session_get_private(session)); - assert(tech_pvt != NULL); - - switch (sig) { - case SWITCH_SIG_KILL: - switch_clear_flag_locked(tech_pvt, TFLAG_IO); - switch_clear_flag_locked(tech_pvt, TFLAG_VOICE); - switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); - //switch_thread_cond_signal(tech_pvt->cond); - break; - case SWITCH_SIG_BREAK: - switch_set_flag_locked(tech_pvt, TFLAG_BREAK); - break; - default: - break; - } + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "CHANNEL KILL\n"); + switch_channel_t *channel = NULL; + KhompPvt *tech_pvt = NULL; + + channel = switch_core_session_get_channel(session); + assert(channel != NULL); + + tech_pvt = static_cast<KhompPvt*>(switch_core_session_get_private(session)); + assert(tech_pvt != NULL); + + switch (sig) { + case SWITCH_SIG_KILL: + switch_clear_flag_locked(tech_pvt, TFLAG_IO); + switch_clear_flag_locked(tech_pvt, TFLAG_VOICE); + switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); + //switch_thread_cond_signal(tech_pvt->_cond); + break; + case SWITCH_SIG_BREAK: + switch_set_flag_locked(tech_pvt, TFLAG_BREAK); + break; + default: + break; + } - return SWITCH_STATUS_SUCCESS; + return SWITCH_STATUS_SUCCESS; } static switch_status_t channel_on_exchange_media(switch_core_session_t *session) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "CHANNEL LOOPBACK\n"); - return SWITCH_STATUS_SUCCESS; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "CHANNEL LOOPBACK\n"); + return SWITCH_STATUS_SUCCESS; } static switch_status_t channel_on_soft_execute(switch_core_session_t *session) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "CHANNEL TRANSMIT\n"); - return SWITCH_STATUS_SUCCESS; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "CHANNEL TRANSMIT\n"); + return SWITCH_STATUS_SUCCESS; } static switch_status_t channel_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf) { - private_t *tech_pvt = static_cast<private_t*>(switch_core_session_get_private(session)); - switch_assert(tech_pvt != NULL); + KhompPvt *tech_pvt = static_cast<KhompPvt*>(switch_core_session_get_private(session)); + switch_assert(tech_pvt != NULL); - return SWITCH_STATUS_SUCCESS; + return SWITCH_STATUS_SUCCESS; } static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id) { - switch_channel_t *channel = NULL; - private_t *tech_pvt = NULL; - //switch_time_t started = switch_time_now(); - //unsigned int elapsed; - switch_byte_t *data; - - channel = switch_core_session_get_channel(session); - assert(channel != NULL); - - tech_pvt = static_cast<private_t*>(switch_core_session_get_private(session)); - assert(tech_pvt != NULL); - tech_pvt->read_frame.flags = SFF_NONE; - *frame = NULL; - - - while (switch_test_flag(tech_pvt, TFLAG_IO)) { - - if (switch_test_flag(tech_pvt, TFLAG_BREAK)) { - switch_clear_flag(tech_pvt, TFLAG_BREAK); - goto cng; - } - - if (!switch_test_flag(tech_pvt, TFLAG_IO)) { - return SWITCH_STATUS_FALSE; - } - - //if (switch_test_flag(tech_pvt, TFLAG_IO) && switch_test_flag(tech_pvt, TFLAG_VOICE)) { - // switch_clear_flag_locked(tech_pvt, TFLAG_VOICE); - if (!tech_pvt->read_frame.datalen) { - continue; - } - *frame = &tech_pvt->read_frame; + switch_channel_t *channel = NULL; + KhompPvt *tech_pvt = NULL; + //switch_time_t started = switch_time_now(); + //unsigned int elapsed; + switch_byte_t *data; + + channel = switch_core_session_get_channel(session); + assert(channel != NULL); + + tech_pvt = static_cast<KhompPvt*>(switch_core_session_get_private(session)); + assert(tech_pvt != NULL); + tech_pvt->_read_frame.flags = SFF_NONE; + *frame = NULL; + + + while (switch_test_flag(tech_pvt, TFLAG_IO)) { + + if (switch_test_flag(tech_pvt, TFLAG_BREAK)) { + switch_clear_flag(tech_pvt, TFLAG_BREAK); + goto cng; + } + + if (!switch_test_flag(tech_pvt, TFLAG_IO)) { + return SWITCH_STATUS_FALSE; + } + + switch_clear_flag_locked(tech_pvt, TFLAG_VOICE); + if (!tech_pvt->_read_frame.datalen) { + continue; + } + *frame = &tech_pvt->_read_frame; #ifdef BIGENDIAN - if (switch_test_flag(tech_pvt, TFLAG_LINEAR)) { - switch_swap_linear((*frame)->data, (int) (*frame)->datalen / 2); - } + if (switch_test_flag(tech_pvt, TFLAG_LINEAR)) { + switch_swap_linear((*frame)->data, (int) (*frame)->datalen / 2); + } #endif - return SWITCH_STATUS_SUCCESS; - //} + return SWITCH_STATUS_SUCCESS; - switch_cond_next(); - } + switch_cond_next(); + } - return SWITCH_STATUS_FALSE; + return SWITCH_STATUS_FALSE; cng: - data = (switch_byte_t *) tech_pvt->read_frame.data; - data[0] = 65; - data[1] = 0; - tech_pvt->read_frame.datalen = 2; - tech_pvt->read_frame.flags = SFF_CNG; - *frame = &tech_pvt->read_frame; - return SWITCH_STATUS_SUCCESS; + data = (switch_byte_t *) tech_pvt->_read_frame.data; + data[0] = 65; + data[1] = 0; + tech_pvt->_read_frame.datalen = 2; + tech_pvt->_read_frame.flags = SFF_CNG; + *frame = &tech_pvt->_read_frame; + return SWITCH_STATUS_SUCCESS; } static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id) { - switch_channel_t *channel = NULL; - private_t *tech_pvt = NULL; - //switch_frame_t *pframe; - - channel = switch_core_session_get_channel(session); - assert(channel != NULL); - - tech_pvt = static_cast<private_t*>(switch_core_session_get_private(session)); - assert(tech_pvt != NULL); - - if (!switch_test_flag(tech_pvt, TFLAG_IO)) { - return SWITCH_STATUS_FALSE; - } + switch_channel_t *channel = NULL; + KhompPvt *tech_pvt = NULL; + //switch_frame_t *pframe; + + channel = switch_core_session_get_channel(session); + assert(channel != NULL); + + tech_pvt = static_cast<KhompPvt*>(switch_core_session_get_private(session)); + assert(tech_pvt != NULL); + + if (!switch_test_flag(tech_pvt, TFLAG_IO)) { + return SWITCH_STATUS_FALSE; + } #ifdef BIGENDIAN - if (switch_test_flag(tech_pvt, TFLAG_LINEAR)) { - switch_swap_linear(frame->data, (int) frame->datalen / 2); - } + if (switch_test_flag(tech_pvt, TFLAG_LINEAR)) { + switch_swap_linear(frame->data, (int) frame->datalen / 2); + } #endif - return SWITCH_STATUS_SUCCESS; + return SWITCH_STATUS_SUCCESS; } static switch_status_t channel_answer_channel(switch_core_session_t *session) { - private_t *tech_pvt; - switch_channel_t *channel = NULL; + KhompPvt *tech_pvt; + switch_channel_t *channel = NULL; - channel = switch_core_session_get_channel(session); - assert(channel != NULL); + channel = switch_core_session_get_channel(session); + assert(channel != NULL); - tech_pvt = static_cast<private_t*>(switch_core_session_get_private(session)); - assert(tech_pvt != NULL); + tech_pvt = static_cast<KhompPvt*>(switch_core_session_get_private(session)); + assert(tech_pvt != NULL); - return SWITCH_STATUS_SUCCESS; + return SWITCH_STATUS_SUCCESS; } static switch_status_t channel_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg) { - switch_channel_t *channel; - private_t *tech_pvt; + switch_channel_t *channel; + KhompPvt *tech_pvt; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "When the fuck is this called?.\n"); - channel = switch_core_session_get_channel(session); - assert(channel != NULL); + channel = switch_core_session_get_channel(session); + assert(channel != NULL); - tech_pvt = (private_t *) switch_core_session_get_private(session); - assert(tech_pvt != NULL); + tech_pvt = (KhompPvt *) switch_core_session_get_private(session); + assert(tech_pvt != NULL); - switch (msg->message_id) { - case SWITCH_MESSAGE_INDICATE_ANSWER: - { - channel_answer_channel(session); - } - break; - default: - break; - } + switch (msg->message_id) { + case SWITCH_MESSAGE_INDICATE_ANSWER: + { + channel_answer_channel(session); + } + break; + default: + break; + } - return SWITCH_STATUS_SUCCESS; + return SWITCH_STATUS_SUCCESS; } /* Make sure when you have 2 sessions in the same scope that you pass the appropriate one to the routines that allocate memory or you will have 1 channel with memory allocated from another channel's pool! */ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event, - switch_caller_profile_t *outbound_profile, - switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags) + switch_caller_profile_t *outbound_profile, + switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags) { - char *argv[3] = { 0 }; - int argc = 0; + char *argv[3] = { 0 }; + int argc = 0; - if ((*new_session = switch_core_session_request(khomp_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, pool)) != 0) { - private_t *tech_pvt; - switch_channel_t *channel; - switch_caller_profile_t *caller_profile; - - switch_core_session_add_stream(*new_session, NULL); - if ((tech_pvt = (private_t *) switch_core_session_alloc(*new_session, sizeof(private_t))) != 0) { - channel = switch_core_session_get_channel(*new_session); - tech_init(tech_pvt, *new_session); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Hey where is my memory pool?\n"); - switch_core_session_destroy(new_session); - return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; - } + if ((*new_session = switch_core_session_request(Globals::_khomp_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, pool)) != 0) { + KhompPvt *tech_pvt; + switch_channel_t *channel; + switch_caller_profile_t *caller_profile; + + switch_core_session_add_stream(*new_session, NULL); + if ((tech_pvt = (KhompPvt *) switch_core_session_alloc(*new_session, sizeof(KhompPvt))) != 0) { + channel = switch_core_session_get_channel(*new_session); + tech_init(tech_pvt, *new_session); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Hey where is my memory pool?\n"); + switch_core_session_destroy(new_session); + return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; + } - if (outbound_profile) { - char name[128]; + if (outbound_profile) { + char name[128]; - snprintf(name, sizeof(name), "Khomp/%s", outbound_profile->destination_number); - switch_channel_set_name(channel, name); + snprintf(name, sizeof(name), "Khomp/%s", outbound_profile->destination_number); + switch_channel_set_name(channel, name); /* Let's setup our own vars on tech_pvt */ if ((argc = switch_separate_string(outbound_profile->destination_number, '/', argv, (sizeof(argv) / sizeof(argv[0])))) < 3) @@ -503,220 +479,148 @@ } else { - tech_pvt->KDeviceId = atoi(argv[0]); - tech_pvt->KChannel = atoi(argv[1]); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Dialing to %s out from Board:%u, Channel:%u.\n", - argv[2], - tech_pvt->KDeviceId, - tech_pvt->KChannel); +// usar algoritmo de busca de canais (spec.*). +// tech_pvt->_KDeviceId = atoi(argv[0]); +// tech_pvt->_KChannel = atoi(argv[1]); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Dialing to %s out\n",// from Board:%u, Channel:%u.\n", + argv[2] + //, tech_pvt->_KDeviceId, tech_pvt->_KChannel + ); } - caller_profile = switch_caller_profile_clone(*new_session, outbound_profile); - switch_channel_set_caller_profile(channel, caller_profile); - tech_pvt->caller_profile = caller_profile; - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Doh! no caller profile\n"); - switch_core_session_destroy(new_session); + caller_profile = switch_caller_profile_clone(*new_session, outbound_profile); + switch_channel_set_caller_profile(channel, caller_profile); + tech_pvt->_caller_profile = caller_profile; + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Doh! no caller profile\n"); + switch_core_session_destroy(new_session); /* Destroy the channel session */ - k3l->setSession(tech_pvt->KDeviceId, tech_pvt->KChannel, NULL); - return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; - } + // Globals::_k3lapi.setSession(tech_pvt->_KDeviceId, tech_pvt->_KChannel, NULL); + return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; + } - switch_channel_set_flag(channel, CF_OUTBOUND); - switch_set_flag_locked(tech_pvt, TFLAG_OUTBOUND); - switch_channel_set_state(channel, CS_INIT); + switch_channel_set_flag(channel, CF_OUTBOUND); + switch_set_flag_locked(tech_pvt, TFLAG_OUTBOUND); + switch_channel_set_state(channel, CS_INIT); try { /* Lets make the call! */ char params[ 255 ]; - sprintf(params, "dest_addr=\"%s\" orig_addr=\"%s\"", argv[2], outbound_profile->caller_id_number); + sprintf(params, "dest_addr=\"%s\"", argv[2]); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "We are calling with params: %s.\n", params); - k3l->command(tech_pvt->KDeviceId,tech_pvt->KChannel, CM_MAKE_CALL, params); + //Globals::_k3lapi.command(tech_pvt->_KDeviceId,tech_pvt->_KChannel, CM_MAKE_CALL, params); } catch(K3LAPI::failed_command & e) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not place call! Cause: code%x and rc%d.\n", e.code, e.rc); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not place call! Cause: code%x and rc%d.\n", e.code, e.rc); return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; } /* Add the new session the the channel's info */ - k3l->setSession(tech_pvt->KDeviceId, tech_pvt->KChannel, *new_session); + //Globals::_k3lapi.setSession(tech_pvt->_KDeviceId, tech_pvt->_KChannel, *new_session); - return SWITCH_CAUSE_SUCCESS; - } + return SWITCH_CAUSE_SUCCESS; + } - return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; + return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; } static switch_status_t channel_receive_event(switch_core_session_t *session, switch_event_t *event) { - struct private_object *tech_pvt = static_cast<private_t*>(switch_core_session_get_private(session)); - char *body = switch_event_get_body(event); - switch_assert(tech_pvt != NULL); - - if (!body) { - body = ""; - } + struct KhompPvt *tech_pvt = static_cast<KhompPvt*>(switch_core_session_get_private(session)); + char *body = switch_event_get_body(event); + switch_assert(tech_pvt != NULL); - return SWITCH_STATUS_SUCCESS; -} - - - -switch_state_handler_table_t khomp_state_handlers = { - /*.on_init */ channel_on_init, - /*.on_routing */ channel_on_routing, - /*.on_execute */ channel_on_execute, - /*.on_hangup */ channel_on_hangup, - /*.on_exchange_media */ channel_on_exchange_media, - /*.on_soft_execute */ channel_on_soft_execute -}; - -switch_io_routines_t khomp_io_routines = { - /*.outgoing_channel */ channel_outgoing_channel, - /*.read_frame */ channel_read_frame, - /*.write_frame */ channel_write_frame, - /*.kill_channel */ channel_kill_channel, - /*.send_dtmf */ channel_send_dtmf, - /*.receive_message */ channel_receive_message, - /*.receive_event */ channel_receive_event -}; + if (!body) { + body = (char *)""; + } -static switch_status_t load_config(void) -{ - const char *cf = "khomp.conf"; - switch_xml_t cfg, xml, settings, param; + return SWITCH_STATUS_SUCCESS; +} - memset(&globals, 0, sizeof(globals)); - switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, module_pool); - if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", cf); - return SWITCH_STATUS_TERM; - } - - if ((settings = switch_xml_child(cfg, "settings"))) { - for (param = switch_xml_child(settings, "param"); param; param = param->next) { - char *var = (char *) switch_xml_attr_soft(param, "name"); - char *val = (char *) switch_xml_attr_soft(param, "value"); - - if (!strcmp(var, "debug")) { - globals.debug = atoi(val); - } else if (!strcmp(var, "port")) { - globals.port = atoi(val); - } else if (!strcmp(var, "ip")) { - set_global_ip(val); - } else if (!strcmp(var, "codec-master")) { - if (!strcasecmp(val, "us")) { - switch_set_flag(&globals, GFLAG_MY_CODEC_PREFS); - } - } else if (!strcmp(var, "dialplan")) { - set_global_dialplan(val); - } else if (!strcmp(var, "codec-prefs")) { - set_global_codec_string(val); - globals.codec_order_last = switch_separate_string(globals.codec_string, ',', globals.codec_order, SWITCH_MAX_CODECS); - } else if (!strcmp(var, "codec-rates")) { - set_global_codec_rates_string(val); - globals.codec_rates_last = switch_separate_string(globals.codec_rates_string, ',', globals.codec_rates, SWITCH_MAX_CODECS); - } - } - } - - if (!globals.dialplan) { - set_global_dialplan("default"); - } - - if (!globals.port) { - globals.port = 4569; - } - switch_xml_free(xml); - return SWITCH_STATUS_SUCCESS; -} SWITCH_MODULE_LOAD_FUNCTION(mod_khomp_load) { - module_pool = pool; + Globals::_module_pool = pool; - memset(&globals, 0, sizeof(globals)); - - load_config(); + /* start config system! */ + Opt::initialize(); + + Opt::obtain(); - switch_api_interface_t *api_interface; + //load_config(); - *module_interface = switch_loadable_module_create_module_interface(pool, "mod_khomp"); - khomp_endpoint_interface = static_cast<switch_endpoint_interface_t*>(switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE)); - khomp_endpoint_interface->interface_name = "khomp"; - khomp_endpoint_interface->io_routines = &khomp_io_routines; - khomp_endpoint_interface->state_handler = &khomp_state_handlers; /* Spawn our k3l global var that will be used along the module for sending info to the boards */ - k3lSetGlobalParam (klpResetFwOnStartup, 1); - k3lSetGlobalParam (klpDisableInternalVoIP, 1); - - k3l = new K3LAPI(); /* Start the API and connect to KServer */ - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Starting K3L...\n"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Starting K3L...\n"); try { - k3l->start(); + Globals::_k3lapi.start(); } catch (K3LAPI::start_failed & e) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "K3L not started. Reason:%s.\n", e.msg.c_str()); return SWITCH_STATUS_TERM; } - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "K3L started.\n"); - + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "K3L started.\n"); + k3lRegisterEventHandler( khomp_event_callback ); - k3lRegisterAudioListener (NULL, khomp_audio_listener); + k3lRegisterAudioListener (NULL, khomp_audio_listener); + + *module_interface = switch_loadable_module_create_module_interface(pool, "mod_khomp"); + Globals::_khomp_endpoint_interface = static_cast<switch_endpoint_interface_t*>(switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE)); + Globals::_khomp_endpoint_interface->interface_name = "khomp"; + Globals::_khomp_endpoint_interface->io_routines = &khomp_io_routines; + Globals::_khomp_endpoint_interface->state_handler = &khomp_state_handlers; /* Add all the specific API functions */ - SWITCH_ADD_API(api_interface, "khomp", "Khomp Menu", khomp, KHOMP_SYNTAX); + SWITCH_ADD_API(Globals::_api_interface, "khomp", "Khomp Menu", khomp, KHOMP_SYNTAX); - /* indicate that the module should continue to be loaded */ - return SWITCH_STATUS_SUCCESS; + /* indicate that the module should continue to be loaded */ + return SWITCH_STATUS_SUCCESS; } /* SWITCH_MODULE_RUNTIME_FUNCTION(mod_khomp_runtime) { - return SWITCH_STATUS_TERM; + return SWITCH_STATUS_TERM; } */ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_khomp_shutdown) { - int x = 0; + int x = 0; - running = -1; + Globals::_running = -1; - while (running) { - if (x++ > 100) { - break; - } - switch_yield(20000); - } - - /* Free dynamically allocated strings */ - switch_safe_free(globals.dialplan); - switch_safe_free(globals.codec_string); - switch_safe_free(globals.codec_rates_string); - switch_safe_free(globals.ip); - - /* Finnish him! */ - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Stopping K3L...\n"); - k3l->stop(); - delete k3l; - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "the K3L API has been stopped!\n"); - - return SWITCH_STATUS_SUCCESS; + while (Globals::_running) { + if (x++ > 100) { + break; + } + switch_yield(20000); + } + + /* Free dynamically allocated strings */ + switch_safe_free(Opt::_dialplan); + switch_safe_free(Opt::_codec_string); + switch_safe_free(Opt::_codec_rates_string); + switch_safe_free(Opt::_ip); + + /* Finnish him! */ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Stopping K3L...\n"); + Globals::_k3lapi.stop(); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "the K3L API has been stopped!\n"); + + return SWITCH_STATUS_SUCCESS; } /* @@ -725,27 +629,27 @@ */ SWITCH_STANDARD_API(khomp) { - char *argv[10] = { 0 }; - int argc = 0; - void *val; - char *myarg = NULL; - switch_status_t status = SWITCH_STATUS_SUCCESS; + char *argv[10] = { 0 }; + int argc = 0; + void *val; + char *myarg = NULL; + switch_status_t status = SWITCH_STATUS_SUCCESS; /* We should not ever get a session here */ - if (session) return status; + if (session) return status; - if (switch_strlen_zero(cmd) || !(myarg = strdup(cmd))) { - stream->write_function(stream, "USAGE: %s\n", KHOMP_SYNTAX); - return SWITCH_STATUS_FALSE; - } - - if ((argc = switch_separate_string(myarg, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) < 1) { - stream->write_function(stream, "USAGE: %s\n", KHOMP_SYNTAX); - goto done; - } + if (switch_strlen_zero(cmd) || !(myarg = strdup(cmd))) { + stream->write_function(stream, "USAGE: %s\n", KHOMP_SYNTAX); + return SWITCH_STATUS_FALSE; + } + + if ((argc = switch_separate_string(myarg, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) < 1) { + stream->write_function(stream, "USAGE: %s\n", KHOMP_SYNTAX); + goto done; + } /* Below show ... */ - if (argv[0] && !strncasecmp(argv[0], "show", 4)) { + if (argv[0] && !strncasecmp(argv[0], "show", 4)) { /* Show the API summary and information */ if (argv[1] && !strncasecmp(argv[1], "info", 4)) { printSystemSummary(stream); @@ -761,13 +665,13 @@ printChannels(stream, NULL, NULL); } - } else { - stream->write_function(stream, "USAGE: %s\n", KHOMP_SYNTAX); - } + } else { + stream->write_function(stream, "USAGE: %s\n", KHOMP_SYNTAX); + } done: - switch_safe_free(myarg); - return status; + switch_safe_free(myarg); + return status; } @@ -775,13 +679,13 @@ static void printChannels(switch_stream_handle_t* stream, unsigned int device, unsigned int link) { if (!device) { // Print all channels from all boards and links - stream->write_function(stream, "|--------- Khomp ----------|\n"); - stream->write_function(stream, "| Board | Channel | Status |\n"); - for (int board=0 ; board < k3l->device_count() ; board++) { - for (int channel=0 ; channel < k3l->channel_count(board) ; channel++) { + stream->write_function(stream, "|--------- Khomp ----------|\n"); + stream->write_function(stream, "| Board | Channel | Status |\n"); + for (int board=0 ; board < Globals::_k3lapi.device_count() ; board++) { + for (int channel=0 ; channel < Globals::_k3lapi.channel_count(board) ; channel++) { try { K3L_CHANNEL_CONFIG channelConfig; - channelConfig = k3l->channel_config( board, channel ); + channelConfig = Globals::_k3lapi.channel_config( board, channel ); } catch (...){ stream->write_function(stream, "OOOPSS. Something went wrong, cleanup this mess!\n"); @@ -821,12 +725,12 @@ // We want to see all links from all devices if (!device) { - for(int device=0 ; device < k3l->device_count() ; device++) + for(int device=0 ; device < Globals::_k3lapi.device_count() ; device++) { - K3L_LINK_CONFIG & config = k3l->link_config(device, link); + K3L_LINK_CONFIG & config = Globals::_k3lapi.link_config(device, link); K3L_LINK_STATUS status; - for(int link=0 ; link < k3l->link_count(device) ; link++) + for(int link=0 ; link < Globals::_k3lapi.link_count(device) ; link++) { const char * E1Status = ""; if (k3lGetDeviceStatus (device, link + ksoLink, &status, sizeof(status)) == ksSuccess) @@ -922,13 +826,13 @@ , apiCfg.VpdVersionNeeded , apiCfg.StrVersion); } - for (unsigned int i = 0; i < k3l->device_count(); i++) + for (unsigned int i = 0; i < Globals::_k3lapi.device_count(); i++) { - K3L_DEVICE_CONFIG & devCfg = k3l->device_config(i); + K3L_DEVICE_CONFIG & devCfg = Globals::_k3lapi.device_config(i); stream->write_function(stream, " ------------------------------------------------------------------\n"); - switch (k3l->device_type(i)) + switch (Globals::_k3lapi.device_type(i)) { /* E1 boards */ case kdtE1: @@ -1001,7 +905,7 @@ } default: stream->write_function(stream, "| [[ %02d ]] Unknown type '%02d'! Please contact Khomp support for help! |\n" - , i , k3l->device_type(i)); + , i , Globals::_k3lapi.device_type(i)); break; } } @@ -1010,120 +914,17 @@ } /* End of helper functions */ -/* Create a new channel on incoming call */ -KLibraryStatus khomp_channel_from_event(unsigned int KDeviceId, unsigned int KChannel, K3L_EVENT * event) -{ - switch_core_session_t *session = NULL; - private_t *tech_pvt = NULL; - switch_channel_t *channel = NULL; - char name[128]; - - if (!(session = switch_core_session_request(khomp_endpoint_interface, SWITCH_CALL_DIRECTION_INBOUND, NULL))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Initilization Error!\n"); - return ksFail; - } - - switch_core_session_add_stream(session, NULL); - - tech_pvt = (private_t *) switch_core_session_alloc(session, sizeof(private_t)); - assert(tech_pvt != NULL); - channel = switch_core_session_get_channel(session); - if (tech_init(tech_pvt, session) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Initilization Error!\n"); - switch_core_session_destroy(&session); - return ksFail; - } - - - /* Get all data from event */ - std::string cidNum; - std::string destination_number; - try - { - cidNum = k3l->get_param(event, "orig_addr"); - destination_number = k3l->get_param(event, "dest_addr"); - } - catch ( K3LAPI::get_param_failed & err ) - { - // TODO: Can we set NULL variables? What should we do if this fails? - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Could not get param %s on channel %u, board %u.\n", err.name.c_str(), KChannel, KDeviceId); - } - - /*if (switch_strlen_zero(sigmsg->channel->caller_data.cid_num.digits)) { - if (!switch_strlen_zero(sigmsg->channel->caller_data.ani.digits)) { - switch_set_string(sigmsg->channel->caller_data.cid_num.digits, sigmsg->channel->caller_data.ani.digits); - } else { - switch_set_string(sigmsg->channel->caller_data.cid_num.digits, sigmsg->channel->chan_number); - } - } - */ - - /* Set the caller profile - Look at documentation */ - tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session), - "Khomp", - "XML", // TODO: Dialplan module to use? - NULL, - NULL, - NULL, - cidNum.c_str(), - NULL, - NULL, - (char *) modname, - "default", // TODO: Context to look for on the dialplan? - destination_number.c_str()); - - assert(tech_pvt->caller_profile != NULL); - /* END */ - - /* WHAT??? - Look at documentation */ - //switch_set_flag(tech_pvt->caller_profile, SWITCH_CPF_NONE); - /* END */ - - /* */ - snprintf(name, sizeof(name), "Khomp/%u/%u/%s", KDeviceId, KChannel, tech_pvt->caller_profile->destination_number); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Connect inbound channel %s\n", name); - switch_channel_set_name(channel, name); - switch_channel_set_caller_profile(channel, tech_pvt->caller_profile); - /* END */ - - - switch_channel_set_state(channel, CS_INIT); - if (switch_core_session_thread_launch(session) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error spawning thread\n"); - switch_core_session_destroy(&session); - return ksFail; - } - - /* WHAT? - if (zap_channel_add_token(sigmsg->channel, switch_core_session_get_uuid(session), 0) != ZAP_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error adding token\n"); - switch_core_session_destroy(&session); - return ZAP_FAIL; - } - */ - - /* Set the session to the channel */ - k3l->setSession(KDeviceId, KChannel, session); - - return ksSuccess; -} - static int32 Kstdcall khomp_event_callback(int32 obj, K3L_EVENT * e) -{ +{ /* TODO: How do we make sure channels inside FreeSWITCH only change to valid states on K3L? */ switch(e->Code) { case EV_NEW_CALL: - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "New call on %u to %s. [EV_NEW_CALL]\n", obj, k3l->get_param(e, "dest_addr").c_str()); - if (khomp_channel_from_event(e->DeviceId, obj, e) != ksSuccess ) - { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Something bad happened while getting channel session. Device:%u/Channel:%u. [EV_CONNECT]\n", e->DeviceId, obj); - return ksFail; - } + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "New call on %u to %s. [EV_NEW_CALL]\n", obj, Globals::_k3lapi.get_param(e, "dest_addr").c_str()); try { - k3l->command(e->DeviceId, obj, CM_RINGBACK, NULL); - k3l->command(e->DeviceId, obj, CM_CONNECT, NULL); + Globals::_k3lapi.command(e->DeviceId, obj, CM_RINGBACK, NULL); + Globals::_k3lapi.command(e->DeviceId, obj, CM_CONNECT, NULL); } catch (K3LAPI::failed_command & err) { @@ -1131,43 +932,31 @@ } break; case EV_DISCONNECT: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Called party dropped the call on: %u. Releasing channel. [EV_DISCONNECT]\n", obj); + if (channel_on_hangup(KhompPvt::khompPvt(e->DeviceId, obj)->session()) != SWITCH_STATUS_SUCCESS) + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not hangup channel: %u on board %u. Releasing board channel anyway. [EV_DISCONNECT]\n", obj, e->DeviceId); + try { - switch_core_session_t * session = NULL; - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Called party dropped the call on: %u. Releasing channel. [EV_DISCONNECT]\n", obj); - try - { - session = k3l->getSession(e->DeviceId, obj); - } - catch(K3LAPI::invalid_channel & err) - { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Session does not exist on channel: %u on board %u. Releasing board channel anyway. [EV_DISCONNECT]\n", obj, e->DeviceId); - } - if (channel_on_hangup(session) != SWITCH_STATUS_SUCCESS) - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not hangup channel: %u on board %u. Releasing board channel anyway. [EV_DISCONNECT]\n", obj, e->DeviceId); - try - { - k3l->setSession(e->DeviceId, obj, NULL); - } - catch(K3LAPI::invalid_channel & err) - { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "We are trying to set session on an non existent channel: %u on board %u. Releasing channel. [EV_DISCONNECT]\n", obj, e->DeviceId); - } - /* Do we need to release on the board? */ - k3l->command(e->DeviceId, obj, CM_DISCONNECT, NULL); + Globals::_k3lapi.command(e->DeviceId, obj, CM_DISCONNECT, NULL); + KhompPvt::khompPvt(e->DeviceId, obj)->session(NULL); + } + catch(K3LAPI::invalid_channel & err) + { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not send CM_DISCONNECT!\n"); } break; case EV_CONNECT: - switch_core_session_t* session; + switch_core_session_t* session; try { - session = k3l->getSession(e->DeviceId ,obj); + session = KhompPvt::khompPvt(e->DeviceId, obj)->session(); switch_channel_t *channel; channel = switch_core_session_get_channel(session); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Call will be answered on board %u, channel %u. [EV_CONNECT]\n", e->DeviceId, obj); switch_channel_mark_answered(channel); /* Start listening for audio */ const size_t buffer_size = 16; - k3l->command(e->DeviceId, obj, CM_LISTEN, (const char *) &buffer_size); + Globals::_k3lapi.command(e->DeviceId, obj, CM_LISTEN, (const char *) &buffer_size); } catch (K3LAPI::invalid_session & err) { @@ -1229,7 +1018,7 @@ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Channel %u on board %u reported failure. [EV_CHANNEL_FAIL]\n", obj, e->DeviceId); break; case EV_LINK_STATUS: - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Link %u on board %u changed. [EV_LINK_STATUS]\n", e->DeviceId, obj); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Link %u on board %u changed. [EV_LINK_STATUS]\n", e->DeviceId, obj); break; case EV_PHYSICAL_LINK_DOWN: switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Link %u on board %u is DOWN. [EV_PHYSICAL_LINK_DOWN]\n", e->DeviceId, obj); @@ -1275,14 +1064,12 @@ default: switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "New Event has just arrived on %u with untreated code: %x\n", obj, e->Code); } - + return ksSuccess; } - static void Kstdcall khomp_audio_listener (int32 deviceid, int32 mixer, byte * read_buffer, int32 read_size) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "New audio buffer for deviceid %d, mixer %d, with size %d\n", deviceid, mixer, read_size); } /* For Emacs: