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