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: 235012 $")
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 .transcoding_mmr = 1,
00334 .transcoding_jbig = 1,
00335 };
00336
00337
00338 if (s->caller_mode == FALSE) {
00339
00340
00341
00342
00343 if ((t38_state = ast_channel_get_t38_state(s->chan)) == T38_STATE_NEGOTIATED) {
00344 return 1;
00345 } else if ((t38_state != T38_STATE_UNAVAILABLE) &&
00346 (t38_parameters.request_response = AST_T38_REQUEST_NEGOTIATE,
00347 (ast_indicate_data(s->chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) == 0))) {
00348
00349 unsigned int timeout = 5000;
00350 int ms;
00351
00352 ast_debug(1, "Negotiating T.38 for receive on %s\n", s->chan->name);
00353 while (timeout > 0) {
00354 ms = ast_waitfor(s->chan, 1000);
00355 if (ms < 0) {
00356 ast_log(LOG_WARNING, "something bad happened while channel '%s' was polling.\n", s->chan->name);
00357 return -1;
00358 }
00359 if (!ms) {
00360
00361 if (timeout > 0) {
00362 timeout -= 1000;
00363 continue;
00364 } else {
00365 ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 negotiation.\n", s->chan->name);
00366 break;
00367 }
00368 }
00369 if (!(inf = ast_read(s->chan))) {
00370 return -1;
00371 }
00372 if ((inf->frametype == AST_FRAME_CONTROL) &&
00373 (inf->subclass == AST_CONTROL_T38_PARAMETERS) &&
00374 (inf->datalen == sizeof(t38_parameters))) {
00375 struct ast_control_t38_parameters *parameters = inf->data.ptr;
00376
00377 switch (parameters->request_response) {
00378 case AST_T38_NEGOTIATED:
00379 ast_debug(1, "Negotiated T.38 for receive on %s\n", s->chan->name);
00380 res = 1;
00381 break;
00382 case AST_T38_REFUSED:
00383 ast_log(LOG_WARNING, "channel '%s' refused to negotiate T.38\n", s->chan->name);
00384 break;
00385 default:
00386 ast_log(LOG_ERROR, "channel '%s' failed to negotiate T.38\n", s->chan->name);
00387 break;
00388 }
00389 ast_frfree(inf);
00390 if (res == 1) {
00391 return 1;
00392 } else {
00393 break;
00394 }
00395 }
00396 ast_frfree(inf);
00397 }
00398 }
00399 }
00400
00401 #if SPANDSP_RELEASE_DATE >= 20080725
00402
00403 t30state = &fax.t30;
00404 #else
00405
00406 t30state = &fax.t30_state;
00407 #endif
00408
00409 original_read_fmt = s->chan->readformat;
00410 if (original_read_fmt != AST_FORMAT_SLINEAR) {
00411 res = ast_set_read_format(s->chan, AST_FORMAT_SLINEAR);
00412 if (res < 0) {
00413 ast_log(LOG_WARNING, "Unable to set to linear read mode, giving up\n");
00414 goto done;
00415 }
00416 }
00417
00418 original_write_fmt = s->chan->writeformat;
00419 if (original_write_fmt != AST_FORMAT_SLINEAR) {
00420 res = ast_set_write_format(s->chan, AST_FORMAT_SLINEAR);
00421 if (res < 0) {
00422 ast_log(LOG_WARNING, "Unable to set to linear write mode, giving up\n");
00423 goto done;
00424 }
00425 }
00426
00427
00428 fax_init(&fax, s->caller_mode);
00429
00430
00431 set_logging(&fax.logging);
00432 set_logging(&t30state->logging);
00433
00434
00435 set_local_info(t30state, s);
00436 set_file(t30state, s);
00437 set_ecm(t30state, TRUE);
00438
00439 fax_set_transmit_on_idle(&fax, TRUE);
00440
00441 t30_set_phase_e_handler(t30state, phase_e_handler, s);
00442
00443 start = state_change = ast_tvnow();
00444
00445 ast_activate_generator(s->chan, &generator, &fax);
00446
00447 while (!s->finished) {
00448 inf = NULL;
00449
00450 if ((res = ast_waitfor(s->chan, 25)) < 0) {
00451 ast_debug(1, "Error waiting for a frame\n");
00452 break;
00453 }
00454
00455
00456 now = ast_tvnow();
00457 if (ast_tvdiff_sec(now, start) > WATCHDOG_TOTAL_TIMEOUT || ast_tvdiff_sec(now, state_change) > WATCHDOG_STATE_TIMEOUT) {
00458 ast_log(LOG_WARNING, "It looks like we hung. Aborting.\n");
00459 res = -1;
00460 break;
00461 }
00462
00463 if (!res) {
00464
00465 continue;
00466 }
00467
00468
00469 res = 0;
00470
00471 if (!(inf = ast_read(s->chan))) {
00472 ast_debug(1, "Channel hangup\n");
00473 res = -1;
00474 break;
00475 }
00476
00477 ast_debug(10, "frame %d/%d, len=%d\n", inf->frametype, inf->subclass, inf->datalen);
00478
00479
00480
00481
00482 if (inf->frametype == AST_FRAME_VOICE && inf->subclass == AST_FORMAT_SLINEAR) {
00483 if (fax_rx(&fax, inf->data.ptr, inf->samples) < 0) {
00484
00485 ast_log(LOG_WARNING, "fax_rx returned error\n");
00486 res = -1;
00487 break;
00488 }
00489 if (last_state != t30state->state) {
00490 state_change = ast_tvnow();
00491 last_state = t30state->state;
00492 }
00493 } else if ((inf->frametype == AST_FRAME_CONTROL) &&
00494 (inf->subclass == AST_CONTROL_T38_PARAMETERS)) {
00495 struct ast_control_t38_parameters *parameters = inf->data.ptr;
00496
00497 if (parameters->request_response == AST_T38_NEGOTIATED) {
00498
00499 s->t38parameters = *parameters;
00500 ast_debug(1, "T38 negotiated, finishing audio loop\n");
00501 res = 1;
00502 break;
00503 } else if (parameters->request_response == AST_T38_REQUEST_NEGOTIATE) {
00504 t38_parameters.request_response = AST_T38_NEGOTIATED;
00505 ast_debug(1, "T38 request received, accepting\n");
00506
00507 ast_indicate_data(s->chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
00508
00509
00510
00511 }
00512 }
00513
00514 ast_frfree(inf);
00515 }
00516
00517 ast_debug(1, "Loop finished, res=%d\n", res);
00518
00519 if (inf)
00520 ast_frfree(inf);
00521
00522 ast_deactivate_generator(s->chan);
00523
00524
00525
00526
00527 if (res > 0) {
00528 t30_set_phase_e_handler(t30state, NULL, NULL);
00529 }
00530
00531 t30_terminate(t30state);
00532 fax_release(&fax);
00533
00534 done:
00535 if (original_write_fmt != AST_FORMAT_SLINEAR) {
00536 if (ast_set_write_format(s->chan, original_write_fmt) < 0)
00537 ast_log(LOG_WARNING, "Unable to restore write format on '%s'\n", s->chan->name);
00538 }
00539
00540 if (original_read_fmt != AST_FORMAT_SLINEAR) {
00541 if (ast_set_read_format(s->chan, original_read_fmt) < 0)
00542 ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", s->chan->name);
00543 }
00544
00545 return res;
00546
00547 }
00548
00549 static int transmit_t38(fax_session *s)
00550 {
00551 int res = 0;
00552 t38_terminal_state_t t38;
00553 struct ast_frame *inf = NULL;
00554 int last_state = 0;
00555 struct timeval now, start, state_change, last_frame;
00556 t30_state_t *t30state;
00557 t38_core_state_t *t38state;
00558
00559 #if SPANDSP_RELEASE_DATE >= 20080725
00560
00561 t30state = &t38.t30;
00562 t38state = &t38.t38_fe.t38;
00563 #else
00564
00565 t30state = &t38.t30_state;
00566 t38state = &t38.t38;
00567 #endif
00568
00569
00570 memset(&t38, 0, sizeof(t38));
00571 if (t38_terminal_init(&t38, s->caller_mode, t38_tx_packet_handler, s->chan) == NULL) {
00572 ast_log(LOG_WARNING, "Unable to start T.38 termination.\n");
00573 res = -1;
00574 goto disable_t38;
00575 }
00576
00577 t38_set_max_datagram_size(t38state, s->t38parameters.max_ifp);
00578
00579 if (s->t38parameters.fill_bit_removal) {
00580 t38_set_fill_bit_removal(t38state, TRUE);
00581 }
00582 if (s->t38parameters.transcoding_mmr) {
00583 t38_set_mmr_transcoding(t38state, TRUE);
00584 }
00585 if (s->t38parameters.transcoding_jbig) {
00586 t38_set_jbig_transcoding(t38state, TRUE);
00587 }
00588
00589
00590 set_logging(&t38.logging);
00591 set_logging(&t30state->logging);
00592 set_logging(&t38state->logging);
00593
00594
00595 set_local_info(t30state, s);
00596 set_file(t30state, s);
00597 set_ecm(t30state, TRUE);
00598
00599 t30_set_phase_e_handler(t30state, phase_e_handler, s);
00600
00601 now = start = state_change = ast_tvnow();
00602
00603 while (!s->finished) {
00604
00605 res = ast_waitfor(s->chan, 20);
00606 if (res < 0)
00607 break;
00608 else if (res > 0)
00609 res = 0;
00610
00611 last_frame = now;
00612 now = ast_tvnow();
00613 t38_terminal_send_timeout(&t38, ast_tvdiff_us(now, last_frame) / (1000000 / 8000));
00614
00615 inf = ast_read(s->chan);
00616 if (inf == NULL) {
00617 ast_debug(1, "Channel hangup\n");
00618 res = -1;
00619 break;
00620 }
00621
00622 ast_debug(10, "frame %d/%d, len=%d\n", inf->frametype, inf->subclass, inf->datalen);
00623
00624 if (inf->frametype == AST_FRAME_MODEM && inf->subclass == AST_MODEM_T38) {
00625 t38_core_rx_ifp_packet(t38state, inf->data.ptr, inf->datalen, inf->seqno);
00626
00627
00628 if (last_state != t30state->state) {
00629 state_change = ast_tvnow();
00630 last_state = t30state->state;
00631 }
00632 } else if (inf->frametype == AST_FRAME_CONTROL && inf->subclass == AST_CONTROL_T38_PARAMETERS) {
00633 struct ast_control_t38_parameters *parameters = inf->data.ptr;
00634 if (parameters->request_response == AST_T38_TERMINATED) {
00635 ast_debug(1, "T38 down, finishing\n");
00636 break;
00637 }
00638 }
00639
00640 ast_frfree(inf);
00641 inf = NULL;
00642
00643
00644 if (ast_tvdiff_sec(now, start) > WATCHDOG_TOTAL_TIMEOUT || ast_tvdiff_sec(now, state_change) > WATCHDOG_STATE_TIMEOUT) {
00645 ast_log(LOG_WARNING, "It looks like we hung. Aborting.\n");
00646 res = -1;
00647 break;
00648 }
00649 }
00650
00651 ast_debug(1, "Loop finished, res=%d\n", res);
00652
00653 if (inf)
00654 ast_frfree(inf);
00655
00656 t30_terminate(t30state);
00657 t38_terminal_release(&t38);
00658
00659 disable_t38:
00660
00661
00662
00663 if ((s->caller_mode == FALSE) &&
00664 (ast_channel_get_t38_state(s->chan) == T38_STATE_NEGOTIATED)) {
00665 struct ast_control_t38_parameters t38_parameters = { .request_response = AST_T38_REQUEST_TERMINATE, };
00666
00667 if (ast_indicate_data(s->chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) == 0) {
00668
00669 unsigned int timeout = 5000;
00670 int ms;
00671
00672 ast_debug(1, "Shutting down T.38 on %s\n", s->chan->name);
00673 while (timeout > 0) {
00674 ms = ast_waitfor(s->chan, 1000);
00675 if (ms < 0) {
00676 ast_log(LOG_WARNING, "something bad happened while channel '%s' was polling.\n", s->chan->name);
00677 return -1;
00678 }
00679 if (!ms) {
00680
00681 if (timeout > 0) {
00682 timeout -= 1000;
00683 continue;
00684 } else {
00685 ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 shutdown.\n", s->chan->name);
00686 break;
00687 }
00688 }
00689 if (!(inf = ast_read(s->chan))) {
00690 return -1;
00691 }
00692 if ((inf->frametype == AST_FRAME_CONTROL) &&
00693 (inf->subclass == AST_CONTROL_T38_PARAMETERS) &&
00694 (inf->datalen == sizeof(t38_parameters))) {
00695 struct ast_control_t38_parameters *parameters = inf->data.ptr;
00696
00697 switch (parameters->request_response) {
00698 case AST_T38_TERMINATED:
00699 ast_debug(1, "Shut down T.38 on %s\n", s->chan->name);
00700 break;
00701 case AST_T38_REFUSED:
00702 ast_log(LOG_WARNING, "channel '%s' refused to disable T.38\n", s->chan->name);
00703 break;
00704 default:
00705 ast_log(LOG_ERROR, "channel '%s' failed to disable T.38\n", s->chan->name);
00706 break;
00707 }
00708 ast_frfree(inf);
00709 break;
00710 }
00711 ast_frfree(inf);
00712 }
00713 }
00714 }
00715
00716 return res;
00717 }
00718
00719 static int transmit(fax_session *s)
00720 {
00721 int res = 0;
00722
00723
00724
00725 pbx_builtin_setvar_helper(s->chan, "FAXSTATUS", "FAILED");
00726 pbx_builtin_setvar_helper(s->chan, "FAXERROR", "Channel problems");
00727
00728 pbx_builtin_setvar_helper(s->chan, "FAXMODE", NULL);
00729 pbx_builtin_setvar_helper(s->chan, "REMOTESTATIONID", NULL);
00730 pbx_builtin_setvar_helper(s->chan, "FAXPAGES", NULL);
00731 pbx_builtin_setvar_helper(s->chan, "FAXRESOLUTION", NULL);
00732 pbx_builtin_setvar_helper(s->chan, "FAXBITRATE", NULL);
00733
00734 if (s->chan->_state != AST_STATE_UP) {
00735
00736
00737 res = ast_answer(s->chan);
00738 if (res) {
00739 ast_log(LOG_WARNING, "Could not answer channel '%s'\n", s->chan->name);
00740 return res;
00741 }
00742 }
00743
00744 s->t38state = ast_channel_get_t38_state(s->chan);
00745 if (s->t38state != T38_STATE_NEGOTIATED) {
00746
00747 pbx_builtin_setvar_helper(s->chan, "FAXMODE", "audio");
00748 res = transmit_audio(s);
00749 if (res > 0) {
00750
00751 s->t38state = ast_channel_get_t38_state(s->chan);
00752 if (s->t38state != T38_STATE_NEGOTIATED) {
00753 ast_log(LOG_ERROR, "Audio loop reports T38 switchover but t38state != T38_STATE_NEGOTIATED\n");
00754 }
00755 }
00756 }
00757
00758 if (s->t38state == T38_STATE_NEGOTIATED) {
00759 pbx_builtin_setvar_helper(s->chan, "FAXMODE", "T38");
00760 res = transmit_t38(s);
00761 }
00762
00763 if (res) {
00764 ast_log(LOG_WARNING, "Transmission error\n");
00765 res = -1;
00766 } else if (s->finished < 0) {
00767 ast_log(LOG_WARNING, "Transmission failed\n");
00768 } else if (s->finished > 0) {
00769 ast_debug(1, "Transmission finished Ok\n");
00770 }
00771
00772 return res;
00773 }
00774
00775
00776
00777 static int sndfax_exec(struct ast_channel *chan, void *data)
00778 {
00779 int res = 0;
00780 char *parse;
00781 fax_session session = { 0, };
00782
00783 AST_DECLARE_APP_ARGS(args,
00784 AST_APP_ARG(file_name);
00785 AST_APP_ARG(options);
00786 );
00787
00788 if (chan == NULL) {
00789 ast_log(LOG_ERROR, "Fax channel is NULL. Giving up.\n");
00790 return -1;
00791 }
00792
00793
00794 if (ast_strlen_zero(data)) {
00795
00796 ast_log(LOG_ERROR, "SendFAX requires an argument (filename)\n");
00797 return -1;
00798 }
00799
00800 parse = ast_strdupa(data);
00801 AST_STANDARD_APP_ARGS(args, parse);
00802
00803 session.caller_mode = TRUE;
00804
00805 if (args.options) {
00806 if (strchr(args.options, 'a'))
00807 session.caller_mode = FALSE;
00808 }
00809
00810
00811 session.direction = 1;
00812 session.file_name = args.file_name;
00813 session.chan = chan;
00814 session.finished = 0;
00815
00816 res = transmit(&session);
00817
00818 return res;
00819 }
00820
00821 static int rcvfax_exec(struct ast_channel *chan, void *data)
00822 {
00823 int res = 0;
00824 char *parse;
00825 fax_session session;
00826
00827 AST_DECLARE_APP_ARGS(args,
00828 AST_APP_ARG(file_name);
00829 AST_APP_ARG(options);
00830 );
00831
00832 if (chan == NULL) {
00833 ast_log(LOG_ERROR, "Fax channel is NULL. Giving up.\n");
00834 return -1;
00835 }
00836
00837
00838 if (ast_strlen_zero(data)) {
00839
00840 ast_log(LOG_ERROR, "ReceiveFAX requires an argument (filename)\n");
00841 return -1;
00842 }
00843
00844 parse = ast_strdupa(data);
00845 AST_STANDARD_APP_ARGS(args, parse);
00846
00847 session.caller_mode = FALSE;
00848
00849 if (args.options) {
00850 if (strchr(args.options, 'c'))
00851 session.caller_mode = TRUE;
00852 }
00853
00854
00855 session.direction = 0;
00856 session.file_name = args.file_name;
00857 session.chan = chan;
00858 session.finished = 0;
00859
00860 res = transmit(&session);
00861
00862 return res;
00863 }
00864
00865 static int unload_module(void)
00866 {
00867 int res;
00868
00869 res = ast_unregister_application(app_sndfax_name);
00870 res |= ast_unregister_application(app_rcvfax_name);
00871
00872 return res;
00873 }
00874
00875 static int load_module(void)
00876 {
00877 int res ;
00878
00879 res = ast_register_application(app_sndfax_name, sndfax_exec, app_sndfax_synopsis, app_sndfax_desc);
00880 res |= ast_register_application(app_rcvfax_name, rcvfax_exec, app_rcvfax_synopsis, app_rcvfax_desc);
00881
00882
00883 span_set_message_handler(NULL);
00884
00885 return res;
00886 }
00887
00888
00889 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Simple FAX Application",
00890 .load = load_module,
00891 .unload = unload_module,
00892 );
00893
00894