<p>Joshua Colp has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/16292">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">app_fax: Remove deprecated module.<br><br>ASTERISK-29587<br><br>Change-Id: I038237bbb56b1161d7d5e20cda11ed32e13d3ca2<br>---<br>D apps/app_fax.c<br>1 file changed, 0 insertions(+), 1,005 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/92/16292/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/apps/app_fax.c b/apps/app_fax.c</span><br><span>deleted file mode 100644</span><br><span>index 442df66..0000000</span><br><span>--- a/apps/app_fax.c</span><br><span>+++ /dev/null</span><br><span>@@ -1,1005 +0,0 @@</span><br><span style="color: hsl(0, 100%, 40%);">-/*</span><br><span style="color: hsl(0, 100%, 40%);">- * Asterisk -- An open source telephony toolkit.</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * Simple fax applications</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * 2007-2008, Dmitry Andrianov <asterisk@dima.spb.ru></span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * Code based on original implementation by Steve Underwood <steveu@coppice.org></span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * This program is free software, distributed under the terms of</span><br><span style="color: hsl(0, 100%, 40%);">- * the GNU General Public License</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*** MODULEINFO</span><br><span style="color: hsl(0, 100%, 40%);">-      <depend>spandsp</depend></span><br><span style="color: hsl(0, 100%, 40%);">-    <conflict>res_fax</conflict></span><br><span style="color: hsl(0, 100%, 40%);">-        <defaultenabled>no</defaultenabled></span><br><span style="color: hsl(0, 100%, 40%);">- <support_level>deprecated</support_level></span><br><span style="color: hsl(0, 100%, 40%);">-   <replacement>res_fax</replacement></span><br><span style="color: hsl(0, 100%, 40%);">-  <deprecated_in>16</deprecated_in></span><br><span style="color: hsl(0, 100%, 40%);">-   <removed_in>19</removed_in></span><br><span style="color: hsl(0, 100%, 40%);">-***/</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* Needed for spandsp headers */</span><br><span style="color: hsl(0, 100%, 40%);">-#define ASTMM_LIBC ASTMM_IGNORE</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk.h"</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#include <string.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <stdlib.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <stdio.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <inttypes.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <pthread.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <errno.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <tiffio.h></span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#define SPANDSP_EXPOSE_INTERNAL_STRUCTURES</span><br><span style="color: hsl(0, 100%, 40%);">-#include <spandsp.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <spandsp/version.h></span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/lock.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/file.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/logger.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/channel.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/pbx.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/app.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/dsp.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/module.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/stasis.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/stasis_channels.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/format_cache.h"</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*** DOCUMENTATION</span><br><span style="color: hsl(0, 100%, 40%);">-  <application name="SendFAX" language="en_US" module="app_fax"></span><br><span style="color: hsl(0, 100%, 40%);">-              <synopsis></span><br><span style="color: hsl(0, 100%, 40%);">-                        Send a Fax</span><br><span style="color: hsl(0, 100%, 40%);">-              </synopsis></span><br><span style="color: hsl(0, 100%, 40%);">-               <syntax></span><br><span style="color: hsl(0, 100%, 40%);">-                  <parameter name="filename" required="true"></span><br><span style="color: hsl(0, 100%, 40%);">-                           <para>Filename of TIFF file to fax</para></span><br><span style="color: hsl(0, 100%, 40%);">-                   </parameter></span><br><span style="color: hsl(0, 100%, 40%);">-                      <parameter name="a" required="false"></span><br><span style="color: hsl(0, 100%, 40%);">-                         <para>Makes the application behave as the answering machine</para></span><br><span style="color: hsl(0, 100%, 40%);">-                          <para>(Default behavior is as calling machine)</para></span><br><span style="color: hsl(0, 100%, 40%);">-                       </parameter></span><br><span style="color: hsl(0, 100%, 40%);">-              </syntax></span><br><span style="color: hsl(0, 100%, 40%);">-         <description></span><br><span style="color: hsl(0, 100%, 40%);">-                     <para>Send a given TIFF file to the channel as a FAX.</para></span><br><span style="color: hsl(0, 100%, 40%);">-                        <para>This application sets the following channel variables:</para></span><br><span style="color: hsl(0, 100%, 40%);">-                 <variablelist></span><br><span style="color: hsl(0, 100%, 40%);">-                            <variable name="LOCALSTATIONID"></span><br><span style="color: hsl(0, 100%, 40%);">-                                        <para>To identify itself to the remote end</para></span><br><span style="color: hsl(0, 100%, 40%);">-                           </variable></span><br><span style="color: hsl(0, 100%, 40%);">-                               <variable name="LOCALHEADERINFO"></span><br><span style="color: hsl(0, 100%, 40%);">-                                       <para>To generate a header line on each page</para></span><br><span style="color: hsl(0, 100%, 40%);">-                         </variable></span><br><span style="color: hsl(0, 100%, 40%);">-                               <variable name="FAXSTATUS"></span><br><span style="color: hsl(0, 100%, 40%);">-                                     <value name="SUCCESS"/></span><br><span style="color: hsl(0, 100%, 40%);">-                                 <value name="FAILED"/></span><br><span style="color: hsl(0, 100%, 40%);">-                          </variable></span><br><span style="color: hsl(0, 100%, 40%);">-                               <variable name="FAXERROR"></span><br><span style="color: hsl(0, 100%, 40%);">-                                      <para>Cause of failure</para></span><br><span style="color: hsl(0, 100%, 40%);">-                               </variable></span><br><span style="color: hsl(0, 100%, 40%);">-                               <variable name="REMOTESTATIONID"></span><br><span style="color: hsl(0, 100%, 40%);">-                                       <para>The CSID of the remote side</para></span><br><span style="color: hsl(0, 100%, 40%);">-                            </variable></span><br><span style="color: hsl(0, 100%, 40%);">-                               <variable name="FAXPAGES"></span><br><span style="color: hsl(0, 100%, 40%);">-                                      <para>Number of pages sent</para></span><br><span style="color: hsl(0, 100%, 40%);">-                           </variable></span><br><span style="color: hsl(0, 100%, 40%);">-                               <variable name="FAXBITRATE"></span><br><span style="color: hsl(0, 100%, 40%);">-                                    <para>Transmission rate</para></span><br><span style="color: hsl(0, 100%, 40%);">-                              </variable></span><br><span style="color: hsl(0, 100%, 40%);">-                               <variable name="FAXRESOLUTION"></span><br><span style="color: hsl(0, 100%, 40%);">-                                 <para>Resolution of sent fax</para></span><br><span style="color: hsl(0, 100%, 40%);">-                         </variable></span><br><span style="color: hsl(0, 100%, 40%);">-                       </variablelist></span><br><span style="color: hsl(0, 100%, 40%);">-           </description></span><br><span style="color: hsl(0, 100%, 40%);">-    </application></span><br><span style="color: hsl(0, 100%, 40%);">-    <application name="ReceiveFAX" language="en_US" module="app_fax"></span><br><span style="color: hsl(0, 100%, 40%);">-           <synopsis></span><br><span style="color: hsl(0, 100%, 40%);">-                        Receive a Fax</span><br><span style="color: hsl(0, 100%, 40%);">-           </synopsis></span><br><span style="color: hsl(0, 100%, 40%);">-               <syntax></span><br><span style="color: hsl(0, 100%, 40%);">-                  <parameter name="filename" required="true"></span><br><span style="color: hsl(0, 100%, 40%);">-                           <para>Filename of TIFF file save incoming fax</para></span><br><span style="color: hsl(0, 100%, 40%);">-                        </parameter></span><br><span style="color: hsl(0, 100%, 40%);">-                      <parameter name="c" required="false"></span><br><span style="color: hsl(0, 100%, 40%);">-                         <para>Makes the application behave as the calling machine</para></span><br><span style="color: hsl(0, 100%, 40%);">-                            <para>(Default behavior is as answering machine)</para></span><br><span style="color: hsl(0, 100%, 40%);">-                     </parameter></span><br><span style="color: hsl(0, 100%, 40%);">-              </syntax></span><br><span style="color: hsl(0, 100%, 40%);">-         <description></span><br><span style="color: hsl(0, 100%, 40%);">-                     <para>Receives a FAX from the channel into the given filename</span><br><span style="color: hsl(0, 100%, 40%);">-                     overwriting the file if it already exists.</para></span><br><span style="color: hsl(0, 100%, 40%);">-                 <para>File created will be in TIFF format.</para></span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-                   <para>This application sets the following channel variables:</para></span><br><span style="color: hsl(0, 100%, 40%);">-                 <variablelist></span><br><span style="color: hsl(0, 100%, 40%);">-                            <variable name="LOCALSTATIONID"></span><br><span style="color: hsl(0, 100%, 40%);">-                                        <para>To identify itself to the remote end</para></span><br><span style="color: hsl(0, 100%, 40%);">-                           </variable></span><br><span style="color: hsl(0, 100%, 40%);">-                               <variable name="LOCALHEADERINFO"></span><br><span style="color: hsl(0, 100%, 40%);">-                                       <para>To generate a header line on each page</para></span><br><span style="color: hsl(0, 100%, 40%);">-                         </variable></span><br><span style="color: hsl(0, 100%, 40%);">-                               <variable name="FAXSTATUS"></span><br><span style="color: hsl(0, 100%, 40%);">-                                     <value name="SUCCESS"/></span><br><span style="color: hsl(0, 100%, 40%);">-                                 <value name="FAILED"/></span><br><span style="color: hsl(0, 100%, 40%);">-                          </variable></span><br><span style="color: hsl(0, 100%, 40%);">-                               <variable name="FAXERROR"></span><br><span style="color: hsl(0, 100%, 40%);">-                                      <para>Cause of failure</para></span><br><span style="color: hsl(0, 100%, 40%);">-                               </variable></span><br><span style="color: hsl(0, 100%, 40%);">-                               <variable name="REMOTESTATIONID"></span><br><span style="color: hsl(0, 100%, 40%);">-                                       <para>The CSID of the remote side</para></span><br><span style="color: hsl(0, 100%, 40%);">-                            </variable></span><br><span style="color: hsl(0, 100%, 40%);">-                               <variable name="FAXPAGES"></span><br><span style="color: hsl(0, 100%, 40%);">-                                      <para>Number of pages sent</para></span><br><span style="color: hsl(0, 100%, 40%);">-                           </variable></span><br><span style="color: hsl(0, 100%, 40%);">-                               <variable name="FAXBITRATE"></span><br><span style="color: hsl(0, 100%, 40%);">-                                    <para>Transmission rate</para></span><br><span style="color: hsl(0, 100%, 40%);">-                              </variable></span><br><span style="color: hsl(0, 100%, 40%);">-                               <variable name="FAXRESOLUTION"></span><br><span style="color: hsl(0, 100%, 40%);">-                                 <para>Resolution of sent fax</para></span><br><span style="color: hsl(0, 100%, 40%);">-                         </variable></span><br><span style="color: hsl(0, 100%, 40%);">-                       </variablelist></span><br><span style="color: hsl(0, 100%, 40%);">-           </description></span><br><span style="color: hsl(0, 100%, 40%);">-    </application></span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- ***/</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static const char app_sndfax_name[] = "SendFAX";</span><br><span style="color: hsl(0, 100%, 40%);">-static const char app_rcvfax_name[] = "ReceiveFAX";</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#define MAX_SAMPLES 240</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* Watchdog. I have seen situations when remote fax disconnects (because of poor line</span><br><span style="color: hsl(0, 100%, 40%);">-   quality) while SpanDSP continues staying in T30_STATE_IV_CTC state forever.</span><br><span style="color: hsl(0, 100%, 40%);">-   To avoid this, we terminate when we see that T30 state does not change for 5 minutes.</span><br><span style="color: hsl(0, 100%, 40%);">-   We also terminate application when more than 30 minutes passed regardless of</span><br><span style="color: hsl(0, 100%, 40%);">-   state changes. This is just a precaution measure - no fax should take that long */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#define WATCHDOG_TOTAL_TIMEOUT    30 * 60</span><br><span style="color: hsl(0, 100%, 40%);">-#define WATCHDOG_STATE_TIMEOUT   5 * 60</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-typedef struct {</span><br><span style="color: hsl(0, 100%, 40%);">-  struct ast_channel *chan;</span><br><span style="color: hsl(0, 100%, 40%);">-       enum ast_t38_state t38state;    /* T38 state of the channel */</span><br><span style="color: hsl(0, 100%, 40%);">-  int direction;                  /* Fax direction: 0 - receiving, 1 - sending */</span><br><span style="color: hsl(0, 100%, 40%);">- int caller_mode;</span><br><span style="color: hsl(0, 100%, 40%);">-        char *file_name;</span><br><span style="color: hsl(0, 100%, 40%);">-        struct ast_control_t38_parameters t38parameters;</span><br><span style="color: hsl(0, 100%, 40%);">-        volatile int finished;</span><br><span style="color: hsl(0, 100%, 40%);">-} fax_session;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static void span_message(int level, const char *msg)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-       if (level == SPAN_LOG_ERROR) {</span><br><span style="color: hsl(0, 100%, 40%);">-          ast_log(LOG_ERROR, "%s", msg);</span><br><span style="color: hsl(0, 100%, 40%);">-        } else if (level == SPAN_LOG_WARNING) {</span><br><span style="color: hsl(0, 100%, 40%);">-         ast_log(LOG_WARNING, "%s", msg);</span><br><span style="color: hsl(0, 100%, 40%);">-      } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                ast_debug(1, "%s", msg);</span><br><span style="color: hsl(0, 100%, 40%);">-      }</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static int t38_tx_packet_handler(t38_core_state_t *s, void *user_data, const uint8_t *buf, int len, int count)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-       struct ast_channel *chan = (struct ast_channel *) user_data;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    struct ast_frame outf = {</span><br><span style="color: hsl(0, 100%, 40%);">-               .frametype = AST_FRAME_MODEM,</span><br><span style="color: hsl(0, 100%, 40%);">-           .subclass.integer = AST_MODEM_T38,</span><br><span style="color: hsl(0, 100%, 40%);">-              .src = __FUNCTION__,</span><br><span style="color: hsl(0, 100%, 40%);">-    };</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-      /* TODO: Asterisk does not provide means of resending the same packet multiple</span><br><span style="color: hsl(0, 100%, 40%);">-    times so count is ignored at the moment */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    AST_FRAME_SET_BUFFER(&outf, buf, 0, len);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-   if (ast_write(chan, &outf) < 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                ast_log(LOG_WARNING, "Unable to write frame to channel; %s\n", strerror(errno));</span><br><span style="color: hsl(0, 100%, 40%);">-              return -1;</span><br><span style="color: hsl(0, 100%, 40%);">-      }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static void phase_e_handler(t30_state_t *f, void *user_data, int result)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-     RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);</span><br><span style="color: hsl(0, 100%, 40%);">- RAII_VAR(struct ast_json *, json_filenames, NULL, ast_json_unref);</span><br><span style="color: hsl(0, 100%, 40%);">-      RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);</span><br><span style="color: hsl(0, 100%, 40%);">-  const char *local_ident;</span><br><span style="color: hsl(0, 100%, 40%);">-        const char *far_ident;</span><br><span style="color: hsl(0, 100%, 40%);">-  char buf[20];</span><br><span style="color: hsl(0, 100%, 40%);">-   fax_session *s = (fax_session *) user_data;</span><br><span style="color: hsl(0, 100%, 40%);">-     t30_stats_t stat;</span><br><span style="color: hsl(0, 100%, 40%);">-       int pages_transferred;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  ast_debug(1, "Fax phase E handler. result=%d\n", result);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     t30_get_transfer_statistics(f, &stat);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-      s = (fax_session *) user_data;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  if (result != T30_ERR_OK) {</span><br><span style="color: hsl(0, 100%, 40%);">-             s->finished = -1;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-            /* FAXSTATUS is already set to FAILED */</span><br><span style="color: hsl(0, 100%, 40%);">-                pbx_builtin_setvar_helper(s->chan, "FAXERROR", t30_completion_code_to_str(result));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-                ast_log(LOG_WARNING, "Error transmitting fax. result=%d: %s.\n", result, t30_completion_code_to_str(result));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-         return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       s->finished = 1;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     local_ident = S_OR(t30_get_tx_ident(f), "");</span><br><span style="color: hsl(0, 100%, 40%);">-  far_ident = S_OR(t30_get_rx_ident(f), "");</span><br><span style="color: hsl(0, 100%, 40%);">-    pbx_builtin_setvar_helper(s->chan, "FAXSTATUS", "SUCCESS");</span><br><span style="color: hsl(0, 100%, 40%);">-      pbx_builtin_setvar_helper(s->chan, "FAXERROR", NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-      pbx_builtin_setvar_helper(s->chan, "REMOTESTATIONID", far_ident);</span><br><span style="color: hsl(0, 100%, 40%);">-#if SPANDSP_RELEASE_DATE >= 20090220</span><br><span style="color: hsl(0, 100%, 40%);">-   pages_transferred = (s->direction) ? stat.pages_tx : stat.pages_rx;</span><br><span style="color: hsl(0, 100%, 40%);">-#else</span><br><span style="color: hsl(0, 100%, 40%);">-     pages_transferred = stat.pages_transferred;</span><br><span style="color: hsl(0, 100%, 40%);">-#endif</span><br><span style="color: hsl(0, 100%, 40%);">-       snprintf(buf, sizeof(buf), "%d", pages_transferred);</span><br><span style="color: hsl(0, 100%, 40%);">-  pbx_builtin_setvar_helper(s->chan, "FAXPAGES", buf);</span><br><span style="color: hsl(0, 100%, 40%);">-       snprintf(buf, sizeof(buf), "%d", stat.y_resolution);</span><br><span style="color: hsl(0, 100%, 40%);">-  pbx_builtin_setvar_helper(s->chan, "FAXRESOLUTION", buf);</span><br><span style="color: hsl(0, 100%, 40%);">-  snprintf(buf, sizeof(buf), "%d", stat.bit_rate);</span><br><span style="color: hsl(0, 100%, 40%);">-      pbx_builtin_setvar_helper(s->chan, "FAXBITRATE", buf);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     ast_debug(1, "Fax transmitted successfully.\n");</span><br><span style="color: hsl(0, 100%, 40%);">-      ast_debug(1, "  Remote station ID: %s\n", far_ident);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_debug(1, "  Pages transferred: %d\n", pages_transferred);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_debug(1, "  Image resolution:  %d x %d\n", stat.x_resolution, stat.y_resolution);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_debug(1, "  Transfer Rate:     %d\n", stat.bit_rate);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     json_filenames = ast_json_pack("[s]", s->file_name);</span><br><span style="color: hsl(0, 100%, 40%);">-       if (!json_filenames) {</span><br><span style="color: hsl(0, 100%, 40%);">-          return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-       ast_json_ref(json_filenames);</span><br><span style="color: hsl(0, 100%, 40%);">-   json_object = ast_json_pack("{s: s, s: s, s: s, s: i, s: i, s: i, s: o}",</span><br><span style="color: hsl(0, 100%, 40%);">-             "type", s->direction ? "send" : "receive",</span><br><span style="color: hsl(0, 100%, 40%);">-             "remote_station_id", AST_JSON_UTF8_VALIDATE(far_ident),</span><br><span style="color: hsl(0, 100%, 40%);">-               "local_station_id", AST_JSON_UTF8_VALIDATE(local_ident),</span><br><span style="color: hsl(0, 100%, 40%);">-              "fax_pages", pages_transferred,</span><br><span style="color: hsl(0, 100%, 40%);">-               "fax_resolution", stat.y_resolution,</span><br><span style="color: hsl(0, 100%, 40%);">-          "fax_bitrate", stat.bit_rate,</span><br><span style="color: hsl(0, 100%, 40%);">-         "filenames", json_filenames);</span><br><span style="color: hsl(0, 100%, 40%);">- message = ast_channel_blob_create_from_cache(ast_channel_uniqueid(s->chan), ast_channel_fax_type(), json_object);</span><br><span style="color: hsl(0, 100%, 40%);">-    if (!message) {</span><br><span style="color: hsl(0, 100%, 40%);">-         return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-       stasis_publish(ast_channel_topic(s->chan), message);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* === Helper functions to configure fax === */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* Setup SPAN logging according to Asterisk debug level */</span><br><span style="color: hsl(0, 100%, 40%);">-static int set_logging(logging_state_t *state)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-        int level = SPAN_LOG_WARNING + option_debug;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    span_log_set_message_handler(state, span_message);</span><br><span style="color: hsl(0, 100%, 40%);">-      span_log_set_level(state, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | level);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static void set_local_info(t30_state_t *state, fax_session *s)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-       const char *x;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  x = pbx_builtin_getvar_helper(s->chan, "LOCALSTATIONID");</span><br><span style="color: hsl(0, 100%, 40%);">-  if (!ast_strlen_zero(x))</span><br><span style="color: hsl(0, 100%, 40%);">-                t30_set_tx_ident(state, x);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     x = pbx_builtin_getvar_helper(s->chan, "LOCALHEADERINFO");</span><br><span style="color: hsl(0, 100%, 40%);">- if (!ast_strlen_zero(x))</span><br><span style="color: hsl(0, 100%, 40%);">-                t30_set_tx_page_header_info(state, x);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static void set_file(t30_state_t *state, fax_session *s)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-        if (s->direction)</span><br><span style="color: hsl(0, 100%, 40%);">-            t30_set_tx_file(state, s->file_name, -1, -1);</span><br><span style="color: hsl(0, 100%, 40%);">-        else</span><br><span style="color: hsl(0, 100%, 40%);">-            t30_set_rx_file(state, s->file_name, -1);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static void set_ecm(t30_state_t *state, int ecm)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-  t30_set_ecm_capability(state, ecm);</span><br><span style="color: hsl(0, 100%, 40%);">-     t30_set_supported_compressions(state, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* === Generator === */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* This function is only needed to return passed params so</span><br><span style="color: hsl(0, 100%, 40%);">-   generator_activate will save it to channel's generatordata */</span><br><span style="color: hsl(0, 100%, 40%);">-static void *fax_generator_alloc(struct ast_channel *chan, void *params)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-       return params;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static int fax_generator_generate(struct ast_channel *chan, void *data, int len, int samples)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-   fax_state_t *fax = (fax_state_t*) data;</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t buffer[AST_FRIENDLY_OFFSET + MAX_SAMPLES * sizeof(uint16_t)];</span><br><span style="color: hsl(0, 100%, 40%);">-   int16_t *buf = (int16_t *) (buffer + AST_FRIENDLY_OFFSET);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-      struct ast_frame outf = {</span><br><span style="color: hsl(0, 100%, 40%);">-               .frametype = AST_FRAME_VOICE,</span><br><span style="color: hsl(0, 100%, 40%);">-           .subclass.format = ast_format_slin,</span><br><span style="color: hsl(0, 100%, 40%);">-             .src = __FUNCTION__,</span><br><span style="color: hsl(0, 100%, 40%);">-    };</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-      if (samples > MAX_SAMPLES) {</span><br><span style="color: hsl(0, 100%, 40%);">-         ast_log(LOG_WARNING, "Only generating %d samples, where %d requested\n", MAX_SAMPLES, samples);</span><br><span style="color: hsl(0, 100%, 40%);">-               samples = MAX_SAMPLES;</span><br><span style="color: hsl(0, 100%, 40%);">-  }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       if ((len = fax_tx(fax, buf, samples)) > 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-         outf.samples = len;</span><br><span style="color: hsl(0, 100%, 40%);">-             AST_FRAME_SET_BUFFER(&outf, buffer, AST_FRIENDLY_OFFSET, len * sizeof(int16_t));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-            if (ast_write(chan, &outf) < 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                        ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", ast_channel_name(chan), strerror(errno));</span><br><span style="color: hsl(0, 100%, 40%);">-                 return -1;</span><br><span style="color: hsl(0, 100%, 40%);">-              }</span><br><span style="color: hsl(0, 100%, 40%);">-       }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static struct ast_generator generator = {</span><br><span style="color: hsl(0, 100%, 40%);">-     .alloc = fax_generator_alloc,</span><br><span style="color: hsl(0, 100%, 40%);">-   .generate = fax_generator_generate,</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* === Transmission === */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static int transmit_audio(fax_session *s)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-       int res = -1;</span><br><span style="color: hsl(0, 100%, 40%);">-   struct ast_format *original_read_fmt;</span><br><span style="color: hsl(0, 100%, 40%);">-   struct ast_format *original_write_fmt = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-   fax_state_t fax;</span><br><span style="color: hsl(0, 100%, 40%);">-        t30_state_t *t30state;</span><br><span style="color: hsl(0, 100%, 40%);">-  struct ast_frame *inf = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-   int last_state = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-     struct timeval now, start, state_change;</span><br><span style="color: hsl(0, 100%, 40%);">-        enum ast_t38_state t38_state;</span><br><span style="color: hsl(0, 100%, 40%);">-   struct ast_control_t38_parameters t38_parameters = { .version = 0,</span><br><span style="color: hsl(0, 100%, 40%);">-                                                           .max_ifp = 800,</span><br><span style="color: hsl(0, 100%, 40%);">-                                                         .rate = AST_T38_RATE_14400,</span><br><span style="color: hsl(0, 100%, 40%);">-                                                             .rate_management = AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF,</span><br><span style="color: hsl(0, 100%, 40%);">-                                                             .fill_bit_removal = 1,</span><br><span style="color: hsl(0, 100%, 40%);">-/*</span><br><span style="color: hsl(0, 100%, 40%);">- * spandsp has API calls to support MMR and JBIG transcoding, but they aren't</span><br><span style="color: hsl(0, 100%, 40%);">- * implemented quite yet... so don't offer them to the remote endpoint</span><br><span style="color: hsl(0, 100%, 40%);">- *                                                           .transcoding_mmr = 1,</span><br><span style="color: hsl(0, 100%, 40%);">- *                                                         .transcoding_jbig = 1,</span><br><span style="color: hsl(0, 100%, 40%);">-*/</span><br><span style="color: hsl(0, 100%, 40%);">-   };</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-      /* if in called party mode, try to use T.38 */</span><br><span style="color: hsl(0, 100%, 40%);">-  if (s->caller_mode == FALSE) {</span><br><span style="color: hsl(0, 100%, 40%);">-               /* check if we are already in T.38 mode (unlikely), or if we can request</span><br><span style="color: hsl(0, 100%, 40%);">-                 * a switch... if so, request it now and wait for the result, rather</span><br><span style="color: hsl(0, 100%, 40%);">-             * than starting an audio FAX session that will have to be cancelled</span><br><span style="color: hsl(0, 100%, 40%);">-             */</span><br><span style="color: hsl(0, 100%, 40%);">-             if ((t38_state = ast_channel_get_t38_state(s->chan)) == T38_STATE_NEGOTIATED) {</span><br><span style="color: hsl(0, 100%, 40%);">-                      return 1;</span><br><span style="color: hsl(0, 100%, 40%);">-               } else if ((t38_state != T38_STATE_UNAVAILABLE) &&</span><br><span style="color: hsl(0, 100%, 40%);">-                         (t38_parameters.request_response = AST_T38_REQUEST_NEGOTIATE,</span><br><span style="color: hsl(0, 100%, 40%);">-                            (ast_indicate_data(s->chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) == 0))) {</span><br><span style="color: hsl(0, 100%, 40%);">-                   /* wait up to five seconds for negotiation to complete */</span><br><span style="color: hsl(0, 100%, 40%);">-                       unsigned int timeout = 5000;</span><br><span style="color: hsl(0, 100%, 40%);">-                    int ms;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-                 ast_debug(1, "Negotiating T.38 for receive on %s\n", ast_channel_name(s->chan));</span><br><span style="color: hsl(0, 100%, 40%);">-                   while (timeout > 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                                ms = ast_waitfor(s->chan, 1000);</span><br><span style="color: hsl(0, 100%, 40%);">-                             if (ms < 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                                        ast_log(LOG_WARNING, "something bad happened while channel '%s' was polling.\n", ast_channel_name(s->chan));</span><br><span style="color: hsl(0, 100%, 40%);">-                                       return -1;</span><br><span style="color: hsl(0, 100%, 40%);">-                              }</span><br><span style="color: hsl(0, 100%, 40%);">-                               if (!ms) {</span><br><span style="color: hsl(0, 100%, 40%);">-                                      /* nothing happened */</span><br><span style="color: hsl(0, 100%, 40%);">-                                  if (timeout > 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                                           timeout -= 1000;</span><br><span style="color: hsl(0, 100%, 40%);">-                                                continue;</span><br><span style="color: hsl(0, 100%, 40%);">-                                       } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                                                ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 negotiation.\n", ast_channel_name(s->chan));</span><br><span style="color: hsl(0, 100%, 40%);">-                                          break;</span><br><span style="color: hsl(0, 100%, 40%);">-                                  }</span><br><span style="color: hsl(0, 100%, 40%);">-                               }</span><br><span style="color: hsl(0, 100%, 40%);">-                               if (!(inf = ast_read(s->chan))) {</span><br><span style="color: hsl(0, 100%, 40%);">-                                    return -1;</span><br><span style="color: hsl(0, 100%, 40%);">-                              }</span><br><span style="color: hsl(0, 100%, 40%);">-                               if ((inf->frametype == AST_FRAME_CONTROL) &&</span><br><span style="color: hsl(0, 100%, 40%);">-                             (inf->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&</span><br><span style="color: hsl(0, 100%, 40%);">-                             (inf->datalen == sizeof(t38_parameters))) {</span><br><span style="color: hsl(0, 100%, 40%);">-                                      struct ast_control_t38_parameters *parameters = inf->data.ptr;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-                                       switch (parameters->request_response) {</span><br><span style="color: hsl(0, 100%, 40%);">-                                      case AST_T38_NEGOTIATED:</span><br><span style="color: hsl(0, 100%, 40%);">-                                                ast_debug(1, "Negotiated T.38 for receive on %s\n", ast_channel_name(s->chan));</span><br><span style="color: hsl(0, 100%, 40%);">-                                            res = 1;</span><br><span style="color: hsl(0, 100%, 40%);">-                                                break;</span><br><span style="color: hsl(0, 100%, 40%);">-                                  case AST_T38_REFUSED:</span><br><span style="color: hsl(0, 100%, 40%);">-                                           ast_log(LOG_WARNING, "channel '%s' refused to negotiate T.38\n", ast_channel_name(s->chan));</span><br><span style="color: hsl(0, 100%, 40%);">-                                               break;</span><br><span style="color: hsl(0, 100%, 40%);">-                                  default:</span><br><span style="color: hsl(0, 100%, 40%);">-                                                ast_log(LOG_ERROR, "channel '%s' failed to negotiate T.38\n", ast_channel_name(s->chan));</span><br><span style="color: hsl(0, 100%, 40%);">-                                          break;</span><br><span style="color: hsl(0, 100%, 40%);">-                                  }</span><br><span style="color: hsl(0, 100%, 40%);">-                                       ast_frfree(inf);</span><br><span style="color: hsl(0, 100%, 40%);">-                                        if (res == 1) {</span><br><span style="color: hsl(0, 100%, 40%);">-                                         return 1;</span><br><span style="color: hsl(0, 100%, 40%);">-                                       } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                                                break;</span><br><span style="color: hsl(0, 100%, 40%);">-                                  }</span><br><span style="color: hsl(0, 100%, 40%);">-                               }</span><br><span style="color: hsl(0, 100%, 40%);">-                               ast_frfree(inf);</span><br><span style="color: hsl(0, 100%, 40%);">-                        }</span><br><span style="color: hsl(0, 100%, 40%);">-               }</span><br><span style="color: hsl(0, 100%, 40%);">-       }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#if SPANDSP_RELEASE_DATE >= 20080725</span><br><span style="color: hsl(0, 100%, 40%);">-        /* for spandsp shaphots 0.0.6 and higher */</span><br><span style="color: hsl(0, 100%, 40%);">-        t30state = &fax.t30;</span><br><span style="color: hsl(0, 100%, 40%);">-#else</span><br><span style="color: hsl(0, 100%, 40%);">-        /* for spandsp release 0.0.5 */</span><br><span style="color: hsl(0, 100%, 40%);">-        t30state = &fax.t30_state;</span><br><span style="color: hsl(0, 100%, 40%);">-#endif</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    original_read_fmt = ao2_bump(ast_channel_readformat(s->chan));</span><br><span style="color: hsl(0, 100%, 40%);">-        res = ast_set_read_format(s->chan, ast_format_slin);</span><br><span style="color: hsl(0, 100%, 40%);">- if (res < 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-               ast_log(LOG_WARNING, "Unable to set to linear read mode, giving up\n");</span><br><span style="color: hsl(0, 100%, 40%);">-               goto done;</span><br><span style="color: hsl(0, 100%, 40%);">-      }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       original_write_fmt = ao2_bump(ast_channel_writeformat(s->chan));</span><br><span style="color: hsl(0, 100%, 40%);">-     res = ast_set_write_format(s->chan, ast_format_slin);</span><br><span style="color: hsl(0, 100%, 40%);">-        if (res < 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-               ast_log(LOG_WARNING, "Unable to set to linear write mode, giving up\n");</span><br><span style="color: hsl(0, 100%, 40%);">-              goto done;</span><br><span style="color: hsl(0, 100%, 40%);">-      }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       /* Initialize T30 terminal */</span><br><span style="color: hsl(0, 100%, 40%);">-   fax_init(&fax, s->caller_mode);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  /* Setup logging */</span><br><span style="color: hsl(0, 100%, 40%);">-     set_logging(&fax.logging);</span><br><span style="color: hsl(0, 100%, 40%);">-  set_logging(&t30state->logging);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* Configure terminal */</span><br><span style="color: hsl(0, 100%, 40%);">-        set_local_info(t30state, s);</span><br><span style="color: hsl(0, 100%, 40%);">-    set_file(t30state, s);</span><br><span style="color: hsl(0, 100%, 40%);">-  set_ecm(t30state, TRUE);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        fax_set_transmit_on_idle(&fax, TRUE);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       t30_set_phase_e_handler(t30state, phase_e_handler, s);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  start = state_change = ast_tvnow();</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     ast_activate_generator(s->chan, &generator, &fax);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-   while (!s->finished) {</span><br><span style="color: hsl(0, 100%, 40%);">-               inf = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-             if ((res = ast_waitfor(s->chan, 25)) < 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                       ast_debug(1, "Error waiting for a frame\n");</span><br><span style="color: hsl(0, 100%, 40%);">-                  break;</span><br><span style="color: hsl(0, 100%, 40%);">-          }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-               /* Watchdog */</span><br><span style="color: hsl(0, 100%, 40%);">-          now = ast_tvnow();</span><br><span style="color: hsl(0, 100%, 40%);">-              if (ast_tvdiff_sec(now, start) > WATCHDOG_TOTAL_TIMEOUT || ast_tvdiff_sec(now, state_change) > WATCHDOG_STATE_TIMEOUT) {</span><br><span style="color: hsl(0, 100%, 40%);">-                  ast_log(LOG_WARNING, "It looks like we hung. Aborting.\n");</span><br><span style="color: hsl(0, 100%, 40%);">-                   res = -1;</span><br><span style="color: hsl(0, 100%, 40%);">-                       break;</span><br><span style="color: hsl(0, 100%, 40%);">-          }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-               if (!res) {</span><br><span style="color: hsl(0, 100%, 40%);">-                     /* There was timeout waiting for a frame. Loop around and wait again */</span><br><span style="color: hsl(0, 100%, 40%);">-                 continue;</span><br><span style="color: hsl(0, 100%, 40%);">-               }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-               /* There is a frame available. Get it */</span><br><span style="color: hsl(0, 100%, 40%);">-                res = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-                if (!(inf = ast_read(s->chan))) {</span><br><span style="color: hsl(0, 100%, 40%);">-                    ast_debug(1, "Channel hangup\n");</span><br><span style="color: hsl(0, 100%, 40%);">-                     res = -1;</span><br><span style="color: hsl(0, 100%, 40%);">-                       break;</span><br><span style="color: hsl(0, 100%, 40%);">-          }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-               ast_debug(10, "frame %d/%s, len=%d\n", inf->frametype, ast_format_get_name(inf->subclass.format), inf->datalen);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-             /* Check the frame type. Format also must be checked because there is a chance</span><br><span style="color: hsl(0, 100%, 40%);">-             that a frame in old format was already queued before we set channel format</span><br><span style="color: hsl(0, 100%, 40%);">-              to slinear so it will still be received by ast_read */</span><br><span style="color: hsl(0, 100%, 40%);">-               if (inf->frametype == AST_FRAME_VOICE &&</span><br><span style="color: hsl(0, 100%, 40%);">-                     (ast_format_cmp(inf->subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL)) {</span><br><span style="color: hsl(0, 100%, 40%);">-                   if (fax_rx(&fax, inf->data.ptr, inf->samples) < 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                               /* I know fax_rx never returns errors. The check here is for good style only */</span><br><span style="color: hsl(0, 100%, 40%);">-                         ast_log(LOG_WARNING, "fax_rx returned error\n");</span><br><span style="color: hsl(0, 100%, 40%);">-                              res = -1;</span><br><span style="color: hsl(0, 100%, 40%);">-                               break;</span><br><span style="color: hsl(0, 100%, 40%);">-                  }</span><br><span style="color: hsl(0, 100%, 40%);">-                       if (last_state != t30state->state) {</span><br><span style="color: hsl(0, 100%, 40%);">-                         state_change = ast_tvnow();</span><br><span style="color: hsl(0, 100%, 40%);">-                             last_state = t30state->state;</span><br><span style="color: hsl(0, 100%, 40%);">-                        }</span><br><span style="color: hsl(0, 100%, 40%);">-               } else if ((inf->frametype == AST_FRAME_CONTROL) &&</span><br><span style="color: hsl(0, 100%, 40%);">-                     (inf->subclass.integer == AST_CONTROL_T38_PARAMETERS)) {</span><br><span style="color: hsl(0, 100%, 40%);">-                  struct ast_control_t38_parameters *parameters = inf->data.ptr;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-                       if (parameters->request_response == AST_T38_NEGOTIATED) {</span><br><span style="color: hsl(0, 100%, 40%);">-                            /* T38 switchover completed */</span><br><span style="color: hsl(0, 100%, 40%);">-                          s->t38parameters = *parameters;</span><br><span style="color: hsl(0, 100%, 40%);">-                              ast_debug(1, "T38 negotiated, finishing audio loop\n");</span><br><span style="color: hsl(0, 100%, 40%);">-                               res = 1;</span><br><span style="color: hsl(0, 100%, 40%);">-                                break;</span><br><span style="color: hsl(0, 100%, 40%);">-                  } else if (parameters->request_response == AST_T38_REQUEST_NEGOTIATE) {</span><br><span style="color: hsl(0, 100%, 40%);">-                              t38_parameters.request_response = AST_T38_NEGOTIATED;</span><br><span style="color: hsl(0, 100%, 40%);">-                           ast_debug(1, "T38 request received, accepting\n");</span><br><span style="color: hsl(0, 100%, 40%);">-                            /* Complete T38 switchover */</span><br><span style="color: hsl(0, 100%, 40%);">-                           ast_indicate_data(s->chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));</span><br><span style="color: hsl(0, 100%, 40%);">-                         /* Do not break audio loop, wait until channel driver finally acks switchover</span><br><span style="color: hsl(0, 100%, 40%);">-                            * with AST_T38_NEGOTIATED</span><br><span style="color: hsl(0, 100%, 40%);">-                               */</span><br><span style="color: hsl(0, 100%, 40%);">-                     }</span><br><span style="color: hsl(0, 100%, 40%);">-               }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-               ast_frfree(inf);</span><br><span style="color: hsl(0, 100%, 40%);">-                inf = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-     }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       ast_debug(1, "Loop finished, res=%d\n", res);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (inf)</span><br><span style="color: hsl(0, 100%, 40%);">-                ast_frfree(inf);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        ast_deactivate_generator(s->chan);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-   /* If we are switching to T38, remove phase E handler. Otherwise it will be executed</span><br><span style="color: hsl(0, 100%, 40%);">-       by t30_terminate, display diagnostics and set status variables although no transmittion</span><br><span style="color: hsl(0, 100%, 40%);">-         has taken place yet. */</span><br><span style="color: hsl(0, 100%, 40%);">-      if (res > 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-               t30_set_phase_e_handler(t30state, NULL, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-  }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       t30_terminate(t30state);</span><br><span style="color: hsl(0, 100%, 40%);">-        fax_release(&fax);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-done:</span><br><span style="color: hsl(0, 100%, 40%);">-     if (original_write_fmt) {</span><br><span style="color: hsl(0, 100%, 40%);">-               if (ast_set_write_format(s->chan, original_write_fmt) < 0)</span><br><span style="color: hsl(0, 100%, 40%);">-                        ast_log(LOG_WARNING, "Unable to restore write format on '%s'\n", ast_channel_name(s->chan));</span><br><span style="color: hsl(0, 100%, 40%);">-               ao2_ref(original_write_fmt, -1);</span><br><span style="color: hsl(0, 100%, 40%);">-        }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       if (original_read_fmt) {</span><br><span style="color: hsl(0, 100%, 40%);">-                if (ast_set_read_format(s->chan, original_read_fmt) < 0)</span><br><span style="color: hsl(0, 100%, 40%);">-                  ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", ast_channel_name(s->chan));</span><br><span style="color: hsl(0, 100%, 40%);">-                ao2_ref(original_read_fmt, -1);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       return res;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static int transmit_t38(fax_session *s)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-    int res = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-    t38_terminal_state_t t38;</span><br><span style="color: hsl(0, 100%, 40%);">-       struct ast_frame *inf = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-   int last_state = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-     struct timeval now, start, state_change, last_frame;</span><br><span style="color: hsl(0, 100%, 40%);">-    t30_state_t *t30state;</span><br><span style="color: hsl(0, 100%, 40%);">-  t38_core_state_t *t38state;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#if SPANDSP_RELEASE_DATE >= 20080725</span><br><span style="color: hsl(0, 100%, 40%);">-      /* for spandsp shaphots 0.0.6 and higher */</span><br><span style="color: hsl(0, 100%, 40%);">-     t30state = &t38.t30;</span><br><span style="color: hsl(0, 100%, 40%);">-        t38state = &t38.t38_fe.t38;</span><br><span style="color: hsl(0, 100%, 40%);">-#else</span><br><span style="color: hsl(0, 100%, 40%);">-    /* for spandsp releases 0.0.5 */</span><br><span style="color: hsl(0, 100%, 40%);">-        t30state = &t38.t30_state;</span><br><span style="color: hsl(0, 100%, 40%);">-  t38state = &t38.t38;</span><br><span style="color: hsl(0, 100%, 40%);">-#endif</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  /* Initialize terminal */</span><br><span style="color: hsl(0, 100%, 40%);">-       memset(&t38, 0, sizeof(t38));</span><br><span style="color: hsl(0, 100%, 40%);">-       if (t38_terminal_init(&t38, s->caller_mode, t38_tx_packet_handler, s->chan) == NULL) {</span><br><span style="color: hsl(0, 100%, 40%);">-                ast_log(LOG_WARNING, "Unable to start T.38 termination.\n");</span><br><span style="color: hsl(0, 100%, 40%);">-          res = -1;</span><br><span style="color: hsl(0, 100%, 40%);">-               goto disable_t38;</span><br><span style="color: hsl(0, 100%, 40%);">-       }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       t38_set_max_datagram_size(t38state, s->t38parameters.max_ifp);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       if (s->t38parameters.fill_bit_removal) {</span><br><span style="color: hsl(0, 100%, 40%);">-             t38_set_fill_bit_removal(t38state, TRUE);</span><br><span style="color: hsl(0, 100%, 40%);">-       }</span><br><span style="color: hsl(0, 100%, 40%);">-       if (s->t38parameters.transcoding_mmr) {</span><br><span style="color: hsl(0, 100%, 40%);">-              t38_set_mmr_transcoding(t38state, TRUE);</span><br><span style="color: hsl(0, 100%, 40%);">-        }</span><br><span style="color: hsl(0, 100%, 40%);">-       if (s->t38parameters.transcoding_jbig) {</span><br><span style="color: hsl(0, 100%, 40%);">-             t38_set_jbig_transcoding(t38state, TRUE);</span><br><span style="color: hsl(0, 100%, 40%);">-       }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       /* Setup logging */</span><br><span style="color: hsl(0, 100%, 40%);">-     set_logging(&t38.logging);</span><br><span style="color: hsl(0, 100%, 40%);">-  set_logging(&t30state->logging);</span><br><span style="color: hsl(0, 100%, 40%);">- set_logging(&t38state->logging);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* Configure terminal */</span><br><span style="color: hsl(0, 100%, 40%);">-        set_local_info(t30state, s);</span><br><span style="color: hsl(0, 100%, 40%);">-    set_file(t30state, s);</span><br><span style="color: hsl(0, 100%, 40%);">-  set_ecm(t30state, TRUE);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        t30_set_phase_e_handler(t30state, phase_e_handler, s);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  now = start = state_change = ast_tvnow();</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       while (!s->finished) {</span><br><span style="color: hsl(0, 100%, 40%);">-               inf = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-             if ((res = ast_waitfor(s->chan, 25)) < 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                       ast_debug(1, "Error waiting for a frame\n");</span><br><span style="color: hsl(0, 100%, 40%);">-                  break;</span><br><span style="color: hsl(0, 100%, 40%);">-          }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-               last_frame = now;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-               /* Watchdog */</span><br><span style="color: hsl(0, 100%, 40%);">-          now = ast_tvnow();</span><br><span style="color: hsl(0, 100%, 40%);">-              if (ast_tvdiff_sec(now, start) > WATCHDOG_TOTAL_TIMEOUT || ast_tvdiff_sec(now, state_change) > WATCHDOG_STATE_TIMEOUT) {</span><br><span style="color: hsl(0, 100%, 40%);">-                  ast_log(LOG_WARNING, "It looks like we hung. Aborting.\n");</span><br><span style="color: hsl(0, 100%, 40%);">-                   res = -1;</span><br><span style="color: hsl(0, 100%, 40%);">-                       break;</span><br><span style="color: hsl(0, 100%, 40%);">-          }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-               t38_terminal_send_timeout(&t38, ast_tvdiff_us(now, last_frame) / (1000000 / 8000));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-         if (!res) {</span><br><span style="color: hsl(0, 100%, 40%);">-                     /* There was timeout waiting for a frame. Loop around and wait again */</span><br><span style="color: hsl(0, 100%, 40%);">-                 continue;</span><br><span style="color: hsl(0, 100%, 40%);">-               }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-               /* There is a frame available. Get it */</span><br><span style="color: hsl(0, 100%, 40%);">-                res = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-                if (!(inf = ast_read(s->chan))) {</span><br><span style="color: hsl(0, 100%, 40%);">-                    ast_debug(1, "Channel hangup\n");</span><br><span style="color: hsl(0, 100%, 40%);">-                     res = -1;</span><br><span style="color: hsl(0, 100%, 40%);">-                       break;</span><br><span style="color: hsl(0, 100%, 40%);">-          }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-               ast_debug(10, "frame %d/%d, len=%d\n", inf->frametype, inf->subclass.integer, inf->datalen);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-         if (inf->frametype == AST_FRAME_MODEM && inf->subclass.integer == AST_MODEM_T38) {</span><br><span style="color: hsl(0, 100%, 40%);">-                        t38_core_rx_ifp_packet(t38state, inf->data.ptr, inf->datalen, inf->seqno);</span><br><span style="color: hsl(0, 100%, 40%);">-                     if (last_state != t30state->state) {</span><br><span style="color: hsl(0, 100%, 40%);">-                         state_change = ast_tvnow();</span><br><span style="color: hsl(0, 100%, 40%);">-                             last_state = t30state->state;</span><br><span style="color: hsl(0, 100%, 40%);">-                        }</span><br><span style="color: hsl(0, 100%, 40%);">-               } else if (inf->frametype == AST_FRAME_CONTROL && inf->subclass.integer == AST_CONTROL_T38_PARAMETERS) {</span><br><span style="color: hsl(0, 100%, 40%);">-                  struct ast_control_t38_parameters *parameters = inf->data.ptr;</span><br><span style="color: hsl(0, 100%, 40%);">-                       if (parameters->request_response == AST_T38_TERMINATED) {</span><br><span style="color: hsl(0, 100%, 40%);">-                            ast_debug(1, "T38 down, finishing\n");</span><br><span style="color: hsl(0, 100%, 40%);">-                                break;</span><br><span style="color: hsl(0, 100%, 40%);">-                  }</span><br><span style="color: hsl(0, 100%, 40%);">-               }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-               ast_frfree(inf);</span><br><span style="color: hsl(0, 100%, 40%);">-                inf = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-     }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       ast_debug(1, "Loop finished, res=%d\n", res);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (inf)</span><br><span style="color: hsl(0, 100%, 40%);">-                ast_frfree(inf);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        t30_terminate(t30state);</span><br><span style="color: hsl(0, 100%, 40%);">-        t38_terminal_release(&t38);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-disable_t38:</span><br><span style="color: hsl(0, 100%, 40%);">-     /* if we are not the caller, it's our job to shut down the T.38</span><br><span style="color: hsl(0, 100%, 40%);">-      * session when the FAX transmisson is complete.</span><br><span style="color: hsl(0, 100%, 40%);">-         */</span><br><span style="color: hsl(0, 100%, 40%);">-     if ((s->caller_mode == FALSE) &&</span><br><span style="color: hsl(0, 100%, 40%);">-         (ast_channel_get_t38_state(s->chan) == T38_STATE_NEGOTIATED)) {</span><br><span style="color: hsl(0, 100%, 40%);">-          struct ast_control_t38_parameters t38_parameters = { .request_response = AST_T38_REQUEST_TERMINATE, };</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-          if (ast_indicate_data(s->chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) == 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                      /* wait up to five seconds for negotiation to complete */</span><br><span style="color: hsl(0, 100%, 40%);">-                       unsigned int timeout = 5000;</span><br><span style="color: hsl(0, 100%, 40%);">-                    int ms;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-                 ast_debug(1, "Shutting down T.38 on %s\n", ast_channel_name(s->chan));</span><br><span style="color: hsl(0, 100%, 40%);">-                     while (timeout > 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                                ms = ast_waitfor(s->chan, 1000);</span><br><span style="color: hsl(0, 100%, 40%);">-                             if (ms < 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                                        ast_log(LOG_WARNING, "something bad happened while channel '%s' was polling.\n", ast_channel_name(s->chan));</span><br><span style="color: hsl(0, 100%, 40%);">-                                       return -1;</span><br><span style="color: hsl(0, 100%, 40%);">-                              }</span><br><span style="color: hsl(0, 100%, 40%);">-                               if (!ms) {</span><br><span style="color: hsl(0, 100%, 40%);">-                                      /* nothing happened */</span><br><span style="color: hsl(0, 100%, 40%);">-                                  if (timeout > 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                                           timeout -= 1000;</span><br><span style="color: hsl(0, 100%, 40%);">-                                                continue;</span><br><span style="color: hsl(0, 100%, 40%);">-                                       } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                                                ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 shutdown.\n", ast_channel_name(s->chan));</span><br><span style="color: hsl(0, 100%, 40%);">-                                             break;</span><br><span style="color: hsl(0, 100%, 40%);">-                                  }</span><br><span style="color: hsl(0, 100%, 40%);">-                               }</span><br><span style="color: hsl(0, 100%, 40%);">-                               if (!(inf = ast_read(s->chan))) {</span><br><span style="color: hsl(0, 100%, 40%);">-                                    return -1;</span><br><span style="color: hsl(0, 100%, 40%);">-                              }</span><br><span style="color: hsl(0, 100%, 40%);">-                               if ((inf->frametype == AST_FRAME_CONTROL) &&</span><br><span style="color: hsl(0, 100%, 40%);">-                             (inf->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&</span><br><span style="color: hsl(0, 100%, 40%);">-                             (inf->datalen == sizeof(t38_parameters))) {</span><br><span style="color: hsl(0, 100%, 40%);">-                                      struct ast_control_t38_parameters *parameters = inf->data.ptr;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-                                       switch (parameters->request_response) {</span><br><span style="color: hsl(0, 100%, 40%);">-                                      case AST_T38_TERMINATED:</span><br><span style="color: hsl(0, 100%, 40%);">-                                                ast_debug(1, "Shut down T.38 on %s\n", ast_channel_name(s->chan));</span><br><span style="color: hsl(0, 100%, 40%);">-                                         break;</span><br><span style="color: hsl(0, 100%, 40%);">-                                  case AST_T38_REFUSED:</span><br><span style="color: hsl(0, 100%, 40%);">-                                           ast_log(LOG_WARNING, "channel '%s' refused to disable T.38\n", ast_channel_name(s->chan));</span><br><span style="color: hsl(0, 100%, 40%);">-                                         break;</span><br><span style="color: hsl(0, 100%, 40%);">-                                  default:</span><br><span style="color: hsl(0, 100%, 40%);">-                                                ast_log(LOG_ERROR, "channel '%s' failed to disable T.38\n", ast_channel_name(s->chan));</span><br><span style="color: hsl(0, 100%, 40%);">-                                            break;</span><br><span style="color: hsl(0, 100%, 40%);">-                                  }</span><br><span style="color: hsl(0, 100%, 40%);">-                                       ast_frfree(inf);</span><br><span style="color: hsl(0, 100%, 40%);">-                                        break;</span><br><span style="color: hsl(0, 100%, 40%);">-                          }</span><br><span style="color: hsl(0, 100%, 40%);">-                               ast_frfree(inf);</span><br><span style="color: hsl(0, 100%, 40%);">-                        }</span><br><span style="color: hsl(0, 100%, 40%);">-               }</span><br><span style="color: hsl(0, 100%, 40%);">-       }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       return res;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static int transmit(fax_session *s)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-        int res = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    /* Clear all channel variables which to be set by the application.</span><br><span style="color: hsl(0, 100%, 40%);">-         Pre-set status to error so in case of any problems we can just leave */</span><br><span style="color: hsl(0, 100%, 40%);">-      pbx_builtin_setvar_helper(s->chan, "FAXSTATUS", "FAILED");</span><br><span style="color: hsl(0, 100%, 40%);">-       pbx_builtin_setvar_helper(s->chan, "FAXERROR", "Channel problems");</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-      pbx_builtin_setvar_helper(s->chan, "FAXMODE", NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-       pbx_builtin_setvar_helper(s->chan, "REMOTESTATIONID", NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-       pbx_builtin_setvar_helper(s->chan, "FAXPAGES", "0");</span><br><span style="color: hsl(0, 100%, 40%);">-     pbx_builtin_setvar_helper(s->chan, "FAXRESOLUTION", NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- pbx_builtin_setvar_helper(s->chan, "FAXBITRATE", NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    if (ast_channel_state(s->chan) != AST_STATE_UP) {</span><br><span style="color: hsl(0, 100%, 40%);">-            /* Shouldn't need this, but checking to see if channel is already answered</span><br><span style="color: hsl(0, 100%, 40%);">-           * Theoretically asterisk should already have answered before running the app */</span><br><span style="color: hsl(0, 100%, 40%);">-                res = ast_answer(s->chan);</span><br><span style="color: hsl(0, 100%, 40%);">-           if (res) {</span><br><span style="color: hsl(0, 100%, 40%);">-                      ast_log(LOG_WARNING, "Could not answer channel '%s'\n", ast_channel_name(s->chan));</span><br><span style="color: hsl(0, 100%, 40%);">-                        return res;</span><br><span style="color: hsl(0, 100%, 40%);">-             }</span><br><span style="color: hsl(0, 100%, 40%);">-       }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       s->t38state = ast_channel_get_t38_state(s->chan);</span><br><span style="color: hsl(0, 100%, 40%);">- if (s->t38state != T38_STATE_NEGOTIATED) {</span><br><span style="color: hsl(0, 100%, 40%);">-           /* T38 is not negotiated on the channel yet. First start regular transmission. If it switches to T38, follow */</span><br><span style="color: hsl(0, 100%, 40%);">-         pbx_builtin_setvar_helper(s->chan, "FAXMODE", "audio");</span><br><span style="color: hsl(0, 100%, 40%);">-          res = transmit_audio(s);</span><br><span style="color: hsl(0, 100%, 40%);">-                if (res > 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-                       /* transmit_audio reports switchover to T38. Update t38state */</span><br><span style="color: hsl(0, 100%, 40%);">-                 s->t38state = ast_channel_get_t38_state(s->chan);</span><br><span style="color: hsl(0, 100%, 40%);">-                 if (s->t38state != T38_STATE_NEGOTIATED) {</span><br><span style="color: hsl(0, 100%, 40%);">-                           ast_log(LOG_ERROR, "Audio loop reports T38 switchover but t38state != T38_STATE_NEGOTIATED\n");</span><br><span style="color: hsl(0, 100%, 40%);">-                       }</span><br><span style="color: hsl(0, 100%, 40%);">-               }</span><br><span style="color: hsl(0, 100%, 40%);">-       }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       if (s->t38state == T38_STATE_NEGOTIATED) {</span><br><span style="color: hsl(0, 100%, 40%);">-           pbx_builtin_setvar_helper(s->chan, "FAXMODE", "T38");</span><br><span style="color: hsl(0, 100%, 40%);">-            res = transmit_t38(s);</span><br><span style="color: hsl(0, 100%, 40%);">-  }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       if (res) {</span><br><span style="color: hsl(0, 100%, 40%);">-              ast_log(LOG_WARNING, "Transmission error\n");</span><br><span style="color: hsl(0, 100%, 40%);">-         res = -1;</span><br><span style="color: hsl(0, 100%, 40%);">-       } else if (s->finished < 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-             ast_log(LOG_WARNING, "Transmission failed\n");</span><br><span style="color: hsl(0, 100%, 40%);">-        } else if (s->finished > 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-             ast_debug(1, "Transmission finished Ok\n");</span><br><span style="color: hsl(0, 100%, 40%);">-   }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       return res;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* === Application functions === */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static int sndfax_exec(struct ast_channel *chan, const char *data)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-      int res = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-    char *parse;</span><br><span style="color: hsl(0, 100%, 40%);">-    fax_session session = { 0, };</span><br><span style="color: hsl(0, 100%, 40%);">-   char restore_digit_detect = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  AST_DECLARE_APP_ARGS(args,</span><br><span style="color: hsl(0, 100%, 40%);">-              AST_APP_ARG(file_name);</span><br><span style="color: hsl(0, 100%, 40%);">-         AST_APP_ARG(options);</span><br><span style="color: hsl(0, 100%, 40%);">-   );</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-      if (chan == NULL) {</span><br><span style="color: hsl(0, 100%, 40%);">-             ast_log(LOG_ERROR, "Fax channel is NULL. Giving up.\n");</span><br><span style="color: hsl(0, 100%, 40%);">-              return -1;</span><br><span style="color: hsl(0, 100%, 40%);">-      }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       /* The next few lines of code parse out the filename and header from the input string */</span><br><span style="color: hsl(0, 100%, 40%);">-        if (ast_strlen_zero(data)) {</span><br><span style="color: hsl(0, 100%, 40%);">-            /* No data implies no filename or anything is present */</span><br><span style="color: hsl(0, 100%, 40%);">-                ast_log(LOG_ERROR, "SendFAX requires an argument (filename)\n");</span><br><span style="color: hsl(0, 100%, 40%);">-              return -1;</span><br><span style="color: hsl(0, 100%, 40%);">-      }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       parse = ast_strdupa(data);</span><br><span style="color: hsl(0, 100%, 40%);">-      AST_STANDARD_APP_ARGS(args, parse);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     session.caller_mode = TRUE;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     if (args.options) {</span><br><span style="color: hsl(0, 100%, 40%);">-             if (strchr(args.options, 'a'))</span><br><span style="color: hsl(0, 100%, 40%);">-                  session.caller_mode = FALSE;</span><br><span style="color: hsl(0, 100%, 40%);">-    }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       /* Done parsing */</span><br><span style="color: hsl(0, 100%, 40%);">-      session.direction = 1;</span><br><span style="color: hsl(0, 100%, 40%);">-  session.file_name = args.file_name;</span><br><span style="color: hsl(0, 100%, 40%);">-     session.chan = chan;</span><br><span style="color: hsl(0, 100%, 40%);">-    session.finished = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-   /* get current digit detection mode, then disable digit detection if enabled */</span><br><span style="color: hsl(0, 100%, 40%);">- {</span><br><span style="color: hsl(0, 100%, 40%);">-               int dummy = sizeof(restore_digit_detect);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-               ast_channel_queryoption(chan, AST_OPTION_DIGIT_DETECT, &restore_digit_detect, &dummy, 0);</span><br><span style="color: hsl(0, 100%, 40%);">-       }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       if (restore_digit_detect) {</span><br><span style="color: hsl(0, 100%, 40%);">-             char new_digit_detect = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-              ast_channel_setoption(chan, AST_OPTION_DIGIT_DETECT, &new_digit_detect, sizeof(new_digit_detect), 0);</span><br><span style="color: hsl(0, 100%, 40%);">-       }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       /* disable FAX tone detection if enabled */</span><br><span style="color: hsl(0, 100%, 40%);">-     {</span><br><span style="color: hsl(0, 100%, 40%);">-               char new_fax_detect = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-                ast_channel_setoption(chan, AST_OPTION_FAX_DETECT, &new_fax_detect, sizeof(new_fax_detect), 0);</span><br><span style="color: hsl(0, 100%, 40%);">-     }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       res = transmit(&session);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-   if (restore_digit_detect) {</span><br><span style="color: hsl(0, 100%, 40%);">-             ast_channel_setoption(chan, AST_OPTION_DIGIT_DETECT, &restore_digit_detect, sizeof(restore_digit_detect), 0);</span><br><span style="color: hsl(0, 100%, 40%);">-       }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       return res;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static int rcvfax_exec(struct ast_channel *chan, const char *data)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- int res = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-    char *parse;</span><br><span style="color: hsl(0, 100%, 40%);">-    fax_session session;</span><br><span style="color: hsl(0, 100%, 40%);">-    char restore_digit_detect = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  AST_DECLARE_APP_ARGS(args,</span><br><span style="color: hsl(0, 100%, 40%);">-              AST_APP_ARG(file_name);</span><br><span style="color: hsl(0, 100%, 40%);">-         AST_APP_ARG(options);</span><br><span style="color: hsl(0, 100%, 40%);">-   );</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-      if (chan == NULL) {</span><br><span style="color: hsl(0, 100%, 40%);">-             ast_log(LOG_ERROR, "Fax channel is NULL. Giving up.\n");</span><br><span style="color: hsl(0, 100%, 40%);">-              return -1;</span><br><span style="color: hsl(0, 100%, 40%);">-      }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       /* The next few lines of code parse out the filename and header from the input string */</span><br><span style="color: hsl(0, 100%, 40%);">-        if (ast_strlen_zero(data)) {</span><br><span style="color: hsl(0, 100%, 40%);">-            /* No data implies no filename or anything is present */</span><br><span style="color: hsl(0, 100%, 40%);">-                ast_log(LOG_ERROR, "ReceiveFAX requires an argument (filename)\n");</span><br><span style="color: hsl(0, 100%, 40%);">-           return -1;</span><br><span style="color: hsl(0, 100%, 40%);">-      }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       parse = ast_strdupa(data);</span><br><span style="color: hsl(0, 100%, 40%);">-      AST_STANDARD_APP_ARGS(args, parse);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     session.caller_mode = FALSE;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    if (args.options) {</span><br><span style="color: hsl(0, 100%, 40%);">-             if (strchr(args.options, 'c'))</span><br><span style="color: hsl(0, 100%, 40%);">-                  session.caller_mode = TRUE;</span><br><span style="color: hsl(0, 100%, 40%);">-     }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       /* Done parsing */</span><br><span style="color: hsl(0, 100%, 40%);">-      session.direction = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-  session.file_name = args.file_name;</span><br><span style="color: hsl(0, 100%, 40%);">-     session.chan = chan;</span><br><span style="color: hsl(0, 100%, 40%);">-    session.finished = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-   /* get current digit detection mode, then disable digit detection if enabled */</span><br><span style="color: hsl(0, 100%, 40%);">- {</span><br><span style="color: hsl(0, 100%, 40%);">-               int dummy = sizeof(restore_digit_detect);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-               ast_channel_queryoption(chan, AST_OPTION_DIGIT_DETECT, &restore_digit_detect, &dummy, 0);</span><br><span style="color: hsl(0, 100%, 40%);">-       }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       if (restore_digit_detect) {</span><br><span style="color: hsl(0, 100%, 40%);">-             char new_digit_detect = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-              ast_channel_setoption(chan, AST_OPTION_DIGIT_DETECT, &new_digit_detect, sizeof(new_digit_detect), 0);</span><br><span style="color: hsl(0, 100%, 40%);">-       }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       /* disable FAX tone detection if enabled */</span><br><span style="color: hsl(0, 100%, 40%);">-     {</span><br><span style="color: hsl(0, 100%, 40%);">-               char new_fax_detect = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-                ast_channel_setoption(chan, AST_OPTION_FAX_DETECT, &new_fax_detect, sizeof(new_fax_detect), 0);</span><br><span style="color: hsl(0, 100%, 40%);">-     }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       res = transmit(&session);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-   if (restore_digit_detect) {</span><br><span style="color: hsl(0, 100%, 40%);">-             ast_channel_setoption(chan, AST_OPTION_DIGIT_DETECT, &restore_digit_detect, sizeof(restore_digit_detect), 0);</span><br><span style="color: hsl(0, 100%, 40%);">-       }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       return res;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static int unload_module(void)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-     int res;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        res = ast_unregister_application(app_sndfax_name);</span><br><span style="color: hsl(0, 100%, 40%);">-      res |= ast_unregister_application(app_rcvfax_name);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     return res;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static int load_module(void)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-       int res ;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       res = ast_register_application_xml(app_sndfax_name, sndfax_exec);</span><br><span style="color: hsl(0, 100%, 40%);">-       res |= ast_register_application_xml(app_rcvfax_name, rcvfax_exec);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-      /* The default SPAN message handler prints to stderr. It is something we do not want */</span><br><span style="color: hsl(0, 100%, 40%);">- span_set_message_handler(NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return res;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Simple FAX Application",</span><br><span style="color: hsl(0, 100%, 40%);">-  .support_level = AST_MODULE_SUPPORT_DEPRECATED,</span><br><span style="color: hsl(0, 100%, 40%);">- .load = load_module,</span><br><span style="color: hsl(0, 100%, 40%);">-    .unload = unload_module,</span><br><span style="color: hsl(0, 100%, 40%);">-);</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/16292">change 16292</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/c/asterisk/+/16292"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 19 </div>
<div style="display:none"> Gerrit-Change-Id: I038237bbb56b1161d7d5e20cda11ed32e13d3ca2 </div>
<div style="display:none"> Gerrit-Change-Number: 16292 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Joshua Colp <jcolp@sangoma.com> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>