79 #include "asterisk/res_fax.h"
88 #include "asterisk/stasis_channels.h"
427 static const char app_receivefax[] =
"ReceiveFAX";
428 static const char app_sendfax[] =
"SendFAX";
431 unsigned int consec_frames;
432 unsigned int consec_ms;
433 unsigned char silence;
437 struct timeval base_tv;
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)
486 static int fax_logger_level = -1;
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
528 enum ast_fax_modems modems;
529 uint32_t statusevents:1;
531 unsigned int minrate;
532 unsigned int maxrate;
533 unsigned int t38timeout;
538 static const struct fax_options default_options = {
539 .minrate = RES_FAX_MINRATE,
540 .maxrate = RES_FAX_MAXRATE,
541 .statusevents = RES_FAX_STATUSEVENTS,
542 .modems = RES_FAX_MODEM,
543 .ecm = AST_FAX_OPTFLAG_TRUE,
544 .t38timeout = RES_FAX_T38TIMEOUT,
547 AST_RWLOCK_DEFINE_STATIC(options_lock);
549 static void get_general_options(
struct fax_options* options);
550 static void set_general_options(
const struct fax_options* options);
552 static const char *config =
"res_fax.conf";
554 static int global_fax_debug = 0;
557 OPT_CALLEDMODE = (1 << 0),
558 OPT_CALLERMODE = (1 << 1),
559 OPT_DEBUG = (1 << 2),
560 OPT_STATUS = (1 << 3),
561 OPT_ALLOWAUDIO = (1 << 5),
562 OPT_REQUEST_T38 = (1 << 6),
563 OPT_FORCE_AUDIO = (1 << 7),
580 unsigned int last_consec_frames, last_consec_ms;
581 unsigned char wassil;
589 wassil = history->silence;
590 history->silence = (dspsilence != 0) ? 1 : 0;
591 if (history->silence != wassil) {
592 last_consec_frames = history->consec_frames;
593 last_consec_ms = history->consec_ms;
594 history->consec_frames = 0;
595 history->consec_ms = 0;
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");
605 history->consec_frames++;
606 history->consec_ms += (frame->
samples / 8);
646 ao2_cleanup(new_details);
666 ast_channel_lock(chan);
668 ast_channel_unlock(chan);
671 if (!(details = datastore->
data)) {
672 ast_log(LOG_WARNING,
"Huh? channel '%s' has a FAX datastore without data!\n", ast_channel_name(chan));
673 ast_channel_unlock(chan);
677 ast_channel_unlock(chan);
709 get_general_options(&options);
720 d->
modems = options.modems;
735 .rate = AST_T38_RATE_14400,
736 .rate_management = AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF,
773 ast_log(LOG_WARNING,
"channel '%s' can't get a FAX details structure for the datastore!\n", ast_channel_name(chan));
776 if (!(datastore = ast_datastore_alloc(&fax_datastore, NULL))) {
778 ast_log(LOG_WARNING,
"channel '%s' can't get a datastore!\n", ast_channel_name(chan));
782 datastore->
data = details;
789 ast_channel_lock(chan);
791 ast_channel_unlock(chan);
798 get_general_options(&options);
800 return options.maxrate;
806 get_general_options(&options);
808 return options.minrate;
811 static int update_modem_bits(
enum ast_fax_modems *bits,
const char *value)
813 char *m[5], *tok, *v = (
char *) value, *rest;
816 if (!strchr(v,
',')) {
820 tok = strtok_r(v,
", ", &rest);
821 while (tok && i < ARRAY_LEN(m) - 1) {
823 tok = strtok_r(NULL,
", ", &rest);
829 for (j = 0; j < i; j++) {
830 if (!strcasecmp(m[j],
"v17")) {
831 *bits |= AST_FAX_MODEM_V17;
832 }
else if (!strcasecmp(m[j],
"v27")) {
833 *bits |= AST_FAX_MODEM_V27TER;
834 }
else if (!strcasecmp(m[j],
"v29")) {
835 *bits |= AST_FAX_MODEM_V29;
836 }
else if (!strcasecmp(m[j],
"v34")) {
837 *bits |= AST_FAX_MODEM_V34;
839 ast_log(LOG_WARNING,
"ignoring invalid modem setting: '%s', valid options {v17 | v27 | v29 | v34}\n", m[j]);
845 static char *ast_fax_caps_to_str(
enum ast_fax_capabilities caps,
char *buf,
size_t bufsize)
848 size_t size = bufsize;
851 if (caps & AST_FAX_TECH_SEND) {
858 if (caps & AST_FAX_TECH_RECEIVE) {
865 if (caps & AST_FAX_TECH_AUDIO) {
872 if (caps & AST_FAX_TECH_T38) {
879 if (caps & AST_FAX_TECH_MULTI_DOC) {
886 if (caps & AST_FAX_TECH_GATEWAY) {
893 if (caps & AST_FAX_TECH_V21_DETECT) {
904 static int ast_fax_modem_to_str(
enum ast_fax_modems bits,
char *tbuf,
size_t bufsize)
908 if (bits & AST_FAX_MODEM_V17) {
912 if (bits & AST_FAX_MODEM_V27TER) {
919 if (bits & AST_FAX_MODEM_V29) {
926 if (bits & AST_FAX_MODEM_V34) {
937 static int check_modem_rate(
enum ast_fax_modems modems,
unsigned int rate)
942 if (!(modems & (AST_FAX_MODEM_V27TER | AST_FAX_MODEM_V34))) {
948 if (!(modems & (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V29 | AST_FAX_MODEM_V34))) {
954 if (!(modems & (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V34))) {
960 if (!(modems & AST_FAX_MODEM_V34)) {
982 AST_RWLIST_INSERT_TAIL(&
faxmodules, fax, list);
985 ast_verb(3,
"Registered handler for '%s' (%s)\n", fax->tech->
type, fax->tech->
description);
995 ast_verb(3,
"Unregistering FAX module type '%s'\n", tech->
type);
998 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&
faxmodules, fax, list) {
999 if (fax->tech != tech) {
1002 AST_RWLIST_REMOVE_CURRENT(list);
1004 ast_verb(4,
"Unregistered FAX module type '%s'\n", tech->
type);
1007 AST_RWLIST_TRAVERSE_SAFE_END;
1015 case AST_FAX_STATE_UNINITIALIZED:
1016 return "Uninitialized";
1017 case AST_FAX_STATE_INITIALIZED:
1018 return "Initialized";
1019 case AST_FAX_STATE_OPEN:
1021 case AST_FAX_STATE_ACTIVE:
1023 case AST_FAX_STATE_COMPLETE:
1025 case AST_FAX_STATE_RESERVED:
1027 case AST_FAX_STATE_INACTIVE:
1030 ast_log(LOG_WARNING,
"unhandled FAX state: %u\n", state);
1035 void ast_fax_log(
int level,
const char *file,
const int line,
const char *
function,
const char *msg)
1037 if (fax_logger_level != -1) {
1040 ast_log(level, file, line,
function,
"%s", msg);
1049 if (sscanf(ratestr,
"%d", &rate) != 1) {
1050 ast_log(LOG_ERROR,
"failed to sscanf '%s' to rate\n", ratestr);
1064 ast_log(LOG_WARNING,
"ignoring invalid rate '%s'. Valid options are {2400 | 4800 | 7200 | 9600 | 12000 | 14400 | 28800 | 33600}\n", ratestr);
1088 if (s->
state == AST_FAX_STATE_RESERVED) {
1090 s->
state = AST_FAX_STATE_INACTIVE;
1124 if (s->
state != AST_FAX_STATE_INACTIVE) {
1154 s->
state = AST_FAX_STATE_INACTIVE;
1162 AST_RWLIST_TRAVERSE(&
faxmodules, faxmod, list) {
1163 if ((faxmod->tech->
caps & details->
caps) != details->
caps) {
1170 s->
tech = faxmod->tech;
1176 char caps[128] =
"";
1177 ast_log(LOG_ERROR,
"Could not locate a FAX technology module with capabilities (%s)\n", ast_fax_caps_to_str(details->
caps, caps,
sizeof(caps)));
1192 s->
state = AST_FAX_STATE_RESERVED;
1230 if (s->
state == AST_FAX_STATE_RESERVED) {
1232 s->
state = AST_FAX_STATE_UNINITIALIZED;
1241 s->
state = AST_FAX_STATE_UNINITIALIZED;
1282 AST_RWLIST_TRAVERSE(&
faxmodules, faxmod, list) {
1283 if ((faxmod->tech->
caps & details->
caps) != details->
caps) {
1294 s->
tech = faxmod->tech;
1300 char caps[128] =
"";
1301 ast_log(LOG_ERROR,
"Could not locate a FAX technology module with capabilities (%s)\n", ast_fax_caps_to_str(details->
caps, caps,
sizeof(caps)));
1308 ast_log(LOG_ERROR,
"FAX session failed to initialize.\n");
1314 ast_log(LOG_ERROR,
"failed to add FAX session '%u' to container.\n", s->
id);
1334 if (!details || !json_array) {
1371 char *filenames, *c;
1383 size += strlen(separator) + strlen(prefix) + strlen(doc->filename);
1410 struct ast_json *json_filenames = NULL;
1416 json_filenames = generate_filenames_json(details);
1417 if (!json_filenames) {
1421 json_object =
ast_json_pack(
"{s: s, s: s, s: s, s: s, s: o}",
1423 "operation", (details->
caps & AST_FAX_TECH_GATEWAY)
1425 : (details->
caps & AST_FAX_TECH_RECEIVE) ?
"receive" :
"send",
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); \
1494 details->
caps |= AST_FAX_TECH_T38;
1498 details->
caps |= AST_FAX_TECH_AUDIO;
1512 ast_log(LOG_ERROR,
"channel '%s' is in an unsupported T.38 negotiation state, cannot continue.\n", ast_channel_name(chan));
1515 details->
caps |= AST_FAX_TECH_T38;
1519 ast_log(LOG_ERROR,
"channel '%s' is in an unsupported T.38 negotiation state, cannot continue.\n", ast_channel_name(chan));
1531 struct timeval start;
1534 ast_debug(1,
"Shutting down T.38 on %s\n", ast_channel_name(chan));
1536 ast_debug(1,
"error while disabling T.38 on channel '%s'\n", ast_channel_name(chan));
1550 ast_debug(1,
"error while disabling T.38 on channel '%s'\n", ast_channel_name(chan));
1559 (frame->
datalen ==
sizeof(t38_parameters))) {
1564 ast_debug(1,
"Shut down T.38 on %s\n", ast_channel_name(chan));
1567 ast_log(LOG_WARNING,
"channel '%s' refused to disable T.38\n", ast_channel_name(chan));
1571 ast_log(LOG_ERROR,
"channel '%s' failed to disable T.38\n", ast_channel_name(chan));
1582 ast_debug(1,
"channel '%s' timed-out during T.38 shutdown\n", ast_channel_name(chan));
1592 int timeout = RES_FAX_TIMEOUT;
1594 unsigned int expected_frametype = -1;
1598 const char *tempvar;
1605 struct timeval start;
1610 if (t38negotiated) {
1611 details->
caps |= AST_FAX_TECH_T38;
1613 details->
caps |= AST_FAX_TECH_AUDIO;
1618 ast_log(LOG_ERROR,
"Can't create a FAX session, FAX attempt failed.\n");
1623 ast_channel_lock(chan);
1632 ast_channel_unlock(chan);
1636 if (details->
caps & AST_FAX_TECH_AUDIO) {
1639 orig_write_format =
ao2_bump(ast_channel_writeformat(chan));
1641 ast_log(LOG_ERROR,
"channel '%s' failed to set write format to signed linear'.\n", ast_channel_name(chan));
1646 orig_read_format =
ao2_bump(ast_channel_readformat(chan));
1648 ast_log(LOG_ERROR,
"channel '%s' failed to set read format to signed linear.\n", ast_channel_name(chan));
1657 if (!(fax->
smoother = ast_smoother_new(320))) {
1658 ast_log(LOG_WARNING,
"Channel '%s' FAX session '%u' failed to obtain a smoother.\n", ast_channel_name(chan), fax->
id);
1678 GENERIC_FAX_EXEC_ERROR(fax, chan,
"INIT_ERROR",
"failed to start FAX session");
1683 ast_debug(5,
"channel %s will wait on FAX fd %d\n", ast_channel_name(chan), fax->
fd);
1686 remaining_time = timeout;
1688 while (remaining_time > 0) {
1701 ast_debug(1,
"Channel '%s' did not return a frame; probably hung up.\n", ast_channel_name(chan));
1702 GENERIC_FAX_EXEC_SET_VARS(fax, chan,
"HANGUP",
"remote channel hungup");
1715 (frame->
datalen ==
sizeof(t38_parameters))) {
1716 unsigned int was_t38 = t38negotiated;
1725 if (details->
caps & AST_FAX_TECH_T38) {
1741 if (t38negotiated && !was_t38) {
1743 GENERIC_FAX_EXEC_ERROR(fax, chan,
"UNKNOWN",
"T.38 switch failed");
1746 details->
caps &= ~AST_FAX_TECH_AUDIO;
1756 ast_verb(3,
"Channel '%s' switched to T.38 FAX session '%u'.\n", ast_channel_name(chan), fax->
id);
1766 if (ast_smoother_feed(fax->
smoother, frame) < 0) {
1767 GENERIC_FAX_EXEC_ERROR(fax, chan,
"UNKNOWN",
"Failed to feed the smoother");
1769 while ((f = ast_smoother_read(fax->
smoother)) && (f->
data.ptr)) {
1771 debug_check_frame_for_silence(fax, 1, f);
1788 }
else if (ofd == fax->
fd) {
1791 if (!(frame = fax->
tech->
read(fax))) {
1796 debug_check_frame_for_silence(fax, 0, frame);
1804 if (ms && (ofd < 0)) {
1805 if ((errno == 0) || (errno == EINTR)) {
1807 if (remaining_time <= 0)
1808 GENERIC_FAX_EXEC_ERROR(fax, chan,
"TIMEOUT",
"fax session timed-out");
1811 ast_log(LOG_WARNING,
"something bad happened while channel '%s' was polling.\n", ast_channel_name(chan));
1812 GENERIC_FAX_EXEC_ERROR(fax, chan,
"UNKNOWN",
"error polling data");
1818 if (remaining_time <= 0) {
1819 GENERIC_FAX_EXEC_ERROR(fax, chan,
"TIMEOUT",
"fax session timed-out");
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;
1867 ast_log(LOG_ERROR,
"error generating CED tone on %s\n", ast_channel_name(chan));
1877 ast_log(LOG_ERROR,
"error while generating CED tone on %s\n", ast_channel_name(chan));
1887 ast_log(LOG_ERROR,
"error reading frame while generating CED tone on %s\n", ast_channel_name(chan));
1894 (frame->
datalen ==
sizeof(t38_parameters))) {
1908 ast_debug(1,
"Negotiated T.38 for receive on %s\n", ast_channel_name(chan));
1910 details->
caps &= ~AST_FAX_TECH_AUDIO;
1929 ast_debug(1,
"Negotiating T.38 for receive on %s\n", ast_channel_name(chan));
1947 ast_log(LOG_WARNING,
"error on '%s' while waiting for T.38 negotiation.\n", ast_channel_name(chan));
1951 ast_log(LOG_WARNING,
"channel '%s' timed-out during the T.38 negotiation.\n", ast_channel_name(chan));
1952 details->
caps &= ~AST_FAX_TECH_T38;
1957 ast_log(LOG_WARNING,
"error on '%s' while waiting for T.38 negotiation.\n", ast_channel_name(chan));
1963 (frame->
datalen ==
sizeof(t38_parameters))) {
1973 ast_debug(1,
"Negotiated T.38 for receive on %s\n", ast_channel_name(chan));
1975 details->
caps &= ~AST_FAX_TECH_AUDIO;
1980 ast_log(LOG_WARNING,
"channel '%s' refused to negotiate T.38\n", ast_channel_name(chan));
1981 details->
caps &= ~AST_FAX_TECH_T38;
1985 ast_log(LOG_ERROR,
"channel '%s' failed to negotiate T.38\n", ast_channel_name(chan));
1986 details->
caps &= ~AST_FAX_TECH_T38;
2004 ast_log(LOG_WARNING,
"Audio FAX not allowed on channel '%s' and T.38 negotiation failed; aborting.\n", ast_channel_name(chan));
2009 details->
caps |= AST_FAX_TECH_AUDIO;
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;
2039 if (!ast_strlen_zero(remote_station_id)) {
2040 remote_station_id =
ast_strdupa(remote_station_id);
2043 if (!ast_strlen_zero(local_station_id)) {
2047 if (!ast_strlen_zero(fax_pages)) {
2051 if (!ast_strlen_zero(fax_resolution)) {
2055 if (!ast_strlen_zero(fax_bitrate)) {
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");
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");
2129 ast_log(LOG_ERROR,
"maxrate %u is less than minrate %u\n", details->
maxrate, details->
minrate);
2134 ast_fax_modem_to_str(details->
modems, modems,
sizeof(modems));
2135 ast_log(LOG_ERROR,
"'modems' setting '%s' is incompatible with 'minrate' setting %u\n", modems, details->
minrate);
2143 ast_fax_modem_to_str(details->
modems, modems,
sizeof(modems));
2144 ast_log(LOG_ERROR,
"'modems' setting '%s' is incompatible with 'maxrate' setting %u\n", modems, details->
maxrate);
2151 if (ast_strlen_zero(data)) {
2155 ast_log(LOG_WARNING,
"%s requires an argument (filename[,options])\n", app_receivefax);
2161 if (!ast_strlen_zero(args.options) &&
2168 if (ast_strlen_zero(args.filename)) {
2172 ast_log(LOG_WARNING,
"%s requires an argument (filename[,options])\n", app_receivefax);
2177 if (ast_test_flag(&opts, OPT_CALLERMODE) || ast_test_flag(&opts, OPT_CALLEDMODE)) {
2181 ast_log(LOG_WARNING,
"%s does not support polling\n", app_receivefax);
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");
2198 strcpy(doc->filename, args.filename);
2201 ast_verb(3,
"Channel '%s' receiving FAX '%s'\n", ast_channel_name(chan), args.filename);
2203 details->
caps = AST_FAX_TECH_RECEIVE;
2207 if (ast_test_flag(&opts, OPT_DEBUG) || global_fax_debug) {
2212 if (ast_test_flag(&opts, OPT_STATUS)) {
2218 ast_test_flag(&opts, OPT_ALLOWAUDIO) ||
2219 ast_test_flag(&opts, OPT_FORCE_AUDIO)) {
2226 ast_log(LOG_ERROR,
"Unable to reserve FAX session.\n");
2235 ast_log(LOG_WARNING,
"Channel '%s' failed answer attempt.\n", ast_channel_name(chan));
2241 if (!ast_test_flag(&opts, OPT_FORCE_AUDIO)) {
2242 if (set_fax_t38_caps(chan, details)) {
2250 details->
caps |= AST_FAX_TECH_AUDIO;
2253 if (!ast_test_flag(&opts, OPT_FORCE_AUDIO) && (details->
caps & AST_FAX_TECH_T38)) {
2254 if (receivefax_t38_init(chan, details)) {
2259 ast_log(LOG_ERROR,
"error initializing channel '%s' in T.38 mode\n", ast_channel_name(chan));
2269 if (disable_t38(chan)) {
2270 ast_debug(1,
"error disabling T.38 mode on %s\n", ast_channel_name(chan));
2275 ast_log(AST_LOG_ERROR,
"Error publishing ReceiveFAX status message\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)) {
2301 ast_log(LOG_ERROR,
"error generating CNG tone on %s\n", ast_channel_name(chan));
2312 ast_log(LOG_ERROR,
"error while generating CNG tone on %s\n", ast_channel_name(chan));
2322 ast_log(LOG_ERROR,
"error reading frame while generating CNG tone on %s\n", ast_channel_name(chan));
2329 (frame->
datalen ==
sizeof(t38_parameters))) {
2343 ast_debug(1,
"Negotiated T.38 for send on %s\n", ast_channel_name(chan));
2345 details->
caps &= ~AST_FAX_TECH_AUDIO;
2367 ast_debug(1,
"Negotiating T.38 for send on %s\n", ast_channel_name(chan));
2385 ast_log(LOG_WARNING,
"error on '%s' while waiting for T.38 negotiation.\n", ast_channel_name(chan));
2389 ast_log(LOG_WARNING,
"channel '%s' timed-out during the T.38 negotiation.\n", ast_channel_name(chan));
2390 details->
caps &= ~AST_FAX_TECH_T38;
2395 ast_log(LOG_WARNING,
"error on '%s' while waiting for T.38 negotiation.\n", ast_channel_name(chan));
2401 (frame->
datalen ==
sizeof(t38_parameters))) {
2411 ast_debug(1,
"Negotiated T.38 for receive on %s\n", ast_channel_name(chan));
2413 details->
caps &= ~AST_FAX_TECH_AUDIO;
2418 ast_log(LOG_WARNING,
"channel '%s' refused to negotiate T.38\n", ast_channel_name(chan));
2419 details->
caps &= ~AST_FAX_TECH_T38;
2423 ast_log(LOG_ERROR,
"channel '%s' failed to negotiate T.38\n", ast_channel_name(chan));
2424 details->
caps &= ~AST_FAX_TECH_T38;
2444 ast_log(LOG_ERROR,
"error generating second CNG tone on %s\n", ast_channel_name(chan));
2455 ast_log(LOG_ERROR,
"error while generating second CNG tone on %s\n", ast_channel_name(chan));
2464 ast_log(LOG_ERROR,
"error reading frame while generating second CNG tone on %s\n", ast_channel_name(chan));
2471 (frame->
datalen ==
sizeof(t38_parameters))) {
2485 ast_debug(1,
"Negotiated T.38 for send on %s\n", ast_channel_name(chan));
2487 details->
caps &= ~AST_FAX_TECH_AUDIO;
2512 ast_log(LOG_WARNING,
"Audio FAX not allowed on channel '%s' and T.38 negotiation failed; aborting.\n", ast_channel_name(chan));
2517 details->
caps |= AST_FAX_TECH_AUDIO;
2532 json_filenames = generate_filenames_json(details);
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;
2546 if (!ast_strlen_zero(remote_station_id)) {
2547 remote_station_id =
ast_strdupa(remote_station_id);
2550 if (!ast_strlen_zero(local_station_id)) {
2554 if (!ast_strlen_zero(fax_pages)) {
2558 if (!ast_strlen_zero(fax_resolution)) {
2562 if (!ast_strlen_zero(fax_bitrate)) {
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");
2629 ast_log(LOG_ERROR,
"executing SendFAX on a channel with a T.38 Gateway is not supported\n");
2637 ast_log(LOG_ERROR,
"maxrate %u is less than minrate %u\n", details->
maxrate, details->
minrate);
2642 ast_fax_modem_to_str(details->
modems, modems,
sizeof(modems));
2643 ast_log(LOG_ERROR,
"'modems' setting '%s' is incompatible with 'minrate' setting %u\n", modems, details->
minrate);
2651 ast_fax_modem_to_str(details->
modems, modems,
sizeof(modems));
2652 ast_log(LOG_ERROR,
"'modems' setting '%s' is incompatible with 'maxrate' setting %u\n", modems, details->
maxrate);
2659 if (ast_strlen_zero(data)) {
2663 ast_log(LOG_WARNING,
"%s requires an argument (filename[&filename[&filename]][,options])\n", app_sendfax);
2670 if (!ast_strlen_zero(args.options) &&
2677 if (ast_strlen_zero(args.filenames)) {
2681 ast_log(LOG_WARNING,
"%s requires an argument (filename[&filename[&filename]],options])\n", app_sendfax);
2686 if (ast_test_flag(&opts, OPT_CALLERMODE) || ast_test_flag(&opts, OPT_CALLEDMODE)) {
2690 ast_log(LOG_WARNING,
"%s does not support polling\n", app_sendfax);
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");
2715 strcpy(doc->filename, c);
2720 ast_verb(3,
"Channel '%s' sending FAX:\n", ast_channel_name(chan));
2722 ast_verb(3,
" %s\n", doc->filename);
2725 details->
caps = AST_FAX_TECH_SEND;
2727 if (file_count > 1) {
2728 details->
caps |= AST_FAX_TECH_MULTI_DOC;
2732 if (ast_test_flag(&opts, OPT_DEBUG) || global_fax_debug) {
2737 if (ast_test_flag(&opts, OPT_STATUS)) {
2743 ast_test_flag(&opts, OPT_ALLOWAUDIO) ||
2744 ast_test_flag(&opts, OPT_FORCE_AUDIO)) {
2748 if (ast_test_flag(&opts, OPT_REQUEST_T38)) {
2755 ast_log(LOG_ERROR,
"Unable to reserve FAX session.\n");
2764 ast_log(LOG_WARNING,
"Channel '%s' failed answer attempt.\n", ast_channel_name(chan));
2770 if (!ast_test_flag(&opts, OPT_FORCE_AUDIO)) {
2771 if (set_fax_t38_caps(chan, details)) {
2779 details->
caps |= AST_FAX_TECH_AUDIO;
2782 if (!ast_test_flag(&opts, OPT_FORCE_AUDIO) && (details->
caps & AST_FAX_TECH_T38)) {
2783 if (sendfax_t38_init(chan, details)) {
2788 ast_log(LOG_ERROR,
"error initializing channel '%s' in T.38 mode\n", ast_channel_name(chan));
2800 if (disable_t38(chan)) {
2801 ast_debug(1,
"error disabling T.38 mode on %s\n", ast_channel_name(chan));
2806 ast_log(LOG_ERROR,
"Error generating SendFAX manager event\n");
2807 return (!channel_alive) ? -1 : 0;
2812 ast_log(AST_LOG_ERROR,
"Error publishing SendFAX status message\n");
2816 return (!channel_alive) ? -1 : 0;
2822 if (gateway->chan_v21_session) {
2825 ao2_ref(gateway->chan_v21_session, -1);
2826 gateway->chan_v21_session = NULL;
2829 if (gateway->peer_v21_session) {
2832 ao2_ref(gateway->peer_v21_session, -1);
2833 gateway->peer_v21_session = NULL;
2846 gateway->
token = NULL;
2855 ao2_cleanup(gateway->chan_write_format);
2856 ao2_cleanup(gateway->peer_read_format);
2857 ao2_cleanup(gateway->peer_write_format);
2868 v21_details->
caps = AST_FAX_TECH_V21_DETECT;
2886 if (!(gateway->chan_v21_session = fax_v21_session_new(chan))) {
2887 ast_log(LOG_ERROR,
"Can't create V21 session on chan %s for T.38 gateway session\n", ast_channel_name(chan));
2894 details->
caps = AST_FAX_TECH_GATEWAY;
2896 details->
caps &= ~AST_FAX_TECH_GATEWAY;
2897 ast_log(LOG_ERROR,
"Can't reserve a FAX session, gateway attempt failed.\n");
2923 gateway->
s->
state != AST_FAX_STATE_RESERVED && gateway->
s->
state != AST_FAX_STATE_INACTIVE) {
2932 gateway->
token = NULL;
2939 ast_log(LOG_ERROR,
"Can't create a FAX session, gateway attempt failed.\n");
2948 gateway->
token = NULL;
2950 ast_channel_unlock(chan);
2952 ast_channel_lock(chan);
2953 if (start_res < 0) {
2980 .datalen =
sizeof(t38_parameters),
2982 .data.ptr = &t38_parameters,
2988 ast_log(LOG_ERROR,
"no FAX session details found on chan %s for T.38 gateway session, odd\n", ast_channel_name(chan));
2997 ast_log(LOG_ERROR,
"error generating T.38 request control frame on chan %s for T.38 gateway session\n", ast_channel_name(chan));
3006 ast_debug(1,
"requesting T.38 for gateway session for %s\n", ast_channel_name(chan));
3013 struct ast_channel *other = (active == chan) ? peer : chan;
3014 struct ast_fax_session *active_v21_session = (active ==
chan) ? gateway->chan_v21_session : gateway->peer_v21_session;
3020 if (active_v21_session->
tech->
write(active_v21_session, f) == 0 &&
3042 ast_log(LOG_WARNING,
"Detect v21 - no session details for channel '%s'\n",
3043 ast_channel_name(chan));
3048 ast_channel_unlock(chan);
3051 ast_channel_lock(chan);
3053 ast_debug(1,
"detected v21 preamble from %s\n", ast_channel_name(active));
3062 ast_debug(1,
"sending T.38 negotiation request to %s\n", ast_channel_name(active));
3063 if (active == chan) {
3064 ast_channel_unlock(chan);
3067 if (active == chan) {
3068 ast_channel_lock(chan);
3072 ast_debug(1,
"sending T.38 negotiation request to %s\n", ast_channel_name(other));
3076 ast_debug(1,
"neither %s nor %s support T.38 for T.38 gateway session\n", ast_channel_name(active), ast_channel_name(other));
3086 if (active == chan) {
3087 ast_channel_unlock(chan);
3089 ast_channel_lock(chan);
3111 struct ast_channel *other = (active == chan) ? peer : chan;
3130 ast_log(LOG_ERROR,
"no FAX session details found on chan %s for T.38 gateway session, odd\n", ast_channel_name(chan));
3136 ast_channel_unlock(chan);
3138 ast_channel_lock(chan);
3145 ast_debug(1,
"%s is attempting to negotiate T.38 with %s, we'll see what happens\n", ast_channel_name(active), ast_channel_name(other));
3156 ast_debug(1,
"%s is attempting to negotiate T.38 but %s does not support it\n", ast_channel_name(active), ast_channel_name(other));
3157 ast_debug(1,
"starting T.38 gateway for T.38 channel %s and G.711 channel %s\n", ast_channel_name(active), ast_channel_name(other));
3163 ast_log(LOG_ERROR,
"error starting T.38 gateway for T.38 channel %s and G.711 channel %s\n", ast_channel_name(active), ast_channel_name(other));
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));
3216 ast_debug(1,
"%s is attempting to negotiate T.38 after we already negotiated T.38 with %s, disabling the gateway\n", ast_channel_name(active), ast_channel_name(other));
3220 ast_log(LOG_WARNING,
"%s is attempting to negotiate T.38 while %s is in an unsupported state\n", ast_channel_name(active), ast_channel_name(other));
3227 ast_debug(1,
"unable to negotiate T.38 on %s for fax gateway\n", ast_channel_name(active));
3233 ast_channel_unlock(chan);
3235 ast_channel_lock(chan);
3253 ast_debug(1,
"starting T.38 gateway for T.38 channel %s and G.711 channel %s\n", ast_channel_name(active), ast_channel_name(other));
3258 ast_log(LOG_ERROR,
"error starting T.38 gateway for T.38 channel %s and G.711 channel %s\n", ast_channel_name(active), ast_channel_name(other));
3276 ast_debug(1,
"%s attempted to negotiate T.38 but %s refused the request\n", ast_channel_name(other), ast_channel_name(active));
3277 ast_debug(1,
"starting T.38 gateway for T.38 channel %s and G.711 channel %s\n", ast_channel_name(other), ast_channel_name(active));
3282 ast_log(LOG_ERROR,
"error starting T.38 gateway for T.38 channel %s and G.711 channel %s\n", ast_channel_name(other), ast_channel_name(active));
3301 ast_debug(1,
"T.38 channel %s is requesting a shutdown of T.38, disabling the gateway\n", ast_channel_name(active));
3315 ast_debug(1,
"T.38 successfully negotiated between %s and %s, no gateway necessary\n", ast_channel_name(active), ast_channel_name(other));
3329 ast_debug(1,
"T.38 disabled on channel %s\n", ast_channel_name(active));
3349 switch (gateway->
s->
state) {
3350 case AST_FAX_STATE_INITIALIZED:
3351 case AST_FAX_STATE_OPEN:
3352 case AST_FAX_STATE_ACTIVE:
3353 case AST_FAX_STATE_COMPLETE:
3398 ast_log(LOG_ERROR,
"no FAX session details found on chan %s for T.38 gateway session, odd\n", ast_channel_name(chan));
3412 ast_channel_unlock(chan);
3419 ast_channel_lock(chan);
3429 if (ast_test_flag(f, AST_FAX_FRFLAG_GATEWAY)) {
3434 ast_channel_unlock(chan);
3436 ast_channel_lock(chan);
3450 if (chan_is_hungup || peer_is_hungup) {
3454 ast_channel_unlock(chan);
3457 ast_channel_lock(chan);
3461 ast_debug(1,
"not starting gateway for %s and %s; neither channel supports T.38\n", ast_channel_name(chan), ast_channel_name(peer));
3477 ast_channel_unlock(chan);
3483 ao2_replace(gateway->chan_write_format, ast_channel_writeformat(chan));
3485 ao2_replace(gateway->peer_read_format, ast_channel_readformat(peer));
3486 ao2_replace(gateway->peer_write_format, ast_channel_writeformat(peer));
3494 ast_channel_unlock(peer);
3497 if (!(gateway->peer_v21_session = fax_v21_session_new(peer))) {
3498 ast_log(LOG_ERROR,
"Can't create V21 session on chan %s for T.38 gateway session\n", ast_channel_name(peer));
3506 ast_debug(1,
"no fax activity between %s and %s after %d ms, disabling gateway\n", ast_channel_name(chan), ast_channel_name(peer), details->
gateway_timeout);
3551 ast_log(LOG_WARNING,
"unhandled framehook event %u\n", event);
3571 ast_log(LOG_ERROR,
"no FAX session on chan %s for T.38 gateway session, odd", ast_channel_name(chan));
3578 && (readtrans = ast_channel_readtrans(active))) {
3601 short silence_buf[f->
samples];
3605 .data.ptr = silence_buf,
3607 .datalen =
sizeof(silence_buf),
3609 memset(silence_buf, 0,
sizeof(silence_buf));
3629 .
version = AST_FRAMEHOOK_INTERFACE_VERSION,
3632 .disable_inheritance = 1,
3635 if (global_fax_debug) {
3656 fr_hook.
data = gateway;
3657 ast_channel_lock(chan);
3659 ast_channel_unlock(chan);
3679 if (faxdetect->
dsp) {
3680 ast_dsp_free(faxdetect->
dsp);
3681 faxdetect->
dsp = NULL;
3683 ao2_cleanup(faxdetect->
details);
3711 if (!faxdetect->
dsp) {
3718 faxdetect->
dsp = NULL;
3777 ast_channel_unlock(chan);
3782 ast_channel_lock(chan);
3798 ast_debug(1,
"FAXOPT(faxdetect) timeout on %s\n", ast_channel_name(chan));
3808 if (!faxdetect->
dsp) {
3820 (faxdetect->
flags & FAX_DETECT_MODE_T38)) {
3834 control_params = f->
data.ptr;
3846 const char *target_context;
3851 target_context = ast_channel_context(chan);
3853 ast_channel_unlock(chan);
3857 S_COR(ast_channel_caller(chan)->
id.
number.valid, ast_channel_caller(chan)->
id.
number.str, NULL))) {
3858 ast_verb(2,
"Redirecting '%s' to fax extension due to %s detection\n",
3859 ast_channel_name(chan), (result ==
'f') ?
"CNG" :
"T38");
3862 ast_log(LOG_NOTICE,
"Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(chan), target_context);
3865 ast_log(LOG_NOTICE,
"FAX %s detected but no fax extension in context (%s)\n",
3866 (result ==
'f') ?
"CNG" :
"T38", target_context);
3868 ast_channel_lock(chan);
3893 .
version = AST_FRAMEHOOK_INTERFACE_VERSION,
3899 ast_log(LOG_ERROR,
"System cannot provide memory for session requirements.\n");
3910 fr_hook.
data = faxdetect;
3912 ast_channel_lock(chan);
3916 ast_channel_unlock(chan);
3955 tklen = strlen(a->word);
3957 while ((s = ao2_iterator_next(&i))) {
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";
3986 return CLI_SHOWUSAGE;
3989 ast_cli(a->fd,
"FAX For Asterisk Components:\n");
3992 AST_RWLIST_TRAVERSE(&
faxmodules, fax, list) {
3996 ast_cli(a->fd,
"\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")) {
4027 return CLI_SHOWUSAGE;
4030 global_fax_debug = flag;
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");
4055 AST_RWLIST_TRAVERSE(&
faxmodules, fax, list) {
4056 ast_cli(a->fd,
"%-15s : %s\n%-15s : %s\n%-15s : ",
"Type", fax->tech->
type,
"Description", fax->tech->
description,
"Capabilities");
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";
4084 get_general_options(&options);
4086 ast_cli(a->fd,
"FAX For Asterisk Settings:\n");
4087 ast_cli(a->fd,
"\tECM: %s\n", options.ecm ?
"Enabled" :
"Disabled");
4088 ast_cli(a->fd,
"\tStatus Events: %s\n", options.statusevents ?
"On" :
"Off");
4089 ast_cli(a->fd,
"\tMinimum Bit Rate: %u\n", options.minrate);
4090 ast_cli(a->fd,
"\tMaximum Bit Rate: %u\n", options.maxrate);
4091 ast_fax_modem_to_str(options.modems, modems,
sizeof(modems));
4092 ast_cli(a->fd,
"\tModem Modulations Allowed: %s\n", modems);
4093 ast_cli(a->fd,
"\tT.38 Negotiation Timeout: %u\n", options.t38timeout);
4094 ast_cli(a->fd,
"\n\nFAX Technology Modules:\n\n");
4096 AST_RWLIST_TRAVERSE(&
faxmodules, fax, list) {
4097 ast_cli(a->fd,
"%s (%s) Settings:\n", fax->tech->
type, fax->tech->
description);
4112 e->
command =
"fax show session";
4114 "Usage: fax show session <session number>\n"
4115 " Shows status of the named FAX session\n";
4122 return CLI_SHOWUSAGE;
4125 if (sscanf(a->argv[3],
"%u", &tmp.
id) != 1) {
4126 ast_log(LOG_ERROR,
"invalid session id: '%s'\n", a->argv[3]);
4127 return RESULT_SUCCESS;
4130 ast_cli(a->fd,
"\nFAX Session Details:\n--------------------\n\n");
4133 ast_cli(a->fd,
"%-22s : %s\n",
"channel", s->
channame);
4137 ast_cli(a->fd,
"\n\n");
4146 char id_text[256] =
"";
4150 if (sscanf(session_number,
"%30u", &
find_session.id) != 1) {
4162 astman_send_error(s, m,
"Fax technology doesn't provide a handler for FAXSession");
4167 if (!ast_strlen_zero(action_id)) {
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");
4196 ast_cli(a->fd,
"%-20.20s : %d\n",
"Current Sessions",
faxregistry.active_sessions);
4197 ast_cli(a->fd,
"%-20.20s : %d\n",
"Reserved Sessions",
faxregistry.reserved_sessions);
4198 ast_cli(a->fd,
"%-20.20s : %d\n",
"Transmit Attempts",
faxregistry.fax_tx_attempts);
4199 ast_cli(a->fd,
"%-20.20s : %d\n",
"Receive Attempts",
faxregistry.fax_rx_attempts);
4200 ast_cli(a->fd,
"%-20.20s : %d\n",
"Completed FAXes",
faxregistry.fax_complete);
4201 ast_cli(a->fd,
"%-20.20s : %d\n",
"Failed FAXes",
faxregistry.fax_failures);
4203 AST_RWLIST_TRAVERSE(&
faxmodules, fax, list) {
4207 ast_cli(a->fd,
"\n\n");
4216 char id_text[256] =
"";
4220 if (!ast_strlen_zero(action_id)) {
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)");
4294 while ((s = ao2_iterator_next(&i))) {
4299 ast_cli(a->fd,
"%-30.30s %-10.10s %-10u %-5.5s %-10.10s %-15.15s %-30s\n",
4301 fax_session_type(s),
4305 ast_free(filenames);
4311 ast_cli(a->fd,
"\n%d FAX sessions\n\n", session_count);
4316 static int manager_fax_sessions_entry(
struct mansession *s,
4325 ast_log(LOG_ERROR,
"Error generating Files string");
4326 ao2_unlock(session);
4333 "Technology: %s\r\n"
4334 "SessionNumber: %u\r\n"
4335 "SessionType: %s\r\n"
4343 ast_free(filenames);
4344 ao2_unlock(session);
4354 int session_count = 0;
4357 if (!ast_strlen_zero(action_id)) {
4358 snprintf(id_text,
sizeof(id_text),
"ActionID: %s\r\n", action_id);
4364 while ((session = ao2_iterator_next(&iter))) {
4365 if (!manager_fax_sessions_entry(s, session, id_text)) {
4380 AST_CLI_DEFINE(cli_fax_show_version,
"Show versions of FAX For Asterisk components"),
4381 AST_CLI_DEFINE(
cli_fax_set_debug,
"Enable/Disable FAX debugging on new FAX sessions"),
4383 AST_CLI_DEFINE(
cli_fax_show_settings,
"Show the global settings and defaults of both the FAX core and technology modules"),
4389 static void set_general_options(
const struct fax_options *options)
4391 ast_rwlock_wrlock(&options_lock);
4392 general_options = *options;
4393 ast_rwlock_unlock(&options_lock);
4396 static void get_general_options(
struct fax_options *options)
4398 ast_rwlock_rdlock(&options_lock);
4399 *options = general_options;
4400 ast_rwlock_unlock(&options_lock);
4403 static int set_t38timeout(
const char *value,
unsigned int *t38timeout)
4405 unsigned int timeout;
4407 if (sscanf(value,
"%u", &timeout) != 1) {
4408 ast_log(LOG_ERROR,
"Unable to get timeout from '%s'\n", value);
4410 }
else if (timeout) {
4411 *t38timeout = timeout;
4413 ast_log(LOG_ERROR,
"T.38 negotiation timeout must be non-zero\n");
4426 char modems[128] =
"";
4430 options = default_options;
4438 set_general_options(&options);
4443 ast_log(LOG_NOTICE,
"Configuration file '%s' not found, %s options.\n",
4444 config, reload ?
"not changing" :
"using default");
4448 if (cfg == CONFIG_STATUS_FILEINVALID) {
4449 ast_log(LOG_NOTICE,
"Configuration file '%s' is invalid, %s options.\n",
4450 config, reload ?
"not changing" :
"using default");
4454 if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
4459 options = default_options;
4463 for (v = ast_variable_browse(cfg,
"general"); v; v = v->
next) {
4466 if (!strcasecmp(v->
name,
"minrate")) {
4467 ast_debug(3,
"reading minrate '%s' from configuration file\n", v->
value);
4472 options.minrate = rate;
4473 }
else if (!strcasecmp(v->
name,
"maxrate")) {
4474 ast_debug(3,
"reading maxrate '%s' from configuration file\n", v->
value);
4479 options.maxrate = rate;
4480 }
else if (!strcasecmp(v->
name,
"statusevents")) {
4481 ast_debug(3,
"reading statusevents '%s' from configuration file\n", v->
value);
4483 }
else if (!strcasecmp(v->
name,
"ecm")) {
4484 ast_debug(3,
"reading ecm '%s' from configuration file\n", v->
value);
4486 }
else if ((!strcasecmp(v->
name,
"modem")) || (!strcasecmp(v->
name,
"modems"))) {
4488 update_modem_bits(&options.modems, v->
value);
4489 }
else if (!strcasecmp(v->
name,
"t38timeout")) {
4490 if (set_t38timeout(v->
value, &options.t38timeout)) {
4497 if (options.maxrate < options.minrate) {
4498 ast_log(LOG_ERROR,
"maxrate %u is less than minrate %u\n", options.maxrate, options.minrate);
4503 if (check_modem_rate(options.modems, options.minrate)) {
4504 ast_fax_modem_to_str(options.modems, modems,
sizeof(modems));
4505 ast_log(LOG_ERROR,
"'modems' setting '%s' is incompatible with 'minrate' setting %u\n", modems, options.minrate);
4510 if (check_modem_rate(options.modems, options.maxrate)) {
4511 ast_fax_modem_to_str(options.modems, modems,
sizeof(modems));
4512 ast_log(LOG_ERROR,
"'modems' setting '%s' is incompatible with 'maxrate' setting %u\n", modems, options.maxrate);
4517 set_general_options(&options);
4532 ast_log(LOG_ERROR,
"channel '%s' can't read FAXOPT(%s) because it has never been written.\n", ast_channel_name(chan), data);
4535 if (!strcasecmp(data,
"ecm")) {
4537 }
else if (!strcasecmp(data,
"t38gateway") || !strcasecmp(data,
"gateway") ||
4538 !strcasecmp(data,
"t38_gateway") || !strcasecmp(data,
"faxgateway")) {
4540 }
else if (!strcasecmp(data,
"faxdetect")) {
4542 }
else if (!strcasecmp(data,
"error")) {
4544 }
else if (!strcasecmp(data,
"filename")) {
4546 ast_log(LOG_ERROR,
"channel '%s' can't read FAXOPT(%s) because it has never been written.\n", ast_channel_name(chan), data);
4551 }
else if (!strcasecmp(data,
"filenames")) {
4553 ast_log(LOG_ERROR,
"channel '%s' can't read FAXOPT(%s) because it has never been written.\n", ast_channel_name(chan), data);
4557 ast_free(filenames);
4559 ast_log(LOG_ERROR,
"channel '%s' can't read FAXOPT(%s), there was an error generating the filenames list.\n", ast_channel_name(chan), data);
4562 }
else if (!strcasecmp(data,
"headerinfo")) {
4564 }
else if (!strcasecmp(data,
"localstationid")) {
4566 }
else if (!strcasecmp(data,
"maxrate")) {
4567 snprintf(buf, len,
"%u", details->
maxrate);
4568 }
else if (!strcasecmp(data,
"minrate")) {
4569 snprintf(buf, len,
"%u", details->
minrate);
4570 }
else if (!strcasecmp(data,
"pages")) {
4572 }
else if (!strcasecmp(data,
"rate")) {
4574 }
else if (!strcasecmp(data,
"remotestationid")) {
4576 }
else if (!strcasecmp(data,
"resolution")) {
4578 }
else if (!strcasecmp(data,
"sessionid")) {
4579 snprintf(buf, len,
"%u", details->
id);
4580 }
else if (!strcasecmp(data,
"status")) {
4582 }
else if (!strcasecmp(data,
"statusstr")) {
4584 }
else if ((!strcasecmp(data,
"modem")) || (!strcasecmp(data,
"modems"))) {
4585 ast_fax_modem_to_str(details->
modems, buf, len);
4586 }
else if (!strcasecmp(data,
"t38timeout")) {
4587 snprintf(buf, len,
"%u", details->
t38timeout);
4588 }
else if (!strcasecmp(data,
"negotiate_both")) {
4591 ast_log(LOG_WARNING,
"channel '%s' can't read FAXOPT(%s) because it is unhandled!\n", ast_channel_name(chan), data);
4606 ast_log(LOG_WARNING,
"channel '%s' can't set FAXOPT(%s) to '%s' because it failed to create a datastore.\n", ast_channel_name(chan), data, value);
4609 ast_debug(3,
"channel '%s' setting FAXOPT(%s) to '%s'\n", ast_channel_name(chan), data, value);
4611 if (!strcasecmp(data,
"ecm")) {
4614 details->
option.
ecm = AST_FAX_OPTFLAG_TRUE;
4616 details->
option.
ecm = AST_FAX_OPTFLAG_FALSE;
4618 ast_log(LOG_WARNING,
"Unsupported value '%s' passed to FAXOPT(ecm).\n", value);
4620 }
else if (!strcasecmp(data,
"t38gateway") || !strcasecmp(data,
"gateway") ||
4621 !strcasecmp(data,
"t38_gateway") || !strcasecmp(data,
"faxgateway")) {
4623 char *timeout = strchr(val,
',');
4633 unsigned int gwtimeout;
4635 if (sscanf(timeout,
"%30u", &gwtimeout) == 1) {
4638 ast_log(LOG_WARNING,
"Unsupported timeout '%s' passed to FAXOPT(%s).\n", timeout, data);
4644 ast_log(LOG_ERROR,
"Error attaching T.38 gateway to channel %s.\n", ast_channel_name(chan));
4647 ast_debug(1,
"Attached T.38 gateway to channel %s.\n", ast_channel_name(chan));
4650 ast_log(LOG_WARNING,
"Attempt to attach a T.38 gateway on channel (%s) with gateway already running.\n", ast_channel_name(chan));
4653 ast_channel_lock(chan);
4655 ast_channel_unlock(chan);
4658 ast_log(LOG_WARNING,
"Unsupported value '%s' passed to FAXOPT(%s).\n", value, data);
4660 }
else if (!strcasecmp(data,
"faxdetect")) {
4662 char *timeout = strchr(val,
',');
4663 unsigned int fdtimeout = 0;
4671 if (
ast_true(val) || !strcasecmp(val,
"t38") || !strcasecmp(val,
"cng")) {
4674 if (sscanf(timeout,
"%30u", &fdtimeout) == 1) {
4677 ast_log(LOG_WARNING,
"Unsupported timeout '%s' passed to FAXOPT(%s).\n",
4682 if (!strcasecmp(val,
"t38")) {
4683 flags = FAX_DETECT_MODE_T38;
4684 }
else if (!strcasecmp(val,
"cng")) {
4687 flags = FAX_DETECT_MODE_BOTH;
4691 if (faxdetect < 0) {
4692 ast_log(LOG_ERROR,
"Error attaching FAX detect to channel %s.\n", ast_channel_name(chan));
4695 ast_debug(1,
"Attached FAX detect to channel %s.\n", ast_channel_name(chan));
4698 ast_log(LOG_WARNING,
"Attempt to attach a FAX detect on channel (%s) with FAX detect already running.\n", ast_channel_name(chan));
4701 ast_channel_lock(chan);
4703 ast_channel_unlock(chan);
4706 ast_log(LOG_WARNING,
"Unsupported value '%s' passed to FAXOPT(%s).\n", value, data);
4708 }
else if (!strcasecmp(data,
"headerinfo")) {
4710 }
else if (!strcasecmp(data,
"localstationid")) {
4712 }
else if (!strcasecmp(data,
"maxrate")) {
4717 }
else if (!strcasecmp(data,
"minrate")) {
4722 }
else if (!strcasecmp(data,
"t38timeout")) {
4723 if (set_t38timeout(value, &details->
t38timeout)) {
4726 }
else if ((!strcasecmp(data,
"modem")) || (!strcasecmp(data,
"modems"))) {
4727 update_modem_bits(&details->
modems, value);
4728 }
else if (!strcasecmp(data,
"negotiate_both")) {
4731 ast_log(LOG_WARNING,
"channel '%s' set FAXOPT(%s) to '%s' is unhandled!\n", ast_channel_name(chan), data, value);
4753 ast_log(LOG_WARNING,
"failed to unregister function '%s'\n", acf_faxopt.
name);
4757 ast_log(LOG_WARNING,
"failed to unregister '%s'\n", app_sendfax);
4761 ast_log(LOG_WARNING,
"failed to unregister '%s'\n", app_receivefax);
4768 if (fax_logger_level != -1) {
4801 ast_log(LOG_ERROR,
"failed to load configuration file '%s'\n", config);
4808 ast_log(LOG_WARNING,
"failed to register '%s'.\n", app_sendfax);
4813 ast_log(LOG_WARNING,
"failed to register '%s'.\n", app_receivefax);
4820 ast_log(LOG_WARNING,
"failed to register 'FAXSessions' AMI command.\n");
4828 ast_log(LOG_WARNING,
"failed to register 'FAXSession' AMI command.\n");
4837 ast_log(LOG_WARNING,
"failed to register 'FAXStats' AMI command.\n");
4853 static int reload_module(
void)
4860 AST_MODULE_INFO(
ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER,
"Generic FAX Applications",
4861 .support_level = AST_MODULE_SUPPORT_CORE,
4864 .reload = reload_module,
static int receivefax_exec(struct ast_channel *chan, const char *data)
initiate a receive FAX session
struct ast_variable * next
static enum ast_t38_state ast_channel_get_t38_state(struct ast_channel *chan)
Retrieves the current T38 state of a channel.
const ast_string_field result
int(*const switch_to_t38)(struct ast_fax_session *)
struct ast_frame * ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *inf)
Return AST_FRAME_NULL frames when there is silence, AST_FRAME_BUSY on busies, and call progress...
Main Channel structure associated with a channel.
struct ast_json * ast_json_ref(struct ast_json *value)
Increase refcount on value.
Asterisk locking-related definitions:
void astman_append(struct mansession *s, const char *fmt,...)
Asterisk main include file. File version handling, generic pbx functions.
const struct ast_fax_tech * tech
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
static void destroy_faxdetect(void *data)
destroy a FAX detect structure
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
static void destroy_session_details(void *details)
destroy a FAX session details structure
int(*const generate_silence)(struct ast_fax_session *)
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
String manipulation functions.
static struct @442 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.
unsigned long frames_sent
const ast_string_field headerinfo
static int fax_gateway_start(struct fax_gateway *gateway, struct ast_fax_session_details *details, struct ast_channel *chan)
Create a fax session and start T.30<->T.38 gateway mode.
unsigned long frames_received
static unsigned int fax_rate_str_to_int(const char *ratestr)
convert a rate string to a rate
Asterisk version information.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Support for translation of data formats. translate.c.
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_details *details, struct ast_fax_session *reserved, struct ast_fax_tech_token *token)
this is the generic FAX session handling function
char *(*const cli_show_stats)(int)
const char * ast_get_version(void)
Retrieve the Asterisk version string.
used for gateway framehook
Convenient Signal Processing routines.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
Stasis Message Bus API. See Stasis Message Bus API for detailed documentation.
descriptor for a cli entry.
ast_framehook_event
These are the types of events that the framehook's event callback can receive.
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
static void destroy_session(void *session)
destroy a FAX session structure
void ast_fax_tech_unregister(struct ast_fax_tech *tech)
unregister a FAX technology module
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
Structure for variables, used for configurations and for channel variables.
const ast_string_field transfer_rate
int framehook
framehook used in gateway mode
int ast_framehook_detach(struct ast_channel *chan, int framehook_id)
Detach an framehook from a channel.
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
void(*const release_token)(struct ast_fax_tech_token *)
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
static struct ast_frame * fax_gateway_detect_v21(struct fax_gateway *gateway, struct ast_channel *chan, struct ast_channel *peer, struct ast_channel *active, struct ast_frame *f)
static struct fax_detect * fax_detect_new(struct ast_channel *chan, int timeout, int flags)
Create a new fax detect object.
struct ast_smoother * smoother
enum ast_control_t38 request_response
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
static int session_hash_cb(const void *obj, const int flags)
hash callback for ao2
Structure for a data store type.
ast_channel_state
ast_channel states
used for fax detect framehook
int ast_indicate_data(struct ast_channel *chan, int condition, const void *data, size_t datalen)
Indicates condition of channel, with payload.
static int report_send_fax_status(struct ast_channel *chan, struct ast_fax_session_details *details)
Report on the status of a completed fax send attempt.
void ast_logger_unregister_level(const char *name)
Unregister a previously registered logger level.
ast_t38_state
Possible T38 states on channels.
int(*const cancel_session)(struct ast_fax_session *)
#define ast_cli_register_multiple(e, len)
Register multiple commands.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
enum ast_control_t38_rate rate
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
struct ast_frame * ast_translate(struct ast_trans_pvt *tr, struct ast_frame *f, int consume)
translates one or more frames Apply an input frame into the translator and receive zero or one output...
static int session_cmp_cb(void *obj, void *arg, int flags)
compare callback for ao2
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
static void fax_gateway_indicate_t38(struct ast_channel *chan, struct ast_channel *active, struct ast_control_t38_parameters *control_params)
struct ast_channel * ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds, int nfds, int *exception, int *outfd, int *ms)
Waits for activity on a group of channels.
#define ast_strdup(str)
A wrapper for strdup()
Structure for a data store object.
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
const char *const description
void ast_playtones_stop(struct ast_channel *chan)
Stop playing tones on a channel.
static struct ast_frame * fax_gateway_request_t38(struct fax_gateway *gateway, struct ast_channel *chan)
static struct ast_fax_session_details * session_details_new(void)
create a FAX session details structure
I/O Management (derived from Cheops-NG)
struct ast_channel * chan
void ast_fax_log(int level, const char *file, const int line, const char *function, const char *msg)
Log message at FAX or recommended level.
struct ast_fax_session * s
FAX Session.
static int fax_gateway_attach(struct ast_channel *chan, struct ast_fax_session_details *details)
Attach a gateway framehook object to a channel.
static struct ast_frame * fax_gateway_framehook(struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data)
T.30<->T.38 gateway framehook.
int ast_unregister_application(const char *app)
Unregister an application.
Asterisk internal frame definitions.
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
struct ast_frame_subclass subclass
int args
This gets set in ast_cli_register()
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
static int load_module(void)
Load the module.
static struct mansession_session * find_session(uint32_t ident, int incinuse)
static struct ast_frame * fax_detect_framehook(struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data)
Fax Detect Framehook.
#define AST_APP_OPTIONS(holder, options...)
Declares an array of options for an application.
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized...
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
static char * cli_fax_show_sessions(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
display fax sessions
static void fixup_callback(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
Copies fax detection and gateway framehooks during masquerades.
int ast_framehook_attach(struct ast_channel *chan, struct ast_framehook_interface *i)
Attach an framehook onto a channel for frame interception.
Configuration File Parser.
struct ast_fax_debug_info * debug_info
static int acf_faxopt_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
FAXOPT write function modifies the contents of a FAX option.
unsigned int transcoding_mmr
struct ast_fax_t38_parameters our_t38_parameters
int ast_channel_make_compatible(struct ast_channel *chan, struct ast_channel *peer)
Make the frame formats of two channels compatible.
int ast_build_string(char **buffer, size_t *space, const char *fmt,...)
Build a string in a buffer, designed to be called repeatedly.
#define SCOPED_CHANNELLOCK(varname, chan)
scoped lock specialization for channels.
General Asterisk PBX channel definitions.
static char * cli_fax_show_session(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
display details of a specified fax session
enum ast_fax_capabilities caps
struct ast_fax_tech_token *(*const reserve_session)(struct ast_fax_session *)
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
int ast_set_read_format(struct ast_channel *chan, struct ast_format *format)
Sets read format on channel chan.
struct ast_json * ast_json_string_create(const char *value)
Construct a JSON string from value.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
#define ast_strdupa(s)
duplicate a string in memory from the stack
Data structure associated with a custom dialplan function.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
static void destroy_gateway(void *data)
destroy a FAX gateway session structure
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
struct ast_fax_session_details * details
enum ast_control_t38_rate rate
In case you didn't read that giant block of text above the mansession_session struct, the mansession is named this solely to keep the API the same in Asterisk. This structure really represents data that is different from Manager action to Manager action. The mansession_session pointer contained within points to session-specific data.
int detected_v21
1 if a v21 preamble has been detected
unsigned int ast_fax_minrate(void)
get the minimum supported fax rate
struct ast_fax_session_details * details
fax session details
int ast_dsp_set_faxmode(struct ast_dsp *dsp, int faxmode)
Set fax mode.
static struct ast_fax_session * fax_session_new(struct ast_fax_session_details *details, struct ast_channel *chan, struct ast_fax_session *reserved, struct ast_fax_tech_token *token)
create a FAX session
static void destroy_v21_sessions(struct fax_gateway *gateway)
destroy the v21 detection parts of a fax gateway session
The data communicated between the high level applications and the generic fax function.
#define ast_malloc(len)
A wrapper for malloc()
struct ao2_container * container
#define ast_debug(level,...)
Log a DEBUG message.
int ast_set_write_format(struct ast_channel *chan, struct ast_format *format)
Sets write format on channel chan.
static int sendfax_exec(struct ast_channel *chan, const char *data)
initiate a send FAX session
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
struct ast_module * module
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
struct ast_format * chan_read_format
original audio formats
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
const ast_string_field remotestationid
Core PBX routines and definitions.
struct ast_json * ast_json_array_create(void)
Create a empty JSON array.
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
int ast_json_array_append(struct ast_json *array, struct ast_json *value)
Append to an array.
void ast_dsp_set_threshold(struct ast_dsp *dsp, int threshold)
Set the minimum average magnitude threshold to determine talking by the DSP.
struct stasis_topic * ast_channel_topic(struct ast_channel *chan)
A topic which publishes the events for a particular channel.
void ast_dsp_reset(struct ast_dsp *dsp)
Reset total silence count.
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
unsigned int transcoding_mmr
unsigned int transcoding_jbig
static void fax_gateway_framehook_destroy(void *data)
Destroy the gateway data structure when the framehook is detached.
static struct ast_fax_session_details * find_or_create_details(struct ast_channel *chan)
returns a reference counted details structure from the channel's fax datastore. If the datastore does...
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
#define FAX_DETECT_MODE_CNG
FAX Detect flags.
void(*const destroy_session)(struct ast_fax_session *)
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
static struct ast_frame * fax_gateway_detect_t38(struct fax_gateway *gateway, struct ast_channel *chan, struct ast_channel *peer, struct ast_channel *active, struct ast_frame *f)
T38 Gateway Negotiate t38 parameters.
unsigned int pages_transferred
Default structure for translators, with the basic fields and buffers, all allocated as part of the sa...
static void fax_session_release(struct ast_fax_session *s, struct ast_fax_tech_token *token)
Release a session token.
#define ao2_unlink(container, obj)
Remove an object from a container.
static void destroy_callback(void *data)
Helper function used by datastores to destroy the speech structure upon hangup.
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
unsigned int fill_bit_removal
struct timeval timeout_start
the start of our timeout counter
static void set_channel_variables(struct ast_channel *chan, struct ast_fax_session_details *details)
Set fax related channel variables.
struct ast_fax_documents documents
used to register a FAX technology module with res_fax
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
#define FAX_MAXBUCKETS
maximum buckets for res_fax ao2 containers
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
union ast_frame::@224 data
#define ast_calloc(num, len)
A wrapper for calloc()
const char *const version
static int acf_faxopt_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
FAXOPT read function returns the contents of a FAX option.
static char * cli_fax_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
enable FAX debugging
void *(*const new_session)(struct ast_fax_session *, struct ast_fax_tech_token *)
enum ast_fax_modems modems
int ast_write(struct ast_channel *chan, struct ast_frame *frame)
Write a frame to a channel This function writes the given frame to the indicated channel.
void(*const manager_fax_session)(struct mansession *, const char *, struct ast_fax_session *)
Support for logging to various files, console and syslog Configuration in file logger.conf.
struct ast_format * orig_format
original audio formats
Module has failed to load, may be in an inconsistent state.
#define ast_frisolate(fr)
Makes a frame independent of any static storage.
static int unload_module(void)
unload res_fax
enum ast_t38_state t38_state
a flag to track the state of our negotiation
unsigned int ast_fax_maxrate(void)
get the maxiumum supported fax rate
#define ast_string_field_build(x, field, fmt, args...)
Set a field to a complex (built) value.
Structure used to handle boolean flags.
struct stasis_message * ast_channel_blob_create_from_cache(const char *uniqueid, struct stasis_message_type *type, struct ast_json *blob)
Create a ast_channel_blob message, pulling channel state from the cache.
#define ast_module_unref(mod)
Release a reference to the module.
unsigned int transcoding_jbig
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
static void fax_detect_framehook_destroy(void *data)
Deref the faxdetect data structure when the faxdetect framehook is detached.
#define ast_module_running_ref(mod)
Hold a reference to the module if it is running.
struct ast_frame ast_null_frame
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
static struct ast_fax_session * fax_session_reserve(struct ast_fax_session_details *details, struct ast_fax_tech_token **token)
Reserve a fax session.
registered FAX technology modules are put into this list
int ast_dsp_silence(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
Process the audio frame for silence.
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
char *(*const cli_show_session)(struct ast_fax_session *, int)
int ast_logger_register_level(const char *name)
Register a new logger level.
static int set_config(int reload)
configure res_fax
#define ao2_replace(dst, src)
Replace one object reference with another cleaning up the original.
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
const char * ast_fax_session_operation_str(struct ast_fax_session *s)
get string representation of a FAX session's operation
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Standard Command Line Interface.
static int report_receive_fax_status(struct ast_channel *chan, const char *filename)
Report on the final state of a receive fax operation.
union ast_fax_session_details::@249 option
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
static struct ast_fax_session_details * find_details(struct ast_channel *chan)
returns a reference counted pointer to a fax datastore, if it exists
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
struct ast_frame *(*const read)(struct ast_fax_session *)
struct ast_channel * ast_channel_bridge_peer(struct ast_channel *chan)
Get the channel's bridge peer only if the bridge is two-party.
struct ast_fax_tech_token * token
reserved fax session token
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"...
static int fax_detect_attach(struct ast_channel *chan, int timeout, int flags)
Attach a faxdetect framehook object to a channel.
static int report_fax_status(struct ast_channel *chan, struct ast_fax_session_details *details, const char *status)
send a FAX status manager event
int ast_async_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Set the channel to next execute the specified dialplan location.
int ast_answer(struct ast_channel *chan)
Answer a channel.
static struct fax_gateway * fax_gateway_new(struct ast_channel *chan, struct ast_fax_session_details *details)
Create a new fax gateway object.
enum ast_control_t38_rate_management rate_management
int ast_queue_control_data(struct ast_channel *chan, enum ast_control_frame_type control, const void *data, size_t datalen)
Queue a control frame with payload.
The data required to handle a fax session.
static char * fax_session_tab_complete(struct ast_cli_args *a)
fax session tab completion
struct ast_dsp * dsp
DSP Processor.
Data structure associated with a single frame of data.
enum ast_control_t38_rate_management rate_management
static char * cli_fax_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
display global defaults and settings
enum ast_fax_capabilities caps
int ast_fax_tech_register(struct ast_fax_tech *tech)
register a FAX technology module
Abstract JSON element (object, array, string, int, ...).
int ast_playtones_start(struct ast_channel *chan, int vol, const char *tonelist, int interruptible)
Start playing a list of tones on a channel.
Options provided by main asterisk program.
int(*const write)(struct ast_fax_session *, const struct ast_frame *)
struct timeval ast_tvsub(struct timeval a, struct timeval b)
Returns the difference of two timevals a - b.
const ast_string_field resultstr
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
enum ast_frame_type frametype
const ast_string_field localstationid
static char * cli_fax_show_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
display fax stats
const char * ast_fax_state_to_str(enum ast_fax_state state)
convert a ast_fax_state to a string
#define AST_APP_OPTION(option, flagno)
Declares an application option that does not accept an argument.
const ast_string_field error
struct ast_format * format
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
struct timeval timeout_start
the start of our timeout counter
#define ASTERISK_GPL_KEY
The text the key() function should return.
char *(*const cli_show_capabilities)(int)
int(*const start_session)(struct ast_fax_session *)
char *(*const cli_show_settings)(int)
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Asterisk module definitions.
unsigned int fill_bit_removal
static char * cli_fax_show_capabilities(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
display registered FAX capabilities
struct ast_fax_t38_parameters their_t38_parameters
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
struct stasis_message_type * ast_channel_fax_type(void)
Message type for a fax operation.
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
#define AST_JSON_UTF8_VALIDATE(str)
Check str for UTF-8 and replace with an empty string if fails the check.
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
const ast_string_field resolution
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
#define ast_custom_function_register(acf)
Register a custom function.
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
static struct ast_custom_function acf_faxopt
FAXOPT dialplan function.
static char * generate_filenames_string(struct ast_fax_session_details *details, char *prefix, char *separator)
Generate a string of filenames using the given prefix and separator.
#define AST_APP_ARG(name)
Define an application argument.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
#define ao2_link(container, obj)
Add an object to a container.