438 struct timeval base_tv;
452 struct timeval timeout_start;
471 struct timeval timeout_start;
483 #define FAX_DETECT_MODE_CNG (1 << 0) 484 #define FAX_DETECT_MODE_T38 (1 << 1) 485 #define FAX_DETECT_MODE_BOTH (FAX_DETECT_MODE_CNG | FAX_DETECT_MODE_T38) 490 #define FAX_MAXBUCKETS 10 492 #define RES_FAX_TIMEOUT 10000 493 #define FAX_GATEWAY_TIMEOUT RES_FAX_TIMEOUT 522 #define RES_FAX_MINRATE 4800 523 #define RES_FAX_MAXRATE 14400 524 #define RES_FAX_STATUSEVENTS 0 525 #define RES_FAX_MODEM (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V27TER | AST_FAX_MODEM_V29) 526 #define RES_FAX_T38TIMEOUT 5000 553 static const char *
config =
"res_fax.conf";
581 unsigned int last_consec_frames, last_consec_ms;
582 unsigned char wassil;
591 history->
silence = (dspsilence != 0) ? 1 : 0;
592 if (history->
silence != wassil) {
598 if ((last_consec_frames != 0)) {
599 ast_verb(0,
"Channel '%s' fax session '%u', [ %.3ld.%.6ld ], %s sent %u frames (%u ms) of %s.\n",
600 s->
channame, s->
id, (
long) diff.tv_sec, (
long int) diff.tv_usec,
601 (c2s) ?
"channel" :
"stack", last_consec_frames, last_consec_ms,
602 (wassil) ?
"silence" :
"energy");
672 if (!(details = datastore->
data)) {
783 datastore->
data = details;
814 char *m[5], *tok, *v = (
char *) value, *rest;
817 if (!strchr(v,
',')) {
821 tok = strtok_r(v,
", ", &rest);
824 tok = strtok_r(
NULL,
", ", &rest);
830 for (j = 0; j < i; j++) {
831 if (!strcasecmp(m[j],
"v17")) {
833 }
else if (!strcasecmp(m[j],
"v27")) {
835 }
else if (!strcasecmp(m[j],
"v29")) {
837 }
else if (!strcasecmp(m[j],
"v34")) {
840 ast_log(
LOG_WARNING,
"ignoring invalid modem setting: '%s', valid options {v17 | v27 | v29 | v34}\n", m[j]);
849 size_t size = bufsize;
996 ast_verb(3,
"Unregistering FAX module type '%s'\n", tech->
type);
1000 if (fax->
tech != tech) {
1005 ast_verb(4,
"Unregistered FAX module type '%s'\n", tech->
type);
1017 return "Uninitialized";
1019 return "Initialized";
1036 void ast_fax_log(
int level,
const char *
file,
const int line,
const char *
function,
const char *msg)
1041 ast_log(level, file, line,
function,
"%s", msg);
1050 if (sscanf(ratestr,
"%d", &rate) != 1) {
1065 ast_log(
LOG_WARNING,
"ignoring invalid rate '%s'. Valid options are {2400 | 4800 | 7200 | 9600 | 12000 | 14400 | 28800 | 33600}\n", ratestr);
1177 char caps[128] =
"";
1301 char caps[128] =
"";
1335 if (!details || !json_array) {
1372 char *filenames, *
c;
1384 size += strlen(separator) + strlen(prefix) + strlen(doc->
filename);
1418 if (!json_filenames) {
1422 json_object =
ast_json_pack(
"{s: s, s: s, s: s, s: s, s: o}",
1429 "filenames", json_filenames);
1469 #define GENERIC_FAX_EXEC_SET_VARS(fax, chan, errorstr, reason) \ 1471 if (ast_strlen_zero(fax->details->result)) \ 1472 ast_string_field_set(fax->details, result, "FAILED"); \ 1473 if (ast_strlen_zero(fax->details->resultstr)) \ 1474 ast_string_field_set(fax->details, resultstr, reason); \ 1475 if (ast_strlen_zero(fax->details->error)) \ 1476 ast_string_field_set(fax->details, error, errorstr); \ 1477 set_channel_variables(chan, fax->details); \ 1480 #define GENERIC_FAX_EXEC_ERROR_QUIET(fax, chan, errorstr, reason) \ 1482 GENERIC_FAX_EXEC_SET_VARS(fax, chan, errorstr, reason); \ 1485 #define GENERIC_FAX_EXEC_ERROR(fax, chan, errorstr, reason) \ 1487 ast_log(LOG_ERROR, "channel '%s' FAX session '%u' failure, reason: '%s' (%s)\n", ast_channel_name(chan), fax->id, reason, errorstr); \ 1488 GENERIC_FAX_EXEC_ERROR_QUIET(fax, chan, errorstr, reason); \ 1532 struct timeval start;
1560 (frame->
datalen ==
sizeof(t38_parameters))) {
1595 unsigned int expected_frametype = -1;
1599 const char *tempvar;
1606 struct timeval start;
1611 if (t38negotiated) {
1689 while (remaining_time > 0) {
1716 (frame->
datalen ==
sizeof(t38_parameters))) {
1717 unsigned int was_t38 = t38negotiated;
1742 if (t38negotiated && !was_t38) {
1789 }
else if (ofd == fax->
fd) {
1792 if (!(frame = fax->
tech->
read(fax))) {
1805 if (ms && (ofd < 0)) {
1808 if (remaining_time <= 0)
1819 if (remaining_time <= 0) {
1826 ast_debug(3,
"channel '%s' - event loop stopped { timeout: %d, remaining_time: %d }\n",
ast_channel_name(chan), timeout, remaining_time);
1831 if (!strcasecmp(details->
result,
"FAILED")) {
1844 if (orig_read_format) {
1847 if (orig_write_format) {
1861 struct timeval start;
1895 (frame->
datalen ==
sizeof(t38_parameters))) {
1964 (frame->
datalen ==
sizeof(t38_parameters))) {
2025 if (!json_array || !json_filename) {
2032 const char *remote_station_id;
2033 const char *local_station_id;
2034 const char *fax_pages;
2035 const char *fax_resolution;
2036 const char *fax_bitrate;
2041 remote_station_id =
ast_strdupa(remote_station_id);
2060 json_object =
ast_json_pack(
"{s: s, s: s, s: s, s: s, s: s, s: s, s: o}",
2062 "remote_station_id",
S_OR(remote_station_id,
""),
2063 "local_station_id",
S_OR(local_station_id,
""),
2064 "fax_pages",
S_OR(fax_pages,
""),
2065 "fax_resolution",
S_OR(fax_resolution,
""),
2066 "fax_bitrate",
S_OR(fax_bitrate,
""),
2084 char *
parse, modems[128] =
"";
2088 struct ast_fax_tech_token *token =
NULL;
2110 ast_log(
LOG_ERROR,
"System cannot provide memory for session requirements.\n");
2120 ast_string_field_set(details, resultstr,
"can't receive a fax on a channel with a T.38 gateway");
2122 ast_log(
LOG_ERROR,
"executing ReceiveFAX on a channel with a T.38 Gateway is not supported\n");
2136 ast_log(
LOG_ERROR,
"'modems' setting '%s' is incompatible with 'minrate' setting %u\n", modems, details->
minrate);
2145 ast_log(
LOG_ERROR,
"'modems' setting '%s' is incompatible with 'maxrate' setting %u\n", modems, details->
maxrate);
2191 if (!(doc =
ast_calloc(1,
sizeof(*doc) + strlen(
args.filename) + 1))) {
2195 ast_log(
LOG_ERROR,
"System cannot provide memory for session requirements.\n");
2280 return (!channel_alive) ? -1 : 0;
2288 struct timeval start;
2301 if (
ast_playtones_start(chan, 1024,
"!1100/500,!0/3000,!1100/500,!0/3000,!1100/500,!0/3000", 1)) {
2330 (frame->
datalen ==
sizeof(t38_parameters))) {
2402 (frame->
datalen ==
sizeof(t38_parameters))) {
2472 (frame->
datalen ==
sizeof(t38_parameters))) {
2534 if (!json_filenames) {
2539 const char *remote_station_id;
2540 const char *local_station_id;
2541 const char *fax_pages;
2542 const char *fax_resolution;
2543 const char *fax_bitrate;
2548 remote_station_id =
ast_strdupa(remote_station_id);
2566 json_obj =
ast_json_pack(
"{s: s, s: s, s: s, s: s, s: s, s: s, s: o}",
2568 "remote_station_id",
S_OR(remote_station_id,
""),
2569 "local_station_id",
S_OR(local_station_id,
""),
2570 "fax_pages",
S_OR(fax_pages,
""),
2571 "fax_resolution",
S_OR(fax_resolution,
""),
2572 "fax_bitrate",
S_OR(fax_bitrate,
""),
2573 "filenames", json_filenames);
2592 char *
parse, *filenames, *
c, modems[128] =
"";
2593 int channel_alive, file_count;
2596 struct ast_fax_tech_token *token =
NULL;
2618 ast_log(
LOG_ERROR,
"System cannot provide memory for session requirements.\n");
2630 ast_log(
LOG_ERROR,
"executing SendFAX on a channel with a T.38 Gateway is not supported\n");
2644 ast_log(
LOG_ERROR,
"'modems' setting '%s' is incompatible with 'minrate' setting %u\n", modems, details->
minrate);
2653 ast_log(
LOG_ERROR,
"'modems' setting '%s' is incompatible with 'maxrate' setting %u\n", modems, details->
maxrate);
2698 filenames =
args.filenames;
2699 while ((c =
strsep(&filenames,
"&"))) {
2700 if (access(c, (F_OK | R_OK)) < 0) {
2704 ast_log(
LOG_ERROR,
"access failure. Verify '%s' exists and check permissions.\n",
args.filenames);
2708 if (!(doc =
ast_calloc(1,
sizeof(*doc) + strlen(c) + 1))) {
2712 ast_log(
LOG_ERROR,
"System cannot provide memory for session requirements.\n");
2728 if (file_count > 1) {
2808 return (!channel_alive) ? -1 : 0;
2817 return (!channel_alive) ? -1 : 0;
2898 ast_log(
LOG_ERROR,
"Can't reserve a FAX session, gateway attempt failed.\n");
2940 ast_log(
LOG_ERROR,
"Can't create a FAX session, gateway attempt failed.\n");
2954 if (start_res < 0) {
2981 .datalen =
sizeof(t38_parameters),
2983 .data.ptr = &t38_parameters,
3014 struct ast_channel *other = (active == chan) ? peer : chan;
3021 if (active_v21_session->
tech->
write(active_v21_session, f) == 0 &&
3064 if (active == chan) {
3068 if (active == chan) {
3087 if (active == chan) {
3112 struct ast_channel *other = (active == chan) ? peer : chan;
3194 ast_debug(1,
"%s is attempting to negotiate T.38 after we already sent a negotiation request based on v21 preamble detection\n",
ast_channel_name(active));
3350 switch (gateway->
s->
state) {
3451 if (chan_is_hungup || peer_is_hungup) {
3602 short silence_buf[f->
samples];
3606 .data.ptr = silence_buf,
3608 .datalen =
sizeof(silence_buf),
3610 memset(silence_buf, 0,
sizeof(silence_buf));
3633 .disable_inheritance = 1,
3657 fr_hook.
data = gateway;
3680 if (faxdetect->
dsp) {
3712 if (!faxdetect->
dsp) {
3809 if (!faxdetect->
dsp) {
3847 const char *target_context;
3859 ast_verb(2,
"Redirecting '%s' to fax extension due to %s detection\n",
3867 (result ==
'f') ?
"CNG" :
"T38", target_context);
3900 ast_log(
LOG_ERROR,
"System cannot provide memory for session requirements.\n");
3911 fr_hook.
data = faxdetect;
3956 tklen = strlen(a->
word);
3959 snprintf(tbuf,
sizeof(tbuf),
"%u", s->
id);
3960 if (!strncasecmp(a->
word, tbuf, tklen) && ++wordnum > a->
n) {
3977 e->
command =
"fax show version";
3979 "Usage: fax show version\n" 3980 " Show versions of FAX For Asterisk components.\n";
3990 ast_cli(a->
fd,
"FAX For Asterisk Components:\n");
4010 e->
command =
"fax set debug {on|off}";
4012 "Usage: fax set debug { on | off }\n" 4013 " Enable/Disable FAX debugging on new FAX sessions. The basic FAX debugging will result in\n" 4014 " additional events sent to manager sessions with 'call' class permissions. When\n" 4015 " verbosity is greater than '5' events will be displayed to the console and audio versus\n" 4016 " energy analysis will be performed and displayed to the console.\n";
4023 if (!strcasecmp(what,
"on")) {
4025 }
else if (!strcasecmp(what,
"off")) {
4032 ast_cli(a->
fd,
"\n\nFAX Debug %s\n\n", (flag) ?
"Enabled" :
"Disabled");
4041 unsigned int num_modules = 0;
4045 e->
command =
"fax show capabilities";
4047 "Usage: fax show capabilities\n" 4048 " Shows the capabilities of the registered FAX technology modules\n";
4054 ast_cli(a->
fd,
"\n\nRegistered FAX Technology Modules:\n\n");
4062 ast_cli(a->
fd,
"%u registered modules\n\n", num_modules);
4071 char modems[128] =
"";
4076 e->
command =
"fax show settings";
4078 "Usage: fax show settings\n" 4079 " Show the global settings and defaults of both the FAX core and technology modules\n";
4087 ast_cli(a->
fd,
"FAX For Asterisk Settings:\n");
4088 ast_cli(a->
fd,
"\tECM: %s\n", options.
ecm ?
"Enabled" :
"Disabled");
4093 ast_cli(a->
fd,
"\tModem Modulations Allowed: %s\n", modems);
4095 ast_cli(a->
fd,
"\n\nFAX Technology Modules:\n\n");
4113 e->
command =
"fax show session";
4115 "Usage: fax show session <session number>\n" 4116 " Shows status of the named FAX session\n";
4126 if (sscanf(a->
argv[3],
"%u", &tmp.
id) != 1) {
4131 ast_cli(a->
fd,
"\nFAX Session Details:\n--------------------\n\n");
4147 char id_text[256] =
"";
4151 if (sscanf(session_number,
"%30u", &find_session.
id) != 1) {
4163 astman_send_error(s, m,
"Fax technology doesn't provide a handler for FAXSession");
4169 snprintf(id_text,
sizeof(id_text),
"ActionID: %s\r\n", action_id);
4187 e->
command =
"fax show stats";
4189 "Usage: fax show stats\n" 4190 " Shows a statistical summary of FAX transmissions\n";
4196 ast_cli(a->
fd,
"\nFAX Statistics:\n---------------\n\n");
4217 char id_text[256] =
"";
4222 snprintf(id_text,
sizeof(id_text),
"ActionID: %s\r\n", action_id);
4227 "CurrentSessions: %d\r\n" 4228 "ReservedSessions: %d\r\n" 4229 "TransmitAttempts: %d\r\n" 4230 "ReceiveAttempts: %d\r\n" 4231 "CompletedFAXes: %d\r\n" 4232 "FailedFAXes: %d\r\n" 4282 e->
command =
"fax show sessions";
4284 "Usage: fax show sessions\n" 4285 " Shows the current FAX sessions\n";
4291 ast_cli(a->
fd,
"\nCurrent FAX Sessions:\n\n");
4292 ast_cli(a->
fd,
"%-30.30s %-10.10s %-10.10s %-5.5s %-10.10s %-15.15s %-30.30s\n",
4293 "Channel",
"Tech",
"FAXID",
"Type",
"Operation",
"State",
"File(s)");
4300 ast_cli(a->
fd,
"%-30.30s %-10.10s %-10u %-5.5s %-10.10s %-15.15s %-30s\n",
4312 ast_cli(a->
fd,
"\n%d FAX sessions\n\n", session_count);
4334 "Technology: %s\r\n" 4335 "SessionNumber: %u\r\n" 4336 "SessionType: %s\r\n" 4359 snprintf(id_text,
sizeof(id_text),
"ActionID: %s\r\n", action_id);
4408 if (sscanf(value,
"%u", &timeout) != 1) {
4411 }
else if (timeout) {
4427 char modems[128] =
"";
4445 config, reload ?
"not changing" :
"using default");
4451 config, reload ?
"not changing" :
"using default");
4467 if (!strcasecmp(v->
name,
"minrate")) {
4468 ast_debug(3,
"reading minrate '%s' from configuration file\n", v->
value);
4474 }
else if (!strcasecmp(v->
name,
"maxrate")) {
4475 ast_debug(3,
"reading maxrate '%s' from configuration file\n", v->
value);
4481 }
else if (!strcasecmp(v->
name,
"statusevents")) {
4482 ast_debug(3,
"reading statusevents '%s' from configuration file\n", v->
value);
4484 }
else if (!strcasecmp(v->
name,
"ecm")) {
4485 ast_debug(3,
"reading ecm '%s' from configuration file\n", v->
value);
4487 }
else if ((!strcasecmp(v->
name,
"modem")) || (!strcasecmp(v->
name,
"modems"))) {
4490 }
else if (!strcasecmp(v->
name,
"t38timeout")) {
4506 ast_log(
LOG_ERROR,
"'modems' setting '%s' is incompatible with 'minrate' setting %u\n", modems, options.
minrate);
4513 ast_log(
LOG_ERROR,
"'modems' setting '%s' is incompatible with 'maxrate' setting %u\n", modems, options.
maxrate);
4536 if (!strcasecmp(data,
"ecm")) {
4538 }
else if (!strcasecmp(data,
"t38gateway") || !strcasecmp(data,
"gateway") ||
4539 !strcasecmp(data,
"t38_gateway") || !strcasecmp(data,
"faxgateway")) {
4541 }
else if (!strcasecmp(data,
"faxdetect")) {
4543 }
else if (!strcasecmp(data,
"error")) {
4545 }
else if (!strcasecmp(data,
"filename")) {
4552 }
else if (!strcasecmp(data,
"filenames")) {
4563 }
else if (!strcasecmp(data,
"headerinfo")) {
4565 }
else if (!strcasecmp(data,
"localstationid")) {
4567 }
else if (!strcasecmp(data,
"maxrate")) {
4568 snprintf(buf, len,
"%u", details->
maxrate);
4569 }
else if (!strcasecmp(data,
"minrate")) {
4570 snprintf(buf, len,
"%u", details->
minrate);
4571 }
else if (!strcasecmp(data,
"pages")) {
4573 }
else if (!strcasecmp(data,
"rate")) {
4575 }
else if (!strcasecmp(data,
"remotestationid")) {
4577 }
else if (!strcasecmp(data,
"resolution")) {
4579 }
else if (!strcasecmp(data,
"sessionid")) {
4580 snprintf(buf, len,
"%u", details->
id);
4581 }
else if (!strcasecmp(data,
"status")) {
4583 }
else if (!strcasecmp(data,
"statusstr")) {
4585 }
else if ((!strcasecmp(data,
"modem")) || (!strcasecmp(data,
"modems"))) {
4587 }
else if (!strcasecmp(data,
"t38timeout")) {
4588 snprintf(buf, len,
"%u", details->
t38timeout);
4589 }
else if (!strcasecmp(data,
"negotiate_both")) {
4612 if (!strcasecmp(data,
"ecm")) {
4621 }
else if (!strcasecmp(data,
"t38gateway") || !strcasecmp(data,
"gateway") ||
4622 !strcasecmp(data,
"t38_gateway") || !strcasecmp(data,
"faxgateway")) {
4624 char *timeout = strchr(val,
',');
4634 unsigned int gwtimeout;
4636 if (sscanf(timeout,
"%30u", &gwtimeout) == 1) {
4639 ast_log(
LOG_WARNING,
"Unsupported timeout '%s' passed to FAXOPT(%s).\n", timeout, data);
4661 }
else if (!strcasecmp(data,
"faxdetect")) {
4663 char *timeout = strchr(val,
',');
4672 if (
ast_true(val) || !strcasecmp(val,
"t38") || !strcasecmp(val,
"cng")) {
4675 if (sscanf(timeout,
"%30u", &fdtimeout) == 1) {
4683 if (!strcasecmp(val,
"t38")) {
4685 }
else if (!strcasecmp(val,
"cng")) {
4692 if (faxdetect < 0) {
4709 }
else if (!strcasecmp(data,
"headerinfo")) {
4711 }
else if (!strcasecmp(data,
"localstationid")) {
4713 }
else if (!strcasecmp(data,
"maxrate")) {
4718 }
else if (!strcasecmp(data,
"minrate")) {
4723 }
else if (!strcasecmp(data,
"t38timeout")) {
4727 }
else if ((!strcasecmp(data,
"modem")) || (!strcasecmp(data,
"modems"))) {
4729 }
else if (!strcasecmp(data,
"negotiate_both")) {