Eliminate extraneous LOG_DEBUG messages generated by app_fax.
[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_datagram = 400,
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                                 };
480                                 ast_debug(1, "Fax tone detected. Requesting T38\n");
481                                 ast_indicate_data(s->chan, AST_CONTROL_T38_PARAMETERS, &parameters, sizeof(parameters));
482                                 detect_tone = 0;
483                         }
484
485                         ast_frfree(fr);
486                 }
487
488
489                 /* Check the frame type. Format also must be checked because there is a chance
490                    that a frame in old format was already queued before we set channel format
491                    to slinear so it will still be received by ast_read */
492                 if (inf->frametype == AST_FRAME_VOICE && inf->subclass == AST_FORMAT_SLINEAR) {
493                         if (fax_rx(&fax, inf->data.ptr, inf->samples) < 0) {
494                                 /* I know fax_rx never returns errors. The check here is for good style only */
495                                 ast_log(LOG_WARNING, "fax_rx returned error\n");
496                                 res = -1;
497                                 break;
498                         }
499                         if (last_state != t30state->state) {
500                                 state_change = ast_tvnow();
501                                 last_state = t30state->state;
502                         }
503                 } else if (inf->frametype == AST_FRAME_CONTROL && inf->subclass == AST_CONTROL_T38_PARAMETERS) {
504                         struct ast_control_t38_parameters *parameters = inf->data.ptr;
505                         if (parameters->request_response == AST_T38_NEGOTIATED) {
506                                 /* T38 switchover completed */
507                                 s->t38parameters = *parameters;
508                                 ast_debug(1, "T38 negotiated, finishing audio loop\n");
509                                 res = 1;
510                                 break;
511                         } else if (parameters->request_response == AST_T38_REQUEST_NEGOTIATE) {
512                                 ast_debug(1, "T38 request received, accepting\n");
513                                 if (parameters->version > 0) {
514                                         /* Only T.38 Version 0 is supported at this time */
515                                         parameters->version = 0;
516                                 }
517                                 if (parameters->max_datagram > 400) {
518                                         /* Limit incoming datagram size to our default */
519                                         /* TODO: this need to come from the udptl stack, not be hardcoded */
520                                         parameters->max_datagram = 400;
521                                 }
522                                 /* we only support bit rates up to 9.6kbps */
523                                 parameters->rate = AST_T38_RATE_9600;
524                                 /* Complete T38 switchover */
525                                 ast_indicate_data(s->chan, AST_CONTROL_T38_PARAMETERS, parameters, sizeof(*parameters));
526                                 /* Do not break audio loop, wait until channel driver finally acks switchover
527                                    with AST_T38_NEGOTIATED */
528                         }
529                 }
530
531                 ast_frfree(inf);
532         }
533
534         ast_debug(1, "Loop finished, res=%d\n", res);
535
536         if (inf)
537                 ast_frfree(inf);
538
539         if (dsp)
540                 ast_dsp_free(dsp);
541
542         ast_deactivate_generator(s->chan);
543
544         /* If we are switching to T38, remove phase E handler. Otherwise it will be executed
545            by t30_terminate, display diagnostics and set status variables although no transmittion
546            has taken place yet. */
547         if (res > 0) {
548                 t30_set_phase_e_handler(t30state, NULL, NULL);
549         }
550
551         t30_terminate(t30state);
552         fax_release(&fax);
553
554 done:
555         if (original_write_fmt != AST_FORMAT_SLINEAR) {
556                 if (ast_set_write_format(s->chan, original_write_fmt) < 0)
557                         ast_log(LOG_WARNING, "Unable to restore write format on '%s'\n", s->chan->name);
558         }
559
560         if (original_read_fmt != AST_FORMAT_SLINEAR) {
561                 if (ast_set_read_format(s->chan, original_read_fmt) < 0)
562                         ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", s->chan->name);
563         }
564
565         return res;
566
567 }
568
569 static int transmit_t38(fax_session *s)
570 {
571         int res = 0;
572         t38_terminal_state_t t38;
573         struct ast_frame *inf = NULL;
574         int last_state = 0;
575         struct timeval now, start, state_change, last_frame;
576         t30_state_t *t30state;
577         t38_core_state_t *t38state;
578
579 #if SPANDSP_RELEASE_DATE >= 20080725
580         /* for spandsp shaphots 0.0.6 and higher */
581         t30state = &t38.t30;
582         t38state = &t38.t38_fe.t38;
583 #else
584         /* for spandsp releases 0.0.5 */
585         t30state = &t38.t30_state;
586         t38state = &t38.t38;
587 #endif
588
589         /* Initialize terminal */
590         memset(&t38, 0, sizeof(t38));
591         if (t38_terminal_init(&t38, s->caller_mode, t38_tx_packet_handler, s->chan) == NULL) {
592                 ast_log(LOG_WARNING, "Unable to start T.38 termination.\n");
593                 return -1;
594         }
595
596         t38_set_max_datagram_size(t38state, s->t38parameters.max_datagram);
597
598         if (s->t38parameters.fill_bit_removal) {
599                 t38_set_fill_bit_removal(t38state, TRUE);
600         }
601         if (s->t38parameters.transcoding_mmr) {
602                 t38_set_mmr_transcoding(t38state, TRUE);
603         }
604         if (s->t38parameters.transcoding_jbig) {
605                 t38_set_jbig_transcoding(t38state, TRUE);
606         }
607
608         /* Setup logging */
609         set_logging(&t38.logging);
610         set_logging(&t30state->logging);
611         set_logging(&t38state->logging);
612
613         /* Configure terminal */
614         set_local_info(t30state, s);
615         set_file(t30state, s);
616         set_ecm(t30state, TRUE);
617
618         t30_set_phase_e_handler(t30state, phase_e_handler, s);
619
620         now = start = state_change = ast_tvnow();
621
622         while (!s->finished) {
623                 inf = NULL;
624                 if ((res = ast_waitfor(s->chan, 20)) < 0) {
625                         break;
626                 }
627
628                 last_frame = now;
629                 now = ast_tvnow();
630                 /* if nothing arrived, check the watchdog timers */
631                 if (res == 0) {
632                         if (ast_tvdiff_sec(now, start) > WATCHDOG_TOTAL_TIMEOUT || ast_tvdiff_sec(now, state_change) > WATCHDOG_STATE_TIMEOUT) {
633                                 ast_log(LOG_WARNING, "It looks like we hung. Aborting.\n");
634                                 res = -1;
635                                 break;
636                         } else {
637                                 /* timers have not triggered, loop around to wait
638                                  * again
639                                  */
640                                 t38_terminal_send_timeout(&t38, ast_tvdiff_us(now, last_frame) / (1000000 / 8000));
641                                 continue;
642                         }
643                 }
644
645                 t38_terminal_send_timeout(&t38, ast_tvdiff_us(now, last_frame) / (1000000 / 8000));
646
647                 if (!(inf = ast_read(s->chan))) {
648                         ast_debug(1, "Channel hangup\n");
649                         res = -1;
650                         break;
651                 }
652
653                 ast_debug(10, "frame %d/%d, len=%d\n", inf->frametype, inf->subclass, inf->datalen);
654
655                 if (inf->frametype == AST_FRAME_MODEM && inf->subclass == AST_MODEM_T38) {
656                         t38_core_rx_ifp_packet(t38state, inf->data.ptr, inf->datalen, inf->seqno);
657                         if (last_state != t30state->state) {
658                                 state_change = ast_tvnow();
659                                 last_state = t30state->state;
660                         }
661                 } else if (inf->frametype == AST_FRAME_CONTROL && inf->subclass == AST_CONTROL_T38_PARAMETERS) {
662                         struct ast_control_t38_parameters *parameters = inf->data.ptr;
663                         if (parameters->request_response == AST_T38_TERMINATED) {
664                                 ast_debug(1, "T38 down, finishing\n");
665                                 break;
666                         }
667                 }
668
669                 ast_frfree(inf);
670         }
671
672         ast_debug(1, "Loop finished, res=%d\n", res);
673
674         if (inf)
675                 ast_frfree(inf);
676
677         t30_terminate(t30state);
678         t38_terminal_release(&t38);
679
680         return res;
681 }
682
683 static int transmit(fax_session *s)
684 {
685         int res = 0;
686
687         /* Clear all channel variables which to be set by the application.
688            Pre-set status to error so in case of any problems we can just leave */
689         pbx_builtin_setvar_helper(s->chan, "FAXSTATUS", "FAILED"); 
690         pbx_builtin_setvar_helper(s->chan, "FAXERROR", "Channel problems"); 
691
692         pbx_builtin_setvar_helper(s->chan, "FAXMODE", NULL);
693         pbx_builtin_setvar_helper(s->chan, "REMOTESTATIONID", NULL);
694         pbx_builtin_setvar_helper(s->chan, "FAXPAGES", NULL);
695         pbx_builtin_setvar_helper(s->chan, "FAXRESOLUTION", NULL);
696         pbx_builtin_setvar_helper(s->chan, "FAXBITRATE", NULL); 
697
698         if (s->chan->_state != AST_STATE_UP) {
699                 /* Shouldn't need this, but checking to see if channel is already answered
700                  * Theoretically asterisk should already have answered before running the app */
701                 res = ast_answer(s->chan);
702                 if (res) {
703                         ast_log(LOG_WARNING, "Could not answer channel '%s'\n", s->chan->name);
704                         return res;
705                 }
706         }
707
708         s->t38state = ast_channel_get_t38_state(s->chan);
709         if (s->t38state != T38_STATE_NEGOTIATED) {
710                 /* T38 is not negotiated on the channel yet. First start regular transmission. If it switches to T38, follow */ 
711                 pbx_builtin_setvar_helper(s->chan, "FAXMODE", "audio"); 
712                 res = transmit_audio(s);
713                 if (res > 0) {
714                         /* transmit_audio reports switchover to T38. Update t38state */
715                         s->t38state = ast_channel_get_t38_state(s->chan);
716                         if (s->t38state != T38_STATE_NEGOTIATED) {
717                                 ast_log(LOG_ERROR, "Audio loop reports T38 switchover but t38state != T38_STATE_NEGOTIATED\n");
718                         }
719                 }
720         }
721
722         if (s->t38state == T38_STATE_NEGOTIATED) {
723                 pbx_builtin_setvar_helper(s->chan, "FAXMODE", "T38"); 
724                 res = transmit_t38(s);
725         }
726
727         if (res) {
728                 ast_log(LOG_WARNING, "Transmission error\n");
729                 res = -1;
730         } else if (s->finished < 0) {
731                 ast_log(LOG_WARNING, "Transmission failed\n");
732         } else if (s->finished > 0) {
733                 ast_debug(1, "Transmission finished Ok\n");
734         }
735
736         return res;
737 }
738
739 /* === Application functions === */
740
741 static int sndfax_exec(struct ast_channel *chan, const char *data)
742 {
743         int res = 0;
744         char *parse;
745         fax_session session = { 0, };
746         char restore_digit_detect = 0;
747
748         AST_DECLARE_APP_ARGS(args,
749                 AST_APP_ARG(file_name);
750                 AST_APP_ARG(options);
751         );
752
753         if (chan == NULL) {
754                 ast_log(LOG_ERROR, "Fax channel is NULL. Giving up.\n");
755                 return -1;
756         }
757
758         /* The next few lines of code parse out the filename and header from the input string */
759         if (ast_strlen_zero(data)) {
760                 /* No data implies no filename or anything is present */
761                 ast_log(LOG_ERROR, "SendFAX requires an argument (filename)\n");
762                 return -1;
763         }
764
765         parse = ast_strdupa(data);
766         AST_STANDARD_APP_ARGS(args, parse);
767         
768         session.caller_mode = TRUE;
769
770         if (args.options) {
771                 if (strchr(args.options, 'a'))
772                         session.caller_mode = FALSE;
773         }
774
775         /* Done parsing */
776         session.direction = 1;
777         session.file_name = args.file_name;
778         session.chan = chan;
779         session.finished = 0;
780
781         /* get current digit detection mode, then disable digit detection if enabled */
782         {
783                 int dummy = sizeof(restore_digit_detect);
784
785                 ast_channel_queryoption(chan, AST_OPTION_DIGIT_DETECT, &restore_digit_detect, &dummy, 0);
786         }
787
788         if (restore_digit_detect) {
789                 char new_digit_detect = 0;
790
791                 ast_channel_setoption(chan, AST_OPTION_DIGIT_DETECT, &new_digit_detect, sizeof(new_digit_detect), 0);
792         }
793
794         /* disable FAX tone detection if enabled */
795         {
796                 char new_fax_detect = 0;
797
798                 ast_channel_setoption(chan, AST_OPTION_FAX_DETECT, &new_fax_detect, sizeof(new_fax_detect), 0);
799         }
800
801         res = transmit(&session);
802
803         if (restore_digit_detect) {
804                 ast_channel_setoption(chan, AST_OPTION_DIGIT_DETECT, &restore_digit_detect, sizeof(restore_digit_detect), 0);
805         }
806
807         return res;
808 }
809
810 static int rcvfax_exec(struct ast_channel *chan, const char *data)
811 {
812         int res = 0;
813         char *parse;
814         fax_session session;
815         char restore_digit_detect = 0;
816
817         AST_DECLARE_APP_ARGS(args,
818                 AST_APP_ARG(file_name);
819                 AST_APP_ARG(options);
820         );
821
822         if (chan == NULL) {
823                 ast_log(LOG_ERROR, "Fax channel is NULL. Giving up.\n");
824                 return -1;
825         }
826
827         /* The next few lines of code parse out the filename and header from the input string */
828         if (ast_strlen_zero(data)) {
829                 /* No data implies no filename or anything is present */
830                 ast_log(LOG_ERROR, "ReceiveFAX requires an argument (filename)\n");
831                 return -1;
832         }
833
834         parse = ast_strdupa(data);
835         AST_STANDARD_APP_ARGS(args, parse);
836         
837         session.caller_mode = FALSE;
838
839         if (args.options) {
840                 if (strchr(args.options, 'c'))
841                         session.caller_mode = TRUE;
842         }
843
844         /* Done parsing */
845         session.direction = 0;
846         session.file_name = args.file_name;
847         session.chan = chan;
848         session.finished = 0;
849
850         /* get current digit detection mode, then disable digit detection if enabled */
851         {
852                 int dummy = sizeof(restore_digit_detect);
853
854                 ast_channel_queryoption(chan, AST_OPTION_DIGIT_DETECT, &restore_digit_detect, &dummy, 0);
855         }
856
857         if (restore_digit_detect) {
858                 char new_digit_detect = 0;
859
860                 ast_channel_setoption(chan, AST_OPTION_DIGIT_DETECT, &new_digit_detect, sizeof(new_digit_detect), 0);
861         }
862
863         /* disable FAX tone detection if enabled */
864         {
865                 char new_fax_detect = 0;
866
867                 ast_channel_setoption(chan, AST_OPTION_FAX_DETECT, &new_fax_detect, sizeof(new_fax_detect), 0);
868         }
869
870         res = transmit(&session);
871
872         if (restore_digit_detect) {
873                 ast_channel_setoption(chan, AST_OPTION_DIGIT_DETECT, &restore_digit_detect, sizeof(restore_digit_detect), 0);
874         }
875
876         return res;
877 }
878
879 static int unload_module(void)
880 {
881         int res;
882
883         res = ast_unregister_application(app_sndfax_name);      
884         res |= ast_unregister_application(app_rcvfax_name);     
885
886         return res;
887 }
888
889 static int load_module(void)
890 {
891         int res ;
892
893         res = ast_register_application_xml(app_sndfax_name, sndfax_exec);
894         res |= ast_register_application_xml(app_rcvfax_name, rcvfax_exec);
895
896         /* The default SPAN message handler prints to stderr. It is something we do not want */
897         span_set_message_handler(NULL);
898
899         return res;
900 }
901
902
903 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Simple FAX Application",
904                 .load = load_module,
905                 .unload = unload_module,
906                 );
907
908