Rework of T.38 negotiation and UDPTL API to address interoperability problems
[asterisk/asterisk.git] / apps / app_fax.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Simple fax applications
5  * 
6  * 2007-2008, Dmitry Andrianov <asterisk@dima.spb.ru>
7  *
8  * Code based on original implementation by Steve Underwood <steveu@coppice.org>
9  *
10  * This program is free software, distributed under the terms of
11  * the GNU General Public License
12  *
13  */
14
15 /*** MODULEINFO
16          <depend>spandsp</depend>
17 ***/
18  
19 #include "asterisk.h"
20
21 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
22
23 #include <string.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <inttypes.h>
27 #include <pthread.h>
28 #include <errno.h>
29 #include <tiffio.h>
30
31 #include <spandsp.h>
32 #ifdef HAVE_SPANDSP_EXPOSE_H
33 #include <spandsp/expose.h>
34 #endif
35 #include <spandsp/version.h>
36
37 #include "asterisk/lock.h"
38 #include "asterisk/file.h"
39 #include "asterisk/logger.h"
40 #include "asterisk/channel.h"
41 #include "asterisk/pbx.h"
42 #include "asterisk/app.h"
43 #include "asterisk/dsp.h"
44 #include "asterisk/module.h"
45 #include "asterisk/manager.h"
46
47 /*** DOCUMENTATION
48         <application name="SendFAX" language="en_US">
49                 <synopsis>
50                         Send a Fax
51                 </synopsis>
52                 <syntax>
53                         <parameter name="filename" required="true">
54                                 <para>Filename of TIFF file to fax</para>
55                         </parameter>
56                         <parameter name="a" required="false">
57                                 <para>Makes the application behave as the answering machine</para>
58                                 <para>(Default behavior is as calling machine)</para>
59                         </parameter>
60                 </syntax>
61                 <description>
62                         <para>Send a given TIFF file to the channel as a FAX.</para>
63                         <para>This application sets the following channel variables:</para>
64                         <variablelist>
65                                 <variable name="LOCALSTATIONID">
66                                         <para>To identify itself to the remote end</para>
67                                 </variable>
68                                 <variable name="LOCALHEADERINFO">
69                                         <para>To generate a header line on each page</para>
70                                 </variable>
71                                 <variable name="FAXSTATUS">
72                                         <value name="SUCCESS"/>
73                                         <value name="FAILED"/>
74                                 </variable>
75                                 <variable name="FAXERROR">
76                                         <para>Cause of failure</para>
77                                 </variable>
78                                 <variable name="REMOTESTATIONID">
79                                         <para>The CSID of the remote side</para>
80                                 </variable>
81                                 <variable name="FAXPAGES">
82                                         <para>Number of pages sent</para>
83                                 </variable>
84                                 <variable name="FAXBITRATE">
85                                         <para>Transmission rate</para>
86                                 </variable>
87                                 <variable name="FAXRESOLUTION">
88                                         <para>Resolution of sent fax</para>
89                                 </variable>
90                         </variablelist>
91                 </description>
92         </application>
93         <application name="ReceiveFAX" language="en_US">
94                 <synopsis>
95                         Receive a Fax
96                 </synopsis>
97                 <syntax>
98                         <parameter name="filename" required="true">
99                                 <para>Filename of TIFF file save incoming fax</para>
100                         </parameter>
101                         <parameter name="c" required="false">
102                                 <para>Makes the application behave as the calling machine</para> 
103                                 <para>(Default behavior is as answering machine)</para>
104                         </parameter>
105                 </syntax>
106                 <description>
107                         <para>Receives a FAX from the channel into the given filename 
108                         overwriting the file if it already exists.</para>
109                         <para>File created will be in TIFF format.</para>
110
111                         <para>This application sets the following channel variables:</para>
112                         <variablelist>
113                                 <variable name="LOCALSTATIONID">
114                                         <para>To identify itself to the remote end</para>
115                                 </variable>
116                                 <variable name="LOCALHEADERINFO">
117                                         <para>To generate a header line on each page</para>
118                                 </variable>
119                                 <variable name="FAXSTATUS">
120                                         <value name="SUCCESS"/>
121                                         <value name="FAILED"/>
122                                 </variable>
123                                 <variable name="FAXERROR">
124                                         <para>Cause of failure</para>
125                                 </variable>
126                                 <variable name="REMOTESTATIONID">
127                                         <para>The CSID of the remote side</para>
128                                 </variable>
129                                 <variable name="FAXPAGES">
130                                         <para>Number of pages sent</para>
131                                 </variable>
132                                 <variable name="FAXBITRATE">
133                                         <para>Transmission rate</para>
134                                 </variable>
135                                 <variable name="FAXRESOLUTION">
136                                         <para>Resolution of sent fax</para>
137                                 </variable>
138                         </variablelist>
139                 </description>
140         </application>
141
142  ***/
143
144 static const char app_sndfax_name[] = "SendFAX";
145 static const char app_rcvfax_name[] = "ReceiveFAX";
146
147 #define MAX_SAMPLES 240
148
149 /* Watchdog. I have seen situations when remote fax disconnects (because of poor line
150    quality) while SpanDSP continues staying in T30_STATE_IV_CTC state forever.
151    To avoid this, we terminate when we see that T30 state does not change for 5 minutes.
152    We also terminate application when more than 30 minutes passed regardless of
153    state changes. This is just a precaution measure - no fax should take that long */
154
155 #define WATCHDOG_TOTAL_TIMEOUT  30 * 60
156 #define WATCHDOG_STATE_TIMEOUT  5 * 60
157
158 typedef struct {
159         struct ast_channel *chan;
160         enum ast_t38_state t38state;    /* T38 state of the channel */
161         int direction;                  /* Fax direction: 0 - receiving, 1 - sending */
162         int caller_mode;
163         char *file_name;
164         struct ast_control_t38_parameters t38parameters;
165         volatile int finished;
166 } fax_session;
167
168 static void span_message(int level, const char *msg)
169 {
170         if (level == SPAN_LOG_ERROR) {
171                 ast_log(LOG_ERROR, "%s", msg);
172         } else if (level == SPAN_LOG_WARNING) {
173                 ast_log(LOG_WARNING, "%s", msg);
174         } else {
175                 ast_log(LOG_DEBUG, "%s", msg);
176         }
177 }
178
179 static int t38_tx_packet_handler(t38_core_state_t *s, void *user_data, const uint8_t *buf, int len, int count)
180 {
181         struct ast_channel *chan = (struct ast_channel *) user_data;
182
183         struct ast_frame outf = {
184                 .frametype = AST_FRAME_MODEM,
185                 .subclass = AST_MODEM_T38,
186                 .src = __FUNCTION__,
187         };
188
189         /* TODO: Asterisk does not provide means of resending the same packet multiple
190           times so count is ignored at the moment */
191
192         AST_FRAME_SET_BUFFER(&outf, buf, 0, len);
193
194         if (ast_write(chan, &outf) < 0) {
195                 ast_log(LOG_WARNING, "Unable to write frame to channel; %s\n", strerror(errno));
196                 return -1;
197         }
198
199         return 0;
200 }
201
202 static void phase_e_handler(t30_state_t *f, void *user_data, int result)
203 {
204         const char *local_ident;
205         const char *far_ident;
206         char buf[20];
207         fax_session *s = (fax_session *) user_data;
208         t30_stats_t stat;
209         int pages_transferred;
210
211         ast_debug(1, "Fax phase E handler. result=%d\n", result);
212
213         t30_get_transfer_statistics(f, &stat);
214
215         s = (fax_session *) user_data;
216
217         if (result != T30_ERR_OK) {
218                 s->finished = -1;
219
220                 /* FAXSTATUS is already set to FAILED */
221                 pbx_builtin_setvar_helper(s->chan, "FAXERROR", t30_completion_code_to_str(result));
222
223                 ast_log(LOG_WARNING, "Error transmitting fax. result=%d: %s.\n", result, t30_completion_code_to_str(result));
224
225                 return;
226         }
227         
228         s->finished = 1; 
229         
230         local_ident = t30_get_tx_ident(f);
231         far_ident = t30_get_rx_ident(f);
232         pbx_builtin_setvar_helper(s->chan, "FAXSTATUS", "SUCCESS"); 
233         pbx_builtin_setvar_helper(s->chan, "FAXERROR", NULL); 
234         pbx_builtin_setvar_helper(s->chan, "REMOTESTATIONID", far_ident);
235 #if SPANDSP_RELEASE_DATE >= 20090220
236         pages_transferred = (s->direction) ? stat.pages_tx : stat.pages_rx;
237 #else
238         pages_transferred = stat.pages_transferred;
239 #endif
240         snprintf(buf, sizeof(buf), "%d", pages_transferred);
241         pbx_builtin_setvar_helper(s->chan, "FAXPAGES", buf);
242         snprintf(buf, sizeof(buf), "%d", stat.y_resolution);
243         pbx_builtin_setvar_helper(s->chan, "FAXRESOLUTION", buf);
244         snprintf(buf, sizeof(buf), "%d", stat.bit_rate);
245         pbx_builtin_setvar_helper(s->chan, "FAXBITRATE", buf); 
246         
247         ast_debug(1, "Fax transmitted successfully.\n");
248         ast_debug(1, "  Remote station ID: %s\n", far_ident);
249         ast_debug(1, "  Pages transferred: %d\n", pages_transferred);
250         ast_debug(1, "  Image resolution:  %d x %d\n", stat.x_resolution, stat.y_resolution);
251         ast_debug(1, "  Transfer Rate:     %d\n", stat.bit_rate);
252         
253         manager_event(EVENT_FLAG_CALL,
254                       s->direction ? "FaxSent" : "FaxReceived", 
255                       "Channel: %s\r\n"
256                       "Exten: %s\r\n"
257                       "CallerID: %s\r\n"
258                       "RemoteStationID: %s\r\n"
259                       "LocalStationID: %s\r\n"
260                       "PagesTransferred: %d\r\n"
261                       "Resolution: %d\r\n"
262                       "TransferRate: %d\r\n"
263                       "FileName: %s\r\n",
264                       s->chan->name,
265                       s->chan->exten,
266                       S_OR(s->chan->cid.cid_num, ""),
267                       far_ident,
268                       local_ident,
269                       pages_transferred,
270                       stat.y_resolution,
271                       stat.bit_rate,
272                       s->file_name);
273 }
274
275 /* === Helper functions to configure fax === */
276
277 /* Setup SPAN logging according to Asterisk debug level */
278 static int set_logging(logging_state_t *state)
279 {
280         int level = SPAN_LOG_WARNING + option_debug;
281
282         span_log_set_message_handler(state, span_message);
283         span_log_set_level(state, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | level); 
284
285         return 0;
286 }
287
288 static void set_local_info(t30_state_t *state, fax_session *s)
289 {
290         const char *x;
291
292         x = pbx_builtin_getvar_helper(s->chan, "LOCALSTATIONID");
293         if (!ast_strlen_zero(x))
294                 t30_set_tx_ident(state, x);
295
296         x = pbx_builtin_getvar_helper(s->chan, "LOCALHEADERINFO");
297         if (!ast_strlen_zero(x))
298                 t30_set_tx_page_header_info(state, x);
299 }
300
301 static void set_file(t30_state_t *state, fax_session *s)
302 {
303         if (s->direction)
304                 t30_set_tx_file(state, s->file_name, -1, -1);
305         else
306                 t30_set_rx_file(state, s->file_name, -1);
307 }
308
309 static void set_ecm(t30_state_t *state, int ecm)
310 {
311         t30_set_ecm_capability(state, ecm);
312         t30_set_supported_compressions(state, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION);
313 }
314
315 /* === Generator === */
316
317 /* This function is only needed to return passed params so
318    generator_activate will save it to channel's generatordata */
319 static void *fax_generator_alloc(struct ast_channel *chan, void *params)
320 {
321         return params;
322 }
323
324 static int fax_generator_generate(struct ast_channel *chan, void *data, int len, int samples)
325 {
326         fax_state_t *fax = (fax_state_t*) data;
327         uint8_t buffer[AST_FRIENDLY_OFFSET + MAX_SAMPLES * sizeof(uint16_t)];
328         int16_t *buf = (int16_t *) (buffer + AST_FRIENDLY_OFFSET);
329     
330         struct ast_frame outf = {
331                 .frametype = AST_FRAME_VOICE,
332                 .subclass = AST_FORMAT_SLINEAR,
333                 .src = __FUNCTION__,
334         };
335
336         if (samples > MAX_SAMPLES) {
337                 ast_log(LOG_WARNING, "Only generating %d samples, where %d requested\n", MAX_SAMPLES, samples);
338                 samples = MAX_SAMPLES;
339         }
340         
341         if ((len = fax_tx(fax, buf, samples)) > 0) {
342                 outf.samples = len;
343                 AST_FRAME_SET_BUFFER(&outf, buffer, AST_FRIENDLY_OFFSET, len * sizeof(int16_t));
344
345                 if (ast_write(chan, &outf) < 0) {
346                         ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", chan->name, strerror(errno));
347                         return -1;
348                 }
349         }
350
351         return 0;
352 }
353
354 static struct ast_generator generator = {
355         alloc:          fax_generator_alloc,
356         generate:       fax_generator_generate,
357 };
358
359
360 /* === Transmission === */
361
362 static int transmit_audio(fax_session *s)
363 {
364         int res = -1;
365         int original_read_fmt = AST_FORMAT_SLINEAR;
366         int original_write_fmt = AST_FORMAT_SLINEAR;
367         fax_state_t fax;
368         t30_state_t *t30state;
369         struct ast_dsp *dsp = NULL;
370         int detect_tone = 0;
371         struct ast_frame *inf = NULL;
372         struct ast_frame *fr;
373         int last_state = 0;
374         struct timeval now, start, state_change;
375
376 #if SPANDSP_RELEASE_DATE >= 20080725
377         /* for spandsp shaphots 0.0.6 and higher */
378         t30state = &fax.t30;
379 #else
380         /* for spandsp release 0.0.5 */
381         t30state = &fax.t30_state;
382 #endif
383
384         original_read_fmt = s->chan->readformat;
385         if (original_read_fmt != AST_FORMAT_SLINEAR) {
386                 res = ast_set_read_format(s->chan, AST_FORMAT_SLINEAR);
387                 if (res < 0) {
388                         ast_log(LOG_WARNING, "Unable to set to linear read mode, giving up\n");
389                         goto done;
390                 }
391         }
392
393         original_write_fmt = s->chan->writeformat;
394         if (original_write_fmt != AST_FORMAT_SLINEAR) {
395                 res = ast_set_write_format(s->chan, AST_FORMAT_SLINEAR);
396                 if (res < 0) {
397                         ast_log(LOG_WARNING, "Unable to set to linear write mode, giving up\n");
398                         goto done;
399                 }
400         }
401
402         /* Initialize T30 terminal */
403         fax_init(&fax, s->caller_mode);
404
405         /* Setup logging */
406         set_logging(&fax.logging);
407         set_logging(&t30state->logging);
408
409         /* Configure terminal */
410         set_local_info(t30state, s);
411         set_file(t30state, s);
412         set_ecm(t30state, TRUE);
413
414         fax_set_transmit_on_idle(&fax, TRUE);
415
416         t30_set_phase_e_handler(t30state, phase_e_handler, s);
417
418         if (s->t38state == T38_STATE_UNAVAILABLE) {
419                 ast_debug(1, "T38 is unavailable on %s\n", s->chan->name);
420         } else if (!s->direction) {
421                 /* We are receiving side and this means we are the side which should
422                    request T38 when the fax is detected. Use DSP to detect fax tone */
423                 ast_debug(1, "Setting up CNG detection on %s\n", s->chan->name);
424                 dsp = ast_dsp_new();
425                 ast_dsp_set_features(dsp, DSP_FEATURE_FAX_DETECT);
426                 ast_dsp_set_faxmode(dsp, DSP_FAXMODE_DETECT_CNG);
427                 detect_tone = 1;
428         }
429
430         start = state_change = ast_tvnow();
431
432         ast_activate_generator(s->chan, &generator, &fax);
433
434         while (!s->finished) {
435                 inf = NULL;
436
437                 if ((res = ast_waitfor(s->chan, 20)) < 0) {
438                         break;
439                 }
440
441                 /* if nothing arrived, check the watchdog timers */
442                 if (res == 0) {
443                         now = ast_tvnow();
444                         if (ast_tvdiff_sec(now, start) > WATCHDOG_TOTAL_TIMEOUT || ast_tvdiff_sec(now, state_change) > WATCHDOG_STATE_TIMEOUT) {
445                                 ast_log(LOG_WARNING, "It looks like we hung. Aborting.\n");
446                                 res = -1;
447                                 break;
448                         } else {
449                                 /* timers have not triggered, loop around to wait
450                                  * again
451                                  */
452                                 continue;
453                         }
454                 }
455
456                 if (!(inf = ast_read(s->chan))) {
457                         ast_debug(1, "Channel hangup\n");
458                         res = -1;
459                         break;
460                 }
461
462                 ast_debug(10, "frame %d/%d, len=%d\n", inf->frametype, inf->subclass, inf->datalen);
463
464                 /* Detect fax tone */
465                 if (detect_tone && inf->frametype == AST_FRAME_VOICE) {
466                         /* Duplicate frame because ast_dsp_process may free the frame passed */
467                         fr = ast_frdup(inf);
468
469                         /* Do not pass channel to ast_dsp_process otherwise it may queue modified audio frame back */
470                         fr = ast_dsp_process(NULL, dsp, fr);
471                         if (fr && fr->frametype == AST_FRAME_DTMF && fr->subclass == 'f') {
472                                 struct ast_control_t38_parameters parameters = { .request_response = AST_T38_REQUEST_NEGOTIATE,
473                                                                                  .version = 0,
474                                                                                  .max_ifp = 800,
475                                                                                  .rate = AST_T38_RATE_9600,
476                                                                                  .rate_management = AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF,
477                                                                                  .fill_bit_removal = 1,
478                                                                                  .transcoding_mmr = 1,
479                                                                                  .transcoding_jbig = 1,
480                                 };
481                                 ast_debug(1, "Fax tone detected. Requesting T38\n");
482                                 ast_indicate_data(s->chan, AST_CONTROL_T38_PARAMETERS, &parameters, sizeof(parameters));
483                                 detect_tone = 0;
484                         }
485
486                         ast_frfree(fr);
487                 }
488
489
490                 /* Check the frame type. Format also must be checked because there is a chance
491                    that a frame in old format was already queued before we set channel format
492                    to slinear so it will still be received by ast_read */
493                 if (inf->frametype == AST_FRAME_VOICE && inf->subclass == AST_FORMAT_SLINEAR) {
494                         if (fax_rx(&fax, inf->data.ptr, inf->samples) < 0) {
495                                 /* I know fax_rx never returns errors. The check here is for good style only */
496                                 ast_log(LOG_WARNING, "fax_rx returned error\n");
497                                 res = -1;
498                                 break;
499                         }
500                         if (last_state != t30state->state) {
501                                 state_change = ast_tvnow();
502                                 last_state = t30state->state;
503                         }
504                 } else if (inf->frametype == AST_FRAME_CONTROL && inf->subclass == AST_CONTROL_T38_PARAMETERS) {
505                         struct ast_control_t38_parameters *parameters = inf->data.ptr;
506                         if (parameters->request_response == AST_T38_NEGOTIATED) {
507                                 /* T38 switchover completed */
508                                 s->t38parameters = *parameters;
509                                 ast_debug(1, "T38 negotiated, finishing audio loop\n");
510                                 res = 1;
511                                 break;
512                         } else if (parameters->request_response == AST_T38_REQUEST_NEGOTIATE) {
513                                 struct ast_control_t38_parameters our_parameters = { .request_response = AST_T38_NEGOTIATED,
514                                                                                      .version = 0,
515                                                                                      .max_ifp = 800,
516                                                                                      .rate = AST_T38_RATE_9600,
517                                                                                      .rate_management = AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF,
518                                                                                      .fill_bit_removal = 1,
519                                                                                      .transcoding_mmr = 1,
520                                                                                      .transcoding_jbig = 1,
521                                 };
522                                 ast_debug(1, "T38 request received, accepting\n");
523                                 /* Complete T38 switchover */
524                                 ast_indicate_data(s->chan, AST_CONTROL_T38_PARAMETERS, &our_parameters, sizeof(our_parameters));
525                                 /* Do not break audio loop, wait until channel driver finally acks switchover
526                                    with AST_T38_NEGOTIATED */
527                         }
528                 }
529
530                 ast_frfree(inf);
531         }
532
533         ast_debug(1, "Loop finished, res=%d\n", res);
534
535         if (inf)
536                 ast_frfree(inf);
537
538         if (dsp)
539                 ast_dsp_free(dsp);
540
541         ast_deactivate_generator(s->chan);
542
543         /* If we are switching to T38, remove phase E handler. Otherwise it will be executed
544            by t30_terminate, display diagnostics and set status variables although no transmittion
545            has taken place yet. */
546         if (res > 0) {
547                 t30_set_phase_e_handler(t30state, NULL, NULL);
548         }
549
550         t30_terminate(t30state);
551         fax_release(&fax);
552
553 done:
554         if (original_write_fmt != AST_FORMAT_SLINEAR) {
555                 if (ast_set_write_format(s->chan, original_write_fmt) < 0)
556                         ast_log(LOG_WARNING, "Unable to restore write format on '%s'\n", s->chan->name);
557         }
558
559         if (original_read_fmt != AST_FORMAT_SLINEAR) {
560                 if (ast_set_read_format(s->chan, original_read_fmt) < 0)
561                         ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", s->chan->name);
562         }
563
564         return res;
565
566 }
567
568 static int transmit_t38(fax_session *s)
569 {
570         int res = 0;
571         t38_terminal_state_t t38;
572         struct ast_frame *inf = NULL;
573         int last_state = 0;
574         struct timeval now, start, state_change, last_frame;
575         t30_state_t *t30state;
576         t38_core_state_t *t38state;
577
578 #if SPANDSP_RELEASE_DATE >= 20080725
579         /* for spandsp shaphots 0.0.6 and higher */
580         t30state = &t38.t30;
581         t38state = &t38.t38_fe.t38;
582 #else
583         /* for spandsp releases 0.0.5 */
584         t30state = &t38.t30_state;
585         t38state = &t38.t38;
586 #endif
587
588         /* Initialize terminal */
589         memset(&t38, 0, sizeof(t38));
590         if (t38_terminal_init(&t38, s->caller_mode, t38_tx_packet_handler, s->chan) == NULL) {
591                 ast_log(LOG_WARNING, "Unable to start T.38 termination.\n");
592                 return -1;
593         }
594
595         t38_set_max_datagram_size(t38state, s->t38parameters.max_ifp);
596
597         if (s->t38parameters.fill_bit_removal) {
598                 t38_set_fill_bit_removal(t38state, TRUE);
599         }
600         if (s->t38parameters.transcoding_mmr) {
601                 t38_set_mmr_transcoding(t38state, TRUE);
602         }
603         if (s->t38parameters.transcoding_jbig) {
604                 t38_set_jbig_transcoding(t38state, TRUE);
605         }
606
607         /* Setup logging */
608         set_logging(&t38.logging);
609         set_logging(&t30state->logging);
610         set_logging(&t38state->logging);
611
612         /* Configure terminal */
613         set_local_info(t30state, s);
614         set_file(t30state, s);
615         set_ecm(t30state, TRUE);
616
617         t30_set_phase_e_handler(t30state, phase_e_handler, s);
618
619         now = start = state_change = ast_tvnow();
620
621         while (!s->finished) {
622                 inf = NULL;
623                 if ((res = ast_waitfor(s->chan, 20)) < 0) {
624                         break;
625                 }
626
627                 last_frame = now;
628                 now = ast_tvnow();
629                 /* if nothing arrived, check the watchdog timers */
630                 if (res == 0) {
631                         if (ast_tvdiff_sec(now, start) > WATCHDOG_TOTAL_TIMEOUT || ast_tvdiff_sec(now, state_change) > WATCHDOG_STATE_TIMEOUT) {
632                                 ast_log(LOG_WARNING, "It looks like we hung. Aborting.\n");
633                                 res = -1;
634                                 break;
635                         } else {
636                                 /* timers have not triggered, loop around to wait
637                                  * again
638                                  */
639                                 t38_terminal_send_timeout(&t38, ast_tvdiff_us(now, last_frame) / (1000000 / 8000));
640                                 continue;
641                         }
642                 }
643
644                 t38_terminal_send_timeout(&t38, ast_tvdiff_us(now, last_frame) / (1000000 / 8000));
645
646                 if (!(inf = ast_read(s->chan))) {
647                         ast_debug(1, "Channel hangup\n");
648                         res = -1;
649                         break;
650                 }
651
652                 ast_debug(10, "frame %d/%d, len=%d\n", inf->frametype, inf->subclass, inf->datalen);
653
654                 if (inf->frametype == AST_FRAME_MODEM && inf->subclass == AST_MODEM_T38) {
655                         t38_core_rx_ifp_packet(t38state, inf->data.ptr, inf->datalen, inf->seqno);
656                         if (last_state != t30state->state) {
657                                 state_change = ast_tvnow();
658                                 last_state = t30state->state;
659                         }
660                 } else if (inf->frametype == AST_FRAME_CONTROL && inf->subclass == AST_CONTROL_T38_PARAMETERS) {
661                         struct ast_control_t38_parameters *parameters = inf->data.ptr;
662                         if (parameters->request_response == AST_T38_TERMINATED) {
663                                 ast_debug(1, "T38 down, finishing\n");
664                                 break;
665                         }
666                 }
667
668                 ast_frfree(inf);
669         }
670
671         ast_debug(1, "Loop finished, res=%d\n", res);
672
673         if (inf)
674                 ast_frfree(inf);
675
676         t30_terminate(t30state);
677         t38_terminal_release(&t38);
678
679         return res;
680 }
681
682 static int transmit(fax_session *s)
683 {
684         int res = 0;
685
686         /* Clear all channel variables which to be set by the application.
687            Pre-set status to error so in case of any problems we can just leave */
688         pbx_builtin_setvar_helper(s->chan, "FAXSTATUS", "FAILED"); 
689         pbx_builtin_setvar_helper(s->chan, "FAXERROR", "Channel problems"); 
690
691         pbx_builtin_setvar_helper(s->chan, "FAXMODE", NULL);
692         pbx_builtin_setvar_helper(s->chan, "REMOTESTATIONID", NULL);
693         pbx_builtin_setvar_helper(s->chan, "FAXPAGES", NULL);
694         pbx_builtin_setvar_helper(s->chan, "FAXRESOLUTION", NULL);
695         pbx_builtin_setvar_helper(s->chan, "FAXBITRATE", NULL); 
696
697         if (s->chan->_state != AST_STATE_UP) {
698                 /* Shouldn't need this, but checking to see if channel is already answered
699                  * Theoretically asterisk should already have answered before running the app */
700                 res = ast_answer(s->chan);
701                 if (res) {
702                         ast_log(LOG_WARNING, "Could not answer channel '%s'\n", s->chan->name);
703                         return res;
704                 }
705         }
706
707         s->t38state = ast_channel_get_t38_state(s->chan);
708         if (s->t38state != T38_STATE_NEGOTIATED) {
709                 /* T38 is not negotiated on the channel yet. First start regular transmission. If it switches to T38, follow */ 
710                 pbx_builtin_setvar_helper(s->chan, "FAXMODE", "audio"); 
711                 res = transmit_audio(s);
712                 if (res > 0) {
713                         /* transmit_audio reports switchover to T38. Update t38state */
714                         s->t38state = ast_channel_get_t38_state(s->chan);
715                         if (s->t38state != T38_STATE_NEGOTIATED) {
716                                 ast_log(LOG_ERROR, "Audio loop reports T38 switchover but t38state != T38_STATE_NEGOTIATED\n");
717                         }
718                 }
719         }
720
721         if (s->t38state == T38_STATE_NEGOTIATED) {
722                 pbx_builtin_setvar_helper(s->chan, "FAXMODE", "T38"); 
723                 res = transmit_t38(s);
724         }
725
726         if (res) {
727                 ast_log(LOG_WARNING, "Transmission error\n");
728                 res = -1;
729         } else if (s->finished < 0) {
730                 ast_log(LOG_WARNING, "Transmission failed\n");
731         } else if (s->finished > 0) {
732                 ast_debug(1, "Transmission finished Ok\n");
733         }
734
735         return res;
736 }
737
738 /* === Application functions === */
739
740 static int sndfax_exec(struct ast_channel *chan, const char *data)
741 {
742         int res = 0;
743         char *parse;
744         fax_session session = { 0, };
745         char restore_digit_detect = 0;
746
747         AST_DECLARE_APP_ARGS(args,
748                 AST_APP_ARG(file_name);
749                 AST_APP_ARG(options);
750         );
751
752         if (chan == NULL) {
753                 ast_log(LOG_ERROR, "Fax channel is NULL. Giving up.\n");
754                 return -1;
755         }
756
757         /* The next few lines of code parse out the filename and header from the input string */
758         if (ast_strlen_zero(data)) {
759                 /* No data implies no filename or anything is present */
760                 ast_log(LOG_ERROR, "SendFAX requires an argument (filename)\n");
761                 return -1;
762         }
763
764         parse = ast_strdupa(data);
765         AST_STANDARD_APP_ARGS(args, parse);
766         
767         session.caller_mode = TRUE;
768
769         if (args.options) {
770                 if (strchr(args.options, 'a'))
771                         session.caller_mode = FALSE;
772         }
773
774         /* Done parsing */
775         session.direction = 1;
776         session.file_name = args.file_name;
777         session.chan = chan;
778         session.finished = 0;
779
780         /* get current digit detection mode, then disable digit detection if enabled */
781         {
782                 int dummy = sizeof(restore_digit_detect);
783
784                 ast_channel_queryoption(chan, AST_OPTION_DIGIT_DETECT, &restore_digit_detect, &dummy, 0);
785         }
786
787         if (restore_digit_detect) {
788                 char new_digit_detect = 0;
789
790                 ast_channel_setoption(chan, AST_OPTION_DIGIT_DETECT, &new_digit_detect, sizeof(new_digit_detect), 0);
791         }
792
793         /* disable FAX tone detection if enabled */
794         {
795                 char new_fax_detect = 0;
796
797                 ast_channel_setoption(chan, AST_OPTION_FAX_DETECT, &new_fax_detect, sizeof(new_fax_detect), 0);
798         }
799
800         res = transmit(&session);
801
802         if (restore_digit_detect) {
803                 ast_channel_setoption(chan, AST_OPTION_DIGIT_DETECT, &restore_digit_detect, sizeof(restore_digit_detect), 0);
804         }
805
806         return res;
807 }
808
809 static int rcvfax_exec(struct ast_channel *chan, const char *data)
810 {
811         int res = 0;
812         char *parse;
813         fax_session session;
814         char restore_digit_detect = 0;
815
816         AST_DECLARE_APP_ARGS(args,
817                 AST_APP_ARG(file_name);
818                 AST_APP_ARG(options);
819         );
820
821         if (chan == NULL) {
822                 ast_log(LOG_ERROR, "Fax channel is NULL. Giving up.\n");
823                 return -1;
824         }
825
826         /* The next few lines of code parse out the filename and header from the input string */
827         if (ast_strlen_zero(data)) {
828                 /* No data implies no filename or anything is present */
829                 ast_log(LOG_ERROR, "ReceiveFAX requires an argument (filename)\n");
830                 return -1;
831         }
832
833         parse = ast_strdupa(data);
834         AST_STANDARD_APP_ARGS(args, parse);
835         
836         session.caller_mode = FALSE;
837
838         if (args.options) {
839                 if (strchr(args.options, 'c'))
840                         session.caller_mode = TRUE;
841         }
842
843         /* Done parsing */
844         session.direction = 0;
845         session.file_name = args.file_name;
846         session.chan = chan;
847         session.finished = 0;
848
849         /* get current digit detection mode, then disable digit detection if enabled */
850         {
851                 int dummy = sizeof(restore_digit_detect);
852
853                 ast_channel_queryoption(chan, AST_OPTION_DIGIT_DETECT, &restore_digit_detect, &dummy, 0);
854         }
855
856         if (restore_digit_detect) {
857                 char new_digit_detect = 0;
858
859                 ast_channel_setoption(chan, AST_OPTION_DIGIT_DETECT, &new_digit_detect, sizeof(new_digit_detect), 0);
860         }
861
862         /* disable FAX tone detection if enabled */
863         {
864                 char new_fax_detect = 0;
865
866                 ast_channel_setoption(chan, AST_OPTION_FAX_DETECT, &new_fax_detect, sizeof(new_fax_detect), 0);
867         }
868
869         res = transmit(&session);
870
871         if (restore_digit_detect) {
872                 ast_channel_setoption(chan, AST_OPTION_DIGIT_DETECT, &restore_digit_detect, sizeof(restore_digit_detect), 0);
873         }
874
875         return res;
876 }
877
878 static int unload_module(void)
879 {
880         int res;
881
882         res = ast_unregister_application(app_sndfax_name);      
883         res |= ast_unregister_application(app_rcvfax_name);     
884
885         return res;
886 }
887
888 static int load_module(void)
889 {
890         int res ;
891
892         res = ast_register_application_xml(app_sndfax_name, sndfax_exec);
893         res |= ast_register_application_xml(app_rcvfax_name, rcvfax_exec);
894
895         /* The default SPAN message handler prints to stderr. It is something we do not want */
896         span_set_message_handler(NULL);
897
898         return res;
899 }
900
901
902 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Simple FAX Application",
903                 .load = load_module,
904                 .unload = unload_module,
905                 );
906
907