00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "asterisk.h"
00020
00021 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 245731 $")
00022
00023 #include <string.h>
00024 #include <stdlib.h>
00025 #include <stdio.h>
00026 #include <inttypes.h>
00027 #include <pthread.h>
00028 #include <errno.h>
00029 #include <tiffio.h>
00030
00031 #include <spandsp.h>
00032 #ifdef HAVE_SPANDSP_EXPOSE_H
00033 #include <spandsp/expose.h>
00034 #endif
00035 #include <spandsp/version.h>
00036
00037 #include "asterisk/lock.h"
00038 #include "asterisk/file.h"
00039 #include "asterisk/logger.h"
00040 #include "asterisk/channel.h"
00041 #include "asterisk/pbx.h"
00042 #include "asterisk/app.h"
00043 #include "asterisk/dsp.h"
00044 #include "asterisk/module.h"
00045 #include "asterisk/manager.h"
00046
00047 static char *app_sndfax_name = "SendFAX";
00048 static char *app_sndfax_synopsis = "Send a FAX";
00049 static char *app_sndfax_desc =
00050 " SendFAX(filename[|options]):\n"
00051 "Send a given TIFF file to the channel as a FAX.\n"
00052 "The option string may contain zero or more of the following characters:\n"
00053 " 'a' - makes the application behave as an answering machine\n"
00054 " The default behaviour is to behave as a calling machine.\n"
00055 "\n"
00056 "This application uses following variables:\n"
00057 " LOCALSTATIONID to identify itself to the remote end.\n"
00058 " LOCALHEADERINFO to generate a header line on each page.\n"
00059 "\n"
00060 "This application sets the following channel variables upon completion:\n"
00061 " FAXSTATUS - status of operation:\n"
00062 " SUCCESS | FAILED\n"
00063 " FAXERROR - Error when FAILED\n"
00064 " FAXMODE - Mode used:\n"
00065 " audio | T38\n"
00066 " REMOTESTATIONID - CSID of the remote side.\n"
00067 " FAXPAGES - number of pages sent.\n"
00068 " FAXBITRATE - transmition rate.\n"
00069 " FAXRESOLUTION - resolution.\n"
00070 "\n"
00071 "Returns -1 in case of user hang up or any channel error.\n"
00072 "Returns 0 on success.\n";
00073
00074 static char *app_rcvfax_name = "ReceiveFAX";
00075 static char *app_rcvfax_synopsis = "Receive a FAX";
00076 static char *app_rcvfax_desc =
00077 " ReceiveFAX(filename[|options]):\n"
00078 "Receives a fax from the channel into the given filename overwriting\n"
00079 "the file if it already exists. File created will have TIFF format.\n"
00080 "The option string may contain zero or more of the following characters:\n"
00081 " 'c' -- makes the application behave as a calling machine\n"
00082 " The default behaviour is to behave as an answering machine.\n"
00083 "\n"
00084 "This application uses following variables:\n"
00085 " LOCALSTATIONID to identify itself to the remote end.\n"
00086 " LOCALHEADERINFO to generate a header line on each page.\n"
00087 "\n"
00088 "This application sets the following channel variables upon completion:\n"
00089 " FAXSTATUS - status of operation:\n"
00090 " SUCCESS | FAILED\n"
00091 " FAXERROR - Error when FAILED\n"
00092 " FAXMODE - Mode used:\n"
00093 " audio | T38\n"
00094 " REMOTESTATIONID - CSID of the remote side.\n"
00095 " FAXPAGES - number of pages sent.\n"
00096 " FAXBITRATE - transmition rate.\n"
00097 " FAXRESOLUTION - resolution.\n"
00098 "\n"
00099 "Returns -1 in case of user hang up or any channel error.\n"
00100 "Returns 0 on success.\n";
00101
00102 #define MAX_SAMPLES 240
00103
00104
00105
00106
00107
00108
00109
00110 #define WATCHDOG_TOTAL_TIMEOUT 30 * 60
00111 #define WATCHDOG_STATE_TIMEOUT 5 * 60
00112
00113 typedef struct {
00114 struct ast_channel *chan;
00115 enum ast_t38_state t38state;
00116 int direction;
00117 int caller_mode;
00118 char *file_name;
00119 struct ast_control_t38_parameters t38parameters;
00120 volatile int finished;
00121 } fax_session;
00122
00123 static void span_message(int level, const char *msg)
00124 {
00125 if (level == SPAN_LOG_ERROR) {
00126 ast_log(LOG_ERROR, "%s", msg);
00127 } else if (level == SPAN_LOG_WARNING) {
00128 ast_log(LOG_WARNING, "%s", msg);
00129 } else {
00130 ast_log(LOG_DEBUG, "%s", msg);
00131 }
00132 }
00133
00134 static int t38_tx_packet_handler(t38_core_state_t *s, void *user_data, const uint8_t *buf, int len, int count)
00135 {
00136 struct ast_channel *chan = (struct ast_channel *) user_data;
00137
00138 struct ast_frame outf = {
00139 .frametype = AST_FRAME_MODEM,
00140 .subclass = AST_MODEM_T38,
00141 .src = __FUNCTION__,
00142 };
00143
00144
00145
00146
00147 AST_FRAME_SET_BUFFER(&outf, buf, 0, len);
00148
00149 if (ast_write(chan, &outf) < 0) {
00150 ast_log(LOG_WARNING, "Unable to write frame to channel; %s\n", strerror(errno));
00151 return -1;
00152 }
00153
00154 return 0;
00155 }
00156
00157 static void phase_e_handler(t30_state_t *f, void *user_data, int result)
00158 {
00159 const char *local_ident;
00160 const char *far_ident;
00161 char buf[20];
00162 fax_session *s = (fax_session *) user_data;
00163 t30_stats_t stat;
00164 int pages_transferred;
00165
00166 ast_debug(1, "Fax phase E handler. result=%d\n", result);
00167
00168 t30_get_transfer_statistics(f, &stat);
00169
00170 s = (fax_session *) user_data;
00171
00172 if (result != T30_ERR_OK) {
00173 s->finished = -1;
00174
00175
00176 pbx_builtin_setvar_helper(s->chan, "FAXERROR", t30_completion_code_to_str(result));
00177
00178 ast_log(LOG_WARNING, "Error transmitting fax. result=%d: %s.\n", result, t30_completion_code_to_str(result));
00179
00180 return;
00181 }
00182
00183 s->finished = 1;
00184
00185 local_ident = t30_get_tx_ident(f);
00186 far_ident = t30_get_rx_ident(f);
00187 pbx_builtin_setvar_helper(s->chan, "FAXSTATUS", "SUCCESS");
00188 pbx_builtin_setvar_helper(s->chan, "FAXERROR", NULL);
00189 pbx_builtin_setvar_helper(s->chan, "REMOTESTATIONID", far_ident);
00190 #if SPANDSP_RELEASE_DATE >= 20090220
00191 pages_transferred = (s->direction) ? stat.pages_tx : stat.pages_rx;
00192 #else
00193 pages_transferred = stat.pages_transferred;
00194 #endif
00195 snprintf(buf, sizeof(buf), "%d", pages_transferred);
00196 pbx_builtin_setvar_helper(s->chan, "FAXPAGES", buf);
00197 snprintf(buf, sizeof(buf), "%d", stat.y_resolution);
00198 pbx_builtin_setvar_helper(s->chan, "FAXRESOLUTION", buf);
00199 snprintf(buf, sizeof(buf), "%d", stat.bit_rate);
00200 pbx_builtin_setvar_helper(s->chan, "FAXBITRATE", buf);
00201
00202 ast_debug(1, "Fax transmitted successfully.\n");
00203 ast_debug(1, " Remote station ID: %s\n", far_ident);
00204 ast_debug(1, " Pages transferred: %d\n", pages_transferred);
00205 ast_debug(1, " Image resolution: %d x %d\n", stat.x_resolution, stat.y_resolution);
00206 ast_debug(1, " Transfer Rate: %d\n", stat.bit_rate);
00207
00208 manager_event(EVENT_FLAG_CALL,
00209 s->direction ? "FaxSent" : "FaxReceived",
00210 "Channel: %s\r\n"
00211 "Exten: %s\r\n"
00212 "CallerID: %s\r\n"
00213 "RemoteStationID: %s\r\n"
00214 "LocalStationID: %s\r\n"
00215 "PagesTransferred: %d\r\n"
00216 "Resolution: %d\r\n"
00217 "TransferRate: %d\r\n"
00218 "FileName: %s\r\n",
00219 s->chan->name,
00220 s->chan->exten,
00221 S_OR(s->chan->cid.cid_num, ""),
00222 far_ident,
00223 local_ident,
00224 pages_transferred,
00225 stat.y_resolution,
00226 stat.bit_rate,
00227 s->file_name);
00228 }
00229
00230
00231
00232
00233 static int set_logging(logging_state_t *state)
00234 {
00235 int level = SPAN_LOG_WARNING + option_debug;
00236
00237 span_log_set_message_handler(state, span_message);
00238 span_log_set_level(state, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | level);
00239
00240 return 0;
00241 }
00242
00243 static void set_local_info(t30_state_t *state, fax_session *s)
00244 {
00245 const char *x;
00246
00247 x = pbx_builtin_getvar_helper(s->chan, "LOCALSTATIONID");
00248 if (!ast_strlen_zero(x))
00249 t30_set_tx_ident(state, x);
00250
00251 x = pbx_builtin_getvar_helper(s->chan, "LOCALHEADERINFO");
00252 if (!ast_strlen_zero(x))
00253 t30_set_tx_page_header_info(state, x);
00254 }
00255
00256 static void set_file(t30_state_t *state, fax_session *s)
00257 {
00258 if (s->direction)
00259 t30_set_tx_file(state, s->file_name, -1, -1);
00260 else
00261 t30_set_rx_file(state, s->file_name, -1);
00262 }
00263
00264 static void set_ecm(t30_state_t *state, int ecm)
00265 {
00266 t30_set_ecm_capability(state, ecm);
00267 t30_set_supported_compressions(state, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION);
00268 }
00269
00270
00271
00272
00273
00274 static void *fax_generator_alloc(struct ast_channel *chan, void *params)
00275 {
00276 return params;
00277 }
00278
00279 static int fax_generator_generate(struct ast_channel *chan, void *data, int len, int samples)
00280 {
00281 fax_state_t *fax = (fax_state_t*) data;
00282 uint8_t buffer[AST_FRIENDLY_OFFSET + MAX_SAMPLES * sizeof(uint16_t)];
00283 int16_t *buf = (int16_t *) (buffer + AST_FRIENDLY_OFFSET);
00284
00285 struct ast_frame outf = {
00286 .frametype = AST_FRAME_VOICE,
00287 .subclass = AST_FORMAT_SLINEAR,
00288 .src = __FUNCTION__,
00289 };
00290
00291 if (samples > MAX_SAMPLES) {
00292 ast_log(LOG_WARNING, "Only generating %d samples, where %d requested\n", MAX_SAMPLES, samples);
00293 samples = MAX_SAMPLES;
00294 }
00295
00296 if ((len = fax_tx(fax, buf, samples)) > 0) {
00297 outf.samples = len;
00298 AST_FRAME_SET_BUFFER(&outf, buffer, AST_FRIENDLY_OFFSET, len * sizeof(int16_t));
00299
00300 if (ast_write(chan, &outf) < 0) {
00301 ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", chan->name, strerror(errno));
00302 return -1;
00303 }
00304 }
00305
00306 return 0;
00307 }
00308
00309 struct ast_generator generator = {
00310 alloc: fax_generator_alloc,
00311 generate: fax_generator_generate,
00312 };
00313
00314
00315
00316
00317 static int transmit_audio(fax_session *s)
00318 {
00319 int res = -1;
00320 int original_read_fmt = AST_FORMAT_SLINEAR;
00321 int original_write_fmt = AST_FORMAT_SLINEAR;
00322 fax_state_t fax;
00323 t30_state_t *t30state;
00324 struct ast_frame *inf = NULL;
00325 int last_state = 0;
00326 struct timeval now, start, state_change;
00327 enum ast_t38_state t38_state;
00328 struct ast_control_t38_parameters t38_parameters = { .version = 0,
00329 .max_ifp = 800,
00330 .rate = AST_T38_RATE_14400,
00331 .rate_management = AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF,
00332 .fill_bit_removal = 1,
00333
00334
00335
00336
00337
00338
00339 };
00340
00341
00342 if (s->caller_mode == FALSE) {
00343
00344
00345
00346
00347 if ((t38_state = ast_channel_get_t38_state(s->chan)) == T38_STATE_NEGOTIATED) {
00348 return 1;
00349 } else if ((t38_state != T38_STATE_UNAVAILABLE) &&
00350 (t38_parameters.request_response = AST_T38_REQUEST_NEGOTIATE,
00351 (ast_indicate_data(s->chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) == 0))) {
00352
00353 unsigned int timeout = 5000;
00354 int ms;
00355
00356 ast_debug(1, "Negotiating T.38 for receive on %s\n", s->chan->name);
00357 while (timeout > 0) {
00358 ms = ast_waitfor(s->chan, 1000);
00359 if (ms < 0) {
00360 ast_log(LOG_WARNING, "something bad happened while channel '%s' was polling.\n", s->chan->name);
00361 return -1;
00362 }
00363 if (!ms) {
00364
00365 if (timeout > 0) {
00366 timeout -= 1000;
00367 continue;
00368 } else {
00369 ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 negotiation.\n", s->chan->name);
00370 break;
00371 }
00372 }
00373 if (!(inf = ast_read(s->chan))) {
00374 return -1;
00375 }
00376 if ((inf->frametype == AST_FRAME_CONTROL) &&
00377 (inf->subclass == AST_CONTROL_T38_PARAMETERS) &&
00378 (inf->datalen == sizeof(t38_parameters))) {
00379 struct ast_control_t38_parameters *parameters = inf->data.ptr;
00380
00381 switch (parameters->request_response) {
00382 case AST_T38_NEGOTIATED:
00383 ast_debug(1, "Negotiated T.38 for receive on %s\n", s->chan->name);
00384 res = 1;
00385 break;
00386 case AST_T38_REFUSED:
00387 ast_log(LOG_WARNING, "channel '%s' refused to negotiate T.38\n", s->chan->name);
00388 break;
00389 default:
00390 ast_log(LOG_ERROR, "channel '%s' failed to negotiate T.38\n", s->chan->name);
00391 break;
00392 }
00393 ast_frfree(inf);
00394 if (res == 1) {
00395 return 1;
00396 } else {
00397 break;
00398 }
00399 }
00400 ast_frfree(inf);
00401 }
00402 }
00403 }
00404
00405 #if SPANDSP_RELEASE_DATE >= 20080725
00406
00407 t30state = &fax.t30;
00408 #else
00409
00410 t30state = &fax.t30_state;
00411 #endif
00412
00413 original_read_fmt = s->chan->readformat;
00414 if (original_read_fmt != AST_FORMAT_SLINEAR) {
00415 res = ast_set_read_format(s->chan, AST_FORMAT_SLINEAR);
00416 if (res < 0) {
00417 ast_log(LOG_WARNING, "Unable to set to linear read mode, giving up\n");
00418 goto done;
00419 }
00420 }
00421
00422 original_write_fmt = s->chan->writeformat;
00423 if (original_write_fmt != AST_FORMAT_SLINEAR) {
00424 res = ast_set_write_format(s->chan, AST_FORMAT_SLINEAR);
00425 if (res < 0) {
00426 ast_log(LOG_WARNING, "Unable to set to linear write mode, giving up\n");
00427 goto done;
00428 }
00429 }
00430
00431
00432 fax_init(&fax, s->caller_mode);
00433
00434
00435 set_logging(&fax.logging);
00436 set_logging(&t30state->logging);
00437
00438
00439 set_local_info(t30state, s);
00440 set_file(t30state, s);
00441 set_ecm(t30state, TRUE);
00442
00443 fax_set_transmit_on_idle(&fax, TRUE);
00444
00445 t30_set_phase_e_handler(t30state, phase_e_handler, s);
00446
00447 start = state_change = ast_tvnow();
00448
00449 ast_activate_generator(s->chan, &generator, &fax);
00450
00451 while (!s->finished) {
00452 inf = NULL;
00453
00454 if ((res = ast_waitfor(s->chan, 25)) < 0) {
00455 ast_debug(1, "Error waiting for a frame\n");
00456 break;
00457 }
00458
00459
00460 now = ast_tvnow();
00461 if (ast_tvdiff_sec(now, start) > WATCHDOG_TOTAL_TIMEOUT || ast_tvdiff_sec(now, state_change) > WATCHDOG_STATE_TIMEOUT) {
00462 ast_log(LOG_WARNING, "It looks like we hung. Aborting.\n");
00463 res = -1;
00464 break;
00465 }
00466
00467 if (!res) {
00468
00469 continue;
00470 }
00471
00472
00473 res = 0;
00474
00475 if (!(inf = ast_read(s->chan))) {
00476 ast_debug(1, "Channel hangup\n");
00477 res = -1;
00478 break;
00479 }
00480
00481 ast_debug(10, "frame %d/%d, len=%d\n", inf->frametype, inf->subclass, inf->datalen);
00482
00483
00484
00485
00486 if (inf->frametype == AST_FRAME_VOICE && inf->subclass == AST_FORMAT_SLINEAR) {
00487 if (fax_rx(&fax, inf->data.ptr, inf->samples) < 0) {
00488
00489 ast_log(LOG_WARNING, "fax_rx returned error\n");
00490 res = -1;
00491 break;
00492 }
00493 if (last_state != t30state->state) {
00494 state_change = ast_tvnow();
00495 last_state = t30state->state;
00496 }
00497 } else if ((inf->frametype == AST_FRAME_CONTROL) &&
00498 (inf->subclass == AST_CONTROL_T38_PARAMETERS)) {
00499 struct ast_control_t38_parameters *parameters = inf->data.ptr;
00500
00501 if (parameters->request_response == AST_T38_NEGOTIATED) {
00502
00503 s->t38parameters = *parameters;
00504 ast_debug(1, "T38 negotiated, finishing audio loop\n");
00505 res = 1;
00506 break;
00507 } else if (parameters->request_response == AST_T38_REQUEST_NEGOTIATE) {
00508 t38_parameters.request_response = AST_T38_NEGOTIATED;
00509 ast_debug(1, "T38 request received, accepting\n");
00510
00511 ast_indicate_data(s->chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
00512
00513
00514
00515 }
00516 }
00517
00518 ast_frfree(inf);
00519 inf = NULL;
00520 }
00521
00522 ast_debug(1, "Loop finished, res=%d\n", res);
00523
00524 if (inf)
00525 ast_frfree(inf);
00526
00527 ast_deactivate_generator(s->chan);
00528
00529
00530
00531
00532 if (res > 0) {
00533 t30_set_phase_e_handler(t30state, NULL, NULL);
00534 }
00535
00536 t30_terminate(t30state);
00537 fax_release(&fax);
00538
00539 done:
00540 if (original_write_fmt != AST_FORMAT_SLINEAR) {
00541 if (ast_set_write_format(s->chan, original_write_fmt) < 0)
00542 ast_log(LOG_WARNING, "Unable to restore write format on '%s'\n", s->chan->name);
00543 }
00544
00545 if (original_read_fmt != AST_FORMAT_SLINEAR) {
00546 if (ast_set_read_format(s->chan, original_read_fmt) < 0)
00547 ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", s->chan->name);
00548 }
00549
00550 return res;
00551
00552 }
00553
00554 static int transmit_t38(fax_session *s)
00555 {
00556 int res = 0;
00557 t38_terminal_state_t t38;
00558 struct ast_frame *inf = NULL;
00559 int last_state = 0;
00560 struct timeval now, start, state_change, last_frame;
00561 t30_state_t *t30state;
00562 t38_core_state_t *t38state;
00563
00564 #if SPANDSP_RELEASE_DATE >= 20080725
00565
00566 t30state = &t38.t30;
00567 t38state = &t38.t38_fe.t38;
00568 #else
00569
00570 t30state = &t38.t30_state;
00571 t38state = &t38.t38;
00572 #endif
00573
00574
00575 memset(&t38, 0, sizeof(t38));
00576 if (t38_terminal_init(&t38, s->caller_mode, t38_tx_packet_handler, s->chan) == NULL) {
00577 ast_log(LOG_WARNING, "Unable to start T.38 termination.\n");
00578 res = -1;
00579 goto disable_t38;
00580 }
00581
00582 t38_set_max_datagram_size(t38state, s->t38parameters.max_ifp);
00583
00584 if (s->t38parameters.fill_bit_removal) {
00585 t38_set_fill_bit_removal(t38state, TRUE);
00586 }
00587 if (s->t38parameters.transcoding_mmr) {
00588 t38_set_mmr_transcoding(t38state, TRUE);
00589 }
00590 if (s->t38parameters.transcoding_jbig) {
00591 t38_set_jbig_transcoding(t38state, TRUE);
00592 }
00593
00594
00595 set_logging(&t38.logging);
00596 set_logging(&t30state->logging);
00597 set_logging(&t38state->logging);
00598
00599
00600 set_local_info(t30state, s);
00601 set_file(t30state, s);
00602 set_ecm(t30state, TRUE);
00603
00604 t30_set_phase_e_handler(t30state, phase_e_handler, s);
00605
00606 now = start = state_change = ast_tvnow();
00607
00608 while (!s->finished) {
00609
00610 res = ast_waitfor(s->chan, 20);
00611 if (res < 0)
00612 break;
00613 else if (res > 0)
00614 res = 0;
00615
00616 last_frame = now;
00617 now = ast_tvnow();
00618 t38_terminal_send_timeout(&t38, ast_tvdiff_us(now, last_frame) / (1000000 / 8000));
00619
00620 inf = ast_read(s->chan);
00621 if (inf == NULL) {
00622 ast_debug(1, "Channel hangup\n");
00623 res = -1;
00624 break;
00625 }
00626
00627 ast_debug(10, "frame %d/%d, len=%d\n", inf->frametype, inf->subclass, inf->datalen);
00628
00629 if (inf->frametype == AST_FRAME_MODEM && inf->subclass == AST_MODEM_T38) {
00630 t38_core_rx_ifp_packet(t38state, inf->data.ptr, inf->datalen, inf->seqno);
00631
00632
00633 if (last_state != t30state->state) {
00634 state_change = ast_tvnow();
00635 last_state = t30state->state;
00636 }
00637 } else if (inf->frametype == AST_FRAME_CONTROL && inf->subclass == AST_CONTROL_T38_PARAMETERS) {
00638 struct ast_control_t38_parameters *parameters = inf->data.ptr;
00639 if (parameters->request_response == AST_T38_TERMINATED) {
00640 ast_debug(1, "T38 down, finishing\n");
00641 break;
00642 }
00643 }
00644
00645 ast_frfree(inf);
00646 inf = NULL;
00647
00648
00649 if (ast_tvdiff_sec(now, start) > WATCHDOG_TOTAL_TIMEOUT || ast_tvdiff_sec(now, state_change) > WATCHDOG_STATE_TIMEOUT) {
00650 ast_log(LOG_WARNING, "It looks like we hung. Aborting.\n");
00651 res = -1;
00652 break;
00653 }
00654 }
00655
00656 ast_debug(1, "Loop finished, res=%d\n", res);
00657
00658 if (inf)
00659 ast_frfree(inf);
00660
00661 t30_terminate(t30state);
00662 t38_terminal_release(&t38);
00663
00664 disable_t38:
00665
00666
00667
00668 if ((s->caller_mode == FALSE) &&
00669 (ast_channel_get_t38_state(s->chan) == T38_STATE_NEGOTIATED)) {
00670 struct ast_control_t38_parameters t38_parameters = { .request_response = AST_T38_REQUEST_TERMINATE, };
00671
00672 if (ast_indicate_data(s->chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) == 0) {
00673
00674 unsigned int timeout = 5000;
00675 int ms;
00676
00677 ast_debug(1, "Shutting down T.38 on %s\n", s->chan->name);
00678 while (timeout > 0) {
00679 ms = ast_waitfor(s->chan, 1000);
00680 if (ms < 0) {
00681 ast_log(LOG_WARNING, "something bad happened while channel '%s' was polling.\n", s->chan->name);
00682 return -1;
00683 }
00684 if (!ms) {
00685
00686 if (timeout > 0) {
00687 timeout -= 1000;
00688 continue;
00689 } else {
00690 ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 shutdown.\n", s->chan->name);
00691 break;
00692 }
00693 }
00694 if (!(inf = ast_read(s->chan))) {
00695 return -1;
00696 }
00697 if ((inf->frametype == AST_FRAME_CONTROL) &&
00698 (inf->subclass == AST_CONTROL_T38_PARAMETERS) &&
00699 (inf->datalen == sizeof(t38_parameters))) {
00700 struct ast_control_t38_parameters *parameters = inf->data.ptr;
00701
00702 switch (parameters->request_response) {
00703 case AST_T38_TERMINATED:
00704 ast_debug(1, "Shut down T.38 on %s\n", s->chan->name);
00705 break;
00706 case AST_T38_REFUSED:
00707 ast_log(LOG_WARNING, "channel '%s' refused to disable T.38\n", s->chan->name);
00708 break;
00709 default:
00710 ast_log(LOG_ERROR, "channel '%s' failed to disable T.38\n", s->chan->name);
00711 break;
00712 }
00713 ast_frfree(inf);
00714 break;
00715 }
00716 ast_frfree(inf);
00717 }
00718 }
00719 }
00720
00721 return res;
00722 }
00723
00724 static int transmit(fax_session *s)
00725 {
00726 int res = 0;
00727
00728
00729
00730 pbx_builtin_setvar_helper(s->chan, "FAXSTATUS", "FAILED");
00731 pbx_builtin_setvar_helper(s->chan, "FAXERROR", "Channel problems");
00732
00733 pbx_builtin_setvar_helper(s->chan, "FAXMODE", NULL);
00734 pbx_builtin_setvar_helper(s->chan, "REMOTESTATIONID", NULL);
00735 pbx_builtin_setvar_helper(s->chan, "FAXPAGES", NULL);
00736 pbx_builtin_setvar_helper(s->chan, "FAXRESOLUTION", NULL);
00737 pbx_builtin_setvar_helper(s->chan, "FAXBITRATE", NULL);
00738
00739 if (s->chan->_state != AST_STATE_UP) {
00740
00741
00742 res = ast_answer(s->chan);
00743 if (res) {
00744 ast_log(LOG_WARNING, "Could not answer channel '%s'\n", s->chan->name);
00745 return res;
00746 }
00747 }
00748
00749 s->t38state = ast_channel_get_t38_state(s->chan);
00750 if (s->t38state != T38_STATE_NEGOTIATED) {
00751
00752 pbx_builtin_setvar_helper(s->chan, "FAXMODE", "audio");
00753 res = transmit_audio(s);
00754 if (res > 0) {
00755
00756 s->t38state = ast_channel_get_t38_state(s->chan);
00757 if (s->t38state != T38_STATE_NEGOTIATED) {
00758 ast_log(LOG_ERROR, "Audio loop reports T38 switchover but t38state != T38_STATE_NEGOTIATED\n");
00759 }
00760 }
00761 }
00762
00763 if (s->t38state == T38_STATE_NEGOTIATED) {
00764 pbx_builtin_setvar_helper(s->chan, "FAXMODE", "T38");
00765 res = transmit_t38(s);
00766 }
00767
00768 if (res) {
00769 ast_log(LOG_WARNING, "Transmission error\n");
00770 res = -1;
00771 } else if (s->finished < 0) {
00772 ast_log(LOG_WARNING, "Transmission failed\n");
00773 } else if (s->finished > 0) {
00774 ast_debug(1, "Transmission finished Ok\n");
00775 }
00776
00777 return res;
00778 }
00779
00780
00781
00782 static int sndfax_exec(struct ast_channel *chan, void *data)
00783 {
00784 int res = 0;
00785 char *parse;
00786 fax_session session = { 0, };
00787
00788 AST_DECLARE_APP_ARGS(args,
00789 AST_APP_ARG(file_name);
00790 AST_APP_ARG(options);
00791 );
00792
00793 if (chan == NULL) {
00794 ast_log(LOG_ERROR, "Fax channel is NULL. Giving up.\n");
00795 return -1;
00796 }
00797
00798
00799 if (ast_strlen_zero(data)) {
00800
00801 ast_log(LOG_ERROR, "SendFAX requires an argument (filename)\n");
00802 return -1;
00803 }
00804
00805 parse = ast_strdupa(data);
00806 AST_STANDARD_APP_ARGS(args, parse);
00807
00808 session.caller_mode = TRUE;
00809
00810 if (args.options) {
00811 if (strchr(args.options, 'a'))
00812 session.caller_mode = FALSE;
00813 }
00814
00815
00816 session.direction = 1;
00817 session.file_name = args.file_name;
00818 session.chan = chan;
00819 session.finished = 0;
00820
00821 res = transmit(&session);
00822
00823 return res;
00824 }
00825
00826 static int rcvfax_exec(struct ast_channel *chan, void *data)
00827 {
00828 int res = 0;
00829 char *parse;
00830 fax_session session;
00831
00832 AST_DECLARE_APP_ARGS(args,
00833 AST_APP_ARG(file_name);
00834 AST_APP_ARG(options);
00835 );
00836
00837 if (chan == NULL) {
00838 ast_log(LOG_ERROR, "Fax channel is NULL. Giving up.\n");
00839 return -1;
00840 }
00841
00842
00843 if (ast_strlen_zero(data)) {
00844
00845 ast_log(LOG_ERROR, "ReceiveFAX requires an argument (filename)\n");
00846 return -1;
00847 }
00848
00849 parse = ast_strdupa(data);
00850 AST_STANDARD_APP_ARGS(args, parse);
00851
00852 session.caller_mode = FALSE;
00853
00854 if (args.options) {
00855 if (strchr(args.options, 'c'))
00856 session.caller_mode = TRUE;
00857 }
00858
00859
00860 session.direction = 0;
00861 session.file_name = args.file_name;
00862 session.chan = chan;
00863 session.finished = 0;
00864
00865 res = transmit(&session);
00866
00867 return res;
00868 }
00869
00870 static int unload_module(void)
00871 {
00872 int res;
00873
00874 res = ast_unregister_application(app_sndfax_name);
00875 res |= ast_unregister_application(app_rcvfax_name);
00876
00877 return res;
00878 }
00879
00880 static int load_module(void)
00881 {
00882 int res ;
00883
00884 res = ast_register_application(app_sndfax_name, sndfax_exec, app_sndfax_synopsis, app_sndfax_desc);
00885 res |= ast_register_application(app_rcvfax_name, rcvfax_exec, app_rcvfax_synopsis, app_rcvfax_desc);
00886
00887
00888 span_set_message_handler(NULL);
00889
00890 return res;
00891 }
00892
00893
00894 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Simple FAX Application",
00895 .load = load_module,
00896 .unload = unload_module,
00897 );
00898
00899