2 * Application to receive a TIFF FAX file
3 * based on app_rxfax.c from: Copyright (C) 2003, Steve Underwood <steveu@coppice.org>
4 * based on app_rxfax.c from www.callweaver.org
5 * PATCHED BY (C) 20007 by Antonio Gallo <agx@linux.it>
7 * - added more env variables
13 Desciption: Receive a FAX to a file
19 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
31 #include <spandsp/version.h>
33 #include "asterisk/lock.h"
34 #include "asterisk/file.h"
35 #include "asterisk/logger.h"
36 #include "asterisk/channel.h"
37 #include "asterisk/pbx.h"
38 #include "asterisk/module.h"
39 #include "asterisk/manager.h"
42 #define AST_MODULE "app_rxfax"
45 static char *app = "RxFAX";
47 static char *synopsis = "Receive a FAX to a file";
49 static char *descrip =
50 " RxFAX(filename[|caller][|debug]): Receives a FAX from the channel into the\n"
51 "given filename. If the file exists it will be overwritten. The file\n"
52 "should be in TIFF/F format.\n"
53 "The \"caller\" option makes the application behave as a calling machine,\n"
54 "rather than the answering machine. The default behaviour is to behave as\n"
55 "an answering machine.\n"
56 "The \"ecm\" option enables ECM.\n"
57 "Uses LOCALSTATIONID to identify itself to the remote end.\n"
58 " LOCALSUBADDRESS to specify a sub-address to the remote end.\n"
59 " LOCALHEADERINFO to generate a header line on each page.\n"
61 " FAX_FORCE_V17 to force V.17 only\n"
62 " FAX_FORCE_V27 to force V.27 only\n"
63 " FAX_FORCE_V29 to force V.29 only\n"
64 " FAX_FORCE_V34 to force V.34 only\n"
66 "Sets REMOTESTATIONID to the sender CSID.\n"
67 " FAXPAGES to the number of pages received.\n"
68 " FAXBITRATE to the transmition rate.\n"
69 " FAXRESOLUTION to the resolution.\n"
70 " PHASEESTATUS to the phase E result status.\n"
71 " PHASEESTRING to the phase E result string.\n"
72 "Note that PHASEESTATUS=0 means that the fax was handled correctly. But that doesn't\n"
73 "imply that any pages were sent. Actually you should also check FAXPAGES to be\n"
74 "greater than zero.\n"
75 "Returns -1 when the user hangs up.\n"
76 "Returns 0 otherwise.\n";
78 #define MAX_BLOCK_SIZE 240
80 static FILE *rxfax_logfile = NULL;
82 static void file_log(const char *msg)
86 if (rxfax_logfile==NULL)
88 fprintf(rxfax_logfile, msg);
91 static void span_message(int level, const char *msg)
93 if (msg==NULL) return;
95 if (level == SPAN_LOG_ERROR)
96 ast_level = __LOG_ERROR;
97 else if (level == SPAN_LOG_WARNING)
98 ast_level = __LOG_WARNING;
100 ast_level = __LOG_DEBUG;
101 ast_log(ast_level, _A_, "%s", msg);
105 /*- End of function --------------------------------------------------------*/
107 static int phase_b_handler(t30_state_t *s, void *user_data, int result)
109 if (rxfax_logfile!=NULL) {
110 fprintf( rxfax_logfile, "[phase_b_handler] mark\n" );
111 fflush(rxfax_logfile);
116 /*- End of function --------------------------------------------------------*/
117 static void phase_e_handler(t30_state_t *s, void *user_data, int result)
119 struct ast_channel *chan;
120 const char *tx_ident;
121 const char *rx_ident;
125 chan = (struct ast_channel *) user_data;
126 t30_get_transfer_statistics(s, &t);
128 tx_ident = t30_get_tx_ident(s);
129 if (tx_ident == NULL)
131 rx_ident = t30_get_rx_ident(s);
132 if (rx_ident == NULL)
134 pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", rx_ident);
135 snprintf(buf, sizeof(buf), "%d", t.pages_transferred);
136 pbx_builtin_setvar_helper(chan, "FAXPAGES", buf);
137 snprintf(buf, sizeof(buf), "%d", t.y_resolution);
138 pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", buf);
139 snprintf(buf, sizeof(buf), "%d", t.bit_rate);
140 pbx_builtin_setvar_helper(chan, "FAXBITRATE", buf);
141 snprintf(buf, sizeof(buf), "%d", result);
142 pbx_builtin_setvar_helper(chan, "PHASEESTATUS", buf);
143 snprintf(buf, sizeof(buf), "%s", t30_completion_code_to_str(result));
144 pbx_builtin_setvar_helper(chan, "PHASEESTRING", buf);
146 ast_log(LOG_DEBUG, "==============================================================================\n");
147 if (result == T30_ERR_OK)
149 ast_log(LOG_DEBUG, "Fax successfully received.\n");
150 ast_log(LOG_DEBUG, "Remote station id: %s\n", rx_ident);
151 ast_log(LOG_DEBUG, "Local station id: %s\n", tx_ident);
152 ast_log(LOG_DEBUG, "Pages transferred: %i\n", t.pages_transferred);
153 ast_log(LOG_DEBUG, "Image resolution: %i x %i\n", t.x_resolution, t.y_resolution);
154 ast_log(LOG_DEBUG, "Transfer Rate: %i\n", t.bit_rate);
155 manager_event(EVENT_FLAG_CALL,
156 "FaxReceived", "Channel: %s\nExten: %s\nCallerID: %s\nRemoteStationID: %s\nLocalStationID: %s\nPagesTransferred: %i\nResolution: %i\nTransferRate: %i\nFileName: %s\n",
159 (chan->cid.cid_num) ? chan->cid.cid_num : "",
166 if (rxfax_logfile!=NULL) {
167 fprintf( rxfax_logfile, "\n[FAX OK] Remote: %s Local: %s Pages: %i Speed: %i\n\n",
168 rx_ident, tx_ident, t.pages_transferred, t.bit_rate
170 fflush(rxfax_logfile);
175 ast_log(LOG_DEBUG, "Fax receive not successful - result (%d) %s.\n", result, t30_completion_code_to_str(result));
176 if (rxfax_logfile!=NULL) {
177 fprintf( rxfax_logfile, "\n[FAX ERROR] code: %d %s\n\n", result, t30_completion_code_to_str(result) );
178 fflush(rxfax_logfile);
181 ast_log(LOG_DEBUG, "==============================================================================\n");
183 /*- End of function --------------------------------------------------------*/
185 static int phase_d_handler(t30_state_t *s, void *user_data, int result)
187 struct ast_channel *chan;
190 chan = (struct ast_channel *) user_data;
193 t30_get_transfer_statistics(s, &t);
194 ast_log(LOG_DEBUG, "==============================================================================\n");
195 ast_log(LOG_DEBUG, "Pages transferred: %i\n", t.pages_transferred);
196 ast_log(LOG_DEBUG, "Image size: %i x %i\n", t.width, t.length);
197 ast_log(LOG_DEBUG, "Image resolution %i x %i\n", t.x_resolution, t.y_resolution);
198 ast_log(LOG_DEBUG, "Transfer Rate: %i\n", t.bit_rate);
199 ast_log(LOG_DEBUG, "Bad rows %i\n", t.bad_rows);
200 ast_log(LOG_DEBUG, "Longest bad row run %i\n", t.longest_bad_row_run);
201 ast_log(LOG_DEBUG, "Compression type %s\n", t4_encoding_to_str(t.encoding));
202 ast_log(LOG_DEBUG, "Image size (bytes) %i\n", t.image_size);
203 ast_log(LOG_DEBUG, "==============================================================================\n");
204 if (rxfax_logfile!=NULL) {
205 fprintf( rxfax_logfile, "\n[phase_d_handler] Page: %i at %i\n\n", t.pages_transferred, t.bit_rate );
206 fflush(rxfax_logfile);
211 /*- End of function --------------------------------------------------------*/
213 static int rxfax_exec(struct ast_channel *chan, void *data)
216 char target_file[256];
217 char template_file[256];
227 struct ast_frame *inf = NULL;
228 struct ast_frame outf;
233 struct ast_module_user *u;
235 int original_read_fmt;
236 int original_write_fmt;
239 /* Basic initial checkings */
242 ast_log(LOG_WARNING, "Fax receive channel is NULL. Giving up.\n");
243 file_log("FATAL ERROR: Fax receive channel is NULL. Giving up.\n");
247 //span_set_message_handler(span_message);
248 /* make sure they are initialized to zero */
249 memset( &fax, 0, sizeof(fax));
251 /* Resetting channel variables related to T38 */
252 pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", "");
253 pbx_builtin_setvar_helper(chan, "FAXPAGES", "");
254 pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", "");
255 pbx_builtin_setvar_helper(chan, "FAXBITRATE", "");
256 pbx_builtin_setvar_helper(chan, "PHASEESTATUS", "");
257 pbx_builtin_setvar_helper(chan, "PHASEESTRING", "");
259 /* Parsig parameters */
261 /* The next few lines of code parse out the filename and header from the input string */
264 /* No data implies no filename or anything is present */
265 ast_log(LOG_WARNING, "Rxfax requires an argument (filename)\n");
266 file_log("ERROR: Rxfax requires an argument (filename)\n");
270 calling_party = FALSE;
272 target_file[0] = '\0';
275 for (option = 0, v = s = data; v; option++, s++) {
278 s = (v) ? v : s + strlen(s);
279 strncpy((char *) tbuf, t, s - t);
282 /* The first option is always the file name */
286 strncpy(target_file, t, len);
287 target_file[len] = '\0';
288 /* Allow the use of %d in the file name for a wild card of sorts, to
289 create a new file with the specified name scheme */
290 if ((x = strchr(target_file, '%')) && x[1] == 'd') {
291 strcpy(template_file, target_file);
294 snprintf(target_file, 256, template_file, 1);
296 } while (ast_fileexists(target_file, "", chan->language) != -1);
298 } else if (strncmp("caller", t, s - t) == 0) {
299 calling_party = TRUE;
300 } else if (strncmp("debug", t, s - t) == 0) {
302 } else if (strncmp("ecm", t, s - t) == 0) {
309 u = ast_module_user_add(chan);
311 if (chan->_state != AST_STATE_UP)
313 /* Shouldn't need this, but checking to see if channel is already answered
314 * Theoretically the PBX should already have answered before running the app */
315 res = ast_answer(chan);
316 /* NO NEED TO WARN ANYMORE
319 ast_log(LOG_WARNING, "Could not answer channel '%s'\n", chan->name);
320 file_log("Could not answer channel\n" );
325 /* Setting read and write formats */
327 original_read_fmt = chan->readformat;
328 if (original_read_fmt != AST_FORMAT_SLINEAR)
330 res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
333 ast_log(LOG_WARNING, "Unable to set to linear read mode, giving up\n");
334 file_log("ERROR: Unable to set to linear read mode, giving up\n");
335 ast_module_user_remove(u);
340 original_write_fmt = chan->writeformat;
341 if (original_write_fmt != AST_FORMAT_SLINEAR)
343 res = ast_set_write_format(chan, AST_FORMAT_SLINEAR);
346 ast_log(LOG_WARNING, "Unable to set to linear write mode, giving up\n");
347 file_log("ERROR: Unable to set to linear write mode, giving up\n");
348 res = ast_set_read_format(chan, original_read_fmt);
350 ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
351 ast_module_user_remove(u);
356 /* Remove any app level gain adjustments and disable echo cancel. */
359 ast_channel_setoption(chan, AST_OPTION_RXGAIN, &sc, sizeof(sc), 0);
360 ast_channel_setoption(chan, AST_OPTION_TXGAIN, &sc, sizeof(sc), 0);
361 ast_channel_setoption(chan, AST_OPTION_ECHOCAN, &sc, sizeof(sc), 0);
363 /* This is the main loop */
365 uint8_t __buf[sizeof(uint16_t)*MAX_BLOCK_SIZE + 2*AST_FRIENDLY_OFFSET];
366 uint8_t *buf = __buf + AST_FRIENDLY_OFFSET;
368 memset(&fax, 0, sizeof(fax));
370 if (fax_init(&fax, calling_party) == NULL)
372 ast_log(LOG_WARNING, "Unable to set to start fax_init\n");
373 file_log("ERROR: Unable to set to start fax_init\n");
374 ast_module_user_remove(u);
377 fax_set_transmit_on_idle(&fax, TRUE);
378 span_log_set_message_handler(&fax.logging, span_message);
379 span_log_set_message_handler(&fax.t30_state.logging, span_message);
382 span_log_set_level(&fax.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW);
383 span_log_set_level(&fax.t30_state.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW);
385 x = pbx_builtin_getvar_helper(chan, "LOCALSTATIONID");
387 t30_set_tx_ident(&fax.t30_state, x);
388 x = pbx_builtin_getvar_helper(chan, "LOCALSUBADDRESS");
390 t30_set_tx_sub_address(&fax.t30_state, x);
391 x = pbx_builtin_getvar_helper(chan, "LOCALHEADERINFO");
393 t30_set_tx_page_header_info(&fax.t30_state, x);
394 t30_set_rx_file(&fax.t30_state, target_file, -1);
395 t30_set_phase_b_handler(&fax.t30_state, phase_b_handler, chan);
396 t30_set_phase_d_handler(&fax.t30_state, phase_d_handler, chan);
397 t30_set_phase_e_handler(&fax.t30_state, phase_e_handler, chan);
399 // Default Support ALL
400 t30_set_supported_modems(&(fax.t30_state), T30_SUPPORT_V29 | T30_SUPPORT_V27TER | T30_SUPPORT_V17 );
402 x = pbx_builtin_getvar_helper(chan, "FAX_DISABLE_V17");
404 t30_set_supported_modems(&(fax.t30_state), T30_SUPPORT_V29 | T30_SUPPORT_V27TER);
406 x = pbx_builtin_getvar_helper(chan, "FAX_FORCE_V17");
408 t30_set_supported_modems(&(fax.t30_state), T30_SUPPORT_V17);
409 x = pbx_builtin_getvar_helper(chan, "FAX_FORCE_V27");
411 t30_set_supported_modems(&(fax.t30_state), T30_SUPPORT_V27TER);
412 x = pbx_builtin_getvar_helper(chan, "FAX_FORCE_V29");
414 t30_set_supported_modems(&(fax.t30_state), T30_SUPPORT_V29);
415 x = pbx_builtin_getvar_helper(chan, "FAX_FORCE_V34");
417 t30_set_supported_modems(&(fax.t30_state), T30_SUPPORT_V34);
419 /* Support for different image sizes && resolutions*/
420 t30_set_supported_image_sizes(&fax.t30_state, T30_SUPPORT_US_LETTER_LENGTH | T30_SUPPORT_US_LEGAL_LENGTH | T30_SUPPORT_UNLIMITED_LENGTH
421 | T30_SUPPORT_215MM_WIDTH | T30_SUPPORT_255MM_WIDTH | T30_SUPPORT_303MM_WIDTH);
422 t30_set_supported_resolutions(&fax.t30_state, T30_SUPPORT_STANDARD_RESOLUTION | T30_SUPPORT_FINE_RESOLUTION | T30_SUPPORT_SUPERFINE_RESOLUTION
423 | T30_SUPPORT_R8_RESOLUTION | T30_SUPPORT_R16_RESOLUTION);
425 t30_set_ecm_capability(&(fax.t30_state), TRUE);
426 t30_set_supported_compressions(&(fax.t30_state), T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION);
427 ast_log(LOG_DEBUG, "Enabling ECM mode for app_rxfax\n" );
428 file_log("DEBUG: Enabling ECM mode for app_rxfax\n" );
430 t30_set_ecm_capability(&(fax.t30_state), FALSE);
431 t30_set_supported_compressions(&(fax.t30_state), T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION );
435 /* This is the main loop */
439 /* temporary workwaround vars */
445 if (ast_check_hangup(chan)) {
446 ast_log(LOG_WARNING, "Channel has been hanged at fax.\n");
447 file_log("INFO: Channel has been hanged at fax.\n");
452 if ((res = ast_waitfor(chan, 20)) < 0) {
453 ast_log(LOG_WARNING, "Channel ast_waitfor < 0.\n");
454 file_log("WARNING: Channel ast_waitfor < 0.\n");
459 if ((fax.current_rx_type == T30_MODEM_DONE) || (fax.current_tx_type == T30_MODEM_DONE)) {
460 /* Avoid spamming debug info */
462 ast_log(LOG_WARNING, "Channel T30 DONE < 0.\n");
463 file_log("DEBUG: Channel T30 DONE.\n");
467 * NOTE: if i break here it seems to have bad behavios on some faxes that
468 * will not result as successfull send even if it has benn fully received
470 /*JUST WARNING: res = 0;
473 * Workaround: let 256 more packet to pass thru then definitively hangup
482 inf = ast_read(chan);
485 ast_log(LOG_WARNING, "Channel INF is NULL.\n");
486 file_log("DEBUG: Channel INF is NULL.\n");
488 // While trasmiitting i got: Received a DCN from remote after sending a page
496 //if (inf->frametype == AST_FRAME_VOICE) {
497 /* Check the frame type. Format also must be checked because there is a chance
498 that a frame in old format was already queued before we set chanel format
499 to slinear so it will still be received by ast_read */
500 if (inf->frametype == AST_FRAME_VOICE && inf->subclass == AST_FORMAT_SLINEAR) {
501 if (fax_rx(&fax, inf->data, inf->samples)) {
502 ast_log(LOG_WARNING, "RXFAX: fax_rx returned error\n");
507 samples = (inf->samples <= MAX_BLOCK_SIZE) ? inf->samples : MAX_BLOCK_SIZE;
508 len = fax_tx(&fax, (int16_t *) &buf[AST_FRIENDLY_OFFSET], samples);
511 ast_log(LOG_WARNING, "len <=0 using samples.\n");
512 file_log("len <= 0 using samples.\n");
515 memset(&outf, 0, sizeof(outf));
516 outf.frametype = AST_FRAME_VOICE;
517 outf.subclass = AST_FORMAT_SLINEAR;
518 outf.datalen = len*sizeof(int16_t);
520 outf.data = &buf[AST_FRIENDLY_OFFSET];
521 outf.offset = AST_FRIENDLY_OFFSET;
524 memset(&buf[AST_FRIENDLY_OFFSET], 0, outf.datalen);
526 if (ast_write(chan, &outf) < 0)
528 ast_log(LOG_WARNING, "Unable to write frame to channel; %s\n", strerror(errno));
529 file_log("ERROR: Unable to write frame to channel\n");
537 /* TODO put a Watchdog here */
546 t30_terminate(&fax.t30_state);
549 /* Restoring initial channel formats. */
551 if (original_read_fmt != AST_FORMAT_SLINEAR)
553 res = ast_set_read_format(chan, original_read_fmt);
555 ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
557 if (original_write_fmt != AST_FORMAT_SLINEAR)
559 res = ast_set_write_format(chan, original_write_fmt);
561 ast_log(LOG_WARNING, "Unable to restore write format on '%s'\n", chan->name);
563 ast_module_user_remove(u);
566 /*- End of function --------------------------------------------------------*/
568 static int unload_module(void)
571 ast_module_user_hangup_all();
572 res = ast_unregister_application(app);
574 fclose(rxfax_logfile);
575 rxfax_logfile = NULL;
579 /*- End of function --------------------------------------------------------*/
581 static int load_module(void)
583 ast_log(LOG_NOTICE, "RxFax using spandsp %i %i\n", SPANDSP_RELEASE_DATE, SPANDSP_RELEASE_TIME );
584 rxfax_logfile = fopen("/var/log/rxfax.log", "w+" );
586 ast_log(LOG_WARNING, "RxFax output also available in /var/log/rxfax.log\n" );
587 return ast_register_application(app, rxfax_exec, synopsis, descrip);
589 /*- End of function --------------------------------------------------------*/
591 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Trivial FAX Receive Application");
593 /*- End of file ------------------------------------------------------------*/