- fxo-busy-disconnection timer for desconnection on FXO

- khomp set changes configuration
- KR2GotCategory variable
- Disconnection forced R2 signaling (collect call)
- restricted, omits the number of origin
- Option to enable/disable dial with '#' on FXS
- Added KR2StrCategory
- Added "khomp dump config" command
- KISDNOrigTypeOfNumber, KISDNDestTypeOfNumber, KISDNOrigNumberingPlan,
KISDNDestNumberingPlan, KISDNOrigPresentation
- New version of commons
- Updated documentation
This commit is contained in:
Geovani Ricardo Wiedenhoft 2011-02-17 17:41:56 -02:00
parent d46ea5d346
commit 2f9357b2a7
33 changed files with 654 additions and 272 deletions

View File

@ -272,6 +272,15 @@ a FXS branch.
<param name="fxs-bina" value="yes"/> <param name="fxs-bina" value="yes"/>
--> -->
<!--
Enables/disables the use of sharp (#) as an end-of-number digit on FXS
channels for instant dialing. This does not affect special numbers which
start on sharp, like #8 or #1.
(default = yes)
<param name="fxs-sharp-dial" value="yes" />
-->
<!-- <!--
This is the delay time to really disconnect a channel after the disconnect This is the delay time to really disconnect a channel after the disconnect
event arrive. If a connect event comes up in this interval, then the event arrive. If a connect event comes up in this interval, then the
@ -312,6 +321,21 @@ you may need to set this option to 'no'.
<param name="ignore-letter-dtmfs" value="yes"/> <param name="ignore-letter-dtmfs" value="yes"/>
--> -->
<!--
When there is a request to indicate busy for an incoming KFXO call, the
ringing channel is taken off hook and then placed on hook, so it now goes
to answered state and we can send audio throught the line.
If the off/on hook time interval is too short, the PSTN may ignore it, and
keep the line in a ringing state. If it is too long, the call may be charged.
The option below defines the delay between the line being answered and being
disconnected, in miliseconds (from 50ms to 90000ms).
(default = 1250)
<param name="fxo-busy-disconnection" value="1250"/>
-->
<!-- <!--
For KFXO series boards, defines if audio will be allowed being sent into For KFXO series boards, defines if audio will be allowed being sent into
outgoing calls before it has been connected. outgoing calls before it has been connected.

View File

@ -69,6 +69,6 @@
#define COMMONS_VERSION_MINOR 1 #define COMMONS_VERSION_MINOR 1
#define COMMONS_AT_LEAST(x,y) \ #define COMMONS_AT_LEAST(x,y) \
(COMMONS_VERSION_MAJOR > x || (COMMONS_VERSION_MAJOR == x && COMMONS_VERSION_MINOR >= y)) ((COMMONS_VERSION_MAJOR > x) || (COMMONS_VERSION_MAJOR == x && COMMONS_VERSION_MINOR >= y))
#endif /* _CONFIG_COMMONS_HPP_ */ #endif /* _CONFIG_COMMONS_HPP_ */

View File

@ -690,6 +690,32 @@ namespace Config
iter->second.set(object, value); iter->second.set(object, value);
} }
template < typename Object >
Messages commit(Object * const object, const std::string & name)
{
Messages msgs;
OptionMap::iterator i = _map.find(name);
if (i != _map.end())
{
try
{
i->second.commit(object);
}
catch (Failure & e)
{
msgs.push_back(e.what());
}
}
else
{
msgs.push_back(STG(FMT("unable to find option: %s") % name));
};
return msgs;
}
template < typename Object > template < typename Object >
Messages commit(Object * const object) Messages commit(Object * const object)
{ {
@ -718,7 +744,7 @@ namespace Config
} }
template < typename Object > template < typename Object >
bool loaded(Object * object, std::string name) bool loaded(Object * object, const std::string & name)
{ {
OptionMap::iterator iter = find_option(name); OptionMap::iterator iter = find_option(name);

View File

@ -144,9 +144,8 @@ bool Configfile::deserialize(std::ifstream & fd)
if (adjust(section, opt, val)) if (adjust(section, opt, val))
continue; continue;
_errors.push_back(STG(FMT("option '%s' does " _errors.push_back(STG(FMT("option '%s' does not exist or '%s' is not "
"not exist or '%s' is not a valid value (at section '%s')") "a valid value (at section '%s')") % opt % val % section->name()));
% opt % val % section->name()));
} }
} }

View File

@ -205,6 +205,15 @@ std::string K3LAPIBase::get_param(K3L_EVENT *ev, const char *name) const
return res; return res;
} }
std::string K3LAPIBase::get_param_optional(K3L_EVENT *ev, const char *name) const
{
std::string res;
(void)get_param(ev, name, res);
return res;
}
void K3LAPIBase::init(void) void K3LAPIBase::init(void)
{ {
if (_device_count != 0) return; if (_device_count != 0) return;

View File

@ -317,7 +317,9 @@ struct K3LAPIBase
/* pega valores em strings de eventos */ /* pega valores em strings de eventos */
KLibraryStatus get_param(K3L_EVENT *ev, const char *name, std::string &res) const; KLibraryStatus get_param(K3L_EVENT *ev, const char *name, std::string &res) const;
std::string get_param(K3L_EVENT *ev, const char *name) const; std::string get_param(K3L_EVENT *ev, const char *name) const;
std::string get_param_optional(K3L_EVENT *ev, const char *name) const;
/* inicializa valores em cache */ /* inicializa valores em cache */

View File

@ -52,22 +52,16 @@
#include <refcounter.hpp> #include <refcounter.hpp>
#include <flagger.hpp> #include <flagger.hpp>
#if defined(COMMONS_LIBRARY_USING_ASTERISK) #if defined(COMMONS_LIBRARY_USING_ASTERISK) || defined(COMMONS_LIBRARY_USING_FREESWITCH)
extern "C" extern "C"
{ {
#include <asterisk.h> #include <time.h>
#include <asterisk/localtime.h>
} }
#elif defined(COMMONS_LIBRARY_USING_CALLWEAVER) #elif defined(COMMONS_LIBRARY_USING_CALLWEAVER)
extern "C" extern "C"
{ {
#include <callweaver/localtime.h> #include <callweaver/localtime.h>
} }
#elif defined(COMMONS_LIBRARY_USING_FREESWITCH)
extern "C"
{
#include <time.h>
}
#endif #endif
/* /*
@ -424,77 +418,26 @@ struct Logger
if (opt._flags[Option::DATETIME]) if (opt._flags[Option::DATETIME])
{ {
#if defined(COMMONS_LIBRARY_USING_ASTERISK) #if defined(COMMONS_LIBRARY_USING_ASTERISK) || defined(COMMONS_LIBRARY_USING_CALLWEAVER) || defined(COMMONS_LIBRARY_USING_FREESWITCH)
#if ASTERISK_AT_LEAST(1,6,0)
struct timeval tv;
struct ast_tm lt;
gettimeofday(&tv, NULL);
#else
time_t tv; time_t tv;
struct tm lt; struct tm lt;
time (&tv); time (&tv);
#endif
#if ASTERISK_AT_LEAST(1,4,5)
ast_localtime (&tv, &lt, NULL);
#else
localtime_r (&tv, &lt); localtime_r (&tv, &lt);
#endif
#elif defined(COMMONS_LIBRARY_USING_CALLWEAVER) || defined(COMMONS_LIBRARY_USING_FREESWITCH)
time_t tv;
struct tm lt;
time (&tv);
localtime_r (&tv, &lt);
#endif
out_msg += STG(FMT("[%02d-%02d-%02d %02d:%02d:%02d] ") out_msg += STG(FMT("[%02d-%02d-%02d %02d:%02d:%02d] ")
% (lt.tm_year % 100) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour % (lt.tm_year % 100) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour
% lt.tm_min % lt.tm_sec); % lt.tm_min % lt.tm_sec);
#endif
} }
if (opt._flags[Option::DATETIMEMS]) if (opt._flags[Option::DATETIMEMS])
{ {
#if defined(COMMONS_LIBRARY_USING_ASTERISK) #if defined(COMMONS_LIBRARY_USING_ASTERISK) || defined(COMMONS_LIBRARY_USING_CALLWEAVER) || defined(COMMONS_LIBRARY_USING_FREESWITCH)
#if ASTERISK_AT_LEAST(1,6,0)
struct timeval tv;
struct ast_tm lt;
gettimeofday(&tv, NULL);
#else
time_t tv; time_t tv;
struct tm lt; struct tm lt;
time (&tv); time (&tv);
#endif
#if ASTERISK_AT_LEAST(1,4,5)
ast_localtime (&tv, &lt, NULL);
#else
localtime_r (&tv, &lt);
#endif
#if ASTERISK_AT_LEAST(1,6,0)
out_msg += STG(FMT("[%02d-%02d-%02d %02d:%02d:%02d:%04d] ")
% (lt.tm_year % 100) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour % lt.tm_min
% lt.tm_sec % (tv.tv_usec / 1000));
#else
out_msg += STG(FMT("[%02d-%02d-%02d %02d:%02d:%02d:%04d] ")
% (lt.tm_year % 100) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour % lt.tm_min
% lt.tm_sec % (tv * 1000));
#endif
#elif defined(COMMONS_LIBRARY_USING_CALLWEAVER) || defined(COMMONS_LIBRARY_USING_FREESWITCH)
time_t tv;
struct tm lt;
time (&tv);
localtime_r (&tv, &lt); localtime_r (&tv, &lt);
out_msg += STG(FMT("[%02d-%02d-%02d %02d:%02d:%02d:%04d] ") out_msg += STG(FMT("[%02d-%02d-%02d %02d:%02d:%02d:%04d] ")

View File

@ -52,7 +52,7 @@
/* This struct uses static polymorphism, and derived classes should implement * /* This struct uses static polymorphism, and derived classes should implement *
* the "lock/trylock/unlock()" methods for correct code compilation. * * the "lock/trylock/unlock()" methods for correct code compilation. *
* The base class also features reference counting, so derived classes should * * The base class also features reference counting, so derived classes should *
* implement the "unreference()" method for releasing resources. */ * implement the "unreference_data()" method for releasing resources. */
template < typename Implementor > template < typename Implementor >
struct SimpleLockCommon: COUNTER_SUPER( SimpleLockCommon < Implementor > ) struct SimpleLockCommon: COUNTER_SUPER( SimpleLockCommon < Implementor > )
@ -95,7 +95,7 @@ struct SimpleLockCommon: COUNTER_SUPER( SimpleLockCommon < Implementor > )
protected: protected:
void unreference(void) void unreference(void)
{ {
static_cast<Implementor*>(this)->unreference(); static_cast<Implementor*>(this)->unreference_data();
} }
}; };

View File

@ -73,7 +73,7 @@ struct SimpleLockBasic: public SimpleLockCommon < Implementor >
/* do nothing */ /* do nothing */
}; };
void unreference() void unreference_data()
{ {
switch_mutex_destroy(_mutex); switch_mutex_destroy(_mutex);

View File

@ -2505,9 +2505,11 @@ std::string Verbose::command(const int32 cmd_code, const int32 dev_idx, const in
case VerboseTraits::K_CM_LOG_REQUEST: case VerboseTraits::K_CM_LOG_REQUEST:
case VerboseTraits::K_CM_LOG_CREATE_DISPATCHER: case VerboseTraits::K_CM_LOG_CREATE_DISPATCHER:
case VerboseTraits::K_CM_LOG_DESTROY_DISPATCHER: case VerboseTraits::K_CM_LOG_DESTROY_DISPATCHER:
case VerboseTraits::K_CM_PING: case VerboseTraits::K_CM_PING:
#endif #endif
//#if K3L_AT_LEAST(2,1,0)
// case VerboseTraits::K_CM_LOG_UPDATE:
//#endif
return show(buf, commandName(code), Target(NONE)); return show(buf, commandName(code), Target(NONE));
#if K3L_AT_LEAST(2,1,0) #if K3L_AT_LEAST(2,1,0)
case VerboseTraits::K_CM_START_FAX_TX: case VerboseTraits::K_CM_START_FAX_TX:

View File

@ -29,7 +29,10 @@
</p> </p>
<pre><b>Sintaxe:</b> &lt;param name="..." value="..."/&gt; <pre><b>Sintaxe:</b> &lt;param name="..." value="..."/&gt;
</pre> </pre>
<ul><li><b>dialplan</b>: Nome do módulo de <i>dialplan</i> em uso. <p><br />
</p>
<ul><li><b>accountcode</b>: Define o account code padrão para chamadas no Endpoint. Esta opção pode ser qualquer string alfanumérica;
</li><li><b>dialplan</b>: Nome do módulo de <i>dialplan</i> em uso.
</li><li><b>auto-fax-adjustment</b>: Ativa ("yes") ou desativa ("no") o ajuste automático do canal (desabilitar o cancelador de eco e a supressão DTMF) ao detectar tom de FAX; </li><li><b>auto-fax-adjustment</b>: Ativa ("yes") ou desativa ("no") o ajuste automático do canal (desabilitar o cancelador de eco e a supressão DTMF) ao detectar tom de FAX;
</li><li><b>auto-gain-control</b>: Ativa ("yes") ou desativa ("no") a ativação do controle automático de ganho (AGC) pelo Endpoint; </li><li><b>auto-gain-control</b>: Ativa ("yes") ou desativa ("no") a ativação do controle automático de ganho (AGC) pelo Endpoint;
</li><li><b>context-digital</b>: Contexto de entrada para ligações em placas digitais (o padrão é "khomp-DD-LL", onde "DD" será substituído, no momento da ligação, pelo número do dispositivo, "LL" pelo número do link, "CCC" pelo número do canal e "SSSS" pelo número serial do dispositivo); </li><li><b>context-digital</b>: Contexto de entrada para ligações em placas digitais (o padrão é "khomp-DD-LL", onde "DD" será substituído, no momento da ligação, pelo número do dispositivo, "LL" pelo número do link, "CCC" pelo número do canal e "SSSS" pelo número serial do dispositivo);
@ -49,6 +52,7 @@
</li><li><b>fxs-global-orig</b>: Número inicial para numeração seqüencial de ramais das placas <b>KFXS</b> que não estiverem listadas na seção <b>&lt;fxs-branches&gt;</b> (a numeração segue ordem crescente por número da placa e número do canal físico) (o padrão é "0"); </li><li><b>fxs-global-orig</b>: Número inicial para numeração seqüencial de ramais das placas <b>KFXS</b> que não estiverem listadas na seção <b>&lt;fxs-branches&gt;</b> (a numeração segue ordem crescente por número da placa e número do canal físico) (o padrão é "0");
</li><li><b>fxs-co-dialtone</b>: Seqüências de números, separados por vírgula, que disparam um tom contínuo (de central pública) em ramais FXS (ex: "0,99" faz com que, ao discar "0" ou "99", o usuário receba o tom de linha contínuo) (o padrão é vazio); </li><li><b>fxs-co-dialtone</b>: Seqüências de números, separados por vírgula, que disparam um tom contínuo (de central pública) em ramais FXS (ex: "0,99" faz com que, ao discar "0" ou "99", o usuário receba o tom de linha contínuo) (o padrão é vazio);
</li><li><b>fxs-bina</b>: Quando ativada ("yes"), ligações para ramais FXS enviarão os dígitos correspondentes ao telefone de origem em sinalização BINA DTMF (o valor padrão é "no"); </li><li><b>fxs-bina</b>: Quando ativada ("yes"), ligações para ramais FXS enviarão os dígitos correspondentes ao telefone de origem em sinalização BINA DTMF (o valor padrão é "no");
</li><li><b>language</b>: Define idioma para ligações nas placas Khomp;
</li><li><b>ignore-letter-dtmfs</b>: Define se o canal deve ignorar DTMFs incomuns detectados pela placa (A, B, C e D). Entretanto, se você necessita passar esses dígitos pela placa, você deve ajustar esta opção para "no" (o valor padrão é "yes"); </li><li><b>ignore-letter-dtmfs</b>: Define se o canal deve ignorar DTMFs incomuns detectados pela placa (A, B, C e D). Entretanto, se você necessita passar esses dígitos pela placa, você deve ajustar esta opção para "no" (o valor padrão é "yes");
</li><li><b>input-volume</b>: Define o volume de entrada das ligações, varia de -10 a +10&nbsp;; </li><li><b>input-volume</b>: Define o volume de entrada das ligações, varia de -10 a +10&nbsp;;
</li><li><b>kommuter-activation</b>: Define se a ativação de dispositivos kommuter encontrados no sistema será feita de forma automática ("auto"), ou de forma manual ("manual") pelo usuário, através do comando "khomp kommuter on/off"; </li><li><b>kommuter-activation</b>: Define se a ativação de dispositivos kommuter encontrados no sistema será feita de forma automática ("auto"), ou de forma manual ("manual") pelo usuário, através do comando "khomp kommuter on/off";
@ -119,6 +123,8 @@
<ul><li>context; <ul><li>context;
</li><li>input-volume; </li><li>input-volume;
</li><li>output-volume; </li><li>output-volume;
</li><li>language;
</li><li>accountcode;
</li><li>calleridnum; </li><li>calleridnum;
</li><li>calleridname; </li><li>calleridname;
</li><li>flash-to-digits. </li><li>flash-to-digits.
@ -1011,7 +1017,7 @@ install: ** for knowing how to proceed with the installation. **
<p>Este configurador, por sua vez, mostra todas as opções possíveis de configuração da placa. Os parâmetros que não forem configurados assumem os valores padrão automaticamente, e são compatíveis com a maior parte dos sistemas. Maiores detalhes sobre este programa podem ser obtidos na seção de número '2'. <p>Este configurador, por sua vez, mostra todas as opções possíveis de configuração da placa. Os parâmetros que não forem configurados assumem os valores padrão automaticamente, e são compatíveis com a maior parte dos sistemas. Maiores detalhes sobre este programa podem ser obtidos na seção de número '2'.
</p><p><br /> </p><p><br />
</p> </p>
<ul><li> <b>IMPORTANTE</b>: Para o FreeSWITCH iniciar, é preciso que a placa da khomp esteja configurada e todos módulos estejam rodando (conforme mostrado acima). <b>Caso a placa não esteja configurada, o FreeSWITCH não iniciará</b>.<br /><br />Se você deseja rodar o sistema sem a placa da Khomp, é preciso configurar o FreeSWITCH para ele não carregar o módulo da Khomp. Para isso, abra o arquivo "<i>/usr/local/freeswitch/conf/autoload_configs/modules.conf.xml</i>", e comente a linha que carrega o módulo:<br /> <ul><li> <b>IMPORTANTE</b>: Para o FreeSWITCH iniciar, é preciso que a placa da khomp esteja configurada e todos módulos estejam rodando (conforme mostrado acima). <br /><br />Se você deseja rodar o sistema sem a placa da Khomp, é preciso configurar o FreeSWITCH para ele não carregar o módulo da Khomp. Para isso, abra o arquivo <b>/usr/local/freeswitch/conf/autoload_configs/modules.conf.xml</b>, e comente a linha que carrega o módulo:<br />
</li></ul> </li></ul>
<pre> <pre>
&lt;!-- &lt;load module=&quot;mod_khomp&quot; /&gt; --&gt; &lt;!-- &lt;load module=&quot;mod_khomp&quot; /&gt; --&gt;
@ -1080,4 +1086,6 @@ Por fim, para carregar o servidor de processos, basta executar o seguinte comand
O <i>script</i> <b>/etc/init.d/khompdrv</b> é responsável por carregar os módulos <i>kpci9030.ko</i> e <i>kpex8311.ko</i> no <i>kernel</i>, que deve ser realizada automaticamente na inicialização do sistema. Em caso de problemas, verifique a seção <a href="#Solu.C3.A7.C3.A3o_de_problemas" title="">Solução de problemas</a>. O <i>script</i> <b>/etc/init.d/khompdrv</b> é responsável por carregar os módulos <i>kpci9030.ko</i> e <i>kpex8311.ko</i> no <i>kernel</i>, que deve ser realizada automaticamente na inicialização do sistema. Em caso de problemas, verifique a seção <a href="#Solu.C3.A7.C3.A3o_de_problemas" title="">Solução de problemas</a>.
<br /> <br />
</p><p><br /> </p><p><br />
Para mais detalhes: <a href="http://www.khomp.com.br" class="external free" title="http://www.khomp.com.br" rel="nofollow">http://www.khomp.com.br</a>
</p><p><br />
</p></body></html> </p></body></html>

View File

@ -6,7 +6,7 @@
<a name="Utilizando_o_Endpoint_da_Khomp" id="Utilizando_o_Endpoint_da_Khomp"></a><h1> <span class="mw-headline"> Utilizando o <i>Endpoint</i> da Khomp </span></h1> <a name="Utilizando_o_Endpoint_da_Khomp" id="Utilizando_o_Endpoint_da_Khomp"></a><h1> <span class="mw-headline"> Utilizando o <i>Endpoint</i> da Khomp </span></h1>
<p>Após a instalação e inicialização dos serviços necessários pela Khomp, o FreeSWITCH já pode ser carregado ou inicializado. <p>Após a instalação e inicialização dos serviços necessários pela Khomp, o FreeSWITCH já pode ser carregado ou inicializado.
</p> </p>
<ul><li> <b>AVISO</b>: É imprescindível que o <b>FreeSWITCH</b> não seja executado utilizando a opção que desabilita o escalonamento em tempo real (-nort), <b>especialmente</b> se este estiver sendo executado lado-a-lado com servidores <i>web</i> ou servidores de banco de dados. Não realizar este procedimento pode resultar em perda de qualidade do áudio, gerando um sério comprometimento no andamento das ligações do sistema. <ul><li> <b>AVISO</b>: Evite usar a opção <b>-nort</b>, pois ela desabilita escalonamento em tempo real, é imprescindível que o <b>FreeSWITCH</b> esteja utilizando o escalonamento em tempo real, especialmente se este estiver sendo executado lado-a-lado com servidores <i>web</i> ou servidores de banco de dados. Utilizar a opção <b>-nort</b> pode resultar em perda de qualidade do áudio, gerando um sério comprometimento nas ligações do sistema.
</li></ul> </li></ul>
<p>Após a inicialização do FreeSWITCH, pode-se verificar se o módulo da Khomp foi carregado através do seguinte comando:<br /> <p>Após a inicialização do FreeSWITCH, pode-se verificar se o módulo da Khomp foi carregado através do seguinte comando:<br />
</p> </p>

View File

@ -6,10 +6,9 @@
<a name="Using_the_Khomp_Endpoint" id="Using_the_Khomp_Endpoint"></a><h1> <span class="mw-headline"> Using the Khomp Endpoint </span></h1> <a name="Using_the_Khomp_Endpoint" id="Using_the_Khomp_Endpoint"></a><h1> <span class="mw-headline"> Using the Khomp Endpoint </span></h1>
<p>After installation and startup services required by Khomp, FreeSWITCH can now be loaded or initialized. <p>After installation and startup services required by Khomp, FreeSWITCH can now be loaded or initialized.
</p> </p>
<ul><li><b>WARNING</b>: It is imperative that the<b>FreeSWITCH</b> is not executed using the option that disables the escalation in real time (-nort), <b>especially</b> if this is running side-by server-side with web servers or database. Failure to do so may result in loss of audio quality, causing a serious commitment on the progress of system connections. <ul><li><b>WARNING</b>: Avoid using the <b>-nort</b>, as it disables real-time scheduling, it is essential that the <b>FreeSwitch</b> are using real-time scheduling, especially if it is running side-by-side with <i>web</i> servers or database . Use the <b>-nort</b> may result in loss of audio quality, causing a serious commitment on the progress of system connections.
</li></ul> </li></ul>
<p>After initialization of FreeSWITCH, you can verify that the module was loaded Khomp through the following command: <br /> <p>After initialization of FreeSWITCH, you can verify that the module was loaded Khomp through the following command: <br />
</p><p><br />
</p> </p>
<pre> freeswitch@hostname&gt; module_exists mod_khomp <pre> freeswitch@hostname&gt; module_exists mod_khomp
</pre> </pre>

View File

@ -30,7 +30,8 @@ If you need to set advanced parameters of the board and/or signaling, the progra
</p> </p>
<pre><b>Sintaxe:</b> &lt;param name="..." value="..."/&gt; <pre><b>Sintaxe:</b> &lt;param name="..." value="..."/&gt;
</pre> </pre>
<ul><li><b>dialplan</b>: Name of the dialplan module in use. <ul><li><b>accountcode</b>: Sets the default account code to calls in the Endpoint. This option can be any alphanumeric string;
</li><li><b>dialplan</b>: Name of the dialplan module in use.
</li><li><b>auto-fax-adjustment</b>: Enable ("yes") or disables ("no") the automatic adjustment of the channel (disable the echo canceller and the suppression DTMF) tone to detect FAX (local option)&nbsp;; </li><li><b>auto-fax-adjustment</b>: Enable ("yes") or disables ("no") the automatic adjustment of the channel (disable the echo canceller and the suppression DTMF) tone to detect FAX (local option)&nbsp;;
</li><li><b>auto-gain-control</b>:Enable ("yes") or disables ("no") the activation of the automatic gain control (AGC) by the Endpoint (local option); </li><li><b>auto-gain-control</b>:Enable ("yes") or disables ("no") the activation of the automatic gain control (AGC) by the Endpoint (local option);
</li><li><b>context-digital</b>: Context for incoming connections on digital boards (the default is "khomp-DD-LL", where "DD" will be replaced at the time of connection by the device number, "LL" by the number of the link, "CCC" by channel number and "SSSS" for the device serial number); </li><li><b>context-digital</b>: Context for incoming connections on digital boards (the default is "khomp-DD-LL", where "DD" will be replaced at the time of connection by the device number, "LL" by the number of the link, "CCC" by channel number and "SSSS" for the device serial number);
@ -54,6 +55,7 @@ If you need to set advanced parameters of the board and/or signaling, the progra
</li><li><b>input-volume</b>: Sets the volume gain for incoming audio (entering the board), from -10 to +10 (local option); </li><li><b>input-volume</b>: Sets the volume gain for incoming audio (entering the board), from -10 to +10 (local option);
</li><li><b>kommuter-activation</b>: Sets whether to activate devices kommuter found in the system will be done automatically ("auto") by the channel, or manually ("manual") by the user through the command "khomp kommuter on/off" </li><li><b>kommuter-activation</b>: Sets whether to activate devices kommuter found in the system will be done automatically ("auto") by the channel, or manually ("manual") by the user through the command "khomp kommuter on/off"
</li><li><b>kommuter-timeout</b>: Sets the timeout (in seconds) for initializing the kommuter devices. If this timeout is reached without receiving notification of the channel, the devices will switch back to "off" condition. The minimum value is "0", where the links will always remain switched "on", and the maximum is "255"; </li><li><b>kommuter-timeout</b>: Sets the timeout (in seconds) for initializing the kommuter devices. If this timeout is reached without receiving notification of the channel, the devices will switch back to "off" condition. The minimum value is "0", where the links will always remain switched "on", and the maximum is "255";
</li><li><b>language</b>: Set language to Khomp board calls;
</li><li><b>log-to-console</b>: Set log messages to be printed on the console; </li><li><b>log-to-console</b>: Set log messages to be printed on the console;
</li><li><b>log-to-disk</b> (old "log"): Set log messages to be saved to disk; </li><li><b>log-to-disk</b> (old "log"): Set log messages to be saved to disk;
</li><li><b>out-of-band-DTMF</b> (former <b>dtmfsuppression</b>): Activate ("yes") or disables ("no") the removal and DTMF sending these out-of-band (local option); </li><li><b>out-of-band-DTMF</b> (former <b>dtmfsuppression</b>): Activate ("yes") or disables ("no") the removal and DTMF sending these out-of-band (local option);
@ -125,6 +127,8 @@ For details, please refer to the configuration file for examples.
</li><li>output-volume; </li><li>output-volume;
</li><li>calleridnum; </li><li>calleridnum;
</li><li>calleridname; </li><li>calleridname;
</li><li>language;
</li><li>accountcode;
</li><li>flash-to-digits. </li><li>flash-to-digits.
</li></ul> </li></ul>
<p>Each option is separated from each other by a pipe "|" or a slash "/" and defined after the colon ":". Example: <p>Each option is separated from each other by a pipe "|" or a slash "/" and defined after the colon ":". Example:
@ -1018,7 +1022,7 @@ install: ** for knowing how to proceed with the installation. **
</pre> </pre>
<p>This configurator, in turn, shows all possible options for card configuration. The parameters that are not configured automatically assume the default values, and are compatible with most systems. More details about this program can be obtained from the section number '2 '. <p>This configurator, in turn, shows all possible options for card configuration. The parameters that are not configured automatically assume the default values, and are compatible with most systems. More details about this program can be obtained from the section number '2 '.
</p> </p>
<ul><li> <b>ATTENTION'<i>: To start FreeSWITCH&reg;, it is necessary that the board is configured Khomp and all modules are running (as shown above). </i></b><i>If the card is not configured, FreeSWITCH will not start<b>.<br /> <br /> If you want to run the system without the board Khomp, you need to configure FreeSWITCH for it does not load the module Khomp. To do this, open the "</b></i><b>/usr/local/freeswitch/conf/autoload_configs/modules.conf.xml</b> and comment the line:<br /> <ul><li> <b>ATTENTION</b>: To start FreeSWITCH&reg;, it is necessary that the Khomp board is configured and all modules are running (as shown above). <br /> <br /> If you want to run the system without the Khomp board, you need to configure FreeSWITCH for it does not load the module Khomp. To do this, open the <b>/usr/local/freeswitch/conf/autoload_configs/modules.conf.xml</b> and comment the line:<br />
</li></ul> </li></ul>
<pre> <pre>
&lt;!-- &lt;load module=&quot;mod_khomp&quot; /&gt; --&gt; &lt;!-- &lt;load module=&quot;mod_khomp&quot; /&gt; --&gt;
@ -1060,7 +1064,7 @@ install: ** for knowing how to proceed with the installation. **
<br /> <br />
</p> </p>
<a name="Ap.C3.AAndice" id="Ap.C3.AAndice"></a><h1> <span class="mw-headline"> Apêndice </span></h1> <a name="Ap.C3.AAndice" id="Ap.C3.AAndice"></a><h1> <span class="mw-headline"> Apêndice </span></h1>
<p>Nesta seção, encontram-se informações úteis sobre o Endpoint e componentes relacionados. <p>This section presents useful informations about Endpoint and related components.
</p> </p>
<a name="Arrangement_of_installed_files" id="Arrangement_of_installed_files"></a><h2> <span class="mw-headline"> Arrangement of installed files </span></h2> <a name="Arrangement_of_installed_files" id="Arrangement_of_installed_files"></a><h2> <span class="mw-headline"> Arrangement of installed files </span></h2>
<p>The directories created/modified in this facility are: <p>The directories created/modified in this facility are:
@ -1084,5 +1088,6 @@ install: ** for knowing how to proceed with the installation. **
</pre> </pre>
<p>The script <b>/etc/init.d/khompdrv</b> is responsible for loading modules <b>kpci9030.ko</b> and <b>kpex8311.ko</b> in the kernel, which should be carried out automatically at system startup. In case of problems, check the <a href="#Troubleshooting" title="">Troubleshooting</a> section. <p>The script <b>/etc/init.d/khompdrv</b> is responsible for loading modules <b>kpci9030.ko</b> and <b>kpex8311.ko</b> in the kernel, which should be carried out automatically at system startup. In case of problems, check the <a href="#Troubleshooting" title="">Troubleshooting</a> section.
</p><p><br /> </p><p><br />
</p><p>For more details: <a href="http://www.khomp.com.br" class="external free" title="http://www.khomp.com.br" rel="nofollow">http://www.khomp.com.br</a>
</p><p><br /> </p><p><br />
</p></body></html> </p></body></html>

View File

@ -733,17 +733,21 @@ struct Cli
options.push_back("fxs-global-orig"); options.push_back("fxs-global-orig");
options.push_back("fxs-co-dialtone"); options.push_back("fxs-co-dialtone");
options.push_back("fxs-bina"); options.push_back("fxs-bina");
options.push_back("fxs-sharp-dial");
options.push_back("disconnect-delay"); options.push_back("disconnect-delay");
options.push_back("delay-ringback-co"); options.push_back("delay-ringback-co");
options.push_back("delay-ringback-pbx"); options.push_back("delay-ringback-pbx");
options.push_back("ignore-letter-dtmfs"); options.push_back("ignore-letter-dtmfs");
options.push_back("fxo-send-pre-audio"); options.push_back("fxo-send-pre-audio");
options.push_back("fxo-busy-disconnection");
options.push_back("fxs-digit-timeout"); options.push_back("fxs-digit-timeout");
options.push_back("drop-collect-call"); options.push_back("drop-collect-call");
options.push_back("kommuter-activation"); options.push_back("kommuter-activation");
options.push_back("kommuter-timeout"); options.push_back("kommuter-timeout");
options.push_back("user-transfer-digits"); options.push_back("user-transfer-digits");
options.push_back("flash-to-digits"); options.push_back("flash-to-digits");
options.push_back("accountcode");
options.push_back("audio-packet-length");
brief = "Get configuration options in the Khomp channel."; brief = "Get configuration options in the Khomp channel.";
@ -821,17 +825,21 @@ struct Cli
options.push_back("fxs-global-orig"); options.push_back("fxs-global-orig");
options.push_back("fxs-co-dialtone"); options.push_back("fxs-co-dialtone");
options.push_back("fxs-bina"); options.push_back("fxs-bina");
options.push_back("fxs-sharp-dial");
options.push_back("disconnect-delay"); options.push_back("disconnect-delay");
options.push_back("delay-ringback-co"); options.push_back("delay-ringback-co");
options.push_back("delay-ringback-pbx"); options.push_back("delay-ringback-pbx");
options.push_back("ignore-letter-dtmfs"); options.push_back("ignore-letter-dtmfs");
options.push_back("fxo-send-pre-audio"); options.push_back("fxo-send-pre-audio");
options.push_back("fxo-busy-disconnection");
options.push_back("fxs-digit-timeout"); options.push_back("fxs-digit-timeout");
options.push_back("drop-collect-call"); options.push_back("drop-collect-call");
options.push_back("kommuter-activation"); options.push_back("kommuter-activation");
options.push_back("kommuter-timeout"); options.push_back("kommuter-timeout");
options.push_back("user-transfer-digits"); options.push_back("user-transfer-digits");
options.push_back("flash-to-digits"); options.push_back("flash-to-digits");
options.push_back("accountcode");
options.push_back("audio-packet-length");
brief = "Ajust configuration options in the Khomp channel."; brief = "Ajust configuration options in the Khomp channel.";
@ -933,6 +941,36 @@ struct Cli
bool execute(int argc, char *argv[]); bool execute(int argc, char *argv[]);
} KhompRevision; } KhompRevision;
/* khomp dump config */
static struct _KhompDumpConfig : public Command
{
_KhompDumpConfig()
{
complete_name = "dump config";
brief = "Dump configuration values on screen.";
usage = \
"\nUsage: khomp dump config\n\n" \
"Dump configuration values loaded on memory.\n ";
_commands.push_back(this);
}
/* just to hide unavaible options */
bool removeUnavaible(const std::string &s)
{
if(s == "atxfer" || s == "blindxfer" || s == "callgroup" ||
s == "mohclass" || s == "native-bridge" || s == "recording" ||
s == "record-prefix" || s == "transferdigittimeout" ||
s == "pickupgroup" || s == "has-ctbus" ||
s == "user-transfer-digits")
return true;
return false;
}
bool execute(int argc, char *argv[]);
} KhompDumpConfig;
/* khomp send command */ /* khomp send command */
static struct _KhompSendCommand : public Command static struct _KhompSendCommand : public Command
{ {

View File

@ -231,6 +231,8 @@ struct KVoIPSeize
#define CM_USER_INFORMATION 0x0F #define CM_USER_INFORMATION 0x0F
#define CM_USER_INFORMATION_EX 0x2B
#define CM_VOIP_SEIZE 0x23 #define CM_VOIP_SEIZE 0x23
@ -369,6 +371,8 @@ struct KVoIPSeize
#define EV_USER_INFORMATION 0x0F #define EV_USER_INFORMATION 0x0F
#define EV_USER_INFORMATION_EX 0x1D
#define EV_DIALED_DIGIT 0x10 #define EV_DIALED_DIGIT 0x10
#define EV_SIP_REGISTER_INFO 0x11 #define EV_SIP_REGISTER_INFO 0x11
@ -713,6 +717,8 @@ enum KH100CtbusFreq
#define CM_START_CADENCE 0xA1 #define CM_START_CADENCE 0xA1
#define CM_STOP_CADENCE 0xA2 #define CM_STOP_CADENCE 0xA2
#define CM_SET_INPUT_MODE 0xA3
#if !defined KR2D_H #if !defined KR2D_H
#define KR2D_H #define KR2D_H
@ -925,6 +931,7 @@ enum KSignGroupII
#ifndef _KISDN_H_ #ifndef _KISDN_H_
#define _KISDN_H_ #define _KISDN_H_
#define KMAX_USER_USER_LEN 32 #define KMAX_USER_USER_LEN 32
#define KMAX_USER_USER_EX_LEN 254
#define KMAX_SUBADRESS_INFORMATION_LEN 20 #define KMAX_SUBADRESS_INFORMATION_LEN 20
enum KQ931Cause enum KQ931Cause
@ -1845,6 +1852,12 @@ struct KUserInformation
int32 UserInfoLength; int32 UserInfoLength;
byte UserInfo[ KMAX_USER_USER_LEN ]; byte UserInfo[ KMAX_USER_USER_LEN ];
}; };
struct KUserInformationEx
{
int32 ProtocolDescriptor;
int32 UserInfoLength;
byte UserInfo[ KMAX_USER_USER_EX_LEN ];
};
struct KISDNSubaddressInformation struct KISDNSubaddressInformation
{ {
KQ931TypeOfSubaddress TypeOfSubaddress; KQ931TypeOfSubaddress TypeOfSubaddress;

View File

@ -305,8 +305,6 @@ struct KhompPvt
{ {
try try
{ {
//std::string type((name == "input_volume")?"input":"output");
int i = Strings::tolong(value); int i = Strings::tolong(value);
if (i < -10 || i > 10) if (i < -10 || i > 10)
@ -614,6 +612,7 @@ public:
virtual bool indicateRinging(); virtual bool indicateRinging();
virtual bool sendDtmf(std::string digit); virtual bool sendDtmf(std::string digit);
virtual void cleanupIndications(bool force);
/* Methods */ /* Methods */
@ -849,7 +848,31 @@ public:
if(!name) if(!name)
return NULL; return NULL;
return switch_core_get_variable(name); #if SWITCH_LESS_THAN(1,0,6)
const char * tmp = switch_core_get_variable(name);
if(!tmp) return NULL;
const char * val = strdup(tmp);
return val;
#else
return switch_core_get_variable_dup(name);
#endif
}
void freeFSGlobalVar(const char ** val)
{
if(!val || !*val) return;
#if SWITCH_LESS_THAN(1,0,6)
free((void *)*val);
*val = NULL;
#else
char * v = (char *)*val;
switch_safe_free(v);
*val=NULL;
#endif
} }
bool mixer(const char *file, const char *func, int line, bool mixer(const char *file, const char *func, int line,

View File

@ -138,7 +138,7 @@ struct KhompPvtFXO: public KhompPvt
TriState _var_fax_adjust; TriState _var_fax_adjust;
//ChanTimer::Index _idx_disconnect; ChanTimer::Index _busy_disconnect;
}; };
/******************************************************************************/ /******************************************************************************/
KhompPvtFXO(K3LAPIBase::GenericTarget & target) : KhompPvt(target) KhompPvtFXO(K3LAPIBase::GenericTarget & target) : KhompPvt(target)
@ -240,6 +240,7 @@ struct KhompPvtFXO: public KhompPvt
bool autoGainControl(bool enable); bool autoGainControl(bool enable);
void setAnswerInfo(int answer_info); void setAnswerInfo(int answer_info);
bool indicateBusyUnlocked(int cause, bool sent_signaling = false); bool indicateBusyUnlocked(int cause, bool sent_signaling = false);
static void busyDisconnect(Board::KhompPvt * pvt);
void reportFailToReceive(int fail_code); void reportFailToReceive(int fail_code);
bool validContexts(MatchExtension::ContextListType & contexts, bool validContexts(MatchExtension::ContextListType & contexts,
std::string extra_context = ""); std::string extra_context = "");
@ -266,13 +267,20 @@ struct KhompPvtFXO: public KhompPvt
virtual bool cleanup(CleanupType type = CLN_HARD) virtual bool cleanup(CleanupType type = CLN_HARD)
{ {
//Board::board(_target.device)->_timers.del(callFXO()->_idx_disconnect); try
//callFXO()->_idx_disconnect.reset(); {
Board::board(_target.device)->_timers.del(callFXO()->_busy_disconnect);
}
catch (K3LAPITraits::invalid_device & err)
{
LOG(ERROR, PVT_FMT(target(), "Unable to get device: %d!") % err.device);
}
call()->_flags.clear(Kflags::CALL_WAIT_SEIZE); call()->_flags.clear(Kflags::CALL_WAIT_SEIZE);
call()->_flags.clear(Kflags::EARLY_RINGBACK); call()->_flags.clear(Kflags::EARLY_RINGBACK);
_transfer->clear(); _transfer->clear();
callFXO()->_busy_disconnect.reset();
switch (type) switch (type)
{ {
@ -312,6 +320,16 @@ struct KhompPvtFXO: public KhompPvt
// static void delayedDisconnect(Board::KhompPvt * pvt); // static void delayedDisconnect(Board::KhompPvt * pvt);
void cleanupIndications(bool force)
{
if (call()->_indication == INDICA_BUSY && !force)
{
DBG(FUNC, PVT_FMT(_target, "skipping busy indication cleanup on FXO channel."));
return;
}
KhompPvt::cleanupIndications(force);
}
}; };
/******************************************************************************/ /******************************************************************************/
/******************************************************************************/ /******************************************************************************/

View File

@ -272,24 +272,39 @@ struct KhompPvtISDN: public KhompPvtE1
bool process(std::string name, std::string value = "") bool process(std::string name, std::string value = "")
{ {
if (name == "uui") if ((name == "uui" ) || (name == "uui_ex"))
{ {
Strings::vector_type values; if(value.find("#") != std::string::npos)
Strings::tokenize(value, values, "#", 2);
try
{ {
std::string uui_proto_s = values[0]; Strings::vector_type values;
std::string uui_data_s = values[1]; Strings::tokenize(value, values, "#", 2);
_uui_descriptor = Strings::toulong(uui_proto_s); try
_uui_information.append(uui_data_s); {
std::string uui_proto_s = values[0];
_uui_extended = (name == "uui_ex");
_uui_descriptor = Strings::toulong(uui_proto_s);
_uui_information.clear();
DBG(FUNC, FMT("uui adjusted (%s, '%s')!") % uui_proto_s.c_str() % uui_data_s.c_str()); for (unsigned int i = 0; i < values[1].size(); ++i)
} _uui_information += STG(FMT("%02hhx") % ((unsigned char)values[1][i]));
catch (...)
DBG(FUNC, FMT("uui adjusted (ex=%s, proto=%s, data='%s')!")
% (_uui_extended ? "true" : "false")
% uui_proto_s.c_str()
% _uui_information.c_str());
}
catch (...)
{
LOG(ERROR, FMT("invalid %s protocol descriptor: '%s' is not a number.")
% (_uui_extended ? "uui_ex" : "uui")
% value.c_str());
}
}
else
{ {
LOG(ERROR, FMT("invalid uui protocol descriptor: '%s' is not a number.") % value.c_str()); LOG(ERROR, FMT("invalid %s protocol descriptor, need a '#'.")
% (_uui_extended ? "uui_ex" : "uui"))
} }
} }
else if (name == "usr_xfer") else if (name == "usr_xfer")
@ -306,6 +321,7 @@ struct KhompPvtISDN: public KhompPvtE1
bool clear() bool clear()
{ {
_uui_extended = false;
_uui_descriptor = -1; _uui_descriptor = -1;
_uui_information.clear(); _uui_information.clear();
_isdn_cause = -1; _isdn_cause = -1;
@ -322,6 +338,7 @@ struct KhompPvtISDN: public KhompPvtE1
long int _uui_descriptor; long int _uui_descriptor;
std::string _uui_information; std::string _uui_information;
long int _isdn_cause; long int _isdn_cause;
bool _uui_extended;
/* what should we dial to trigger an user-signaled transfer? */ /* what should we dial to trigger an user-signaled transfer? */
/* used for xfer on user signaling */ /* used for xfer on user signaling */
@ -329,6 +346,13 @@ struct KhompPvtISDN: public KhompPvtE1
std::string _user_xfer_buffer; std::string _user_xfer_buffer;
std::string _digits_buffer; std::string _digits_buffer;
std::string _qsig_number; std::string _qsig_number;
/* isdn information */
std::string _isdn_orig_type_of_number;
std::string _isdn_orig_numbering_plan;
std::string _isdn_dest_type_of_number;
std::string _isdn_dest_numbering_plan;
std::string _isdn_orig_presentation;
}; };
/******************************************************************************/ /******************************************************************************/
@ -429,12 +453,29 @@ struct KhompPvtISDN: public KhompPvtE1
std::string descriptor = STG(FMT("%d") % callISDN()->_uui_descriptor); std::string descriptor = STG(FMT("%d") % callISDN()->_uui_descriptor);
setFSChannelVar("KUserInfoExtended", (callISDN()->_uui_extended ? "true" : "false"));
setFSChannelVar("KUserInfoDescriptor", descriptor.c_str()); setFSChannelVar("KUserInfoDescriptor", descriptor.c_str());
setFSChannelVar("KUserInfoData", callISDN()->_uui_information.c_str()); setFSChannelVar("KUserInfoData", callISDN()->_uui_information.c_str());
callISDN()->_uui_extended = false;
callISDN()->_uui_descriptor = -1; callISDN()->_uui_descriptor = -1;
callISDN()->_uui_information.clear(); callISDN()->_uui_information.clear();
} }
if (!callISDN()->_isdn_orig_type_of_number.empty())
setFSChannelVar("KISDNOrigTypeOfNumber", callISDN()->_isdn_orig_type_of_number.c_str());
if (!callISDN()->_isdn_dest_type_of_number.empty())
setFSChannelVar("KISDNDestTypeOfNumber", callISDN()->_isdn_dest_type_of_number.c_str());
if (!callISDN()->_isdn_orig_numbering_plan.empty())
setFSChannelVar("KISDNOrigNumberingPlan", callISDN()->_isdn_orig_numbering_plan.c_str());
if (!callISDN()->_isdn_dest_numbering_plan.empty())
setFSChannelVar("KISDNDestNumberingPlan", callISDN()->_isdn_dest_numbering_plan.c_str());
if (!callISDN()->_isdn_orig_presentation.empty())
setFSChannelVar("KISDNOrigPresentation", callISDN()->_isdn_orig_presentation.c_str());
} }
catch(Board::KhompPvt::InvalidSwitchChannel & err) catch(Board::KhompPvt::InvalidSwitchChannel & err)
{ {
@ -444,8 +485,33 @@ struct KhompPvtISDN: public KhompPvtE1
KhompPvtE1::setSpecialVariables(); KhompPvtE1::setSpecialVariables();
} }
Transfer<CallISDN, false> * _transfer; virtual void getSpecialVariables()
{
try
{
const char * isdn_orig_type = getFSChannelVar("KISDNOrigTypeOfNumber");
const char * isdn_dest_type = getFSChannelVar("KISDNDestTypeOfNumber");
const char * isdn_orig_numbering = getFSChannelVar("KISDNOrigNumberingPlan");
const char * isdn_dest_numbering = getFSChannelVar("KISDNDestNumberingPlan");
const char * isdn_orig_presentation = getFSChannelVar("KISDNOrigPresentation");
LOG(ERROR, PVT_FMT(_target,"ISDNORIG: %s") % (isdn_orig_type ? isdn_orig_type : ""));
callISDN()->_isdn_orig_type_of_number = (isdn_orig_type ? isdn_orig_type : "");
callISDN()->_isdn_dest_type_of_number = (isdn_dest_type ? isdn_dest_type : "");
callISDN()->_isdn_orig_numbering_plan = (isdn_orig_numbering ? isdn_orig_numbering : "");
callISDN()->_isdn_dest_numbering_plan = (isdn_dest_numbering ? isdn_dest_numbering : "");
callISDN()->_isdn_orig_presentation = (isdn_orig_presentation ? isdn_orig_presentation : "");
}
catch(Board::KhompPvt::InvalidSwitchChannel & err)
{
LOG(ERROR, PVT_FMT(_target, "(ISDN) %s") % err._msg.c_str());
}
KhompPvt::getSpecialVariables();
}
Transfer<CallISDN, false> * _transfer;
}; };
/******************************************************************************/ /******************************************************************************/
/********************************* R2 Channel *********************************/ /********************************* R2 Channel *********************************/
@ -472,7 +538,6 @@ struct KhompPvtR2: public KhompPvtE1
{ {
LOG(ERROR, FMT("invalid r2 category: '%s' is not a number.") % value.c_str()); LOG(ERROR, FMT("invalid r2 category: '%s' is not a number.") % value.c_str());
} }
} }
else else
{ {
@ -554,7 +619,23 @@ struct KhompPvtR2: public KhompPvtE1
{ {
return (CallR2 *)call(); return (CallR2 *)call();
} }
bool forceDisconnect(void)
{
char cmd[] = { 0x07, (char)(_target.object + 1) };
try
{
Globals::k3lapi.raw_command(_target.device, 0, cmd, sizeof(cmd));
}
catch(K3LAPI::failed_raw_command &e)
{
return false;
}
return true;
};
int makeCall(std::string params = ""); int makeCall(std::string params = "");
bool doChannelAnswer(CommandRequest &); bool doChannelAnswer(CommandRequest &);
bool doChannelHangup(CommandRequest &); bool doChannelHangup(CommandRequest &);
@ -609,9 +690,9 @@ struct KhompPvtR2: public KhompPvtE1
/* r2 caller category */ /* r2 caller category */
if (callR2()->_r2_category != -1) if (callR2()->_r2_category != -1)
{ {
setFSChannelVar("KR2GotCategory",Verbose::signGroupII((KSignGroupII)callR2()->_r2_category).c_str()); setFSChannelVar("KR2GotCategory",STG(FMT("%d") % callR2()->_r2_category).c_str());
setFSChannelVar("KR2StrCategory",Verbose::signGroupII((KSignGroupII)callR2()->_r2_category).c_str());
} }
} }
catch(Board::KhompPvt::InvalidSwitchChannel & err) catch(Board::KhompPvt::InvalidSwitchChannel & err)
{ {
@ -834,9 +915,9 @@ struct KhompPvtFXS: public KhompPvt
_ring_off_ext = -1; _ring_off_ext = -1;
_incoming_exten.clear(); _incoming_exten.clear();
_flash_transfer.clear(); //_flash_transfer.clear();
_uuid_other_session.clear(); //_uuid_other_session.clear();
return Call::clear(); return Call::clear();
} }
@ -850,10 +931,10 @@ struct KhompPvtFXS: public KhompPvt
std::string _incoming_exten; std::string _incoming_exten;
ChanTimer::Index _idx_transfer; //ChanTimer::Index _idx_transfer;
std::string _flash_transfer; //std::string _flash_transfer;
std::string _uuid_other_session; //std::string _uuid_other_session;
}; };
@ -936,9 +1017,9 @@ struct KhompPvtFXS: public KhompPvt
std::string extra_context = ""); std::string extra_context = "");
bool isOK(void); bool isOK(void);
bool startTransfer(); //bool startTransfer();
bool stopTransfer(); //bool stopTransfer();
bool transfer(std::string & context, bool blind = false); //bool transfer(std::string & context, bool blind = false);
bool hasNumberDial() { return false; } bool hasNumberDial() { return false; }
@ -996,7 +1077,7 @@ struct KhompPvtFXS: public KhompPvt
static OrigToNseqMapType generateNseqMap(); static OrigToNseqMapType generateNseqMap();
static void dialTimer(KhompPvt * pvt); static void dialTimer(KhompPvt * pvt);
static void transferTimer(KhompPvt * pvt); //static void transferTimer(KhompPvt * pvt);
static std::string padOrig(std::string orig_base, unsigned int padding) static std::string padOrig(std::string orig_base, unsigned int padding)
{ {
@ -1015,21 +1096,16 @@ struct KhompPvtFXS: public KhompPvt
return STG(FMT(STG(FMT("%%0%dd") % orig_size)) % (orig_numb + padding)); return STG(FMT(STG(FMT("%%0%dd") % orig_size)) % (orig_numb + padding));
} }
/* void cleanupIndications(bool force)
virtual void getSpecialVariables()
{ {
try if (call()->_indication == INDICA_BUSY && !force)
{ {
} DBG(FUNC, PVT_FMT(_target, "skipping busy indication cleanup on FXS channel."));
catch(Board::KhompPvt::InvalidSwitchChannel & err) return;
{
LOG(ERROR, PVT_FMT(_target, "(FXS) %s") % err._msg.c_str());
} }
KhompPvt::getSpecialVariables(); KhompPvt::cleanupIndications(force);
} }
*/
}; };
/******************************************************************************/ /******************************************************************************/
/******************************************************************************/ /******************************************************************************/

View File

@ -108,10 +108,13 @@ struct Options
Config::Value< bool > _recording; Config::Value< bool > _recording;
Config::Value< bool > _has_ctbus; Config::Value< bool > _has_ctbus;
Config::Value< bool > _fxs_bina; Config::Value< bool > _fxs_bina;
Config::Value< bool > _fxo_send_pre_audio; Config::Value< bool > _fxs_sharp_dial;
Config::Value< bool > _drop_collect_call; Config::Value< bool > _drop_collect_call;
Config::Value< bool > _ignore_letter_dtmfs; Config::Value< bool > _ignore_letter_dtmfs;
Config::Value< bool > _optimize_audio_path; Config::Value< bool > _optimize_audio_path;
Config::Value< bool > _fxo_send_pre_audio;
Config::Value< unsigned int > _fxo_busy_disconnection;
Config::Value< bool > _auto_fax_adjustment; Config::Value< bool > _auto_fax_adjustment;
Config::Value< unsigned int > _fax_adjustment_timeout; Config::Value< unsigned int > _fax_adjustment_timeout;

View File

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

View File

@ -75,6 +75,7 @@ void Cli::registerCommands(APIFunc func,switch_loadable_module_interface_t **mod
" khomp channels unblock {all | <board> all | <board> <channel>}\n" \ " khomp channels unblock {all | <board> all | <board> <channel>}\n" \
" khomp clear links [<board> [<link>]]\n" \ " khomp clear links [<board> [<link>]]\n" \
" khomp clear statistics [<board> [<channel>]]\n" \ " khomp clear statistics [<board> [<channel>]]\n" \
" khomp dump config\n" \
" khomp get <option>\n" \ " khomp get <option>\n" \
" khomp kommuter {on|off}\n" \ " khomp kommuter {on|off}\n" \
" khomp kommuter count\n" \ " khomp kommuter count\n" \
@ -128,6 +129,10 @@ void Cli::registerCommands(APIFunc func,switch_loadable_module_interface_t **mod
/* is responsible for parse and execute all commands */ /* is responsible for parse and execute all commands */
bool Cli::parseCommands(int argc, char *argv[]) bool Cli::parseCommands(int argc, char *argv[])
{ {
/*
* DEBUG_CLI_CMD();
*/
/* khomp summary */ /* khomp summary */
if (ARG_CMP(0, "summary")) if (ARG_CMP(0, "summary"))
return EXEC_CLI_CMD(Cli::KhompSummary); return EXEC_CLI_CMD(Cli::KhompSummary);
@ -163,7 +168,15 @@ bool Cli::parseCommands(int argc, char *argv[])
if(ARG_CMP(1, "statistics")) if(ARG_CMP(1, "statistics"))
return EXEC_CLI_CMD(Cli::KhompClearStatistics); return EXEC_CLI_CMD(Cli::KhompClearStatistics);
} }
/* khomp dump */
else if(ARG_CMP(0, "dump"))
{
/* khomp dump config */
if(ARG_CMP(1, "config"))
return EXEC_CLI_CMD(Cli::KhompDumpConfig);
}
/* khomp reset */ /* khomp reset */
else if(ARG_CMP(0, "reset")) else if(ARG_CMP(0, "reset"))
{ {
@ -285,6 +298,7 @@ Cli::_KhompShowChannels Cli::KhompShowChannels;
Cli::_KhompShowLinks Cli::KhompShowLinks; Cli::_KhompShowLinks Cli::KhompShowLinks;
Cli::_KhompShowStatistics Cli::KhompShowStatistics; Cli::_KhompShowStatistics Cli::KhompShowStatistics;
Cli::_KhompClearLinks Cli::KhompClearLinks; Cli::_KhompClearLinks Cli::KhompClearLinks;
Cli::_KhompDumpConfig Cli::KhompDumpConfig;
Cli::_KhompClearStatistics Cli::KhompClearStatistics; Cli::_KhompClearStatistics Cli::KhompClearStatistics;
Cli::_KhompResetLinks Cli::KhompResetLinks; Cli::_KhompResetLinks Cli::KhompResetLinks;
Cli::_KhompChannelsDisconnect Cli::KhompChannelsDisconnect; Cli::_KhompChannelsDisconnect Cli::KhompChannelsDisconnect;
@ -337,7 +351,9 @@ bool Cli::_KhompSummary::execute(int argc, char *argv[])
K::Logger::Logg2(classe, stream, "|------------------------------------------------------------------|"); K::Logger::Logg2(classe, stream, "|------------------------------------------------------------------|");
} }
if (k3lGetDeviceConfig(-1, ksoAPI, &apiCfg, sizeof(apiCfg)) == ksSuccess) const bool running = (k3lGetDeviceConfig(-1, ksoAPI, &apiCfg, sizeof(apiCfg)) == ksSuccess);
if(running)
{ {
switch(output_type) switch(output_type)
{ {
@ -376,6 +392,28 @@ bool Cli::_KhompSummary::execute(int argc, char *argv[])
break; break;
} }
} }
else
{
switch(output_type)
{
case Cli::VERBOSE:
{
K::Logger::Logg2(classe, stream, "| Connection to KServer broken, please check system logs! |");
} break;
case Cli::CONCISE:
{
K::Logger::Logg2(classe, stream, "CONNECTION BROKEN");
} break;
case Cli::XML:
{
/* summary/k3lapi */
switch_xml_t xk3lapi = switch_xml_add_child_d(root, "k3lapi",0);
switch_xml_set_txt_d(xk3lapi, "CONNECTION BROKEN");
} break;
}
}
#ifndef MOD_KHOMP_VERSION #ifndef MOD_KHOMP_VERSION
#define MOD_KHOMP_VERSION "unknown" #define MOD_KHOMP_VERSION "unknown"
@ -423,6 +461,20 @@ bool Cli::_KhompSummary::execute(int argc, char *argv[])
break; break;
} }
if(!running)
{
if (output_type == Cli::VERBOSE)
K::Logger::Logg2(classe,stream, " ------------------------------------------------------------------");
if (output_type == Cli::XML)
{
printXMLOutput(stream);
clearRoot();
}
return false;
}
if (output_type == Cli::XML) if (output_type == Cli::XML)
{ {
/* summary/board */ /* summary/board */
@ -2154,6 +2206,38 @@ bool Cli::_KhompClearStatistics::execute(int argc, char *argv[])
return true; return true;
} }
bool Cli::_KhompDumpConfig::execute(int argc, char *argv[])
{
if (argc != 2)
{
printUsage(stream);
return false;
}
const Config::StringSet opts = Globals::options.options();
K::Logger::Logg2(C_CLI, stream, " ------------------------------------------------------------------------");
K::Logger::Logg2(C_CLI, stream, "|--------------------------- Khomp Options Dump -------------------------|");
K::Logger::Logg2(C_CLI, stream, "|------------------------------------------------------------------------|");
for (Config::StringSet::const_iterator itr = opts.begin(); itr != opts.end(); ++itr)
{ try
{
if(removeUnavaible((*itr))) continue;
K::Logger::Logg2(C_CLI, stream, FMT("| %-24s => %42s |")
% (*itr) % Globals::options.get(&(Opt::_options), (*itr)));
}
catch(Config::EmptyValue &e)
{
K::Logger::Logg(C_ERROR, FMT("%s (%s)") % e.what() % (*itr));
}
}
K::Logger::Logg2(C_CLI, stream, " ------------------------------------------------------------------------");
return true;
}
void Cli::_KhompResetLinks::resetLink(unsigned int device, unsigned int link) void Cli::_KhompResetLinks::resetLink(unsigned int device, unsigned int link)
{ {
try try
@ -2718,10 +2802,18 @@ bool Cli::_KhompSet::execute(int argc, char *argv[])
try try
{ {
Globals::options.process(&Opt::_options, (const char *) argv[1], (const char *) args.c_str()); Globals::options.process(&Opt::_options, (const char *) argv[1], (const char *) args.c_str());
const Config::Options::Messages msgs = Globals::options.commit(&Opt::_options, (const char *)argv[1]);
for (Config::Options::Messages::const_iterator i = msgs.begin(); i != msgs.end(); ++i)
{
K::Logger::Logg2(C_ERROR, stream, FMT("%s.") % (*i));
}
K::Logger::Logg2(C_CLI, stream, FMT("Setting %s for value %s") % argv[1] % argv[2]);
} }
catch (Config::Failure &e) catch (Config::Failure &e)
{ {
K::Logger::Logg2(C_CLI,stream, FMT("config processing error: %s.") % e.what()); K::Logger::Logg2(C_ERROR,stream, FMT("config processing error: %s.") % e.what());
} }
return true; return true;
@ -2891,7 +2983,6 @@ bool Cli::_KhompSelectSim::execute(int argc, char *argv[])
K::Logger::Logg2(C_CLI, stream, "ERROR: Unable to select sim card"); K::Logger::Logg2(C_CLI, stream, "ERROR: Unable to select sim card");
return false; return false;
} }
} }
catch (Strings::invalid_value & e) catch (Strings::invalid_value & e)
{ {

View File

@ -1119,12 +1119,7 @@ bool Board::KhompPvt::cleanup(CleanupType type)
/* pára cadências e limpa estado das flags */ /* pára cadências e limpa estado das flags */
stopCadence(); stopCadence();
if (call()->_indication != INDICA_NONE) cleanupIndications(true);
{
call()->_indication = INDICA_NONE;
mixer(KHOMP_LOG, 1, kmsGenerator, kmtSilence);
}
if(call()->_input_volume >= -10 && call()->_input_volume <= 10) if(call()->_input_volume >= -10 && call()->_input_volume <= 10)
setVolume("input" , Opt::_options._input_volume()); setVolume("input" , Opt::_options._input_volume());
@ -1152,6 +1147,15 @@ bool Board::KhompPvt::cleanup(CleanupType type)
return true; return true;
} }
void Board::KhompPvt::cleanupIndications(bool force)
{
if (call()->_indication != INDICA_NONE)
{
call()->_indication = INDICA_NONE;
mixer(KHOMP_LOG, 1, kmsGenerator, kmtSilence);
}
}
bool Board::KhompPvt::isFree(bool just_phy) bool Board::KhompPvt::isFree(bool just_phy)
{ {
//DBG(FUNC, DP(this, "c")); //DBG(FUNC, DP(this, "c"));
@ -1168,28 +1172,6 @@ bool Board::KhompPvt::isFree(bool just_phy)
if(session()) if(session())
return false; return false;
/*
if (!is_gsm())
{
if (calls.at(0).owner != NULL)
{
DBG(FUNC, DP(this, "we have owner, not free!"));
return false;
}
}
else
{
for (int i = 0; i < 6; i++)
{
call_data_type & data = calls.at(i);
if (data.owner != NULL)
return false;
}
}
*/
bool free_state = !(_call->_flags.check(Kflags::IS_INCOMING) || _call->_flags.check(Kflags::IS_OUTGOING)); bool free_state = !(_call->_flags.check(Kflags::IS_INCOMING) || _call->_flags.check(Kflags::IS_OUTGOING));
DBG(FUNC, PVT_FMT(target(), "[free = %s]") % (free_state ? "yes" : "no")); DBG(FUNC, PVT_FMT(target(), "[free = %s]") % (free_state ? "yes" : "no"));
@ -1559,7 +1541,7 @@ bool Board::KhompPvt::echoCancellation(bool enable)
bool Board::KhompPvt::autoGainControl(bool enable) bool Board::KhompPvt::autoGainControl(bool enable)
{ {
bool ret = command(KHOMP_LOG,(enable ? CM_ENABLE_AGC : CM_DISABLE_AGC));//, SCE_SHOW_DEBUG); bool ret = command(KHOMP_LOG,(enable ? CM_ENABLE_AGC : CM_DISABLE_AGC));
return ret; return ret;
} }
@ -1625,10 +1607,11 @@ bool Board::KhompPvt::setCollectCall()
DBG(FUNC, PVT_FMT(_target, "option drop collect call is '%s'") % (Opt::_options._drop_collect_call() ? "yes" : "no")); DBG(FUNC, PVT_FMT(_target, "option drop collect call is '%s'") % (Opt::_options._drop_collect_call() ? "yes" : "no"));
// get global filter configuration value // get global filter configuration value
tmp_var = switch_core_get_variable_dup("KDropCollectCall"); tmp_var = getFSGlobalVar("KDropCollectCall");
confvalues.push_back(getTriStateValue(tmp_var)); confvalues.push_back(getTriStateValue(tmp_var));
DBG(FUNC, PVT_FMT(_target, "global KDropCollectCall was '%s'") % (tmp_var ? tmp_var : "(empty)")); DBG(FUNC, PVT_FMT(_target, "global KDropCollectCall was '%s'") % (tmp_var ? tmp_var : "(empty)"));
switch_safe_free(tmp_var);
freeFSGlobalVar(&tmp_var);
try try
{ {
@ -2052,6 +2035,7 @@ bool Board::KhompPvt::onNoAnswer(K3L_EVENT *e)
DBG(FUNC, PVT_FMT(_target, "Detected: \"%s\"") % Verbose::callStartInfo((KCallStartInfo)e->AddInfo).c_str()); DBG(FUNC, PVT_FMT(_target, "Detected: \"%s\"") % Verbose::callStartInfo((KCallStartInfo)e->AddInfo).c_str());
// Fire a custom event about this // Fire a custom event about this
/* MUST USE THE NEW EVENT SYSTEM
switch_event_t * event; switch_event_t * event;
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, KHOMP_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, KHOMP_EVENT_MAINT) == SWITCH_STATUS_SUCCESS)
{ {
@ -2062,6 +2046,8 @@ bool Board::KhompPvt::onNoAnswer(K3L_EVENT *e)
switch_event_fire(&event); switch_event_fire(&event);
} }
*/
return true; return true;
} }

View File

@ -715,37 +715,47 @@ bool BoardFXO::KhompPvtFXO::indicateBusyUnlocked(int cause, bool sent_signaling)
if(call()->_flags.check(Kflags::IS_INCOMING)) if(call()->_flags.check(Kflags::IS_INCOMING))
{ {
/* already connected or sent signaling... */
mixer(KHOMP_LOG, 1, kmsGenerator, kmtBusy);
if(!call()->_flags.check(Kflags::CONNECTED) && !sent_signaling) if(!call()->_flags.check(Kflags::CONNECTED) && !sent_signaling)
{ {
//we are talking about branches, not trunks /* we are talking about branches, not trunks */
command(KHOMP_LOG, CM_CONNECT); command(KHOMP_LOG, CM_CONNECT);
command(KHOMP_LOG, CM_DISCONNECT); callFXO()->_busy_disconnect = Board::board(_target.device)->_timers.add(Opt::_options._fxo_busy_disconnection(), &BoardFXO::KhompPvtFXO::busyDisconnect, this);
}
else
{
//already connected or sent signaling...
mixer(KHOMP_LOG, 1, kmsGenerator, kmtBusy);
} }
} }
else if(call()->_flags.check(Kflags::IS_OUTGOING)) else if(call()->_flags.check(Kflags::IS_OUTGOING))
{ {
//already connected or sent signaling... /* already connected or sent signaling... */
mixer(KHOMP_LOG, 1, kmsGenerator, kmtBusy); mixer(KHOMP_LOG, 1, kmsGenerator, kmtBusy);
} }
DBG(FUNC,PVT_FMT(_target, "(FXO) r")); DBG(FUNC,PVT_FMT(_target, "(FXO) r"));
return true; return true;
} }
void BoardFXO::KhompPvtFXO::busyDisconnect(Board::KhompPvt * pvt)
{
DBG(FUNC, PVT_FMT(pvt->target(), "Disconnecting FXO"));
try
{
ScopedPvtLock lock(pvt);
pvt->command(KHOMP_LOG, CM_DISCONNECT);
}
catch (...)
{
LOG(ERROR, PVT_FMT(pvt->target(), "unable to lock the pvt !"));
}
}
void BoardFXO::KhompPvtFXO::reportFailToReceive(int fail_code) void BoardFXO::KhompPvtFXO::reportFailToReceive(int fail_code)
{ {
KhompPvt::reportFailToReceive(fail_code); KhompPvt::reportFailToReceive(fail_code);
command(KHOMP_LOG, CM_CONNECT); command(KHOMP_LOG, CM_CONNECT);
command(KHOMP_LOG, CM_DISCONNECT); command(KHOMP_LOG, CM_DISCONNECT);
} }
bool BoardFXO::KhompPvtFXO::validContexts( bool BoardFXO::KhompPvtFXO::validContexts(

View File

@ -312,6 +312,9 @@ int BoardGSM::KhompPvtGSM::makeCall(std::string params)
command(KHOMP_LOG, CM_DISABLE_CALL_ANSWER_INFO); command(KHOMP_LOG, CM_DISABLE_CALL_ANSWER_INFO);
} }
if(!_call->_orig_addr.compare("restricted"))
params += " orig_addr=\"restricted\"";
int ret = KhompPvt::makeCall(params); int ret = KhompPvt::makeCall(params);
if(ret != ksSuccess) if(ret != ksSuccess)

View File

@ -372,18 +372,37 @@ bool BoardE1::onLinkStatus(K3L_EVENT *e)
bool BoardE1::KhompPvtISDN::onSyncUserInformation(K3L_EVENT *e) bool BoardE1::KhompPvtISDN::onSyncUserInformation(K3L_EVENT *e)
{ {
KUserInformation * info = (KUserInformation *) (((char*)e) + sizeof(K3L_EVENT)); DBG(FUNC,PVT_FMT(_target, "Synchronizing"));
callISDN()->_uui_descriptor = info->ProtocolDescriptor; if(callISDN()->_uui_extended)
{
KUserInformationEx * info = (KUserInformationEx *) (((char*)e) + sizeof(K3L_EVENT));
callISDN()->_uui_descriptor = (long int) info->ProtocolDescriptor;
/* clean string */
callISDN()->_uui_information.clear();
/* clean string */ if (info->UserInfoLength)
callISDN()->_uui_information.clear(); {
/* append to a clean string */
for (unsigned int i = 0; i < info->UserInfoLength; ++i)
callISDN()->_uui_information += STG(FMT("%02hhx") % ((unsigned char) info->UserInfo[i]));
}
}
else
{
KUserInformation * info = (KUserInformation *) (((char*)e) + sizeof(K3L_EVENT));
callISDN()->_uui_descriptor = info->ProtocolDescriptor;
/* clean string */
callISDN()->_uui_information.clear();
if (info->UserInfoLength) if (info->UserInfoLength)
{ {
/* append to a clean string */ for (unsigned int i = 0; i < info->UserInfoLength; ++i)
callISDN()->_uui_information.append((const char *)info->UserInfo, info->UserInfoLength); callISDN()->_uui_information += STG(FMT("%02hhx") % ((unsigned char) info->UserInfo[i]));
} }
}
return true; return true;
} }
@ -440,15 +459,20 @@ bool BoardE1::KhompPvtISDN::onNewCall(K3L_EVENT *e)
bool isdn_reverse_charge = false; bool isdn_reverse_charge = false;
std::string isdn_reverse_charge_str; std::string isdn_reverse_charge_str;
bool ret; bool ret;
try try
{ {
callISDN()->_isdn_orig_type_of_number = Globals::k3lapi.get_param(e, "isdn_orig_type_of_number");
callISDN()->_isdn_orig_numbering_plan = Globals::k3lapi.get_param(e, "isdn_orig_numbering_plan");
callISDN()->_isdn_dest_type_of_number = Globals::k3lapi.get_param(e, "isdn_dest_type_of_number");
callISDN()->_isdn_dest_numbering_plan = Globals::k3lapi.get_param(e, "isdn_dest_numbering_plan");
callISDN()->_isdn_orig_presentation = Globals::k3lapi.get_param(e, "isdn_orig_presentation");
isdn_reverse_charge_str = Globals::k3lapi.get_param(e, "isdn_reverse_charge"); isdn_reverse_charge_str = Globals::k3lapi.get_param(e, "isdn_reverse_charge");
isdn_reverse_charge = Strings::toboolean(isdn_reverse_charge_str); isdn_reverse_charge = Strings::toboolean(isdn_reverse_charge_str);
} }
catch(K3LAPI::get_param_failed & err) catch(K3LAPI::get_param_failed & err)
{ {
/* do nothing, maybe the parameter is not sent */ LOG(WARNING, PVT_FMT(_target, "maybe the parameter is not sent (%s)'") % err.name.c_str());
} }
catch (Strings::invalid_value & err) catch (Strings::invalid_value & err)
{ {
@ -866,25 +890,84 @@ int BoardE1::KhompPvtISDN::makeCall(std::string params)
DBG(FUNC,PVT_FMT(_target, "got userinfo")); DBG(FUNC,PVT_FMT(_target, "got userinfo"));
/* grab this information first, avoiding latter side-effects */ /* grab this information first, avoiding latter side-effects */
const char * info_data = call->_uui_information.c_str(); const bool info_extd = call->_uui_extended;
size_t info_size = std::min(call->_uui_information.size(), (size_t)KMAX_USER_USER_LEN); const long int info_desc = call->_uui_descriptor;
const std::string info_data = call->_uui_information.c_str();
const size_t info_size = std::min<size_t>(call->_uui_information.size(), (info_extd ? KMAX_USER_USER_EX_LEN : KMAX_USER_USER_LEN) << 1) >> 1;
KUserInformation info; bool res = true;
info.ProtocolDescriptor = call->_uui_descriptor; if(info_extd)
info.UserInfoLength = info_size;
memcpy((void *) info.UserInfo, (const void *) info_data, info_size);
if (!command(KHOMP_LOG, CM_USER_INFORMATION, (const char *)&info))
{ {
LOG(ERROR,PVT_FMT(_target, "UUI could not be sent before dialing!")); KUserInformationEx info;
info.ProtocolDescriptor = info_desc;
info.UserInfoLength = info_size;
for (unsigned int pos = 0u, index = 0u; pos < info_size; index+=2, ++pos)
info.UserInfo[pos] = (unsigned char)Strings::toulong(info_data.substr(index,2), 16);
if (!command(KHOMP_LOG, CM_USER_INFORMATION_EX, (const char *) &info))
{
LOG(ERROR,PVT_FMT(_target, "UUI could not be sent before dialing!"));
}
}
else
{
KUserInformation info;
info.ProtocolDescriptor = info_desc;
info.UserInfoLength = info_size;
for (unsigned int pos = 0u, index = 0u; pos < info_size; index+=2, ++pos)
info.UserInfo[pos] = (unsigned char)Strings::toulong(info_data.substr(index,2), 16);
if (!command(KHOMP_LOG, CM_USER_INFORMATION, (const char *) &info))
{
LOG(ERROR,PVT_FMT(_target, "UUI could not be sent before dialing!"));
}
} }
call->_uui_extended = false;
call->_uui_descriptor = -1; call->_uui_descriptor = -1;
call->_uui_information.clear(); call->_uui_information.clear();
} }
if (!callISDN()->_isdn_orig_type_of_number.empty())
{
params += "isdn_orig_type_of_number=\"";
params += callISDN()->_isdn_orig_type_of_number;
params += "\" ";
}
if (!callISDN()->_isdn_dest_type_of_number.empty())
{
params += "isdn_dest_type_of_number=\"";
params += callISDN()->_isdn_dest_type_of_number;
params += "\" ";
}
if (!callISDN()->_isdn_orig_numbering_plan.empty())
{
params += "isdn_orig_numbering_plan=\"";
params += callISDN()->_isdn_orig_numbering_plan;
params += "\" ";
}
if (!callISDN()->_isdn_dest_numbering_plan.empty())
{
params += "isdn_dest_numbering_plan=\"";
params += callISDN()->_isdn_dest_numbering_plan;
params += "\" ";
}
if (!callISDN()->_isdn_orig_presentation.empty())
{
params += "isdn_orig_presentation=\"";
params += callISDN()->_isdn_orig_presentation;
params += "\" ";
}
int ret = KhompPvtE1::makeCall(params); int ret = KhompPvtE1::makeCall(params);
call->_cleanup_upon_hangup = (ret == ksInvalidParams || ret == ksBusy); call->_cleanup_upon_hangup = (ret == ksInvalidParams || ret == ksBusy);
@ -995,12 +1078,6 @@ bool BoardE1::KhompPvtR2::doChannelAnswer(CommandRequest &cmd)
// is this a collect call? // is this a collect call?
bool has_recv_collect_call = _call->_collect_call; bool has_recv_collect_call = _call->_collect_call;
if(has_recv_collect_call)
DBG(FUNC, PVT_FMT(target(), "receive a collect call"));
if(call()->_flags.check(Kflags::DROP_COLLECT))
DBG(FUNC, PVT_FMT(target(), "flag DROP_COLLECT == true"));
// do we have to drop collect calls? // do we have to drop collect calls?
bool has_drop_collect_call = call()->_flags.check(Kflags::DROP_COLLECT); bool has_drop_collect_call = call()->_flags.check(Kflags::DROP_COLLECT);
@ -1013,29 +1090,37 @@ bool BoardE1::KhompPvtR2::doChannelAnswer(CommandRequest &cmd)
if(do_send_ring) if(do_send_ring)
{ {
call()->_flags.clear(Kflags::NEEDS_RINGBACK_CMD); call()->_flags.clear(Kflags::NEEDS_RINGBACK_CMD);
//TODO: callFailFromCause ??
std::string cause = ( do_drop_call ? STG(FMT("r2_cond_b=\"%d\"") % kgbBusy) : "" ); std::string cause = ( do_drop_call ? STG(FMT("r2_cond_b=\"%d\"") % kgbBusy) : "" );
command(KHOMP_LOG,CM_RINGBACK,cause.c_str()); command(KHOMP_LOG,CM_RINGBACK,cause.c_str());
usleep(75000); usleep(75000);
} }
if(!(do_drop_call && do_send_ring)) if(!do_drop_call)
{ {
command(KHOMP_LOG, CM_CONNECT); command(KHOMP_LOG, CM_CONNECT);
} }
if(has_drop_collect_call && !do_send_ring) if(!do_send_ring && has_drop_collect_call)
{ {
usleep(75000);
if(has_recv_collect_call) if(has_recv_collect_call)
{ {
usleep(75000);
DBG(FUNC, PVT_FMT(target(), "disconnecting collect call doChannelAnswer R2"));
command(KHOMP_LOG,CM_DISCONNECT);
// thou shalt not talk anymore! // thou shalt not talk anymore!
stopListen(); stopListen();
stopStream(); stopStream();
if (call()->_indication == INDICA_NONE)
{
call()->_indication = INDICA_BUSY;
mixer(KHOMP_LOG, 1, kmsGenerator, kmtBusy);
}
DBG(FUNC, PVT_FMT(_target,"forcing disconnect for collect call"));
forceDisconnect();
} }
else else
{ {
@ -1797,6 +1882,8 @@ bool BoardE1::KhompPvtR2::onNewCall(K3L_EVENT *e)
DBG(FUNC,PVT_FMT(_target, "Setting DROP_COLLECT flag")); DBG(FUNC,PVT_FMT(_target, "Setting DROP_COLLECT flag"));
} }
freeFSGlobalVar(&drop_str);
// keeping the hardcore mode // keeping the hardcore mode
if (do_drop_collect && call()->_collect_call) if (do_drop_collect && call()->_collect_call)
{ {
@ -2388,6 +2475,7 @@ void BoardE1::KhompPvtFXS::dialTimer(KhompPvt * pvt)
} }
/*
void BoardE1::KhompPvtFXS::transferTimer(KhompPvt * pvt) void BoardE1::KhompPvtFXS::transferTimer(KhompPvt * pvt)
{ {
DBG(FUNC, PVT_FMT(pvt->target(), "c")); DBG(FUNC, PVT_FMT(pvt->target(), "c"));
@ -2420,7 +2508,7 @@ void BoardE1::KhompPvtFXS::transferTimer(KhompPvt * pvt)
return; return;
} }
/* begin context adjusting + processing */ // begin context adjusting + processing
MatchExtension::ContextListType contexts; MatchExtension::ContextListType contexts;
pvt_fxs->validContexts(contexts); pvt_fxs->validContexts(contexts);
@ -2469,6 +2557,7 @@ void BoardE1::KhompPvtFXS::transferTimer(KhompPvt * pvt)
DBG(FUNC, PVT_FMT(pvt->target(), "r")); DBG(FUNC, PVT_FMT(pvt->target(), "r"));
} }
*/
bool BoardE1::KhompPvtFXS::onChannelRelease(K3L_EVENT *e) bool BoardE1::KhompPvtFXS::onChannelRelease(K3L_EVENT *e)
{ {
@ -2480,22 +2569,23 @@ bool BoardE1::KhompPvtFXS::onChannelRelease(K3L_EVENT *e)
{ {
ScopedPvtLock lock(this); ScopedPvtLock lock(this);
/*
if(!callFXS()->_uuid_other_session.empty() && session()) if(!callFXS()->_uuid_other_session.empty() && session())
{ {
/*
switch_core_session_t *hold_session; //switch_core_session_t *hold_session;
if ((hold_session = switch_core_session_locate(callFXS()->_uuid_other_session.c_str()))) //if ((hold_session = switch_core_session_locate(callFXS()->_uuid_other_session.c_str())))
{ //{
switch_channel_t * hold = switch_core_session_get_channel(hold_session); // switch_channel_t * hold = switch_core_session_get_channel(hold_session);
switch_channel_stop_broadcast(hold); // switch_channel_stop_broadcast(hold);
switch_channel_wait_for_flag(hold, CF_BROADCAST, SWITCH_FALSE, 5000, NULL); // switch_channel_wait_for_flag(hold, CF_BROADCAST, SWITCH_FALSE, 5000, NULL);
switch_core_session_rwunlock(hold_session); // switch_core_session_rwunlock(hold_session);
} //}
*/
try try
{ {
/* get other side of the bridge */ // get other side of the bridge
switch_core_session_t * peer_session = getFSLockedPartnerSession(); switch_core_session_t * peer_session = getFSLockedPartnerSession();
unlockPartner(peer_session); unlockPartner(peer_session);
DBG(FUNC, PVT_FMT(target(), "bridge with the new session")); DBG(FUNC, PVT_FMT(target(), "bridge with the new session"));
@ -2509,6 +2599,7 @@ bool BoardE1::KhompPvtFXS::onChannelRelease(K3L_EVENT *e)
callFXS()->_uuid_other_session.clear(); callFXS()->_uuid_other_session.clear();
} }
*/
ret = KhompPvt::onChannelRelease(e); ret = KhompPvt::onChannelRelease(e);
@ -2523,7 +2614,7 @@ bool BoardE1::KhompPvtFXS::onChannelRelease(K3L_EVENT *e)
return ret; return ret;
} }
/*
bool BoardE1::KhompPvtFXS::startTransfer() bool BoardE1::KhompPvtFXS::startTransfer()
{ {
DBG(FUNC, PVT_FMT(target(), "c")); DBG(FUNC, PVT_FMT(target(), "c"));
@ -2596,7 +2687,7 @@ bool BoardE1::KhompPvtFXS::stopTransfer()
try try
{ {
/* get other side of the bridge */ // get other side of the bridge
switch_core_session_t * peer_session = getFSLockedPartnerSession(); switch_core_session_t * peer_session = getFSLockedPartnerSession();
switch_channel_t * peer_channel = getFSChannel(peer_session); switch_channel_t * peer_channel = getFSChannel(peer_session);
@ -2664,33 +2755,33 @@ static switch_status_t xferHook(switch_core_session_t *session)
else if (state == CS_HANGUP) else if (state == CS_HANGUP)
{ {
switch_core_event_hook_remove_state_change(session, xferHook); switch_core_event_hook_remove_state_change(session, xferHook);
/*
BoardE1::KhompPvtFXS * pvt = static_cast<BoardE1::KhompPvtFXS*>(switch_core_session_get_private(session));
if(!pvt)
{
DBG(FUNC, D("pvt is NULL"));
return SWITCH_STATUS_FALSE;
}
try //BoardE1::KhompPvtFXS * pvt = static_cast<BoardE1::KhompPvtFXS*>(switch_core_session_get_private(session));
{ //
ScopedPvtLock lock(pvt); //if(!pvt)
//{
// DBG(FUNC, D("pvt is NULL"));
// return SWITCH_STATUS_FALSE;
//}
if(!pvt->callFXS()->_uuid_other_session.empty()) //try
{ //{
DBG(FUNC, D("bridge after hangup")); // ScopedPvtLock lock(pvt);
std::string number = pvt->callFXS()->_uuid_other_session;
pvt->callFXS()->_uuid_other_session.clear(); // if(!pvt->callFXS()->_uuid_other_session.empty())
// {
// DBG(FUNC, D("bridge after hangup"));
// std::string number = pvt->callFXS()->_uuid_other_session;
// pvt->callFXS()->_uuid_other_session.clear();
// switch_ivr_uuid_bridge(switch_core_session_get_uuid(session), number.c_str());
// }
//}
//catch(ScopedLockFailed & err)
//{
// LOG(ERROR, PVT_FMT(pvt->target(), "unable to lock: %s!") % err._msg.c_str());
//}
switch_ivr_uuid_bridge(switch_core_session_get_uuid(session), number.c_str());
}
}
catch(ScopedLockFailed & err)
{
LOG(ERROR, PVT_FMT(pvt->target(), "unable to lock: %s!") % err._msg.c_str());
}
*/
} }
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
@ -2716,7 +2807,7 @@ bool BoardE1::KhompPvtFXS::transfer(std::string & context, bool blind)
try try
{ {
/* get other side of the bridge */ // get other side of the bridge
switch_core_session_t * peer_session = getFSLockedPartnerSession(); switch_core_session_t * peer_session = getFSLockedPartnerSession();
switch_channel_t * peer_channel = getFSChannel(peer_session); switch_channel_t * peer_channel = getFSChannel(peer_session);
@ -2774,16 +2865,16 @@ bool BoardE1::KhompPvtFXS::transfer(std::string & context, bool blind)
call()->_flags.set(Kflags::GEN_CO_RING); call()->_flags.set(Kflags::GEN_CO_RING);
startCadence(PLAY_RINGBACK); startCadence(PLAY_RINGBACK);
/*
try //try
{ //{
call()->_idx_co_ring = Board::board(_target.device)->_timers.add(Opt::_options._ringback_co_delay(), &Board::KhompPvt::coRingGen,this); // call()->_idx_co_ring = Board::board(_target.device)->_timers.add(Opt::_options._ringback_co_delay(), &Board::KhompPvt::coRingGen,this);
} //}
catch (K3LAPITraits::invalid_device & err) //catch (K3LAPITraits::invalid_device & err)
{ //{
LOG(ERROR, PVT_FMT(_target, "unable to get device: %d!") % err.device); // LOG(ERROR, PVT_FMT(_target, "unable to get device: %d!") % err.device);
} //}
*/
} }
} }
catch(Board::KhompPvt::InvalidSwitchChannel & err) catch(Board::KhompPvt::InvalidSwitchChannel & err)
@ -2796,6 +2887,7 @@ bool BoardE1::KhompPvtFXS::transfer(std::string & context, bool blind)
return true; return true;
} }
*/
bool BoardE1::KhompPvtFXS::onDtmfDetected(K3L_EVENT *e) bool BoardE1::KhompPvtFXS::onDtmfDetected(K3L_EVENT *e)
{ {
@ -2902,6 +2994,7 @@ bool BoardE1::KhompPvtFXS::onDtmfDetected(K3L_EVENT *e)
break; break;
} }
} }
/*
else if(callFXS()->_flags.check(Kflags::FXS_OFFHOOK) && else if(callFXS()->_flags.check(Kflags::FXS_OFFHOOK) &&
callFXS()->_flags.check(Kflags::FXS_FLASH_TRANSFER)) callFXS()->_flags.check(Kflags::FXS_FLASH_TRANSFER))
{ {
@ -2922,7 +3015,7 @@ bool BoardE1::KhompPvtFXS::onDtmfDetected(K3L_EVENT *e)
callFXS()->_flash_transfer += e->AddInfo; callFXS()->_flash_transfer += e->AddInfo;
/* begin context adjusting + processing */ // begin context adjusting + processing
MatchExtension::ContextListType contexts; MatchExtension::ContextListType contexts;
validContexts(contexts); validContexts(contexts);
@ -2949,7 +3042,7 @@ bool BoardE1::KhompPvtFXS::onDtmfDetected(K3L_EVENT *e)
case MatchExtension::MATCH_MORE: case MatchExtension::MATCH_MORE:
DBG(FUNC, PVT_FMT(target(), "match more...")); DBG(FUNC, PVT_FMT(target(), "match more..."));
/* can match, will match more, and it's an external call? */ // can match, will match more, and it's an external call?
for (DestVectorType::const_iterator i = Opt::_options._fxs_co_dialtone().begin(); i != Opt::_options._fxs_co_dialtone().end(); i++) for (DestVectorType::const_iterator i = Opt::_options._fxs_co_dialtone().begin(); i != Opt::_options._fxs_co_dialtone().end(); i++)
{ {
if (callFXS()->_flash_transfer == (*i)) if (callFXS()->_flash_transfer == (*i))
@ -2975,6 +3068,7 @@ bool BoardE1::KhompPvtFXS::onDtmfDetected(K3L_EVENT *e)
} }
} }
} }
*/
else else
{ {
ret = KhompPvt::onDtmfDetected(e); ret = KhompPvt::onDtmfDetected(e);
@ -3042,6 +3136,7 @@ bool BoardE1::KhompPvtFXS::onFlashDetected(K3L_EVENT *e)
/******************************************************************************/ /******************************************************************************/
//Old implementation, not used //Old implementation, not used
/*
if(callFXS()->_flags.check(Kflags::FXS_FLASH_TRANSFER)) if(callFXS()->_flags.check(Kflags::FXS_FLASH_TRANSFER))
{ {
DBG(FUNC, PVT_FMT(_target, "(FXS) transfer canceled")); DBG(FUNC, PVT_FMT(_target, "(FXS) transfer canceled"));
@ -3078,6 +3173,7 @@ bool BoardE1::KhompPvtFXS::onFlashDetected(K3L_EVENT *e)
DBG(FUNC, PVT_FMT(target(), "(FXS) r (unable to start transfer)")); DBG(FUNC, PVT_FMT(target(), "(FXS) r (unable to start transfer)"));
return false; return false;
} }
*/
/******************************************************************************/ /******************************************************************************/
} }
@ -3207,7 +3303,8 @@ bool BoardE1::KhompPvtFXS::doChannelHangup(CommandRequest &cmd)
try try
{ {
ScopedPvtLock lock(this); ScopedPvtLock lock(this);
/*
if(!callFXS()->_uuid_other_session.empty()) if(!callFXS()->_uuid_other_session.empty())
{ {
DBG(FUNC,PVT_FMT(_target, "unable to transfer")); DBG(FUNC,PVT_FMT(_target, "unable to transfer"));
@ -3225,6 +3322,7 @@ bool BoardE1::KhompPvtFXS::doChannelHangup(CommandRequest &cmd)
} }
callFXS()->_uuid_other_session.clear(); callFXS()->_uuid_other_session.clear();
} }
*/
if (call()->_flags.check(Kflags::IS_INCOMING)) if (call()->_flags.check(Kflags::IS_INCOMING))
{ {

View File

@ -75,11 +75,14 @@ void Opt::initialize(void)
Globals::options.add(Config::Option("recording", &Options::_recording, true)); Globals::options.add(Config::Option("recording", &Options::_recording, true));
Globals::options.add(Config::Option("has-ctbus", &Options::_has_ctbus, false)); Globals::options.add(Config::Option("has-ctbus", &Options::_has_ctbus, false));
Globals::options.add(Config::Option("fxs-bina", &Options::_fxs_bina, true)); Globals::options.add(Config::Option("fxs-bina", &Options::_fxs_bina, true));
Globals::options.add(Config::Option("fxo-send-pre-audio", &Options::_fxo_send_pre_audio, true)); Globals::options.add(Config::Option("fxs-sharp-dial", &Options::_fxs_sharp_dial, true));
Globals::options.add(Config::Option("drop-collect-call", &Options::_drop_collect_call, false)); Globals::options.add(Config::Option("drop-collect-call", &Options::_drop_collect_call, false));
Globals::options.add(Config::Option("ignore-letter-dtmfs", &Options::_ignore_letter_dtmfs, true)); Globals::options.add(Config::Option("ignore-letter-dtmfs", &Options::_ignore_letter_dtmfs, true));
Globals::options.add(Config::Option("optimize-audio-path", &Options::_optimize_audio_path, false)); Globals::options.add(Config::Option("optimize-audio-path", &Options::_optimize_audio_path, false));
Globals::options.add(Config::Option("fxo-send-pre-audio", &Options::_fxo_send_pre_audio, true));
Globals::options.add(Config::Option("fxo-busy-disconnection", &Options::_fxo_busy_disconnection, 1250u, 50u, 90000u));
Globals::options.add(Config::Option("auto-fax-adjustment", &Options::_auto_fax_adjustment, true)); Globals::options.add(Config::Option("auto-fax-adjustment", &Options::_auto_fax_adjustment, true));
Globals::options.add(Config::Option("fax-adjustment-timeout", &Options::_fax_adjustment_timeout, 30u, 3u, 9999u)); Globals::options.add(Config::Option("fax-adjustment-timeout", &Options::_fax_adjustment_timeout, 30u, 3u, 9999u));

View File

@ -78,8 +78,6 @@ static SpecRetType processSpecAtom(std::string & atom, SpecFlagsType & flags, Sp
return processSpecAtoms(allocstr, flags, fun); return processSpecAtoms(allocstr, flags, fun);
} }
//Regex::Expression e("(((([bB])[ ]*([0-9]+))|(([sS])[ ]*([0-9]+)))[ ]*(([cClL])[ ]*([0-9]+)[ ]*([-][ ]*([0-9]+))?)?)|(([rR])[ ]*([0-9]+)[ ]*([-][ ]*([0-9]+))?)", Regex::E_EXTENDED);
Regex::Match what(allocstr, Globals::regex_allocation); Regex::Match what(allocstr, Globals::regex_allocation);
if (!what.matched()) if (!what.matched())

View File

@ -244,21 +244,26 @@ bool MatchExtension::canMatch(std::string & context, std::string & exten,
return true; return true;
} }
size_t finished = exten.find('#'); if (Opt::_options._fxs_sharp_dial())
if(finished != std::string::npos)
{ {
if(exten.size() <= 1) char key_digit = '#';
size_t finished = exten.find_last_of(key_digit);
char last_char = exten.at(exten.size() - 1);
if(finished != std::string::npos && last_char == key_digit)
{ {
DBG(FUNC, FMT("exten=%s size=%d") % exten % exten.size()); if(exten.size() <= 1)
return true; {
DBG(FUNC, FMT("exten=%s size=%d") % exten % exten.size());
return true;
}
exten.erase(finished);
DBG(FUNC, FMT("match exact!!! exten=%s") % exten);
return false;
} }
exten.erase(finished);
DBG(FUNC, FMT("match exact!!! exten=%s") % exten);
return false;
} }
return true; return true;
/* /*