482#define FAX_DETECT_MODE_CNG (1 << 0)
483#define FAX_DETECT_MODE_T38 (1 << 1)
484#define FAX_DETECT_MODE_BOTH (FAX_DETECT_MODE_CNG | FAX_DETECT_MODE_T38)
489#define FAX_MAXBUCKETS 10
491#define RES_FAX_TIMEOUT 10000
492#define FAX_GATEWAY_TIMEOUT RES_FAX_TIMEOUT
521#define RES_FAX_MINRATE 4800
522#define RES_FAX_MAXRATE 14400
523#define RES_FAX_STATUSEVENTS 0
524#define RES_FAX_MODEM (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V27TER | AST_FAX_MODEM_V29)
525#define RES_FAX_T38TIMEOUT 5000
552static const char *
config =
"res_fax.conf";
580 unsigned int last_consec_frames, last_consec_ms;
581 unsigned char wassil;
590 history->
silence = (dspsilence != 0) ? 1 : 0;
591 if (history->
silence != wassil) {
597 if ((last_consec_frames != 0)) {
598 ast_verb(0,
"Channel '%s' fax session '%u', [ %.3ld.%.6ld ], %s sent %u frames (%u ms) of %s.\n",
599 s->
channame, s->
id, (
long) diff.tv_sec, (
long int) diff.tv_usec,
600 (c2s) ?
"channel" :
"stack", last_consec_frames, last_consec_ms,
601 (wassil) ?
"silence" :
"energy");
671 if (!(details = datastore->
data)) {
719 d->option.statusevents =
options.statusevents;
725 d->faxdetect_id = -1;
726 d->gateway_timeout = 0;
727 d->negotiate_both = 0;
782 datastore->
data = details;
813 char *m[5], *tok, *v = (
char *)
value, *rest;
816 if (!strchr(v,
',')) {
820 tok = strtok_r(v,
", ", &rest);
823 tok = strtok_r(
NULL,
", ", &rest);
829 for (j = 0; j < i; j++) {
830 if (!strcasecmp(m[j],
"v17")) {
832 }
else if (!strcasecmp(m[j],
"v27")) {
834 }
else if (!strcasecmp(m[j],
"v29")) {
836 }
else if (!strcasecmp(m[j],
"v34")) {
839 ast_log(
LOG_WARNING,
"ignoring invalid modem setting: '%s', valid options {v17 | v27 | v29 | v34}\n", m[j]);
848 size_t size = bufsize;
1016 return "Uninitialized";
1018 return "Initialized";
1035void ast_fax_log(
int level,
const char *
file,
const int line,
const char *function,
const char *msg)
1049 if (sscanf(ratestr,
"%d", &rate) != 1) {
1064 ast_log(
LOG_WARNING,
"ignoring invalid rate '%s'. Valid options are {2400 | 4800 | 7200 | 9600 | 12000 | 14400 | 28800 | 33600}\n", ratestr);
1176 char caps[128] =
"";
1300 char caps[128] =
"";
1334 if (!details || !json_array) {
1371 char *filenames, *
c;
1383 size += strlen(separator) + strlen(
prefix) + strlen(doc->
filename);
1417 if (!json_filenames) {
1421 json_object =
ast_json_pack(
"{s: s, s: s, s: s, s: s, s: o}",
1428 "filenames", json_filenames);
1468#define GENERIC_FAX_EXEC_SET_VARS(fax, chan, errorstr, reason) \
1470 if (ast_strlen_zero(fax->details->result)) \
1471 ast_string_field_set(fax->details, result, "FAILED"); \
1472 if (ast_strlen_zero(fax->details->resultstr)) \
1473 ast_string_field_set(fax->details, resultstr, reason); \
1474 if (ast_strlen_zero(fax->details->error)) \
1475 ast_string_field_set(fax->details, error, errorstr); \
1476 set_channel_variables(chan, fax->details); \
1479#define GENERIC_FAX_EXEC_ERROR_QUIET(fax, chan, errorstr, reason) \
1481 GENERIC_FAX_EXEC_SET_VARS(fax, chan, errorstr, reason); \
1484#define GENERIC_FAX_EXEC_ERROR(fax, chan, errorstr, reason) \
1486 ast_log(LOG_ERROR, "channel '%s' FAX session '%u' failure, reason: '%s' (%s)\n", ast_channel_name(chan), fax->id, reason, errorstr); \
1487 GENERIC_FAX_EXEC_ERROR_QUIET(fax, chan, errorstr, reason); \
1531 struct timeval start;
1559 (frame->
datalen ==
sizeof(t38_parameters))) {
1594 unsigned int expected_frametype = -1;
1598 const char *tempvar;
1605 struct timeval start;
1610 if (t38negotiated) {
1686 remaining_time = timeout;
1688 while (remaining_time > 0) {
1715 (frame->
datalen ==
sizeof(t38_parameters))) {
1716 unsigned int was_t38 = t38negotiated;
1741 if (t38negotiated && !was_t38) {
1746 details->
caps &= ~AST_FAX_TECH_AUDIO;
1788 }
else if (ofd == fax->
fd) {
1791 if (!(frame = fax->
tech->
read(fax))) {
1804 if (ms && (ofd < 0)) {
1807 if (remaining_time <= 0)
1818 if (remaining_time <= 0) {
1825 ast_debug(3,
"channel '%s' - event loop stopped { timeout: %d, remaining_time: %d }\n",
ast_channel_name(chan), timeout, remaining_time);
1830 if (!strcasecmp(details->
result,
"FAILED")) {
1843 if (orig_read_format) {
1846 if (orig_write_format) {
1860 struct timeval start;
1894 (frame->
datalen ==
sizeof(t38_parameters))) {
1910 details->
caps &= ~AST_FAX_TECH_AUDIO;
1952 details->
caps &= ~AST_FAX_TECH_T38;
1963 (frame->
datalen ==
sizeof(t38_parameters))) {
1975 details->
caps &= ~AST_FAX_TECH_AUDIO;
1981 details->
caps &= ~AST_FAX_TECH_T38;
1986 details->
caps &= ~AST_FAX_TECH_T38;
2024 if (!json_array || !json_filename) {
2031 const char *remote_station_id;
2032 const char *local_station_id;
2033 const char *fax_pages;
2034 const char *fax_resolution;
2035 const char *fax_bitrate;
2040 remote_station_id =
ast_strdupa(remote_station_id);
2059 json_object =
ast_json_pack(
"{s: s, s: s, s: s, s: s, s: s, s: s, s: o}",
2061 "remote_station_id",
S_OR(remote_station_id,
""),
2062 "local_station_id",
S_OR(local_station_id,
""),
2063 "fax_pages",
S_OR(fax_pages,
""),
2064 "fax_resolution",
S_OR(fax_resolution,
""),
2065 "fax_bitrate",
S_OR(fax_bitrate,
""),
2083 char *parse, modems[128] =
"";
2087 struct ast_fax_tech_token *token =
NULL;
2109 ast_log(
LOG_ERROR,
"System cannot provide memory for session requirements.\n");
2118 if (details->gateway_id > 0) {
2119 ast_string_field_set(details, resultstr,
"can't receive a fax on a channel with a T.38 gateway");
2121 ast_log(
LOG_ERROR,
"executing ReceiveFAX on a channel with a T.38 Gateway is not supported\n");
2125 if (details->maxrate < details->minrate) {
2129 ast_log(
LOG_ERROR,
"maxrate %u is less than minrate %u\n", details->maxrate, details->minrate);
2135 ast_log(
LOG_ERROR,
"'modems' setting '%s' is incompatible with 'minrate' setting %u\n", modems, details->minrate);
2144 ast_log(
LOG_ERROR,
"'modems' setting '%s' is incompatible with 'maxrate' setting %u\n", modems, details->maxrate);
2190 if (!(doc =
ast_calloc(1,
sizeof(*doc) + strlen(
args.filename) + 1))) {
2194 ast_log(
LOG_ERROR,
"System cannot provide memory for session requirements.\n");
2279 return (!channel_alive) ? -1 : 0;
2287 struct timeval start;
2300 if (
ast_playtones_start(chan, 1024,
"!1100/500,!0/3000,!1100/500,!0/3000,!1100/500,!0/3000", 1)) {
2329 (frame->
datalen ==
sizeof(t38_parameters))) {
2345 details->
caps &= ~AST_FAX_TECH_AUDIO;
2390 details->
caps &= ~AST_FAX_TECH_T38;
2401 (frame->
datalen ==
sizeof(t38_parameters))) {
2413 details->
caps &= ~AST_FAX_TECH_AUDIO;
2419 details->
caps &= ~AST_FAX_TECH_T38;
2424 details->
caps &= ~AST_FAX_TECH_T38;
2471 (frame->
datalen ==
sizeof(t38_parameters))) {
2487 details->
caps &= ~AST_FAX_TECH_AUDIO;
2533 if (!json_filenames) {
2538 const char *remote_station_id;
2539 const char *local_station_id;
2540 const char *fax_pages;
2541 const char *fax_resolution;
2542 const char *fax_bitrate;
2547 remote_station_id =
ast_strdupa(remote_station_id);
2565 json_obj =
ast_json_pack(
"{s: s, s: s, s: s, s: s, s: s, s: s, s: o}",
2567 "remote_station_id",
S_OR(remote_station_id,
""),
2568 "local_station_id",
S_OR(local_station_id,
""),
2569 "fax_pages",
S_OR(fax_pages,
""),
2570 "fax_resolution",
S_OR(fax_resolution,
""),
2571 "fax_bitrate",
S_OR(fax_bitrate,
""),
2572 "filenames", json_filenames);
2591 char *parse, *filenames, *
c, modems[128] =
"";
2592 int channel_alive, file_count;
2595 struct ast_fax_tech_token *token =
NULL;
2617 ast_log(
LOG_ERROR,
"System cannot provide memory for session requirements.\n");
2626 if (details->gateway_id > 0) {
2629 ast_log(
LOG_ERROR,
"executing SendFAX on a channel with a T.38 Gateway is not supported\n");
2633 if (details->maxrate < details->minrate) {
2637 ast_log(
LOG_ERROR,
"maxrate %u is less than minrate %u\n", details->maxrate, details->minrate);
2643 ast_log(
LOG_ERROR,
"'modems' setting '%s' is incompatible with 'minrate' setting %u\n", modems, details->minrate);
2652 ast_log(
LOG_ERROR,
"'modems' setting '%s' is incompatible with 'maxrate' setting %u\n", modems, details->maxrate);
2697 filenames =
args.filenames;
2698 while ((
c =
strsep(&filenames,
"&"))) {
2699 if (access(
c, (F_OK | R_OK)) < 0) {
2703 ast_log(
LOG_ERROR,
"access failure. Verify '%s' exists and check permissions.\n",
args.filenames);
2707 if (!(doc =
ast_calloc(1,
sizeof(*doc) + strlen(
c) + 1))) {
2711 ast_log(
LOG_ERROR,
"System cannot provide memory for session requirements.\n");
2727 if (file_count > 1) {
2792 details->option.send_cng = 1;
2807 return (!channel_alive) ? -1 : 0;
2816 return (!channel_alive) ? -1 : 0;
2896 details->
caps &= ~AST_FAX_TECH_GATEWAY;
2897 ast_log(
LOG_ERROR,
"Can't reserve a FAX session, gateway attempt failed.\n");
2939 ast_log(
LOG_ERROR,
"Can't create a FAX session, gateway attempt failed.\n");
2953 if (start_res < 0) {
2980 .datalen =
sizeof(t38_parameters),
2982 .data.ptr = &t38_parameters,
3013 struct ast_channel *other = (active == chan) ? peer : chan;
3020 if (active_v21_session->
tech->
write(active_v21_session, f) == 0 &&
3063 if (active == chan) {
3067 if (active == chan) {
3086 if (active == chan) {
3111 struct ast_channel *other = (active == chan) ? peer : chan;
3193 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));
3349 switch (gateway->
s->
state) {
3450 if (chan_is_hungup || peer_is_hungup) {
3463 details->gateway_id = -1;
3468 details->is_t38_negotiated = 0;
3473 if (details->gateway_timeout) {
3508 details->gateway_id = -1;
3513 details->is_t38_negotiated = 0;
3605 .data.ptr = silence_buf,
3607 .datalen =
sizeof(silence_buf),
3609 memset(silence_buf, 0,
sizeof(silence_buf));
3632 .disable_inheritance = 1,
3656 fr_hook.
data = gateway;
3679 if (faxdetect->
dsp) {
3711 if (!faxdetect->
dsp) {
3808 if (!faxdetect->
dsp) {
3846 const char *target_context;
3858 ast_verb(2,
"Redirecting '%s' to fax extension due to %s detection\n",
3866 (
result ==
'f') ?
"CNG" :
"T38", target_context);
3899 ast_log(
LOG_ERROR,
"System cannot provide memory for session requirements.\n");
3910 fr_hook.
data = faxdetect;
3955 tklen = strlen(
a->word);
3958 snprintf(tbuf,
sizeof(tbuf),
"%u", s->
id);
3959 if (!strncasecmp(
a->word, tbuf, tklen) && ++wordnum >
a->n) {
3976 e->
command =
"fax show version";
3978 "Usage: fax show version\n"
3979 " Show versions of FAX For Asterisk components.\n";
3989 ast_cli(
a->fd,
"FAX For Asterisk Components:\n");
4009 e->
command =
"fax set debug {on|off}";
4011 "Usage: fax set debug { on | off }\n"
4012 " Enable/Disable FAX debugging on new FAX sessions. The basic FAX debugging will result in\n"
4013 " additional events sent to manager sessions with 'call' class permissions. When\n"
4014 " verbosity is greater than '5' events will be displayed to the console and audio versus\n"
4015 " energy analysis will be performed and displayed to the console.\n";
4021 what =
a->argv[e->
args-1];
4022 if (!strcasecmp(what,
"on")) {
4024 }
else if (!strcasecmp(what,
"off")) {
4031 ast_cli(
a->fd,
"\n\nFAX Debug %s\n\n", (
flag) ?
"Enabled" :
"Disabled");
4040 unsigned int num_modules = 0;
4044 e->
command =
"fax show capabilities";
4046 "Usage: fax show capabilities\n"
4047 " Shows the capabilities of the registered FAX technology modules\n";
4053 ast_cli(
a->fd,
"\n\nRegistered FAX Technology Modules:\n\n");
4061 ast_cli(
a->fd,
"%u registered modules\n\n", num_modules);
4070 char modems[128] =
"";
4075 e->
command =
"fax show settings";
4077 "Usage: fax show settings\n"
4078 " Show the global settings and defaults of both the FAX core and technology modules\n";
4086 ast_cli(
a->fd,
"FAX For Asterisk Settings:\n");
4088 ast_cli(
a->fd,
"\tStatus Events: %s\n",
options.statusevents ?
"On" :
"Off");
4093 ast_cli(
a->fd,
"\tT.38 Negotiation Timeout: %u\n",
options.t38timeout);
4094 ast_cli(
a->fd,
"\n\nFAX Technology Modules:\n\n");
4112 e->
command =
"fax show session";
4114 "Usage: fax show session <session number>\n"
4115 " Shows status of the named FAX session\n";
4125 if (sscanf(
a->argv[3],
"%u", &
tmp.id) != 1) {
4130 ast_cli(
a->fd,
"\nFAX Session Details:\n--------------------\n\n");
4146 char id_text[256] =
"";
4150 if (sscanf(session_number,
"%30u", &
find_session.id) != 1) {
4161 if (!
session->tech->manager_fax_session) {
4162 astman_send_error(s, m,
"Fax technology doesn't provide a handler for FAXSession");
4168 snprintf(id_text,
sizeof(id_text),
"ActionID: %s\r\n", action_id);
4186 e->
command =
"fax show stats";
4188 "Usage: fax show stats\n"
4189 " Shows a statistical summary of FAX transmissions\n";
4195 ast_cli(
a->fd,
"\nFAX Statistics:\n---------------\n\n");
4216 char id_text[256] =
"";
4221 snprintf(id_text,
sizeof(id_text),
"ActionID: %s\r\n", action_id);
4226 "CurrentSessions: %d\r\n"
4227 "ReservedSessions: %d\r\n"
4228 "TransmitAttempts: %d\r\n"
4229 "ReceiveAttempts: %d\r\n"
4230 "CompletedFAXes: %d\r\n"
4231 "FailedFAXes: %d\r\n"
4281 e->
command =
"fax show sessions";
4283 "Usage: fax show sessions\n"
4284 " Shows the current FAX sessions\n";
4290 ast_cli(
a->fd,
"\nCurrent FAX Sessions:\n\n");
4291 ast_cli(
a->fd,
"%-30.30s %-10.10s %-10.10s %-5.5s %-10.10s %-15.15s %-30.30s\n",
4292 "Channel",
"Tech",
"FAXID",
"Type",
"Operation",
"State",
"File(s)");
4299 ast_cli(
a->fd,
"%-30.30s %-10.10s %-10u %-5.5s %-10.10s %-15.15s %-30s\n",
4333 "Technology: %s\r\n"
4334 "SessionNumber: %u\r\n"
4335 "SessionType: %s\r\n"