Asterisk data retrieval API.
[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         <defaultenabled>no</defaultenabled>
17         <depend>spandsp</depend>
18         <conflict>res_fax</conflict>
19 ***/
20  
21 #include "asterisk.h"
22
23 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
24
25 #include <string.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <inttypes.h>
29 #include <pthread.h>
30 #include <errno.h>
31 #include <tiffio.h>
32
33 #define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
34 #include <spandsp.h>
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.integer = 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         ast_manager_event(s->chan, 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.codec = 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_frame *inf = NULL;
370         int last_state = 0;
371         struct timeval now, start, state_change;
372         enum ast_t38_state t38_state;
373         struct ast_control_t38_parameters t38_parameters = { .version = 0,
374                                                              .max_ifp = 800,
375                                                              .rate = AST_T38_RATE_14400,
376                                                              .rate_management = AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF,
377                                                              .fill_bit_removal = 1,
378 /*
379  * spandsp has API calls to support MMR and JBIG transcoding, but they aren't
380  * implemented quite yet... so don't offer them to the remote endpoint
381  *                                                           .transcoding_mmr = 1,
382  *                                                           .transcoding_jbig = 1,
383 */
384         };
385
386         /* if in called party mode, try to use T.38 */
387         if (s->caller_mode == FALSE) {
388                 /* check if we are already in T.38 mode (unlikely), or if we can request
389                  * a switch... if so, request it now and wait for the result, rather
390                  * than starting an audio FAX session that will have to be cancelled
391                  */
392                 if ((t38_state = ast_channel_get_t38_state(s->chan)) == T38_STATE_NEGOTIATED) {
393                         return 1;
394                 } else if ((t38_state != T38_STATE_UNAVAILABLE) &&
395                            (t38_parameters.request_response = AST_T38_REQUEST_NEGOTIATE,
396                             (ast_indicate_data(s->chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) == 0))) {
397                         /* wait up to five seconds for negotiation to complete */
398                         unsigned int timeout = 5000;
399                         int ms;
400                         
401                         ast_debug(1, "Negotiating T.38 for receive on %s\n", s->chan->name);
402                         while (timeout > 0) {
403                                 ms = ast_waitfor(s->chan, 1000);
404                                 if (ms < 0) {
405                                         ast_log(LOG_WARNING, "something bad happened while channel '%s' was polling.\n", s->chan->name);
406                                         return -1;
407                                 }
408                                 if (!ms) {
409                                         /* nothing happened */
410                                         if (timeout > 0) {
411                                                 timeout -= 1000;
412                                                 continue;
413                                         } else {
414                                                 ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 negotiation.\n", s->chan->name);
415                                                 break;
416                                         }
417                                 }
418                                 if (!(inf = ast_read(s->chan))) {
419                                         return -1;
420                                 }
421                                 if ((inf->frametype == AST_FRAME_CONTROL) &&
422                                     (inf->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
423                                     (inf->datalen == sizeof(t38_parameters))) {
424                                         struct ast_control_t38_parameters *parameters = inf->data.ptr;
425                                         
426                                         switch (parameters->request_response) {
427                                         case AST_T38_NEGOTIATED:
428                                                 ast_debug(1, "Negotiated T.38 for receive on %s\n", s->chan->name);
429                                                 res = 1;
430                                                 break;
431                                         case AST_T38_REFUSED:
432                                                 ast_log(LOG_WARNING, "channel '%s' refused to negotiate T.38\n", s->chan->name);
433                                                 break;
434                                         default:
435                                                 ast_log(LOG_ERROR, "channel '%s' failed to negotiate T.38\n", s->chan->name);
436                                                 break;
437                                         }
438                                         ast_frfree(inf);
439                                         if (res == 1) {
440                                                 return 1;
441                                         } else {
442                                                 break;
443                                         }
444                                 }
445                                 ast_frfree(inf);
446                         }
447                 }
448         }
449
450 #if SPANDSP_RELEASE_DATE >= 20080725
451         /* for spandsp shaphots 0.0.6 and higher */
452         t30state = &fax.t30;
453 #else
454         /* for spandsp release 0.0.5 */
455         t30state = &fax.t30_state;
456 #endif
457
458         original_read_fmt = s->chan->readformat;
459         if (original_read_fmt != AST_FORMAT_SLINEAR) {
460                 res = ast_set_read_format(s->chan, AST_FORMAT_SLINEAR);
461                 if (res < 0) {
462                         ast_log(LOG_WARNING, "Unable to set to linear read mode, giving up\n");
463                         goto done;
464                 }
465         }
466
467         original_write_fmt = s->chan->writeformat;
468         if (original_write_fmt != AST_FORMAT_SLINEAR) {
469                 res = ast_set_write_format(s->chan, AST_FORMAT_SLINEAR);
470                 if (res < 0) {
471                         ast_log(LOG_WARNING, "Unable to set to linear write mode, giving up\n");
472                         goto done;
473                 }
474         }
475
476         /* Initialize T30 terminal */
477         fax_init(&fax, s->caller_mode);
478
479         /* Setup logging */
480         set_logging(&fax.logging);
481         set_logging(&t30state->logging);
482
483         /* Configure terminal */
484         set_local_info(t30state, s);
485         set_file(t30state, s);
486         set_ecm(t30state, TRUE);
487
488         fax_set_transmit_on_idle(&fax, TRUE);
489
490         t30_set_phase_e_handler(t30state, phase_e_handler, s);
491
492         start = state_change = ast_tvnow();
493
494         ast_activate_generator(s->chan, &generator, &fax);
495
496         while (!s->finished) {
497                 inf = NULL;
498
499                 if ((res = ast_waitfor(s->chan, 25)) < 0) {
500                         ast_debug(1, "Error waiting for a frame\n");
501                         break;
502                 }
503
504                 /* Watchdog */
505                 now = ast_tvnow();
506                 if (ast_tvdiff_sec(now, start) > WATCHDOG_TOTAL_TIMEOUT || ast_tvdiff_sec(now, state_change) > WATCHDOG_STATE_TIMEOUT) {
507                         ast_log(LOG_WARNING, "It looks like we hung. Aborting.\n");
508                         res = -1;
509                         break;
510                 }
511
512                 if (!res) {
513                         /* There was timeout waiting for a frame. Loop around and wait again */
514                         continue;
515                 }
516
517                 /* There is a frame available. Get it */
518                 res = 0;
519
520                 if (!(inf = ast_read(s->chan))) {
521                         ast_debug(1, "Channel hangup\n");
522                         res = -1;
523                         break;
524                 }
525
526                 ast_debug(10, "frame %d/%llu, len=%d\n", inf->frametype, (unsigned long long) inf->subclass.codec, inf->datalen);
527
528                 /* Check the frame type. Format also must be checked because there is a chance
529                    that a frame in old format was already queued before we set channel format
530                    to slinear so it will still be received by ast_read */
531                 if (inf->frametype == AST_FRAME_VOICE && inf->subclass.codec == AST_FORMAT_SLINEAR) {
532                         if (fax_rx(&fax, inf->data.ptr, inf->samples) < 0) {
533                                 /* I know fax_rx never returns errors. The check here is for good style only */
534                                 ast_log(LOG_WARNING, "fax_rx returned error\n");
535                                 res = -1;
536                                 break;
537                         }
538                         if (last_state != t30state->state) {
539                                 state_change = ast_tvnow();
540                                 last_state = t30state->state;
541                         }
542                 } else if ((inf->frametype == AST_FRAME_CONTROL) &&
543                            (inf->subclass.integer == AST_CONTROL_T38_PARAMETERS)) {
544                         struct ast_control_t38_parameters *parameters = inf->data.ptr;
545
546                         if (parameters->request_response == AST_T38_NEGOTIATED) {
547                                 /* T38 switchover completed */
548                                 s->t38parameters = *parameters;
549                                 ast_debug(1, "T38 negotiated, finishing audio loop\n");
550                                 res = 1;
551                                 break;
552                         } else if (parameters->request_response == AST_T38_REQUEST_NEGOTIATE) {
553                                 t38_parameters.request_response = AST_T38_NEGOTIATED;
554                                 ast_debug(1, "T38 request received, accepting\n");
555                                 /* Complete T38 switchover */
556                                 ast_indicate_data(s->chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
557                                 /* Do not break audio loop, wait until channel driver finally acks switchover
558                                  * with AST_T38_NEGOTIATED
559                                  */
560                         }
561                 }
562
563                 ast_frfree(inf);
564                 inf = NULL;
565         }
566
567         ast_debug(1, "Loop finished, res=%d\n", res);
568
569         if (inf)
570                 ast_frfree(inf);
571
572         ast_deactivate_generator(s->chan);
573
574         /* If we are switching to T38, remove phase E handler. Otherwise it will be executed
575            by t30_terminate, display diagnostics and set status variables although no transmittion
576            has taken place yet. */
577         if (res > 0) {
578                 t30_set_phase_e_handler(t30state, NULL, NULL);
579         }
580
581         t30_terminate(t30state);
582         fax_release(&fax);
583
584 done:
585         if (original_write_fmt != AST_FORMAT_SLINEAR) {
586                 if (ast_set_write_format(s->chan, original_write_fmt) < 0)
587                         ast_log(LOG_WARNING, "Unable to restore write format on '%s'\n", s->chan->name);
588         }
589
590         if (original_read_fmt != AST_FORMAT_SLINEAR) {
591                 if (ast_set_read_format(s->chan, original_read_fmt) < 0)
592                         ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", s->chan->name);
593         }
594
595         return res;
596
597 }
598
599 static int transmit_t38(fax_session *s)
600 {
601         int res = 0;
602         t38_terminal_state_t t38;
603         struct ast_frame *inf = NULL;
604         int last_state = 0;
605         struct timeval now, start, state_change, last_frame;
606         t30_state_t *t30state;
607         t38_core_state_t *t38state;
608
609 #if SPANDSP_RELEASE_DATE >= 20080725
610         /* for spandsp shaphots 0.0.6 and higher */
611         t30state = &t38.t30;
612         t38state = &t38.t38_fe.t38;
613 #else
614         /* for spandsp releases 0.0.5 */
615         t30state = &t38.t30_state;
616         t38state = &t38.t38;
617 #endif
618
619         /* Initialize terminal */
620         memset(&t38, 0, sizeof(t38));
621         if (t38_terminal_init(&t38, s->caller_mode, t38_tx_packet_handler, s->chan) == NULL) {
622                 ast_log(LOG_WARNING, "Unable to start T.38 termination.\n");
623                 res = -1;
624                 goto disable_t38;
625         }
626
627         t38_set_max_datagram_size(t38state, s->t38parameters.max_ifp);
628
629         if (s->t38parameters.fill_bit_removal) {
630                 t38_set_fill_bit_removal(t38state, TRUE);
631         }
632         if (s->t38parameters.transcoding_mmr) {
633                 t38_set_mmr_transcoding(t38state, TRUE);
634         }
635         if (s->t38parameters.transcoding_jbig) {
636                 t38_set_jbig_transcoding(t38state, TRUE);
637         }
638
639         /* Setup logging */
640         set_logging(&t38.logging);
641         set_logging(&t30state->logging);
642         set_logging(&t38state->logging);
643
644         /* Configure terminal */
645         set_local_info(t30state, s);
646         set_file(t30state, s);
647         set_ecm(t30state, TRUE);
648
649         t30_set_phase_e_handler(t30state, phase_e_handler, s);
650
651         now = start = state_change = ast_tvnow();
652
653         while (!s->finished) {
654                 inf = NULL;
655
656                 if ((res = ast_waitfor(s->chan, 25)) < 0) {
657                         ast_debug(1, "Error waiting for a frame\n");
658                         break;
659                 }
660
661                 last_frame = now;
662
663                 /* Watchdog */
664                 now = ast_tvnow();
665                 if (ast_tvdiff_sec(now, start) > WATCHDOG_TOTAL_TIMEOUT || ast_tvdiff_sec(now, state_change) > WATCHDOG_STATE_TIMEOUT) {
666                         ast_log(LOG_WARNING, "It looks like we hung. Aborting.\n");
667                         res = -1;
668                         break;
669                 }
670                 
671                 t38_terminal_send_timeout(&t38, ast_tvdiff_us(now, last_frame) / (1000000 / 8000));
672
673                 if (!res) {
674                         /* There was timeout waiting for a frame. Loop around and wait again */
675                         continue;
676                 }
677
678                 /* There is a frame available. Get it */
679                 res = 0;
680
681                 if (!(inf = ast_read(s->chan))) {
682                         ast_debug(1, "Channel hangup\n");
683                         res = -1;
684                         break;
685                 }
686
687                 ast_debug(10, "frame %d/%d, len=%d\n", inf->frametype, inf->subclass.integer, inf->datalen);
688
689                 if (inf->frametype == AST_FRAME_MODEM && inf->subclass.integer == AST_MODEM_T38) {
690                         t38_core_rx_ifp_packet(t38state, inf->data.ptr, inf->datalen, inf->seqno);
691                         if (last_state != t30state->state) {
692                                 state_change = ast_tvnow();
693                                 last_state = t30state->state;
694                         }
695                 } else if (inf->frametype == AST_FRAME_CONTROL && inf->subclass.integer == AST_CONTROL_T38_PARAMETERS) {
696                         struct ast_control_t38_parameters *parameters = inf->data.ptr;
697                         if (parameters->request_response == AST_T38_TERMINATED) {
698                                 ast_debug(1, "T38 down, finishing\n");
699                                 break;
700                         }
701                 }
702
703                 ast_frfree(inf);
704                 inf = NULL;
705         }
706
707         ast_debug(1, "Loop finished, res=%d\n", res);
708
709         if (inf)
710                 ast_frfree(inf);
711
712         t30_terminate(t30state);
713         t38_terminal_release(&t38);
714
715 disable_t38:
716         /* if we are not the caller, it's our job to shut down the T.38
717          * session when the FAX transmisson is complete.
718          */
719         if ((s->caller_mode == FALSE) &&
720             (ast_channel_get_t38_state(s->chan) == T38_STATE_NEGOTIATED)) {
721                 struct ast_control_t38_parameters t38_parameters = { .request_response = AST_T38_REQUEST_TERMINATE, };
722
723                 if (ast_indicate_data(s->chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) == 0) {
724                         /* wait up to five seconds for negotiation to complete */
725                         unsigned int timeout = 5000;
726                         int ms;
727                         
728                         ast_debug(1, "Shutting down T.38 on %s\n", s->chan->name);
729                         while (timeout > 0) {
730                                 ms = ast_waitfor(s->chan, 1000);
731                                 if (ms < 0) {
732                                         ast_log(LOG_WARNING, "something bad happened while channel '%s' was polling.\n", s->chan->name);
733                                         return -1;
734                                 }
735                                 if (!ms) {
736                                         /* nothing happened */
737                                         if (timeout > 0) {
738                                                 timeout -= 1000;
739                                                 continue;
740                                         } else {
741                                                 ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 shutdown.\n", s->chan->name);
742                                                 break;
743                                         }
744                                 }
745                                 if (!(inf = ast_read(s->chan))) {
746                                         return -1;
747                                 }
748                                 if ((inf->frametype == AST_FRAME_CONTROL) &&
749                                     (inf->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
750                                     (inf->datalen == sizeof(t38_parameters))) {
751                                         struct ast_control_t38_parameters *parameters = inf->data.ptr;
752                                         
753                                         switch (parameters->request_response) {
754                                         case AST_T38_TERMINATED:
755                                                 ast_debug(1, "Shut down T.38 on %s\n", s->chan->name);
756                                                 break;
757                                         case AST_T38_REFUSED:
758                                                 ast_log(LOG_WARNING, "channel '%s' refused to disable T.38\n", s->chan->name);
759                                                 break;
760                                         default:
761                                                 ast_log(LOG_ERROR, "channel '%s' failed to disable T.38\n", s->chan->name);
762                                                 break;
763                                         }
764                                         ast_frfree(inf);
765                                         break;
766                                 }
767                                 ast_frfree(inf);
768                         }
769                 }
770         }
771
772         return res;
773 }
774
775 static int transmit(fax_session *s)
776 {
777         int res = 0;
778
779         /* Clear all channel variables which to be set by the application.
780            Pre-set status to error so in case of any problems we can just leave */
781         pbx_builtin_setvar_helper(s->chan, "FAXSTATUS", "FAILED"); 
782         pbx_builtin_setvar_helper(s->chan, "FAXERROR", "Channel problems"); 
783
784         pbx_builtin_setvar_helper(s->chan, "FAXMODE", NULL);
785         pbx_builtin_setvar_helper(s->chan, "REMOTESTATIONID", NULL);
786         pbx_builtin_setvar_helper(s->chan, "FAXPAGES", "0");
787         pbx_builtin_setvar_helper(s->chan, "FAXRESOLUTION", NULL);
788         pbx_builtin_setvar_helper(s->chan, "FAXBITRATE", NULL); 
789
790         if (s->chan->_state != AST_STATE_UP) {
791                 /* Shouldn't need this, but checking to see if channel is already answered
792                  * Theoretically asterisk should already have answered before running the app */
793                 res = ast_answer(s->chan);
794                 if (res) {
795                         ast_log(LOG_WARNING, "Could not answer channel '%s'\n", s->chan->name);
796                         return res;
797                 }
798         }
799
800         s->t38state = ast_channel_get_t38_state(s->chan);
801         if (s->t38state != T38_STATE_NEGOTIATED) {
802                 /* T38 is not negotiated on the channel yet. First start regular transmission. If it switches to T38, follow */ 
803                 pbx_builtin_setvar_helper(s->chan, "FAXMODE", "audio"); 
804                 res = transmit_audio(s);
805                 if (res > 0) {
806                         /* transmit_audio reports switchover to T38. Update t38state */
807                         s->t38state = ast_channel_get_t38_state(s->chan);
808                         if (s->t38state != T38_STATE_NEGOTIATED) {
809                                 ast_log(LOG_ERROR, "Audio loop reports T38 switchover but t38state != T38_STATE_NEGOTIATED\n");
810                         }
811                 }
812         }
813
814         if (s->t38state == T38_STATE_NEGOTIATED) {
815                 pbx_builtin_setvar_helper(s->chan, "FAXMODE", "T38"); 
816                 res = transmit_t38(s);
817         }
818
819         if (res) {
820                 ast_log(LOG_WARNING, "Transmission error\n");
821                 res = -1;
822         } else if (s->finished < 0) {
823                 ast_log(LOG_WARNING, "Transmission failed\n");
824         } else if (s->finished > 0) {
825                 ast_debug(1, "Transmission finished Ok\n");
826         }
827
828         return res;
829 }
830
831 /* === Application functions === */
832
833 static int sndfax_exec(struct ast_channel *chan, const char *data)
834 {
835         int res = 0;
836         char *parse;
837         fax_session session = { 0, };
838         char restore_digit_detect = 0;
839
840         AST_DECLARE_APP_ARGS(args,
841                 AST_APP_ARG(file_name);
842                 AST_APP_ARG(options);
843         );
844
845         if (chan == NULL) {
846                 ast_log(LOG_ERROR, "Fax channel is NULL. Giving up.\n");
847                 return -1;
848         }
849
850         /* The next few lines of code parse out the filename and header from the input string */
851         if (ast_strlen_zero(data)) {
852                 /* No data implies no filename or anything is present */
853                 ast_log(LOG_ERROR, "SendFAX requires an argument (filename)\n");
854                 return -1;
855         }
856
857         parse = ast_strdupa(data);
858         AST_STANDARD_APP_ARGS(args, parse);
859         
860         session.caller_mode = TRUE;
861
862         if (args.options) {
863                 if (strchr(args.options, 'a'))
864                         session.caller_mode = FALSE;
865         }
866
867         /* Done parsing */
868         session.direction = 1;
869         session.file_name = args.file_name;
870         session.chan = chan;
871         session.finished = 0;
872
873         /* get current digit detection mode, then disable digit detection if enabled */
874         {
875                 int dummy = sizeof(restore_digit_detect);
876
877                 ast_channel_queryoption(chan, AST_OPTION_DIGIT_DETECT, &restore_digit_detect, &dummy, 0);
878         }
879
880         if (restore_digit_detect) {
881                 char new_digit_detect = 0;
882
883                 ast_channel_setoption(chan, AST_OPTION_DIGIT_DETECT, &new_digit_detect, sizeof(new_digit_detect), 0);
884         }
885
886         /* disable FAX tone detection if enabled */
887         {
888                 char new_fax_detect = 0;
889
890                 ast_channel_setoption(chan, AST_OPTION_FAX_DETECT, &new_fax_detect, sizeof(new_fax_detect), 0);
891         }
892
893         res = transmit(&session);
894
895         if (restore_digit_detect) {
896                 ast_channel_setoption(chan, AST_OPTION_DIGIT_DETECT, &restore_digit_detect, sizeof(restore_digit_detect), 0);
897         }
898
899         return res;
900 }
901
902 static int rcvfax_exec(struct ast_channel *chan, const char *data)
903 {
904         int res = 0;
905         char *parse;
906         fax_session session;
907         char restore_digit_detect = 0;
908
909         AST_DECLARE_APP_ARGS(args,
910                 AST_APP_ARG(file_name);
911                 AST_APP_ARG(options);
912         );
913
914         if (chan == NULL) {
915                 ast_log(LOG_ERROR, "Fax channel is NULL. Giving up.\n");
916                 return -1;
917         }
918
919         /* The next few lines of code parse out the filename and header from the input string */
920         if (ast_strlen_zero(data)) {
921                 /* No data implies no filename or anything is present */
922                 ast_log(LOG_ERROR, "ReceiveFAX requires an argument (filename)\n");
923                 return -1;
924         }
925
926         parse = ast_strdupa(data);
927         AST_STANDARD_APP_ARGS(args, parse);
928         
929         session.caller_mode = FALSE;
930
931         if (args.options) {
932                 if (strchr(args.options, 'c'))
933                         session.caller_mode = TRUE;
934         }
935
936         /* Done parsing */
937         session.direction = 0;
938         session.file_name = args.file_name;
939         session.chan = chan;
940         session.finished = 0;
941
942         /* get current digit detection mode, then disable digit detection if enabled */
943         {
944                 int dummy = sizeof(restore_digit_detect);
945
946                 ast_channel_queryoption(chan, AST_OPTION_DIGIT_DETECT, &restore_digit_detect, &dummy, 0);
947         }
948
949         if (restore_digit_detect) {
950                 char new_digit_detect = 0;
951
952                 ast_channel_setoption(chan, AST_OPTION_DIGIT_DETECT, &new_digit_detect, sizeof(new_digit_detect), 0);
953         }
954
955         /* disable FAX tone detection if enabled */
956         {
957                 char new_fax_detect = 0;
958
959                 ast_channel_setoption(chan, AST_OPTION_FAX_DETECT, &new_fax_detect, sizeof(new_fax_detect), 0);
960         }
961
962         res = transmit(&session);
963
964         if (restore_digit_detect) {
965                 ast_channel_setoption(chan, AST_OPTION_DIGIT_DETECT, &restore_digit_detect, sizeof(restore_digit_detect), 0);
966         }
967
968         return res;
969 }
970
971 static int unload_module(void)
972 {
973         int res;
974
975         res = ast_unregister_application(app_sndfax_name);      
976         res |= ast_unregister_application(app_rcvfax_name);     
977
978         return res;
979 }
980
981 static int load_module(void)
982 {
983         int res ;
984
985         res = ast_register_application_xml(app_sndfax_name, sndfax_exec);
986         res |= ast_register_application_xml(app_rcvfax_name, rcvfax_exec);
987
988         /* The default SPAN message handler prints to stderr. It is something we do not want */
989         span_set_message_handler(NULL);
990
991         return res;
992 }
993
994
995 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Simple FAX Application",
996                 .load = load_module,
997                 .unload = unload_module,
998                 );
999
1000