]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
- fxo-busy-disconnection timer for desconnection on FXO
authorGeovani Ricardo Wiedenhoft <grw@geovani.(none)>
Thu, 17 Feb 2011 19:41:56 +0000 (17:41 -0200)
committerGeovani Ricardo Wiedenhoft <grw@geovani.(none)>
Thu, 17 Feb 2011 19:41:56 +0000 (17:41 -0200)
- 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

33 files changed:
src/mod/endpoints/mod_khomp/Install/files/khomp.conf.xml
src/mod/endpoints/mod_khomp/commons/base/config_commons.hpp
src/mod/endpoints/mod_khomp/commons/base/config_options.hpp
src/mod/endpoints/mod_khomp/commons/base/configurator/configfile.cpp
src/mod/endpoints/mod_khomp/commons/base/k3lapi.cpp
src/mod/endpoints/mod_khomp/commons/base/k3lapi.hpp
src/mod/endpoints/mod_khomp/commons/base/logger.hpp
src/mod/endpoints/mod_khomp/commons/base/simple_lock.hpp
src/mod/endpoints/mod_khomp/commons/base/system/freeswitch/simple_lock.hpp
src/mod/endpoints/mod_khomp/commons/base/verbose.cpp
src/mod/endpoints/mod_khomp/docs/Manual.html
src/mod/endpoints/mod_khomp/docs/Manual.pdf
src/mod/endpoints/mod_khomp/docs/README.html
src/mod/endpoints/mod_khomp/docs/README.pdf
src/mod/endpoints/mod_khomp/docs/README_en.html
src/mod/endpoints/mod_khomp/docs/README_en.pdf
src/mod/endpoints/mod_khomp/docs/User_Guide.html
src/mod/endpoints/mod_khomp/docs/User_Guide.pdf
src/mod/endpoints/mod_khomp/include/cli.h
src/mod/endpoints/mod_khomp/include/k3l.h
src/mod/endpoints/mod_khomp/include/khomp_pvt.h
src/mod/endpoints/mod_khomp/include/khomp_pvt_fxo.h
src/mod/endpoints/mod_khomp/include/khomp_pvt_kxe1.h
src/mod/endpoints/mod_khomp/include/opt.h
src/mod/endpoints/mod_khomp/include/revision.h
src/mod/endpoints/mod_khomp/src/cli.cpp
src/mod/endpoints/mod_khomp/src/khomp_pvt.cpp
src/mod/endpoints/mod_khomp/src/khomp_pvt_fxo.cpp
src/mod/endpoints/mod_khomp/src/khomp_pvt_gsm.cpp
src/mod/endpoints/mod_khomp/src/khomp_pvt_kxe1.cpp
src/mod/endpoints/mod_khomp/src/opt.cpp
src/mod/endpoints/mod_khomp/src/spec.cpp
src/mod/endpoints/mod_khomp/src/utils.cpp

index 79c00516b9066e1dfee951e88836e1c2e1653c0a..069792935ca4e7d0d37bcf1bc4cfb4352c825c55 100644 (file)
@@ -272,6 +272,15 @@ a FXS branch.
 <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
 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"/>
 -->
 
+<!--
+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
 outgoing calls before it has been connected.
index dad16f4e92e653e845db4f69508e1c08923fae34..14f8a19d2cd13763904f46460e0515da6965ada6 100644 (file)
@@ -69,6 +69,6 @@
 #define COMMONS_VERSION_MINOR 1
 
 #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_ */
index 59e381f893e5c8cb144765f8d33ade78996f936c..9196f3b5a826ad49a8e18852e6b7c2703b406679 100644 (file)
@@ -690,6 +690,32 @@ namespace Config
             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 >
         Messages commit(Object * const object)
         {
@@ -718,7 +744,7 @@ namespace Config
         }
 
         template < typename Object >
-        bool loaded(Object * object, std::string name)
+        bool loaded(Object * object, const std::string & name)
         {
             OptionMap::iterator iter = find_option(name);
 
index 8a46587a59f559a395efc77baf1ba5292f092318..02e43df1208f64997efb9208552279cce052b67c 100644 (file)
@@ -144,9 +144,8 @@ bool Configfile::deserialize(std::ifstream & fd)
             if (adjust(section, opt, val))
                 continue;
 
-            _errors.push_back(STG(FMT("option '%s' does "
-                "not exist or '%s' is not a valid value (at section '%s')")
-                % opt % val % section->name()));
+            _errors.push_back(STG(FMT("option '%s' does not exist or '%s' is not "
+                "a valid value (at section '%s')") % opt % val % section->name()));
         }
     }
 
index 09f5c81c0e37617ac7163bdf9dd3f81f7218a8a6..ffc9d93435d1e6b1c15ed2d825b4d3de4c340095 100644 (file)
@@ -205,6 +205,15 @@ std::string K3LAPIBase::get_param(K3L_EVENT *ev, const char *name) const
     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)
 {
     if (_device_count != 0) return;
index ef12a3f676e512650a79551702ef132f16abf460..f65d52405ae0696c78f03e2ec4fdc968b6574dae 100644 (file)
@@ -317,7 +317,9 @@ struct K3LAPIBase
     /* pega valores em strings de eventos */
 
     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_optional(K3L_EVENT *ev, const char *name) const;
 
     /* inicializa valores em cache */
 
index 6c333e7b8737d60efb0fc1a7de74ddbc7316d476..2a119afb9c115edcea0252e7abf80b61a99a4766 100644 (file)
 #include <refcounter.hpp>
 #include <flagger.hpp>
 
-#if defined(COMMONS_LIBRARY_USING_ASTERISK)
+#if defined(COMMONS_LIBRARY_USING_ASTERISK) || defined(COMMONS_LIBRARY_USING_FREESWITCH)
 extern "C"
 {
-    #include <asterisk.h>
-    #include <asterisk/localtime.h>
+    #include <time.h>
 }
 #elif defined(COMMONS_LIBRARY_USING_CALLWEAVER)
 extern "C"
 {
     #include <callweaver/localtime.h>
 }
-#elif defined(COMMONS_LIBRARY_USING_FREESWITCH)
-extern "C"
-{
-    #include <time.h>
-}
 #endif
 /*
 
@@ -424,77 +418,26 @@ struct Logger
 
                     if (opt._flags[Option::DATETIME])
                     {
-#if defined(COMMONS_LIBRARY_USING_ASTERISK)
-#if ASTERISK_AT_LEAST(1,6,0)
-                        struct timeval tv;
-                        struct ast_tm  lt;
-
-                        gettimeofday(&tv, NULL);
-
-#else
+#if defined(COMMONS_LIBRARY_USING_ASTERISK) || defined(COMMONS_LIBRARY_USING_CALLWEAVER) || defined(COMMONS_LIBRARY_USING_FREESWITCH)
                         time_t      tv;
                         struct tm   lt;
 
                         time (&tv);
-#endif
-
-#if ASTERISK_AT_LEAST(1,4,5)
-                        ast_localtime (&tv, &lt, NULL);
-#else
                         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] ")
                             % (lt.tm_year % 100) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour
                             % lt.tm_min % lt.tm_sec);
+#endif
                     }
 
                     if (opt._flags[Option::DATETIMEMS])
                     {
-#if defined(COMMONS_LIBRARY_USING_ASTERISK)
-#if ASTERISK_AT_LEAST(1,6,0)
-                        struct timeval tv;
-                        struct ast_tm  lt;
-
-                        gettimeofday(&tv, NULL);
-
-#else
+#if defined(COMMONS_LIBRARY_USING_ASTERISK) || defined(COMMONS_LIBRARY_USING_CALLWEAVER) || defined(COMMONS_LIBRARY_USING_FREESWITCH)
                         time_t      tv;
                         struct tm   lt;
 
                         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);
 
                         out_msg += STG(FMT("[%02d-%02d-%02d %02d:%02d:%02d:%04d] ")
index 8f22fe6bdbb64c3653f13893e636542e7e7a560b..16d85fb053be570f924f40f387c6c9e0064c1c4b 100644 (file)
@@ -52,7 +52,7 @@
 /* This struct uses static polymorphism, and derived classes should implement  *
  * the "lock/trylock/unlock()" methods for correct code compilation.           *
  * 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 >
 struct SimpleLockCommon: COUNTER_SUPER( SimpleLockCommon < Implementor > )
@@ -95,7 +95,7 @@ struct SimpleLockCommon: COUNTER_SUPER( SimpleLockCommon < Implementor > )
   protected:
     void unreference(void)
     {
-        static_cast<Implementor*>(this)->unreference();
+        static_cast<Implementor*>(this)->unreference_data();
     }
 };
 
index acae57648d582562344cc2261340f9a97aeaa5b5..6b3a17f46d79e2b03397a388cea53f919936c75e 100644 (file)
@@ -73,7 +73,7 @@ struct SimpleLockBasic: public SimpleLockCommon < Implementor >
         /* do nothing */
     };
 
-    void unreference()
+    void unreference_data()
     {
         switch_mutex_destroy(_mutex);
 
index bdc412e231d1f93b3a53632f06cc35218309d4d1..bacd269736d13ce8d8cb7a261bf1d838bb2471ef 100644 (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_CREATE_DISPATCHER:
         case VerboseTraits::K_CM_LOG_DESTROY_DISPATCHER:
-
         case VerboseTraits::K_CM_PING:
 #endif
+//#if K3L_AT_LEAST(2,1,0)
+//        case VerboseTraits::K_CM_LOG_UPDATE:
+//#endif
             return show(buf, commandName(code), Target(NONE));
 #if K3L_AT_LEAST(2,1,0)
         case VerboseTraits::K_CM_START_FAX_TX:
index c4745700b18e0ba8ab1785c4e75298e6f2184d71..b1fcfc0107886dc9431f5ea7b56f88dc733fe237 100644 (file)
 </p>
 <pre><b>Sintaxe:</b> &lt;param name="..." value="..."/&gt;
 </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-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); 
@@ -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-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>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>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"; 
 <ul><li>context; 
 </li><li>input-volume; 
 </li><li>output-volume; 
+</li><li>language; 
+</li><li>accountcode;
 </li><li>calleridnum; 
 </li><li>calleridname;
 </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><p><br />
 </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>
 <pre>
   &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>.
 <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>
\ No newline at end of file
index 260ba542a5a1476b0bb0ecc9bc4b1ef9c313628a..ff578148248bb914d31114c16a29e4dcbb80f10f 100644 (file)
Binary files a/src/mod/endpoints/mod_khomp/docs/Manual.pdf and b/src/mod/endpoints/mod_khomp/docs/Manual.pdf differ
index e4cae5ad3b6c3e76fe457061ace0156a58dad56f..c9756b36a2b0548b498308012cc3b4bcc1999de7 100644 (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>
 <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>
-<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>
 <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>
index 13a5f5469a80ec0d20f7c85e60e193622eaee77a..304f6e0dd347d122c13ad4ee138132fe6eb721f4 100644 (file)
Binary files a/src/mod/endpoints/mod_khomp/docs/README.pdf and b/src/mod/endpoints/mod_khomp/docs/README.pdf differ
index 5d44b8219fab6870cf951d4f3b68f6498187fdfa..c72b84270cfc810b4c9c4b86beb04978daf2d0bd 100644 (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>
 <p>After installation and startup services required by Khomp, FreeSWITCH can now be loaded or initialized.
 </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>
 <p>After initialization of FreeSWITCH, you can verify that the module was loaded Khomp through the following command: <br />
-</p><p><br />
 </p>
 <pre> freeswitch@hostname&gt; module_exists mod_khomp
 </pre>
index a88e9403d4f1549d15cb556dbd08885f0813ddfd..8931da91471c97852a627979755929e13ee52c4e 100644 (file)
Binary files a/src/mod/endpoints/mod_khomp/docs/README_en.pdf and b/src/mod/endpoints/mod_khomp/docs/README_en.pdf differ
index 5d0753ae43229bb6d1bc1364d57c0d7e6ed33c8a..4a1932a1ab3a2a47e655a03f7cda8118ee693829 100644 (file)
@@ -30,7 +30,8 @@ If you need to set advanced parameters of the board and/or signaling, the progra
 </p>
 <pre><b>Sintaxe:</b> &lt;param name="..." value="..."/&gt;
 </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-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);
@@ -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>kommuter-activation</b>: Sets whether to activate devices kommuter found in the system will be done automatically ("auto") by the channel, or manually ("manual") by the user through the command "khomp kommuter on/off" 
 </li><li><b>kommuter-timeout</b>: Sets the timeout (in seconds) for initializing the kommuter devices. If this timeout is reached without receiving notification of the channel, the devices will switch back to "off" condition. The minimum value is "0", where the links will always remain switched "on", and the maximum is "255";
+</li><li><b>language</b>: Set language to Khomp board calls;
 </li><li><b>log-to-console</b>: Set log messages to be printed on the console;
 </li><li><b>log-to-disk</b> (old "log"): Set log messages to be saved to disk;
 </li><li><b>out-of-band-DTMF</b> (former <b>dtmfsuppression</b>): Activate ("yes") or disables ("no") the removal and DTMF sending these out-of-band (local option);
@@ -125,6 +127,8 @@ For details, please refer to the configuration file for examples.
 </li><li>output-volume; 
 </li><li>calleridnum; 
 </li><li>calleridname;
+</li><li>language;
+</li><li>accountcode;
 </li><li>flash-to-digits.
 </li></ul>
 <p>Each option is separated from each other by a pipe "|" or a slash "/" and defined after the colon ":". Example:
@@ -1018,7 +1022,7 @@ install: **  for knowing how to proceed with the installation.  **
 </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>
-<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>
 <pre> 
 &lt;!-- &lt;load module=&quot;mod_khomp&quot; /&gt; --&gt;
@@ -1060,7 +1064,7 @@ install: **  for knowing how to proceed with the installation.  **
 <br />
 </p>
 <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>
 <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:
@@ -1084,5 +1088,6 @@ install: **  for knowing how to proceed with the installation.  **
 </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><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></body></html>
\ No newline at end of file
index e0c33e1c74e1c6f9588831d2b52013482fd13437..a0645460e5a05443c2026f07f4307206db8a1ed3 100644 (file)
Binary files a/src/mod/endpoints/mod_khomp/docs/User_Guide.pdf and b/src/mod/endpoints/mod_khomp/docs/User_Guide.pdf differ
index bb251bb16b524dff17a5d16c26d9c1d54c2ffe8c..5df472bb660635151636c515b8c5f2518b0a5b84 100644 (file)
@@ -733,17 +733,21 @@ struct Cli
             options.push_back("fxs-global-orig");
             options.push_back("fxs-co-dialtone");
             options.push_back("fxs-bina");
+            options.push_back("fxs-sharp-dial");
             options.push_back("disconnect-delay");
             options.push_back("delay-ringback-co");
             options.push_back("delay-ringback-pbx");
             options.push_back("ignore-letter-dtmfs");
             options.push_back("fxo-send-pre-audio");
+            options.push_back("fxo-busy-disconnection");
             options.push_back("fxs-digit-timeout");
             options.push_back("drop-collect-call");
             options.push_back("kommuter-activation");
             options.push_back("kommuter-timeout");
             options.push_back("user-transfer-digits");
             options.push_back("flash-to-digits");
+            options.push_back("accountcode");
+            options.push_back("audio-packet-length");
 
             brief = "Get configuration options in the Khomp channel.";
 
@@ -821,17 +825,21 @@ struct Cli
             options.push_back("fxs-global-orig");
             options.push_back("fxs-co-dialtone");
             options.push_back("fxs-bina");
+            options.push_back("fxs-sharp-dial");
             options.push_back("disconnect-delay");
             options.push_back("delay-ringback-co");
             options.push_back("delay-ringback-pbx");
             options.push_back("ignore-letter-dtmfs");
             options.push_back("fxo-send-pre-audio");
+            options.push_back("fxo-busy-disconnection");
             options.push_back("fxs-digit-timeout");
             options.push_back("drop-collect-call");
             options.push_back("kommuter-activation");
             options.push_back("kommuter-timeout");
             options.push_back("user-transfer-digits");
             options.push_back("flash-to-digits");
+            options.push_back("accountcode");
+            options.push_back("audio-packet-length");
 
             brief = "Ajust configuration options in the Khomp channel.";
 
@@ -933,6 +941,36 @@ struct Cli
         bool execute(int argc, char *argv[]);
     } 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 */
     static struct _KhompSendCommand : public Command
     {
index 046bd666b1394a325187d4e29f0b853865a5cdbf..51686d0296ea0d3b498af6c865d095255d6040fb 100644 (file)
@@ -231,6 +231,8 @@ struct KVoIPSeize
 
 #define CM_USER_INFORMATION         0x0F
 
+#define CM_USER_INFORMATION_EX      0x2B
+
 #define CM_VOIP_SEIZE                          0x23
 
 
@@ -369,6 +371,8 @@ struct KVoIPSeize
 
 #define EV_USER_INFORMATION         0x0F
 
+#define EV_USER_INFORMATION_EX      0x1D 
+
 #define EV_DIALED_DIGIT             0x10
 
 #define EV_SIP_REGISTER_INFO        0x11
@@ -713,6 +717,8 @@ enum KH100CtbusFreq
 #define CM_START_CADENCE                       0xA1
 
 #define CM_STOP_CADENCE                                0xA2
+
+#define CM_SET_INPUT_MODE                              0xA3
 #if !defined KR2D_H
 #define KR2D_H
 
@@ -925,6 +931,7 @@ enum KSignGroupII
 #ifndef _KISDN_H_
 #define _KISDN_H_
 #define KMAX_USER_USER_LEN              32
+#define KMAX_USER_USER_EX_LEN           254
 #define KMAX_SUBADRESS_INFORMATION_LEN  20 
 
 enum KQ931Cause
@@ -1845,6 +1852,12 @@ struct KUserInformation
     int32 UserInfoLength;
     byte  UserInfo[ KMAX_USER_USER_LEN ];
 };
+struct KUserInformationEx
+{
+    int32 ProtocolDescriptor;
+    int32 UserInfoLength;
+    byte  UserInfo[ KMAX_USER_USER_EX_LEN ];
+};
 struct KISDNSubaddressInformation
 {
     KQ931TypeOfSubaddress TypeOfSubaddress;
index d09be88567e900d92773d24ce61211ec81bd8e14..b17d163cc6c6d742add62818394e3dfb3ee70b9f 100644 (file)
@@ -305,8 +305,6 @@ struct KhompPvt
             {
                 try
                 {
-                    //std::string type((name == "input_volume")?"input":"output");
-
                     int i = Strings::tolong(value);
     
                     if (i < -10 || i > 10)
@@ -614,6 +612,7 @@ public:
 
     virtual bool indicateRinging();
     virtual bool sendDtmf(std::string digit);
+    virtual void cleanupIndications(bool force);
 
     /* Methods */
 
@@ -849,7 +848,31 @@ public:
         if(!name)
             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, 
index d91705b626c4e921f5affd9a5f40caea7e79ca63..6e51af35bd95482c7522fa874975f2576cc6f5a4 100644 (file)
@@ -138,7 +138,7 @@ struct KhompPvtFXO: public KhompPvt
 
         TriState _var_fax_adjust;
 
-        //ChanTimer::Index _idx_disconnect;        
+        ChanTimer::Index _busy_disconnect;        
     };
 /******************************************************************************/
     KhompPvtFXO(K3LAPIBase::GenericTarget & target) : KhompPvt(target) 
@@ -240,6 +240,7 @@ struct KhompPvtFXO: public KhompPvt
     bool autoGainControl(bool enable);
     void setAnswerInfo(int answer_info);
     bool indicateBusyUnlocked(int cause, bool sent_signaling = false);
+    static void busyDisconnect(Board::KhompPvt * pvt);
     void reportFailToReceive(int fail_code);
     bool validContexts(MatchExtension::ContextListType & contexts, 
                        std::string extra_context = "");
@@ -266,13 +267,20 @@ struct KhompPvtFXO: public KhompPvt
 
     virtual bool cleanup(CleanupType type = CLN_HARD)
     {
-        //Board::board(_target.device)->_timers.del(callFXO()->_idx_disconnect);
-        //callFXO()->_idx_disconnect.reset();
-        
+        try
+        {
+            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::EARLY_RINGBACK);
 
         _transfer->clear();
+        callFXO()->_busy_disconnect.reset();
 
         switch (type)
         {
@@ -312,6 +320,16 @@ struct KhompPvtFXO: public KhompPvt
 
 //    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);
+    }
 };
 /******************************************************************************/
 /******************************************************************************/
index 0267f33f24d1e5121e6043a188f838a0313d9f94..c32071b981c19738ac780313ee20d01279a23463 100644 (file)
@@ -272,24 +272,39 @@ struct KhompPvtISDN: public KhompPvtE1
 
         bool process(std::string name, std::string value = "")
         {
-            if (name == "uui")
+            if ((name == "uui" ) || (name == "uui_ex"))
             {
-                Strings::vector_type values;
-                Strings::tokenize(value, values, "#", 2);
-
-                try
+                if(value.find("#") != std::string::npos)
                 {
-                    std::string uui_proto_s = values[0];
-                    std::string uui_data_s = values[1];
+                    Strings::vector_type values;
+                    Strings::tokenize(value, values, "#", 2);
 
-                    _uui_descriptor = Strings::toulong(uui_proto_s);
-                    _uui_information.append(uui_data_s);
-
-                    DBG(FUNC, FMT("uui adjusted (%s, '%s')!") % uui_proto_s.c_str() % uui_data_s.c_str());
-                }
-                catch (...)
+                    try
+                    {
+                        std::string uui_proto_s = values[0];
+                        _uui_extended = (name == "uui_ex");
+                        _uui_descriptor = Strings::toulong(uui_proto_s);
+                        _uui_information.clear();
+
+                        for (unsigned int i = 0; i < values[1].size(); ++i) 
+                            _uui_information += STG(FMT("%02hhx") % ((unsigned char)values[1][i]));
+
+                        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")
@@ -306,6 +321,7 @@ struct KhompPvtISDN: public KhompPvtE1
     
         bool clear()
         {
+            _uui_extended = false;
             _uui_descriptor = -1;
             _uui_information.clear();
             _isdn_cause = -1;
@@ -322,6 +338,7 @@ struct KhompPvtISDN: public KhompPvtE1
         long int     _uui_descriptor;
         std::string  _uui_information;
         long int     _isdn_cause;
+        bool         _uui_extended;
 
         /* what should we dial to trigger an user-signaled transfer? */
         /* used for xfer on user signaling */
@@ -329,6 +346,13 @@ struct KhompPvtISDN: public KhompPvtE1
         std::string _user_xfer_buffer;
         std::string _digits_buffer;
         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);
 
+                setFSChannelVar("KUserInfoExtended", (callISDN()->_uui_extended ? "true" : "false"));
                 setFSChannelVar("KUserInfoDescriptor", descriptor.c_str());
                 setFSChannelVar("KUserInfoData", callISDN()->_uui_information.c_str());
 
+                callISDN()->_uui_extended = false; 
                 callISDN()->_uui_descriptor = -1;
                 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)
         {
@@ -444,8 +485,33 @@ struct KhompPvtISDN: public KhompPvtE1
         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 *********************************/
@@ -472,7 +538,6 @@ struct KhompPvtR2: public KhompPvtE1
                 {
                    LOG(ERROR, FMT("invalid r2 category: '%s' is not a number.") % value.c_str());
                 }
-
             }
             else
             {
@@ -554,7 +619,23 @@ struct KhompPvtR2: public KhompPvtE1
     {
         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 = "");
     bool doChannelAnswer(CommandRequest &); 
     bool doChannelHangup(CommandRequest &);
@@ -609,9 +690,9 @@ struct KhompPvtR2: public KhompPvtE1
             /* r2 caller category */
             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)
         {
@@ -834,9 +915,9 @@ struct KhompPvtFXS: public KhompPvt
             _ring_off_ext = -1;
 
             _incoming_exten.clear();
-            _flash_transfer.clear();
+            //_flash_transfer.clear();
 
-            _uuid_other_session.clear();
+            //_uuid_other_session.clear();
  
             return Call::clear();
         }
@@ -850,10 +931,10 @@ struct KhompPvtFXS: public KhompPvt
 
         std::string _incoming_exten;
         
-        ChanTimer::Index _idx_transfer;
+        //ChanTimer::Index _idx_transfer;
 
-        std::string _flash_transfer;
-        std::string _uuid_other_session;
+        //std::string _flash_transfer;
+        //std::string _uuid_other_session;
         
 
     };
@@ -936,9 +1017,9 @@ struct KhompPvtFXS: public KhompPvt
                        std::string extra_context = "");
     bool isOK(void);
 
-    bool startTransfer();
-    bool stopTransfer();
-    bool transfer(std::string & context, bool blind = false);
+    //bool startTransfer();
+    //bool stopTransfer();
+    //bool transfer(std::string & context, bool blind = false);
 
     bool hasNumberDial() { return false; }
     
@@ -996,7 +1077,7 @@ struct KhompPvtFXS: public KhompPvt
 
     static OrigToNseqMapType generateNseqMap();
     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)
     {
@@ -1015,21 +1096,16 @@ struct KhompPvtFXS: public KhompPvt
         return STG(FMT(STG(FMT("%%0%dd") % orig_size)) % (orig_numb + padding));
     }
 
-    /*
-    virtual void getSpecialVariables()
+    void cleanupIndications(bool force)
     {
-        try
+        if (call()->_indication == INDICA_BUSY && !force)
         {
-        }
-        catch(Board::KhompPvt::InvalidSwitchChannel & err)
-        {
-            LOG(ERROR, PVT_FMT(_target, "(FXS) %s") % err._msg.c_str());
+            DBG(FUNC, PVT_FMT(_target, "skipping busy indication cleanup on FXS channel."));
+            return;
         }
 
-        KhompPvt::getSpecialVariables();
+        KhompPvt::cleanupIndications(force);
     }
-    */
-
 };
 /******************************************************************************/
 /******************************************************************************/
index 270adc7068fb6061b5ec49bb5ab2a7b2ee40b964..4bc65361a6656dbbdb2371c9baf7b92b68a8d5f3 100644 (file)
@@ -108,10 +108,13 @@ struct Options
     Config::Value< bool > _recording;
     Config::Value< bool > _has_ctbus;
     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 > _ignore_letter_dtmfs;
     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< unsigned int > _fax_adjustment_timeout;
index b0ace1ad42dc4665df2e48fce17f508e08527c43..717124dda9c822f4a2b66ac0a7112f0dd509e8d3 100644 (file)
@@ -1 +1 @@
-#define MOD_KHOMP_VERSION "1.0 - (rev: 5891)"
+#define MOD_KHOMP_VERSION "1.0 - (rev: 6034)"
index 621afe6a206339d57324066a1786fe51c22d77b7..b5bcbdd9241af40d38d77b61f9ee2c544fdbb1a5 100644 (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 clear links [<board> [<link>]]\n"                                      \
 " khomp clear statistics [<board> [<channel>]]\n"                              \
+" khomp dump config\n"                                                         \
 " khomp get <option>\n"                                                        \
 " khomp kommuter {on|off}\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 */
 bool Cli::parseCommands(int argc, char *argv[])
 {
+    /*
+     * DEBUG_CLI_CMD();
+     */
+
     /* khomp summary */
     if (ARG_CMP(0, "summary"))
         return EXEC_CLI_CMD(Cli::KhompSummary);
@@ -163,7 +168,15 @@ bool Cli::parseCommands(int argc, char *argv[])
         if(ARG_CMP(1, "statistics"))
             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 */
     else if(ARG_CMP(0, "reset"))
     {
@@ -285,6 +298,7 @@ Cli::_KhompShowChannels       Cli::KhompShowChannels;
 Cli::_KhompShowLinks          Cli::KhompShowLinks;
 Cli::_KhompShowStatistics     Cli::KhompShowStatistics;
 Cli::_KhompClearLinks         Cli::KhompClearLinks;
+Cli::_KhompDumpConfig         Cli::KhompDumpConfig;
 Cli::_KhompClearStatistics    Cli::KhompClearStatistics;
 Cli::_KhompResetLinks         Cli::KhompResetLinks;
 Cli::_KhompChannelsDisconnect Cli::KhompChannelsDisconnect;
@@ -337,7 +351,9 @@ bool Cli::_KhompSummary::execute(int argc, char *argv[])
         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)
         {
@@ -376,6 +392,28 @@ bool Cli::_KhompSummary::execute(int argc, char *argv[])
                 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
 #define MOD_KHOMP_VERSION "unknown"
@@ -423,6 +461,20 @@ bool Cli::_KhompSummary::execute(int argc, char *argv[])
             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)
     {
         /* summary/board */
@@ -2154,6 +2206,38 @@ bool Cli::_KhompClearStatistics::execute(int argc, char *argv[])
     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)
 {
     try
@@ -2718,10 +2802,18 @@ bool Cli::_KhompSet::execute(int argc, char *argv[])
     try  
     {    
         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)
     {    
-        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;
@@ -2891,7 +2983,6 @@ bool Cli::_KhompSelectSim::execute(int argc, char *argv[])
             K::Logger::Logg2(C_CLI, stream, "ERROR: Unable to select sim card"); 
             return false;
         }
-
     }
     catch (Strings::invalid_value & e)
     {
index 15009f22865f593cf35e4ac6ea6b7cb20dfe6ccc..e093d685013f6cdc4ff9565474ab06af8a353a6c 100644 (file)
@@ -1119,12 +1119,7 @@ bool Board::KhompPvt::cleanup(CleanupType type)
         /* pára cadências e limpa estado das flags */
         stopCadence();
 
-        if (call()->_indication != INDICA_NONE)
-        {
-            call()->_indication = INDICA_NONE;
-
-            mixer(KHOMP_LOG, 1, kmsGenerator, kmtSilence);
-        }
+        cleanupIndications(true);
 
         if(call()->_input_volume >= -10 && call()->_input_volume <= 10)
             setVolume("input" , Opt::_options._input_volume());
@@ -1152,6 +1147,15 @@ bool Board::KhompPvt::cleanup(CleanupType type)
     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)
 {
     //DBG(FUNC, DP(this, "c"));
@@ -1168,28 +1172,6 @@ bool Board::KhompPvt::isFree(bool just_phy)
         if(session())
             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));
 
                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 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;
 }
 
@@ -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"));
 
     // get global filter configuration value
-    tmp_var = switch_core_get_variable_dup("KDropCollectCall");
+    tmp_var = getFSGlobalVar("KDropCollectCall");
     confvalues.push_back(getTriStateValue(tmp_var));
     DBG(FUNC, PVT_FMT(_target, "global KDropCollectCall was '%s'") % (tmp_var ? tmp_var : "(empty)"));
-       switch_safe_free(tmp_var);
+
+    freeFSGlobalVar(&tmp_var);
 
     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());   
 
     // Fire a custom event about this 
+    /* MUST USE THE NEW EVENT SYSTEM
     switch_event_t * event;
     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);
     }
+    */
+
     return true;
 }
 
index 0f7862dc194eebbeeba66a051e273807081c1b49..413a4e31790c1e62e18ef60ddbdfc4cf4d9b6555 100644 (file)
@@ -715,37 +715,47 @@ bool BoardFXO::KhompPvtFXO::indicateBusyUnlocked(int cause, bool sent_signaling)
 
     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)
         {
-            //we are talking about branches, not trunks 
+            /* we are talking about branches, not trunks */ 
             command(KHOMP_LOG, CM_CONNECT);
-            command(KHOMP_LOG, CM_DISCONNECT);
-        }
-        else
-        {
-            //already connected or sent signaling... 
-            mixer(KHOMP_LOG, 1, kmsGenerator, kmtBusy);
+            callFXO()->_busy_disconnect = Board::board(_target.device)->_timers.add(Opt::_options._fxo_busy_disconnection(), &BoardFXO::KhompPvtFXO::busyDisconnect, this);
         }
     }
     else if(call()->_flags.check(Kflags::IS_OUTGOING))
     {
-        //already connected or sent signaling... 
+        /* already connected or sent signaling... */
         mixer(KHOMP_LOG, 1, kmsGenerator, kmtBusy);
     }
 
     DBG(FUNC,PVT_FMT(_target, "(FXO) r"));
-    
     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)
 {
     KhompPvt::reportFailToReceive(fail_code);
 
     command(KHOMP_LOG, CM_CONNECT);
-
     command(KHOMP_LOG, CM_DISCONNECT);
-
 }
 
 bool BoardFXO::KhompPvtFXO::validContexts(
index 05020a0c5995e05b7fff0972ed887c92bc9fd5a9..a568c986c59ec3b1740cc7955ae4e92678dc4a88 100644 (file)
@@ -312,6 +312,9 @@ int BoardGSM::KhompPvtGSM::makeCall(std::string params)
         command(KHOMP_LOG, CM_DISABLE_CALL_ANSWER_INFO);
     }
 
+    if(!_call->_orig_addr.compare("restricted"))
+        params += " orig_addr=\"restricted\"";
+
     int ret = KhompPvt::makeCall(params);
 
     if(ret != ksSuccess)
index 997973b1df607a13ce66d163d0a18cba6177cb76..aaacd4ecba96a1192db1790f4c50a2aeb86b76cd 100644 (file)
@@ -372,18 +372,37 @@ bool BoardE1::onLinkStatus(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 */
-    callISDN()->_uui_information.clear();
+        if (info->UserInfoLength)
+        {    
+            /* 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)
-    {    
-        /* append to a clean string */
-        callISDN()->_uui_information.append((const char *)info->UserInfo, info->UserInfoLength);
-    }    
+        if (info->UserInfoLength)
+        {    
+            for (unsigned int i = 0; i < info->UserInfoLength; ++i) 
+                callISDN()->_uui_information += STG(FMT("%02hhx") % ((unsigned char) info->UserInfo[i]));
+        }    
+    }
 
     return true;
 }
@@ -440,15 +459,20 @@ bool BoardE1::KhompPvtISDN::onNewCall(K3L_EVENT *e)
     bool isdn_reverse_charge = false;
     std::string isdn_reverse_charge_str;
     bool ret;
-    
+   
     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 = Strings::toboolean(isdn_reverse_charge_str);
     }
     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)
     {
@@ -866,25 +890,84 @@ int BoardE1::KhompPvtISDN::makeCall(std::string params)
         DBG(FUNC,PVT_FMT(_target, "got userinfo"));   
 
         /* grab this information first, avoiding latter side-effects */
-        const char * info_data = call->_uui_information.c_str();
-        size_t       info_size = std::min(call->_uui_information.size(), (size_t)KMAX_USER_USER_LEN);
+        const bool        info_extd = call->_uui_extended;
+        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;
+    
+        if(info_extd)
+        {
+            KUserInformationEx info;
 
-        info.ProtocolDescriptor = call->_uui_descriptor;
-        info.UserInfoLength = info_size;
+            info.ProtocolDescriptor = info_desc;
+            info.UserInfoLength = info_size;
 
-        memcpy((void *) info.UserInfo, (const void *) info_data, 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))
+            if (!command(KHOMP_LOG, CM_USER_INFORMATION_EX, (const char *) &info))
+            {
+                LOG(ERROR,PVT_FMT(_target, "UUI could not be sent before dialing!"));   
+            }
+        } 
+        else
         {
-            LOG(ERROR,PVT_FMT(_target, "UUI could not be sent before dialing!"));   
+            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_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);
 
     call->_cleanup_upon_hangup = (ret == ksInvalidParams || ret == ksBusy);
@@ -995,12 +1078,6 @@ bool BoardE1::KhompPvtR2::doChannelAnswer(CommandRequest &cmd)
         // is this a 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?
         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)
         {       
             call()->_flags.clear(Kflags::NEEDS_RINGBACK_CMD);
+
+            //TODO: callFailFromCause ??
             std::string cause = ( do_drop_call ? STG(FMT("r2_cond_b=\"%d\"") % kgbBusy) : "" );
             command(KHOMP_LOG,CM_RINGBACK,cause.c_str());
 
             usleep(75000);
         }
 
-        if(!(do_drop_call && do_send_ring))
+        if(!do_drop_call)
         {
             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)
             {
-                usleep(75000);
-
-                DBG(FUNC, PVT_FMT(target(), "disconnecting collect call doChannelAnswer R2"));
-                command(KHOMP_LOG,CM_DISCONNECT);
-
                 // thou shalt not talk anymore!
                 stopListen();
                 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
             {
@@ -1797,6 +1882,8 @@ bool BoardE1::KhompPvtR2::onNewCall(K3L_EVENT *e)
                 DBG(FUNC,PVT_FMT(_target, "Setting DROP_COLLECT flag"));
             }
 
+            freeFSGlobalVar(&drop_str);            
+
             // keeping the hardcore mode
             if (do_drop_collect && call()->_collect_call)
             {
@@ -2388,6 +2475,7 @@ void BoardE1::KhompPvtFXS::dialTimer(KhompPvt * pvt)
 
 }
 
+/*
 void BoardE1::KhompPvtFXS::transferTimer(KhompPvt * pvt)
 {
     DBG(FUNC, PVT_FMT(pvt->target(), "c"));
@@ -2420,7 +2508,7 @@ void BoardE1::KhompPvtFXS::transferTimer(KhompPvt * pvt)
             return;
         }
 
-        /* begin context adjusting + processing */
+        // begin context adjusting + processing 
         MatchExtension::ContextListType contexts;
 
         pvt_fxs->validContexts(contexts);
@@ -2469,6 +2557,7 @@ void BoardE1::KhompPvtFXS::transferTimer(KhompPvt * pvt)
     DBG(FUNC, PVT_FMT(pvt->target(), "r"));
 
 }
+*/
 
 bool BoardE1::KhompPvtFXS::onChannelRelease(K3L_EVENT *e)
 {
@@ -2480,22 +2569,23 @@ bool BoardE1::KhompPvtFXS::onChannelRelease(K3L_EVENT *e)
     {
         ScopedPvtLock lock(this);
 
+        /*
         if(!callFXS()->_uuid_other_session.empty() && session())
         {
-            /*
-            switch_core_session_t *hold_session;
-
-            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_stop_broadcast(hold);
-                switch_channel_wait_for_flag(hold, CF_BROADCAST, SWITCH_FALSE, 5000, NULL);
-                switch_core_session_rwunlock(hold_session);
-            }
-            */
+            
+            //switch_core_session_t *hold_session;
+
+            //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_stop_broadcast(hold);
+            //    switch_channel_wait_for_flag(hold, CF_BROADCAST, SWITCH_FALSE, 5000, NULL);
+            //    switch_core_session_rwunlock(hold_session);
+            //}
+            
             try
             {
-                /* get other side of the bridge */
+                // get other side of the bridge 
                 switch_core_session_t * peer_session = getFSLockedPartnerSession();
                 unlockPartner(peer_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();
         }
+        */
 
         ret = KhompPvt::onChannelRelease(e);
 
@@ -2523,7 +2614,7 @@ bool BoardE1::KhompPvtFXS::onChannelRelease(K3L_EVENT *e)
     return ret;
  
 }
-
+/*
 bool BoardE1::KhompPvtFXS::startTransfer()
 {
     DBG(FUNC, PVT_FMT(target(), "c"));
@@ -2596,7 +2687,7 @@ bool BoardE1::KhompPvtFXS::stopTransfer()
 
     try
     {
-        /* get other side of the bridge */
+        // get other side of the bridge 
         switch_core_session_t * peer_session = getFSLockedPartnerSession();
         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) 
     {
         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
-        {
-            ScopedPvtLock lock(pvt);
+        //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;
+        //}
 
-            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();
+        //try
+        //{
+        //    ScopedPvtLock lock(pvt);
+
+        //    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;
@@ -2716,7 +2807,7 @@ bool BoardE1::KhompPvtFXS::transfer(std::string & context, bool blind)
 
     try
     {
-        /* get other side of the bridge */
+        // get other side of the bridge 
         switch_core_session_t * peer_session = getFSLockedPartnerSession();
         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);
             startCadence(PLAY_RINGBACK);
 
-            /*
-            try
-            {
-                call()->_idx_co_ring = Board::board(_target.device)->_timers.add(Opt::_options._ringback_co_delay(), &Board::KhompPvt::coRingGen,this);
-            }
-            catch (K3LAPITraits::invalid_device & err)
-            {
-                LOG(ERROR, PVT_FMT(_target, "unable to get device: %d!") % err.device);
-            }
-            */
+            
+            //try
+            //{
+            //    call()->_idx_co_ring = Board::board(_target.device)->_timers.add(Opt::_options._ringback_co_delay(), &Board::KhompPvt::coRingGen,this);
+            //}
+            //catch (K3LAPITraits::invalid_device & err)
+            //{
+             //   LOG(ERROR, PVT_FMT(_target, "unable to get device: %d!") % err.device);
+            //}
+            
         }
     }
     catch(Board::KhompPvt::InvalidSwitchChannel & err)
@@ -2796,6 +2887,7 @@ bool BoardE1::KhompPvtFXS::transfer(std::string & context, bool blind)
 
     return true;
 }
+*/
 
 bool BoardE1::KhompPvtFXS::onDtmfDetected(K3L_EVENT *e)
 {
@@ -2902,6 +2994,7 @@ bool BoardE1::KhompPvtFXS::onDtmfDetected(K3L_EVENT *e)
                     break;
             }
         }
+        /*
         else if(callFXS()->_flags.check(Kflags::FXS_OFFHOOK) &&
                 callFXS()->_flags.check(Kflags::FXS_FLASH_TRANSFER))
         {
@@ -2922,7 +3015,7 @@ bool BoardE1::KhompPvtFXS::onDtmfDetected(K3L_EVENT *e)
 
             callFXS()->_flash_transfer += e->AddInfo;
     
-            /* begin context adjusting + processing */
+            // begin context adjusting + processing
             MatchExtension::ContextListType contexts;
 
             validContexts(contexts);
@@ -2949,7 +3042,7 @@ bool BoardE1::KhompPvtFXS::onDtmfDetected(K3L_EVENT *e)
                 case MatchExtension::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++)
                     {
                         if (callFXS()->_flash_transfer == (*i))
@@ -2975,6 +3068,7 @@ bool BoardE1::KhompPvtFXS::onDtmfDetected(K3L_EVENT *e)
                 }
             }
         }
+        */
         else
         {
             ret = KhompPvt::onDtmfDetected(e);
@@ -3042,6 +3136,7 @@ bool BoardE1::KhompPvtFXS::onFlashDetected(K3L_EVENT *e)
 
 /******************************************************************************/
         //Old implementation, not used
+        /*
         if(callFXS()->_flags.check(Kflags::FXS_FLASH_TRANSFER))
         {
             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)"));
             return false;
         }
+        */
 /******************************************************************************/
 
     }
@@ -3207,7 +3303,8 @@ bool BoardE1::KhompPvtFXS::doChannelHangup(CommandRequest &cmd)
     try
     {
         ScopedPvtLock lock(this);
-        
+       
+        /*
         if(!callFXS()->_uuid_other_session.empty())
         {
             DBG(FUNC,PVT_FMT(_target, "unable to transfer"));
@@ -3225,6 +3322,7 @@ bool BoardE1::KhompPvtFXS::doChannelHangup(CommandRequest &cmd)
             }
             callFXS()->_uuid_other_session.clear();            
         }
+        */
 
         if (call()->_flags.check(Kflags::IS_INCOMING))
         {
index 8001bab6cffdc9adc79b8b76f5f3732798541edf..5de3fc52d29f887f08e6525202f50b3d8129b011 100644 (file)
@@ -75,11 +75,14 @@ void Opt::initialize(void)
        Globals::options.add(Config::Option("recording",           &Options::_recording,           true));
        Globals::options.add(Config::Option("has-ctbus",           &Options::_has_ctbus,           false));
        Globals::options.add(Config::Option("fxs-bina",            &Options::_fxs_bina,            true));
-       Globals::options.add(Config::Option("fxo-send-pre-audio",  &Options::_fxo_send_pre_audio,  true));
+       Globals::options.add(Config::Option("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("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("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("fax-adjustment-timeout", &Options::_fax_adjustment_timeout, 30u, 3u, 9999u));
 
index 85e46997d8982db98cedfc037c954ae943fcf56c..907708a70455d397f007655f43c5a64b093ccd0d 100644 (file)
@@ -78,8 +78,6 @@ static SpecRetType processSpecAtom(std::string & atom, SpecFlagsType & flags, Sp
                return processSpecAtoms(allocstr, flags, fun);
     }
 
-    //Regex::Expression e("(((([bB])[ ]*([0-9]+))|(([sS])[ ]*([0-9]+)))[ ]*(([cClL])[ ]*([0-9]+)[ ]*([-][ ]*([0-9]+))?)?)|(([rR])[ ]*([0-9]+)[ ]*([-][ ]*([0-9]+))?)", Regex::E_EXTENDED);
-
        Regex::Match what(allocstr, Globals::regex_allocation);
 
        if (!what.matched())
index 178ec0b993bc25e34b0235bdaeb87317ac0faebe..256ee54e3e67e4d2a10017dd80b89e55a5116cf2 100644 (file)
@@ -244,21 +244,26 @@ bool MatchExtension::canMatch(std::string & context, std::string & exten,
         return true;
     }
 
-    size_t finished = exten.find('#');
-
-    if(finished != std::string::npos)
+    if (Opt::_options._fxs_sharp_dial())
     {
-        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());
-            return true;
-        }
+            if(exten.size() <= 1)
+            {
+                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;
 
 /*