2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 2008-2009, Digium, Inc.
6 * Dwayne M. Hubbard <dhubbard@digium.com>
7 * Kevin P. Fleming <kpfleming@digium.com>
9 * See http://www.asterisk.org for more information about
10 * the Asterisk project. Please do not directly contact
11 * any of the maintainers of this project for assistance;
12 * the project provides a web site, mailing lists and IRC
13 * channels for your use.
15 * This program is free software, distributed under the terms of
16 * the GNU General Public License Version 2. See the LICENSE file
17 * at the top of the source tree.
21 <conflict>app_fax</conflict>
26 * \brief Generic FAX Resource for FAX technology resource modules
28 * \author Dwayne M. Hubbard <dhubbard@digium.com>
29 * \author Kevin P. Fleming <kpfleming@digium.com>
31 * A generic FAX resource module that provides SendFAX and ReceiveFAX applications.
32 * This module requires FAX technology modules, like res_fax_spandsp, to register with it
33 * so it can use the technology modules to perform the actual FAX transmissions.
34 * \ingroup applications
39 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
41 #include "asterisk/io.h"
42 #include "asterisk/file.h"
43 #include "asterisk/logger.h"
44 #include "asterisk/module.h"
45 #include "asterisk/app.h"
46 #include "asterisk/lock.h"
47 #include "asterisk/options.h"
48 #include "asterisk/strings.h"
49 #include "asterisk/cli.h"
50 #include "asterisk/utils.h"
51 #include "asterisk/config.h"
52 #include "asterisk/astobj2.h"
53 #include "asterisk/res_fax.h"
54 #include "asterisk/file.h"
55 #include "asterisk/channel.h"
56 #include "asterisk/pbx.h"
57 #include "asterisk/manager.h"
58 #include "asterisk/dsp.h"
59 #include "asterisk/indications.h"
60 #include "asterisk/ast_version.h"
63 <application name="ReceiveFax" language="en_US">
65 Receive a FAX and save as a TIFF/F file.
68 <parameter name="filename" required="true" />
69 <parameter name="options">
72 <para>Enable FAX debugging.</para>
75 <para>Allow audio fallback FAX transfer on T.38 capable channels.</para>
78 <para>Force usage of audio mode on T.38 capable channels.</para>
81 <para>Send progress Manager events (overrides statusevents setting in res_fax.conf).</para>
87 <para>This application is provided by res_fax, which is a FAX technology agnostic module
88 that utilizes FAX technology resource modules to complete a FAX transmission.</para>
89 <para>Session arguments can be set by the FAXOPT function and to check results of the ReceiveFax() application.</para>
92 <ref type="function">FAXOPT</ref>
95 <application name="SendFax" language="en_US">
97 Sends a specified TIFF/F file as a FAX.
100 <parameter name="filename" required="true" argsep="&">
101 <argument name="filename2" multiple="true">
102 <para>TIFF file to send as a FAX.</para>
105 <parameter name="options">
108 <para>Enable FAX debugging.</para>
111 <para>Allow audio fallback FAX transfer on T.38 capable channels.</para>
114 <para>Force usage of audio mode on T.38 capable channels.</para>
117 <para>Send progress Manager events (overrides statusevents setting in res_fax.conf).</para>
120 <para>Initiate a T.38 reinvite on the channel if the remote end does not.</para>
126 <para>This application is provided by res_fax, which is a FAX technology agnostic module
127 that utilizes FAX technology resource modules to complete a FAX transmission.</para>
128 <para>Session arguments can be set by the FAXOPT function and to check results of the SendFax() application.</para>
131 <ref type="function">FAXOPT</ref>
134 <function name="FAXOPT" language="en_US">
136 Gets/sets various pieces of information about a fax session.
139 <parameter name="item" required="true">
142 <para>R/W Error Correction Mode (ECM) enable with 'yes', disable with 'no'.</para>
145 <para>R/O FAX transmission error code upon failure.</para>
147 <enum name="filename">
148 <para>R/O Filename of the first file of the FAX transmission.</para>
150 <enum name="filenames">
151 <para>R/O Filenames of all of the files in the FAX transmission (comma separated).</para>
153 <enum name="headerinfo">
154 <para>R/W FAX header information.</para>
156 <enum name="localstationid">
157 <para>R/W Local Station Identification.</para>
159 <enum name="minrate">
160 <para>R/W Minimum transfer rate set before transmission.</para>
162 <enum name="maxrate">
163 <para>R/W Maximum transfer rate set before transmission.</para>
166 <para>R/W Modem type (v17/v27/v29).</para>
169 <para>R/O Number of pages transferred.</para>
172 <para>R/O Negotiated transmission rate.</para>
174 <enum name="remotestationid">
175 <para>R/O Remote Station Identification after transmission.</para>
177 <enum name="resolution">
178 <para>R/O Negotiated image resolution after transmission.</para>
180 <enum name="sessionid">
181 <para>R/O Session ID of the FAX transmission.</para>
184 <para>R/O Result Status of the FAX transmission.</para>
186 <enum name="statusstr">
187 <para>R/O Verbose Result Status of the FAX transmission.</para>
193 <para>FAXOPT can be used to override the settings for a FAX session listed in <filename>res_fax.conf</filename>,
194 it can also be used to retreive information about a FAX session that has finished eg. pages/status.</para>
197 <ref type="application">ReceiveFax</ref>
198 <ref type="application">SendFax</ref>
203 static const char app_receivefax[] = "ReceiveFAX";
204 static const char app_sendfax[] = "SendFAX";
206 struct debug_info_history {
207 unsigned int consec_frames;
208 unsigned int consec_ms;
209 unsigned char silence;
212 struct ast_fax_debug_info {
213 struct timeval base_tv;
214 struct debug_info_history c2s, s2c;
218 static int fax_logger_level = -1;
220 /*! \brief maximum buckets for res_fax ao2 containers */
221 #define FAX_MAXBUCKETS 10
223 #define RES_FAX_TIMEOUT 10000
225 /*! \brief The faxregistry is used to manage information and statistics for all FAX sessions. */
227 /*! The number of active FAX sessions */
229 /*! The number of reserved FAX sessions */
230 int reserved_sessions;
231 /*! active sessions are astobj2 objects */
232 struct ao2_container *container;
233 /*! Total number of Tx FAX attempts */
235 /*! Total number of Rx FAX attempts */
237 /*! Number of successful FAX transmissions */
239 /*! Number of failed FAX transmissions */
241 /*! the next unique session name */
245 /*! \brief registered FAX technology modules are put into this list */
247 const struct ast_fax_tech *tech;
248 AST_RWLIST_ENTRY(fax_module) list;
250 static AST_RWLIST_HEAD_STATIC(faxmodules, fax_module);
252 #define RES_FAX_MINRATE 2400
253 #define RES_FAX_MAXRATE 14400
254 #define RES_FAX_STATUSEVENTS 0
255 #define RES_FAX_MODEM (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V27 | AST_FAX_MODEM_V29)
258 enum ast_fax_modems modems;
259 uint32_t statusevents:1;
261 unsigned int minrate;
262 unsigned int maxrate;
265 static const char *config = "res_fax.conf";
267 static int global_fax_debug = 0;
270 OPT_CALLEDMODE = (1 << 0),
271 OPT_CALLERMODE = (1 << 1),
272 OPT_DEBUG = (1 << 2),
273 OPT_STATUS = (1 << 3),
274 OPT_ALLOWAUDIO = (1 << 5),
275 OPT_REQUEST_T38 = (1 << 6),
276 OPT_FORCE_AUDIO = (1 << 7),
279 AST_APP_OPTIONS(fax_exec_options, BEGIN_OPTIONS
280 AST_APP_OPTION('a', OPT_CALLEDMODE),
281 AST_APP_OPTION('c', OPT_CALLERMODE),
282 AST_APP_OPTION('d', OPT_DEBUG),
283 AST_APP_OPTION('f', OPT_ALLOWAUDIO),
284 AST_APP_OPTION('F', OPT_FORCE_AUDIO),
285 AST_APP_OPTION('s', OPT_STATUS),
286 AST_APP_OPTION('z', OPT_REQUEST_T38),
289 struct manager_event_info {
290 char context[AST_MAX_CONTEXT];
291 char exten[AST_MAX_EXTENSION];
295 static void debug_check_frame_for_silence(struct ast_fax_session *s, unsigned int c2s, struct ast_frame *frame)
297 struct debug_info_history *history = c2s ? &s->debug_info->c2s : &s->debug_info->s2c;
299 unsigned int last_consec_frames, last_consec_ms;
300 unsigned char wassil;
303 diff = ast_tvsub(ast_tvnow(), s->debug_info->base_tv);
305 ast_dsp_reset(s->debug_info->dsp);
306 ast_dsp_silence(s->debug_info->dsp, frame, &dspsilence);
308 wassil = history->silence;
309 history->silence = (dspsilence != 0) ? 1 : 0;
310 if (history->silence != wassil) {
311 last_consec_frames = history->consec_frames;
312 last_consec_ms = history->consec_ms;
313 history->consec_frames = 0;
314 history->consec_ms = 0;
316 if ((last_consec_frames != 0)) {
317 ast_verb(6, "Channel '%s' fax session '%d', [ %.3ld.%.6ld ], %s sent %d frames (%d ms) of %s.\n",
318 s->channame, s->id, (long) diff.tv_sec, (long int) diff.tv_usec,
319 (c2s) ? "channel" : "stack", last_consec_frames, last_consec_ms,
320 (wassil) ? "silence" : "energy");
324 history->consec_frames++;
325 history->consec_ms += (frame->samples / 8);
328 static void destroy_callback(void *data)
335 static const struct ast_datastore_info fax_datastore = {
337 .destroy = destroy_callback,
340 /*! \brief returns a reference counted pointer to a fax datastore, if it exists */
341 static struct ast_fax_session_details *find_details(struct ast_channel *chan)
343 struct ast_fax_session_details *details;
344 struct ast_datastore *datastore;
346 ast_channel_lock(chan);
347 if (!(datastore = ast_channel_datastore_find(chan, &fax_datastore, NULL))) {
348 ast_channel_unlock(chan);
351 if (!(details = datastore->data)) {
352 ast_log(LOG_WARNING, "Huh? channel '%s' has a FAX datastore without data!\n", chan->name);
353 ast_channel_unlock(chan);
357 ast_channel_unlock(chan);
362 /*! \brief destroy a FAX session details structure */
363 static void destroy_session_details(void *details)
365 struct ast_fax_session_details *d = details;
366 struct ast_fax_document *doc;
368 while ((doc = AST_LIST_REMOVE_HEAD(&d->documents, next))) {
371 ast_string_field_free_memory(d);
374 /*! \brief create a FAX session details structure */
375 static struct ast_fax_session_details *session_details_new(void)
377 struct ast_fax_session_details *d;
379 if (!(d = ao2_alloc(sizeof(*d), destroy_session_details))) {
383 if (ast_string_field_init(d, 512)) {
388 AST_LIST_HEAD_INIT_NOLOCK(&d->documents);
390 /* These options need to be set to the configured default and may be overridden by
391 * SendFAX, ReceiveFAX, or FAXOPT */
392 d->option.request_t38 = AST_FAX_OPTFLAG_FALSE;
393 d->option.send_cng = AST_FAX_OPTFLAG_FALSE;
394 d->option.send_ced = AST_FAX_OPTFLAG_FALSE;
395 d->option.ecm = general_options.ecm;
396 d->option.statusevents = general_options.statusevents;
397 d->modems = general_options.modems;
398 d->minrate = general_options.minrate;
399 d->maxrate = general_options.maxrate;
404 /*! \brief returns a reference counted details structure from the channel's fax datastore. If the datastore
405 * does not exist it will be created */
406 static struct ast_fax_session_details *find_or_create_details(struct ast_channel *chan)
408 struct ast_fax_session_details *details;
409 struct ast_datastore *datastore;
411 if ((details = find_details(chan))) {
414 /* channel does not have one so we must create one */
415 if (!(details = session_details_new())) {
416 ast_log(LOG_WARNING, "channel '%s' can't get a FAX details structure for the datastore!\n", chan->name);
419 if (!(datastore = ast_datastore_alloc(&fax_datastore, NULL))) {
420 ao2_ref(details, -1);
421 ast_log(LOG_WARNING, "channel '%s' can't get a datastore!\n", chan->name);
424 /* add the datastore to the channel and increment the refcount */
425 datastore->data = details;
427 ast_channel_lock(chan);
428 ast_channel_datastore_add(chan, datastore);
429 ast_channel_unlock(chan);
433 unsigned int ast_fax_maxrate(void)
435 return general_options.maxrate;
438 unsigned int ast_fax_minrate(void)
440 return general_options.minrate;
443 static int update_modem_bits(enum ast_fax_modems *bits, const char *value)
445 char *m[5], *tok, *v = (char *)value;
448 if (!(tok = strchr(v, ','))) {
452 tok = strtok(v, ", ");
453 while (tok && (i < 5)) {
455 tok = strtok(NULL, ", ");
461 for (j = 0; j < i; j++) {
462 if (!strcasecmp(m[j], "v17")) {
463 *bits |= AST_FAX_MODEM_V17;
464 } else if (!strcasecmp(m[j], "v27")) {
465 *bits |= AST_FAX_MODEM_V27;
466 } else if (!strcasecmp(m[j], "v29")) {
467 *bits |= AST_FAX_MODEM_V29;
468 } else if (!strcasecmp(m[j], "v34")) {
469 *bits |= AST_FAX_MODEM_V34;
471 ast_log(LOG_WARNING, "ignoring invalid modem setting: '%s', valid options {v17 | v27 | v29 | v34}\n", m[j]);
477 static int ast_fax_modem_to_str(enum ast_fax_modems bits, char *tbuf, size_t bufsize)
481 if (bits & AST_FAX_MODEM_V17) {
485 if (bits & AST_FAX_MODEM_V27) {
492 if (bits & AST_FAX_MODEM_V29) {
499 if (bits & AST_FAX_MODEM_V34) {
510 static int check_modem_rate(enum ast_fax_modems modems, unsigned int rate)
514 if (!(modems & (AST_FAX_MODEM_V27 | AST_FAX_MODEM_V34))) {
519 if (!(modems & (AST_FAX_MODEM_V27 | AST_FAX_MODEM_V34))) {
525 if (!(modems & (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V29 | AST_FAX_MODEM_V34))) {
531 if (!(modems & (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V34))) {
537 if (!(modems & AST_FAX_MODEM_V34)) {
542 /* this should never happen */
549 /*! \brief register a FAX technology module */
550 int ast_fax_tech_register(struct ast_fax_tech *tech)
552 struct fax_module *fax;
554 if (!(fax = ast_calloc(1, sizeof(*fax)))) {
558 AST_RWLIST_WRLOCK(&faxmodules);
559 AST_RWLIST_INSERT_TAIL(&faxmodules, fax, list);
560 AST_RWLIST_UNLOCK(&faxmodules);
561 ast_module_ref(ast_module_info->self);
563 ast_verb(3, "Registered handler for '%s' (%s)\n", fax->tech->type, fax->tech->description);
568 /*! \brief unregister a FAX technology module */
569 void ast_fax_tech_unregister(struct ast_fax_tech *tech)
571 struct fax_module *fax;
573 ast_verb(3, "Unregistering FAX module type '%s'\n", tech->type);
575 AST_RWLIST_WRLOCK(&faxmodules);
576 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&faxmodules, fax, list) {
577 if (fax->tech != tech) {
580 AST_RWLIST_REMOVE_CURRENT(list);
581 ast_module_unref(ast_module_info->self);
583 ast_verb(4, "Unregistered FAX module type '%s'\n", tech->type);
586 AST_RWLIST_TRAVERSE_SAFE_END;
587 AST_RWLIST_UNLOCK(&faxmodules);
590 /*! \brief convert a ast_fax_state to a string */
591 const char *ast_fax_state_to_str(enum ast_fax_state state)
594 case AST_FAX_STATE_UNINITIALIZED:
595 return "Uninitialized";
596 case AST_FAX_STATE_INITIALIZED:
597 return "Initialized";
598 case AST_FAX_STATE_OPEN:
600 case AST_FAX_STATE_ACTIVE:
602 case AST_FAX_STATE_COMPLETE:
604 case AST_FAX_STATE_RESERVED:
606 case AST_FAX_STATE_INACTIVE:
609 ast_log(LOG_WARNING, "unhandled FAX state: %d\n", state);
614 void ast_fax_log(int level, const char *file, const int line, const char *function, const char *msg)
616 if (fax_logger_level != -1) {
617 ast_log_dynamic_level(fax_logger_level, "%s", msg);
619 ast_log(level, file, line, function, "%s", msg);
623 /*! \brief convert a rate string to a rate */
624 static unsigned int fax_rate_str_to_int(const char *ratestr)
628 if (sscanf(ratestr, "%d", &rate) != 1) {
629 ast_log(LOG_ERROR, "failed to sscanf '%s' to rate\n", ratestr);
643 ast_log(LOG_WARNING, "ignoring invalid rate '%s'. Valid options are {2400 | 4800 | 7200 | 9600 | 12000 | 14400 | 28800 | 33600}\n", ratestr);
648 static void fax_session_release(struct ast_fax_session *s, struct ast_fax_tech_token *token)
651 s->tech->release_token(token);
654 if (s->state == AST_FAX_STATE_RESERVED) {
655 ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, -1);
656 s->state = AST_FAX_STATE_INACTIVE;
660 /*! \brief destroy a FAX session structure */
661 static void destroy_session(void *session)
663 struct ast_fax_session *s = session;
666 fax_session_release(s, NULL);
668 s->tech->destroy_session(s);
670 ast_module_unref(s->tech->module);
674 ao2_ref(s->details, -1);
678 ast_dsp_free(s->debug_info->dsp);
679 ast_free(s->debug_info);
683 ast_smoother_free(s->smoother);
686 if (s->state != AST_FAX_STATE_INACTIVE) {
687 ast_atomic_fetchadd_int(&faxregistry.active_sessions, -1);
690 ast_free(s->channame);
691 ast_free(s->chan_uniqueid);
694 static struct ast_fax_session *fax_session_reserve(struct ast_fax_session_details *details, struct ast_fax_tech_token **token)
696 struct ast_fax_session *s;
697 struct fax_module *faxmod;
699 if (!(s = ao2_alloc(sizeof(*s), destroy_session))) {
703 s->state = AST_FAX_STATE_INACTIVE;
705 /* locate a FAX technology module that can handle said requirements
706 * Note: the requirements have not yet been finalized as T.38
707 * negotiation has not yet occured. */
708 AST_RWLIST_RDLOCK(&faxmodules);
709 AST_RWLIST_TRAVERSE(&faxmodules, faxmod, list) {
710 if ((faxmod->tech->caps & details->caps) != details->caps) {
713 ast_debug(4, "Reserving a FAX session from '%s'.\n", faxmod->tech->description);
714 ast_module_ref(faxmod->tech->module);
715 s->tech = faxmod->tech;
718 AST_RWLIST_UNLOCK(&faxmodules);
721 ast_log(LOG_ERROR, "Could not locate a FAX technology module with capabilities (0x%X)\n", details->caps);
726 if (!s->tech->reserve_session) {
727 ast_debug(1, "Selected FAX technology module (%s) does not support reserving sessions.\n", s->tech->description);
731 if (!(*token = s->tech->reserve_session(s))) {
736 s->state = AST_FAX_STATE_RESERVED;
737 ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, 1);
742 /*! \brief create a FAX session */
743 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)
745 struct ast_fax_session *s = NULL;
746 struct fax_module *faxmod;
750 ao2_ref(reserved, +1);
752 if (s->state == AST_FAX_STATE_RESERVED) {
753 ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, -1);
754 s->state = AST_FAX_STATE_UNINITIALIZED;
758 if (!s && !(s = ao2_alloc(sizeof(*s), destroy_session))) {
762 ast_atomic_fetchadd_int(&faxregistry.active_sessions, 1);
763 s->state = AST_FAX_STATE_UNINITIALIZED;
765 if (details->option.debug && (details->caps & AST_FAX_TECH_AUDIO)) {
766 if (!(s->debug_info = ast_calloc(1, sizeof(*(s->debug_info))))) {
767 fax_session_release(s, token);
771 if (!(s->debug_info->dsp = ast_dsp_new())) {
772 ast_free(s->debug_info);
773 s->debug_info = NULL;
774 fax_session_release(s, token);
778 ast_dsp_set_threshold(s->debug_info->dsp, 128);
781 if (!(s->channame = ast_strdup(chan->name))) {
782 fax_session_release(s, token);
787 if (!(s->chan_uniqueid = ast_strdup(chan->uniqueid))) {
788 fax_session_release(s, token);
794 s->details = details;
795 ao2_ref(s->details, 1);
797 details->id = s->id = ast_atomic_fetchadd_int(&faxregistry.nextsessionname, 1);
800 /* locate a FAX technology module that can handle said requirements */
801 AST_RWLIST_RDLOCK(&faxmodules);
802 AST_RWLIST_TRAVERSE(&faxmodules, faxmod, list) {
803 if ((faxmod->tech->caps & details->caps) != details->caps) {
806 ast_debug(4, "Requesting a new FAX session from '%s'.\n", faxmod->tech->description);
807 ast_module_ref(faxmod->tech->module);
808 s->tech = faxmod->tech;
811 AST_RWLIST_UNLOCK(&faxmodules);
814 ast_log(LOG_ERROR, "Could not locate a FAX technology module with capabilities (0x%X)\n", details->caps);
820 if (!(s->tech_pvt = s->tech->new_session(s, token))) {
821 ast_log(LOG_ERROR, "FAX session failed to initialize.\n");
825 /* link the session to the session container */
826 if (!(ao2_link(faxregistry.container, s))) {
827 ast_log(LOG_ERROR, "failed to add FAX session '%d' to container.\n", s->id);
831 ast_debug(4, "channel '%s' using FAX session '%d'\n", s->channame, s->id);
836 static void get_manager_event_info(struct ast_channel *chan, struct manager_event_info *info)
838 pbx_substitute_variables_helper(chan, "${CONTEXT}", info->context, sizeof(info->context));
839 pbx_substitute_variables_helper(chan, "${EXTEN}", info->exten, sizeof(info->exten));
840 pbx_substitute_variables_helper(chan, "${CALLERID(num)}", info->cid, sizeof(info->cid));
844 /* \brief Generate a string of filenames using the given prefix and separator.
845 * \param details the fax session details
846 * \param prefix the prefix to each filename
847 * \param separator the separator between filenames
849 * This function generates a string of filenames from the given details
850 * structure and using the given prefix and separator.
852 * \retval NULL there was an error generating the string
853 * \return the string generated string
855 static char *generate_filenames_string(struct ast_fax_session_details *details, char *prefix, char *separator)
860 struct ast_fax_document *doc;
862 /* don't process empty lists */
863 if (AST_LIST_EMPTY(&details->documents)) {
867 /* Calculate the total length of all of the file names */
868 AST_LIST_TRAVERSE(&details->documents, doc, next) {
869 size += strlen(separator) + strlen(prefix) + strlen(doc->filename);
871 size += 1; /* add space for the terminating null */
873 if (!(filenames = ast_malloc(size))) {
878 ast_build_string(&c, &size, "%s%s", prefix, AST_LIST_FIRST(&details->documents)->filename);
879 AST_LIST_TRAVERSE(&details->documents, doc, next) {
885 ast_build_string(&c, &size, "%s%s%s", separator, prefix, doc->filename);
891 /*! \brief send a FAX status manager event */
892 static int report_fax_status(struct ast_channel *chan, struct ast_fax_session_details *details, const char *status)
894 char *filenames = generate_filenames_string(details, "FileName: ", "\r\n");
899 ast_channel_lock(chan);
900 if (details->option.statusevents) {
901 struct manager_event_info info;
903 get_manager_event_info(chan, &info);
904 manager_event(EVENT_FLAG_CALL,
905 (details->caps & AST_FAX_TECH_RECEIVE) ? "ReceiveFAXStatus" : "SendFAXStatus",
911 "LocalStationID: %s\r\n"
918 details->localstationid,
921 ast_channel_unlock(chan);
927 /*! \brief Set fax related channel variables. */
928 static void set_channel_variables(struct ast_channel *chan, struct ast_fax_session_details *details)
931 pbx_builtin_setvar_helper(chan, "FAXSTATUS", S_OR(details->result, NULL));
932 pbx_builtin_setvar_helper(chan, "FAXERROR", S_OR(details->error, NULL));
933 pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", S_OR(details->resultstr, NULL));
934 pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", S_OR(details->remotestationid, NULL));
935 pbx_builtin_setvar_helper(chan, "FAXBITRATE", S_OR(details->transfer_rate, NULL));
936 pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", S_OR(details->resolution, NULL));
938 snprintf(buf, sizeof(buf), "%d", details->pages_transferred);
939 pbx_builtin_setvar_helper(chan, "FAXPAGES", buf);
942 #define GENERIC_FAX_EXEC_SET_VARS(fax, chan, errorstr, reason) \
944 if (ast_strlen_zero(fax->details->result)) \
945 ast_string_field_set(fax->details, result, "FAILED"); \
946 if (ast_strlen_zero(fax->details->resultstr)) \
947 ast_string_field_set(fax->details, resultstr, reason); \
948 if (ast_strlen_zero(fax->details->error)) \
949 ast_string_field_set(fax->details, error, errorstr); \
950 set_channel_variables(chan, fax->details); \
953 #define GENERIC_FAX_EXEC_ERROR_QUIET(fax, chan, errorstr, reason) \
955 GENERIC_FAX_EXEC_SET_VARS(fax, chan, errorstr, reason); \
959 #define GENERIC_FAX_EXEC_ERROR(fax, chan, errorstr, reason) \
961 ast_log(LOG_ERROR, "channel '%s' FAX session '%d' failure, reason: '%s' (%s)\n", chan->name, fax->id, reason, errorstr); \
962 GENERIC_FAX_EXEC_ERROR_QUIET(fax, chan, errorstr, reason); \
965 static void t38_parameters_ast_to_fax(struct ast_fax_t38_parameters *dst, const struct ast_control_t38_parameters *src)
967 dst->version = src->version;
968 dst->max_ifp = src->max_ifp;
969 dst->rate = src->rate;
970 dst->rate_management = src->rate_management;
971 dst->fill_bit_removal = src->fill_bit_removal;
972 dst->transcoding_mmr = src->transcoding_mmr;
973 dst->transcoding_jbig = src->transcoding_jbig;
976 static void t38_parameters_fax_to_ast(struct ast_control_t38_parameters *dst, const struct ast_fax_t38_parameters *src)
978 dst->version = src->version;
979 dst->max_ifp = src->max_ifp;
980 dst->rate = src->rate;
981 dst->rate_management = src->rate_management;
982 dst->fill_bit_removal = src->fill_bit_removal;
983 dst->transcoding_mmr = src->transcoding_mmr;
984 dst->transcoding_jbig = src->transcoding_jbig;
987 static int set_fax_t38_caps(struct ast_channel *chan, struct ast_fax_session_details *details)
989 switch (ast_channel_get_t38_state(chan)) {
990 case T38_STATE_UNKNOWN:
991 details->caps |= AST_FAX_TECH_T38;
993 case T38_STATE_UNAVAILABLE:
994 details->caps |= AST_FAX_TECH_AUDIO;
996 case T38_STATE_NEGOTIATING: {
997 /* the other end already sent us a T.38 reinvite, so we need to prod the channel
998 * driver into resending their parameters to us if it supports doing so... if
999 * not, we can't proceed, because we can't create a proper reply without them.
1000 * if it does work, the channel driver will send an AST_CONTROL_T38_PARAMETERS
1001 * with a request of AST_T38_REQUEST_NEGOTIATE, which will be read by the function
1002 * that gets called after this one completes
1004 struct ast_control_t38_parameters parameters = { .request_response = AST_T38_REQUEST_PARMS, };
1005 if (ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, ¶meters, sizeof(parameters)) != AST_T38_REQUEST_PARMS) {
1006 ast_log(LOG_ERROR, "channel '%s' is in an unsupported T.38 negotiation state, cannot continue.\n", chan->name);
1009 details->caps |= AST_FAX_TECH_T38;
1013 ast_log(LOG_ERROR, "channel '%s' is in an unsupported T.38 negotiation state, cannot continue.\n", chan->name);
1020 static int disable_t38(struct ast_channel *chan)
1023 struct ast_frame *frame = NULL;
1024 struct ast_control_t38_parameters t38_parameters = { .request_response = AST_T38_REQUEST_TERMINATE, };
1026 ast_debug(1, "Shutting down T.38 on %s\n", chan->name);
1027 if (ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0) {
1028 ast_debug(1, "error while disabling T.38 on channel '%s'\n", chan->name);
1032 /* wait up to five seconds for negotiation to complete */
1036 ms = ast_waitfor(chan, ms);
1038 ast_debug(1, "error while disabling T.38 on channel '%s'\n", chan->name);
1042 if (ms == 0) { /* all done, nothing happened */
1043 ast_debug(1, "channel '%s' timed-out during T.38 shutdown\n", chan->name);
1047 if (!(frame = ast_read(chan))) {
1050 if ((frame->frametype == AST_FRAME_CONTROL) &&
1051 (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
1052 (frame->datalen == sizeof(t38_parameters))) {
1053 struct ast_control_t38_parameters *parameters = frame->data.ptr;
1055 switch (parameters->request_response) {
1056 case AST_T38_TERMINATED:
1057 ast_debug(1, "Shut down T.38 on %s\n", chan->name);
1059 case AST_T38_REFUSED:
1060 ast_log(LOG_WARNING, "channel '%s' refused to disable T.38\n", chan->name);
1064 ast_log(LOG_ERROR, "channel '%s' failed to disable T.38\n", chan->name);
1077 static struct ast_control_t38_parameters our_t38_parameters = {
1080 .rate = AST_T38_RATE_14400,
1081 .rate_management = AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF,
1084 /*! \brief this is the generic FAX session handling function */
1085 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)
1088 int timeout = RES_FAX_TIMEOUT;
1089 int res = 0, chancount;
1090 unsigned int expected_frametype = -1;
1091 union ast_frame_subclass expected_framesubclass = { .integer = -1 };
1092 unsigned int t38negotiated = (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED);
1093 struct ast_control_t38_parameters t38_parameters;
1094 const char *tempvar;
1095 struct ast_fax_session *fax = NULL;
1096 struct ast_frame *frame = NULL;
1097 struct ast_channel *c = chan;
1098 unsigned int orig_write_format = 0, orig_read_format = 0;
1102 /* create the FAX session */
1103 if (!(fax = fax_session_new(details, chan, reserved, token))) {
1104 ast_log(LOG_ERROR, "Can't create a FAX session, FAX attempt failed.\n");
1105 report_fax_status(chan, details, "No Available Resource");
1109 ast_channel_lock(chan);
1110 /* update session details */
1111 if (ast_strlen_zero(details->headerinfo) && (tempvar = pbx_builtin_getvar_helper(chan, "LOCALHEADERINFO"))) {
1112 ast_string_field_set(details, headerinfo, tempvar);
1114 if (ast_strlen_zero(details->localstationid)) {
1115 tempvar = pbx_builtin_getvar_helper(chan, "LOCALSTATIONID");
1116 ast_string_field_set(details, localstationid, tempvar ? tempvar : "unknown");
1118 ast_channel_unlock(chan);
1120 report_fax_status(chan, details, "Allocating Resources");
1122 if (details->caps & AST_FAX_TECH_AUDIO) {
1123 expected_frametype = AST_FRAME_VOICE;;
1124 expected_framesubclass.codec = AST_FORMAT_SLINEAR;
1125 orig_write_format = chan->writeformat;
1126 if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
1127 ast_log(LOG_ERROR, "channel '%s' failed to set write format to signed linear'.\n", chan->name);
1128 ao2_lock(faxregistry.container);
1129 ao2_unlink(faxregistry.container, fax);
1130 ao2_unlock(faxregistry.container);
1132 ast_channel_unlock(chan);
1135 orig_read_format = chan->readformat;
1136 if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0) {
1137 ast_log(LOG_ERROR, "channel '%s' failed to set read format to signed linear.\n", chan->name);
1138 ao2_lock(faxregistry.container);
1139 ao2_unlink(faxregistry.container, fax);
1140 ao2_unlock(faxregistry.container);
1142 ast_channel_unlock(chan);
1145 if (fax->smoother) {
1146 ast_smoother_free(fax->smoother);
1147 fax->smoother = NULL;
1149 if (!(fax->smoother = ast_smoother_new(320))) {
1150 ast_log(LOG_WARNING, "Channel '%s' FAX session '%d' failed to obtain a smoother.\n", chan->name, fax->id);
1153 expected_frametype = AST_FRAME_MODEM;
1154 expected_framesubclass.codec = AST_MODEM_T38;
1157 if (fax->debug_info) {
1158 fax->debug_info->base_tv = ast_tvnow();
1161 /* reset our result fields just in case the fax tech driver wants to
1162 * set custom error messages */
1163 ast_string_field_set(details, result, "");
1164 ast_string_field_set(details, resultstr, "");
1165 ast_string_field_set(details, error, "");
1166 set_channel_variables(chan, details);
1168 if (fax->tech->start_session(fax) < 0) {
1169 GENERIC_FAX_EXEC_ERROR(fax, chan, "INIT_ERROR", "failed to start FAX session");
1172 report_fax_status(chan, details, "FAX Transmission In Progress");
1174 ast_debug(5, "channel %s will wait on FAX fd %d\n", chan->name, fax->fd);
1176 /* handle frames for the session */
1178 while ((res > -1) && (ms > -1) && (timeout > 0)) {
1179 struct ast_channel *ready_chan;
1184 ready_chan = ast_waitfor_nandfds(&c, chancount, &fax->fd, 1, &exception, &ofd, &ms);
1186 if (!(frame = ast_read(chan))) {
1187 /* the channel is probably gone, so lets stop polling on it and let the
1188 * FAX session complete before we exit the application. if needed,
1189 * send the FAX stack silence so the modems can finish their session without
1191 ast_debug(1, "Channel '%s' did not return a frame; probably hung up.\n", chan->name);
1192 GENERIC_FAX_EXEC_SET_VARS(fax, chan, "HANGUP", "remote channel hungup");
1195 timeout -= (1000 - ms);
1196 fax->tech->cancel_session(fax);
1197 if (fax->tech->generate_silence) {
1198 fax->tech->generate_silence(fax);
1203 if ((frame->frametype == AST_FRAME_CONTROL) &&
1204 (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
1205 (frame->datalen == sizeof(t38_parameters))) {
1206 unsigned int was_t38 = t38negotiated;
1207 struct ast_control_t38_parameters *parameters = frame->data.ptr;
1209 switch (parameters->request_response) {
1210 case AST_T38_REQUEST_NEGOTIATE:
1211 /* the other end has requested a switch to T.38, so reply that we are willing, if we can
1214 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
1215 t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
1216 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
1218 case AST_T38_NEGOTIATED:
1219 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
1225 if (t38negotiated && !was_t38) {
1226 fax->tech->switch_to_t38(fax);
1227 details->caps &= ~AST_FAX_TECH_AUDIO;
1228 expected_frametype = AST_FRAME_MODEM;
1229 expected_framesubclass.codec = AST_MODEM_T38;
1230 if (fax->smoother) {
1231 ast_smoother_free(fax->smoother);
1232 fax->smoother = NULL;
1235 report_fax_status(chan, details, "T.38 Negotiated");
1237 ast_verb(3, "Channel '%s' switched to T.38 FAX session '%d'.\n", chan->name, fax->id);
1239 } else if ((frame->frametype == expected_frametype) &&
1240 (!memcmp(&frame->subclass, &expected_framesubclass, sizeof(frame->subclass)))) {
1241 struct ast_frame *f;
1243 if (fax->smoother) {
1244 /* push the frame into a smoother */
1245 if (ast_smoother_feed(fax->smoother, frame) < 0) {
1246 GENERIC_FAX_EXEC_ERROR(fax, chan, "UNKNOWN", "Failed to feed the smoother");
1248 while ((f = ast_smoother_read(fax->smoother)) && (f->data.ptr)) {
1249 if (fax->debug_info) {
1250 debug_check_frame_for_silence(fax, 1, f);
1252 /* write the frame to the FAX stack */
1253 fax->tech->write(fax, f);
1254 fax->frames_received++;
1260 /* write the frame to the FAX stack */
1261 fax->tech->write(fax, frame);
1262 fax->frames_received++;
1264 timeout = RES_FAX_TIMEOUT;
1267 } else if (ofd == fax->fd) {
1268 /* read a frame from the FAX stack and send it out the channel.
1269 * the FAX stack will return a NULL if the FAX session has already completed */
1270 if (!(frame = fax->tech->read(fax))) {
1274 if (fax->debug_info && (frame->frametype == AST_FRAME_VOICE)) {
1275 debug_check_frame_for_silence(fax, 0, frame);
1278 ast_write(chan, frame);
1281 timeout = RES_FAX_TIMEOUT;
1283 if (ms && (ofd < 0)) {
1284 if ((errno == 0) || (errno == EINTR)) {
1285 timeout -= (1000 - ms);
1287 GENERIC_FAX_EXEC_ERROR(fax, chan, "TIMEOUT", "fax session timed-out");
1290 ast_log(LOG_WARNING, "something bad happened while channel '%s' was polling.\n", chan->name);
1291 GENERIC_FAX_EXEC_ERROR(fax, chan, "UNKNOWN", "error polling data");
1296 /* nothing happened */
1300 GENERIC_FAX_EXEC_ERROR(fax, chan, "TIMEOUT", "fax session timed-out");
1303 ast_log(LOG_WARNING, "channel '%s' timed-out during the FAX transmission.\n", chan->name);
1304 GENERIC_FAX_EXEC_ERROR(fax, chan, "TIMEOUT", "fax session timed-out");
1310 ast_debug(3, "channel '%s' - event loop stopped { timeout: %d, ms: %d, res: %d }\n", chan->name, timeout, ms, res);
1312 set_channel_variables(chan, details);
1314 ast_atomic_fetchadd_int(&faxregistry.fax_complete, 1);
1315 if (!strcasecmp(details->result, "FAILED")) {
1316 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1320 ao2_lock(faxregistry.container);
1321 ao2_unlink(faxregistry.container, fax);
1322 ao2_unlock(faxregistry.container);
1326 /* if the channel is still alive, and we changed its read/write formats,
1330 if (orig_read_format) {
1331 ast_set_read_format(chan, orig_read_format);
1333 if (orig_write_format) {
1334 ast_set_write_format(chan, orig_write_format);
1338 /* return the chancount so the calling function can determine if the channel hungup during this FAX session or not */
1342 static int receivefax_t38_init(struct ast_channel *chan, struct ast_fax_session_details *details)
1345 struct ast_frame *frame = NULL;
1346 struct ast_control_t38_parameters t38_parameters;
1348 t38_parameters_ast_to_fax(&details->our_t38_parameters, &our_t38_parameters);
1350 /* don't send any audio if we've already received a T.38 reinvite */
1351 if (ast_channel_get_t38_state(chan) != T38_STATE_NEGOTIATING) {
1352 /* generate 3 seconds of CED */
1353 if (ast_playtones_start(chan, 1024, "!2100/3000", 1)) {
1354 ast_log(LOG_ERROR, "error generating CED tone on %s\n", chan->name);
1360 ms = ast_waitfor(chan, ms);
1362 ast_log(LOG_ERROR, "error while generating CED tone on %s\n", chan->name);
1363 ast_playtones_stop(chan);
1367 if (ms == 0) { /* all done, nothing happened */
1371 if (!(frame = ast_read(chan))) {
1372 ast_log(LOG_ERROR, "error reading frame while generating CED tone on %s\n", chan->name);
1373 ast_playtones_stop(chan);
1377 if ((frame->frametype == AST_FRAME_CONTROL) &&
1378 (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
1379 (frame->datalen == sizeof(t38_parameters))) {
1380 struct ast_control_t38_parameters *parameters = frame->data.ptr;
1382 switch (parameters->request_response) {
1383 case AST_T38_REQUEST_NEGOTIATE:
1384 /* the other end has requested a switch to T.38, so reply that we are willing, if we can
1387 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
1388 t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
1389 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
1390 ast_playtones_stop(chan);
1392 case AST_T38_NEGOTIATED:
1393 ast_debug(1, "Negotiated T.38 for receive on %s\n", chan->name);
1394 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
1395 details->caps &= ~AST_FAX_TECH_AUDIO;
1396 report_fax_status(chan, details, "T.38 Negotiated");
1405 ast_playtones_stop(chan);
1408 /* if T.38 was negotiated, we are done initializing */
1409 if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) {
1414 ast_debug(1, "Negotiating T.38 for receive on %s\n", chan->name);
1416 /* wait up to five seconds for negotiation to complete */
1419 /* set parameters based on the session's parameters */
1420 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
1421 t38_parameters.request_response = AST_T38_REQUEST_NEGOTIATE;
1422 if ((ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0)) {
1427 ms = ast_waitfor(chan, ms);
1429 ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", chan->name);
1433 if (ms == 0) { /* all done, nothing happened */
1434 ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 negotiation.\n", chan->name);
1435 details->caps &= ~AST_FAX_TECH_T38;
1439 if (!(frame = ast_read(chan))) {
1440 ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", chan->name);
1444 if ((frame->frametype == AST_FRAME_CONTROL) &&
1445 (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
1446 (frame->datalen == sizeof(t38_parameters))) {
1447 struct ast_control_t38_parameters *parameters = frame->data.ptr;
1449 switch (parameters->request_response) {
1450 case AST_T38_REQUEST_NEGOTIATE:
1451 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
1452 t38_parameters.request_response = AST_T38_NEGOTIATED;
1453 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
1455 case AST_T38_NEGOTIATED:
1456 ast_debug(1, "Negotiated T.38 for receive on %s\n", chan->name);
1457 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
1458 details->caps &= ~AST_FAX_TECH_AUDIO;
1459 report_fax_status(chan, details, "T.38 Negotiated");
1462 case AST_T38_REFUSED:
1463 ast_log(LOG_WARNING, "channel '%s' refused to negotiate T.38\n", chan->name);
1464 details->caps &= ~AST_FAX_TECH_T38;
1468 ast_log(LOG_ERROR, "channel '%s' failed to negotiate T.38\n", chan->name);
1469 details->caps &= ~AST_FAX_TECH_T38;
1477 /* if T.38 was negotiated, we are done initializing */
1478 if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) {
1482 /* if we made it here, then T.38 failed, check the 'f' flag */
1483 if (details->option.allow_audio != AST_FAX_OPTFLAG_TRUE) {
1484 ast_log(LOG_WARNING, "Audio FAX not allowed on channel '%s' and T.38 negotiation failed; aborting.\n", chan->name);
1488 /* ok, audio fallback is allowed */
1489 details->caps |= AST_FAX_TECH_AUDIO;
1494 /*! \brief initiate a receive FAX session */
1495 static int receivefax_exec(struct ast_channel *chan, const char *data)
1497 char *parse, modems[128] = "";
1499 struct ast_fax_session_details *details;
1500 struct ast_fax_session *s;
1501 struct ast_fax_tech_token *token = NULL;
1502 struct ast_fax_document *doc;
1503 AST_DECLARE_APP_ARGS(args,
1504 AST_APP_ARG(filename);
1505 AST_APP_ARG(options);
1507 struct ast_flags opts = { 0, };
1508 struct manager_event_info info;
1510 /* initialize output channel variables */
1511 pbx_builtin_setvar_helper(chan, "FAXSTATUS", "FAILED");
1512 pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", NULL);
1513 pbx_builtin_setvar_helper(chan, "FAXPAGES", "0");
1514 pbx_builtin_setvar_helper(chan, "FAXBITRATE", NULL);
1515 pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", NULL);
1517 /* Get a FAX session details structure from the channel's FAX datastore and create one if
1518 * it does not already exist. */
1519 if (!(details = find_or_create_details(chan))) {
1520 pbx_builtin_setvar_helper(chan, "FAXERROR", "MEMORY_ERROR");
1521 pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "error allocating memory");
1522 ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
1526 ast_string_field_set(details, result, "FAILED");
1527 ast_string_field_set(details, resultstr, "error starting fax session");
1528 ast_string_field_set(details, error, "INIT_ERROR");
1529 set_channel_variables(chan, details);
1531 if (details->maxrate < details->minrate) {
1532 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
1533 ast_string_field_set(details, resultstr, "maxrate is less than minrate");
1534 set_channel_variables(chan, details);
1535 ast_log(LOG_ERROR, "maxrate %d is less than minrate %d\n", details->maxrate, details->minrate);
1536 ao2_ref(details, -1);
1540 if (check_modem_rate(details->modems, details->minrate)) {
1541 ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
1542 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %d\n", modems, details->minrate);
1543 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
1544 ast_string_field_set(details, resultstr, "incompatible 'modems' and 'minrate' settings");
1545 set_channel_variables(chan, details);
1546 ao2_ref(details, -1);
1550 if (check_modem_rate(details->modems, details->maxrate)) {
1551 ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
1552 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %d\n", modems, details->maxrate);
1553 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
1554 ast_string_field_set(details, resultstr, "incompatible 'modems' and 'maxrate' settings");
1555 set_channel_variables(chan, details);
1556 ao2_ref(details, -1);
1560 if (ast_strlen_zero(data)) {
1561 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
1562 ast_string_field_set(details, resultstr, "invalid arguments");
1563 set_channel_variables(chan, details);
1564 ast_log(LOG_WARNING, "%s requires an argument (filename[,options])\n", app_receivefax);
1565 ao2_ref(details, -1);
1568 parse = ast_strdupa(data);
1569 AST_STANDARD_APP_ARGS(args, parse);
1571 if (!ast_strlen_zero(args.options) &&
1572 ast_app_parse_options(fax_exec_options, &opts, NULL, args.options)) {
1573 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
1574 ast_string_field_set(details, resultstr, "invalid arguments");
1575 set_channel_variables(chan, details);
1576 ao2_ref(details, -1);
1579 if (ast_strlen_zero(args.filename)) {
1580 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
1581 ast_string_field_set(details, resultstr, "invalid arguments");
1582 set_channel_variables(chan, details);
1583 ast_log(LOG_WARNING, "%s requires an argument (filename[,options])\n", app_receivefax);
1584 ao2_ref(details, -1);
1588 /* check for unsupported FAX application options */
1589 if (ast_test_flag(&opts, OPT_CALLERMODE) || ast_test_flag(&opts, OPT_CALLEDMODE)) {
1590 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
1591 ast_string_field_set(details, resultstr, "invalid arguments");
1592 set_channel_variables(chan, details);
1593 ast_log(LOG_WARNING, "%s does not support polling\n", app_receivefax);
1594 ao2_ref(details, -1);
1598 ast_atomic_fetchadd_int(&faxregistry.fax_rx_attempts, 1);
1600 pbx_builtin_setvar_helper(chan, "FAXERROR", "Channel Problems");
1601 pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "Error before FAX transmission started.");
1603 if (!(doc = ast_calloc(1, sizeof(*doc) + strlen(args.filename) + 1))) {
1604 ast_string_field_set(details, error, "MEMORY_ERROR");
1605 ast_string_field_set(details, resultstr, "error allocating memory");
1606 set_channel_variables(chan, details);
1607 ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
1608 ao2_ref(details, -1);
1612 strcpy(doc->filename, args.filename);
1613 AST_LIST_INSERT_TAIL(&details->documents, doc, next);
1615 ast_verb(3, "Channel '%s' receiving FAX '%s'\n", chan->name, args.filename);
1617 details->caps = AST_FAX_TECH_RECEIVE;
1619 /* check for debug */
1620 if (ast_test_flag(&opts, OPT_DEBUG) || global_fax_debug) {
1621 details->option.debug = AST_FAX_OPTFLAG_TRUE;
1624 /* check for request for status events */
1625 if (ast_test_flag(&opts, OPT_STATUS)) {
1626 details->option.statusevents = AST_FAX_OPTFLAG_TRUE;
1629 if ((ast_channel_get_t38_state(chan) == T38_STATE_UNAVAILABLE) ||
1630 ast_test_flag(&opts, OPT_ALLOWAUDIO) ||
1631 ast_test_flag(&opts, OPT_FORCE_AUDIO)) {
1632 details->option.allow_audio = AST_FAX_OPTFLAG_TRUE;
1635 if (!(s = fax_session_reserve(details, &token))) {
1636 ast_string_field_set(details, resultstr, "error reserving fax session");
1637 set_channel_variables(chan, details);
1638 ast_log(LOG_ERROR, "Unable to reserve FAX session.\n");
1639 ao2_ref(details, -1);
1643 /* make sure the channel is up */
1644 if (chan->_state != AST_STATE_UP) {
1645 if (ast_answer(chan)) {
1646 ast_string_field_set(details, resultstr, "error answering channel");
1647 set_channel_variables(chan, details);
1648 ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", chan->name);
1649 fax_session_release(s, token);
1651 ao2_ref(details, -1);
1656 if (!ast_test_flag(&opts, OPT_FORCE_AUDIO)) {
1657 if (set_fax_t38_caps(chan, details)) {
1658 ast_string_field_set(details, error, "T38_NEG_ERROR");
1659 ast_string_field_set(details, resultstr, "error negotiating T.38");
1660 set_channel_variables(chan, details);
1661 fax_session_release(s, token);
1663 ao2_ref(details, -1);
1668 if (!ast_test_flag(&opts, OPT_FORCE_AUDIO) && (details->caps & AST_FAX_TECH_T38)) {
1669 if (receivefax_t38_init(chan, details)) {
1670 ast_string_field_set(details, error, "T38_NEG_ERROR");
1671 ast_string_field_set(details, resultstr, "error negotiating T.38");
1672 set_channel_variables(chan, details);
1673 fax_session_release(s, token);
1675 ao2_ref(details, -1);
1676 ast_log(LOG_ERROR, "error initializing channel '%s' in T.38 mode\n", chan->name);
1680 details->option.send_ced = 1;
1683 if ((channel_alive = generic_fax_exec(chan, details, s, token)) < 0) {
1684 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1687 if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) {
1688 if (disable_t38(chan)) {
1689 ast_debug(1, "error disabling T.38 mode on %s\n", chan->name);
1693 /* send out the AMI completion event */
1694 ast_channel_lock(chan);
1696 get_manager_event_info(chan, &info);
1697 manager_event(EVENT_FLAG_CALL,
1703 "RemoteStationID: %s\r\n"
1704 "LocalStationID: %s\r\n"
1705 "PagesTransferred: %s\r\n"
1706 "Resolution: %s\r\n"
1707 "TransferRate: %s\r\n"
1713 pbx_builtin_getvar_helper(chan, "REMOTESTATIONID"),
1714 pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"),
1715 pbx_builtin_getvar_helper(chan, "FAXPAGES"),
1716 pbx_builtin_getvar_helper(chan, "FAXRESOLUTION"),
1717 pbx_builtin_getvar_helper(chan, "FAXBITRATE"),
1719 ast_channel_unlock(chan);
1722 ao2_ref(details, -1);
1724 /* If the channel hungup return -1; otherwise, return 0 to continue in the dialplan */
1725 return (!channel_alive) ? -1 : 0;
1728 static int sendfax_t38_init(struct ast_channel *chan, struct ast_fax_session_details *details)
1731 struct ast_frame *frame = NULL;
1732 struct ast_control_t38_parameters t38_parameters;
1734 t38_parameters_ast_to_fax(&details->our_t38_parameters, &our_t38_parameters);
1736 /* send CNG tone while listening for the receiver to initiate a switch
1737 * to T.38 mode; if they do, stop sending the CNG tone and proceed with
1740 * 10500 is enough time for 3 CNG tones
1744 /* don't send any audio if we've already received a T.38 reinvite */
1745 if (ast_channel_get_t38_state(chan) != T38_STATE_NEGOTIATING) {
1746 if (ast_playtones_start(chan, 1024, "!1100/500,!0/3000,!1100/500,!0/3000,!1100/500,!0/3000", 1)) {
1747 ast_log(LOG_ERROR, "error generating CNG tone on %s\n", chan->name);
1753 ms = ast_waitfor(chan, ms);
1755 ast_log(LOG_ERROR, "error while generating CNG tone on %s\n", chan->name);
1756 ast_playtones_stop(chan);
1760 if (ms == 0) { /* all done, nothing happened */
1764 if (!(frame = ast_read(chan))) {
1765 ast_log(LOG_ERROR, "error reading frame while generating CNG tone on %s\n", chan->name);
1766 ast_playtones_stop(chan);
1770 if ((frame->frametype == AST_FRAME_CONTROL) &&
1771 (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
1772 (frame->datalen == sizeof(t38_parameters))) {
1773 struct ast_control_t38_parameters *parameters = frame->data.ptr;
1775 switch (parameters->request_response) {
1776 case AST_T38_REQUEST_NEGOTIATE:
1777 /* the other end has requested a switch to T.38, so reply that we are willing, if we can
1780 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
1781 t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
1782 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
1783 ast_playtones_stop(chan);
1785 case AST_T38_NEGOTIATED:
1786 ast_debug(1, "Negotiated T.38 for send on %s\n", chan->name);
1787 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
1788 details->caps &= ~AST_FAX_TECH_AUDIO;
1789 report_fax_status(chan, details, "T.38 Negotiated");
1799 ast_playtones_stop(chan);
1801 if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) {
1805 /* T.38 negotiation did not happen, initiate a switch if requested */
1806 if (details->option.request_t38 == AST_FAX_OPTFLAG_TRUE) {
1807 ast_debug(1, "Negotiating T.38 for send on %s\n", chan->name);
1809 /* wait up to five seconds for negotiation to complete */
1812 /* set parameters based on the session's parameters */
1813 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
1814 t38_parameters.request_response = AST_T38_REQUEST_NEGOTIATE;
1815 if ((ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0)) {
1820 ms = ast_waitfor(chan, ms);
1822 ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", chan->name);
1826 if (ms == 0) { /* all done, nothing happened */
1827 ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 negotiation.\n", chan->name);
1828 details->caps &= ~AST_FAX_TECH_T38;
1832 if (!(frame = ast_read(chan))) {
1833 ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", chan->name);
1837 if ((frame->frametype == AST_FRAME_CONTROL) &&
1838 (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
1839 (frame->datalen == sizeof(t38_parameters))) {
1840 struct ast_control_t38_parameters *parameters = frame->data.ptr;
1842 switch (parameters->request_response) {
1843 case AST_T38_REQUEST_NEGOTIATE:
1844 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
1845 t38_parameters.request_response = AST_T38_NEGOTIATED;
1846 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
1848 case AST_T38_NEGOTIATED:
1849 ast_debug(1, "Negotiated T.38 for receive on %s\n", chan->name);
1850 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
1851 details->caps &= ~AST_FAX_TECH_AUDIO;
1852 report_fax_status(chan, details, "T.38 Negotiated");
1855 case AST_T38_REFUSED:
1856 ast_log(LOG_WARNING, "channel '%s' refused to negotiate T.38\n", chan->name);
1857 details->caps &= ~AST_FAX_TECH_T38;
1861 ast_log(LOG_ERROR, "channel '%s' failed to negotiate T.38\n", chan->name);
1862 details->caps &= ~AST_FAX_TECH_T38;
1870 /* if T.38 was negotiated, we are done initializing */
1871 if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) {
1875 /* send one more CNG tone to get audio going again for some
1876 * carriers if we are going to fall back to audio mode */
1877 if (details->option.allow_audio == AST_FAX_OPTFLAG_TRUE) {
1878 if (ast_playtones_start(chan, 1024, "!1100/500,!0/3000", 1)) {
1879 ast_log(LOG_ERROR, "error generating second CNG tone on %s\n", chan->name);
1885 ms = ast_waitfor(chan, ms);
1887 ast_log(LOG_ERROR, "error while generating second CNG tone on %s\n", chan->name);
1888 ast_playtones_stop(chan);
1892 if (ms == 0) { /* all done, nothing happened */
1896 if (!(frame = ast_read(chan))) {
1897 ast_log(LOG_ERROR, "error reading frame while generating second CNG tone on %s\n", chan->name);
1898 ast_playtones_stop(chan);
1902 if ((frame->frametype == AST_FRAME_CONTROL) &&
1903 (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
1904 (frame->datalen == sizeof(t38_parameters))) {
1905 struct ast_control_t38_parameters *parameters = frame->data.ptr;
1907 switch (parameters->request_response) {
1908 case AST_T38_REQUEST_NEGOTIATE:
1909 /* the other end has requested a switch to T.38, so reply that we are willing, if we can
1912 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
1913 t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
1914 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
1915 ast_playtones_stop(chan);
1917 case AST_T38_NEGOTIATED:
1918 ast_debug(1, "Negotiated T.38 for send on %s\n", chan->name);
1919 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
1920 details->caps &= ~AST_FAX_TECH_AUDIO;
1921 report_fax_status(chan, details, "T.38 Negotiated");
1931 ast_playtones_stop(chan);
1933 /* if T.38 was negotiated, we are done initializing */
1934 if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) {
1940 /* if we made it here, then T.38 failed, check the 'f' flag */
1941 if (details->option.allow_audio == AST_FAX_OPTFLAG_FALSE) {
1942 ast_log(LOG_WARNING, "Audio FAX not allowed on channel '%s' and T.38 negotiation failed; aborting.\n", chan->name);
1946 /* ok, audio fallback is allowed */
1947 details->caps |= AST_FAX_TECH_AUDIO;
1953 /*! \brief initiate a send FAX session */
1954 static int sendfax_exec(struct ast_channel *chan, const char *data)
1956 char *parse, *filenames, *c, modems[128] = "";
1957 int channel_alive, file_count;
1958 struct ast_fax_session_details *details;
1959 struct ast_fax_session *s;
1960 struct ast_fax_tech_token *token = NULL;
1961 struct ast_fax_document *doc;
1962 AST_DECLARE_APP_ARGS(args,
1963 AST_APP_ARG(filenames);
1964 AST_APP_ARG(options);
1966 struct ast_flags opts = { 0, };
1967 struct manager_event_info info;
1969 /* initialize output channel variables */
1970 pbx_builtin_setvar_helper(chan, "FAXSTATUS", "FAILED");
1971 pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", NULL);
1972 pbx_builtin_setvar_helper(chan, "FAXPAGES", "0");
1973 pbx_builtin_setvar_helper(chan, "FAXBITRATE", NULL);
1974 pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", NULL);
1976 /* Get a requirement structure and set it. This structure is used
1977 * to tell the FAX technology module about the higher level FAX session */
1978 if (!(details = find_or_create_details(chan))) {
1979 pbx_builtin_setvar_helper(chan, "FAXERROR", "MEMORY_ERROR");
1980 pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "error allocating memory");
1981 ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
1985 ast_string_field_set(details, result, "FAILED");
1986 ast_string_field_set(details, resultstr, "error starting fax session");
1987 ast_string_field_set(details, error, "INIT_ERROR");
1988 set_channel_variables(chan, details);
1990 if (details->maxrate < details->minrate) {
1991 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
1992 ast_string_field_set(details, resultstr, "maxrate is less than minrate");
1993 set_channel_variables(chan, details);
1994 ast_log(LOG_ERROR, "maxrate %d is less than minrate %d\n", details->maxrate, details->minrate);
1995 ao2_ref(details, -1);
1999 if (check_modem_rate(details->modems, details->minrate)) {
2000 ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
2001 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %d\n", modems, details->minrate);
2002 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2003 ast_string_field_set(details, resultstr, "incompatible 'modems' and 'minrate' settings");
2004 set_channel_variables(chan, details);
2005 ao2_ref(details, -1);
2009 if (check_modem_rate(details->modems, details->maxrate)) {
2010 ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
2011 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %d\n", modems, details->maxrate);
2012 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2013 ast_string_field_set(details, resultstr, "incompatible 'modems' and 'maxrate' settings");
2014 set_channel_variables(chan, details);
2015 ao2_ref(details, -1);
2019 if (ast_strlen_zero(data)) {
2020 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2021 ast_string_field_set(details, resultstr, "invalid arguments");
2022 set_channel_variables(chan, details);
2023 ast_log(LOG_WARNING, "%s requires an argument (filename[&filename[&filename]][,options])\n", app_sendfax);
2024 ao2_ref(details, -1);
2027 parse = ast_strdupa(data);
2028 AST_STANDARD_APP_ARGS(args, parse);
2031 if (!ast_strlen_zero(args.options) &&
2032 ast_app_parse_options(fax_exec_options, &opts, NULL, args.options)) {
2033 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2034 ast_string_field_set(details, resultstr, "invalid arguments");
2035 set_channel_variables(chan, details);
2036 ao2_ref(details, -1);
2039 if (ast_strlen_zero(args.filenames)) {
2040 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2041 ast_string_field_set(details, resultstr, "invalid arguments");
2042 set_channel_variables(chan, details);
2043 ast_log(LOG_WARNING, "%s requires an argument (filename[&filename[&filename]],options])\n", app_sendfax);
2044 ao2_ref(details, -1);
2048 /* check for unsupported FAX application options */
2049 if (ast_test_flag(&opts, OPT_CALLERMODE) || ast_test_flag(&opts, OPT_CALLEDMODE)) {
2050 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2051 ast_string_field_set(details, resultstr, "invalid arguments");
2052 set_channel_variables(chan, details);
2053 ast_log(LOG_WARNING, "%s does not support polling\n", app_sendfax);
2054 ao2_ref(details, -1);
2058 ast_atomic_fetchadd_int(&faxregistry.fax_tx_attempts, 1);
2061 filenames = args.filenames;
2062 while ((c = strsep(&filenames, "&"))) {
2063 if (access(c, (F_OK | R_OK)) < 0) {
2064 ast_string_field_set(details, error, "FILE_ERROR");
2065 ast_string_field_set(details, resultstr, "error reading file");
2066 set_channel_variables(chan, details);
2067 ast_log(LOG_ERROR, "access failure. Verify '%s' exists and check permissions.\n", args.filenames);
2068 ao2_ref(details, -1);
2072 if (!(doc = ast_calloc(1, sizeof(*doc) + strlen(c) + 1))) {
2073 ast_string_field_set(details, error, "MEMORY_ERROR");
2074 ast_string_field_set(details, resultstr, "error allocating memory");
2075 set_channel_variables(chan, details);
2076 ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
2077 ao2_ref(details, -1);
2081 strcpy(doc->filename, c);
2082 AST_LIST_INSERT_TAIL(&details->documents, doc, next);
2086 if (file_count > 1) {
2087 details->caps |= AST_FAX_TECH_MULTI_DOC;
2090 ast_verb(3, "Channel '%s' sending FAX:\n", chan->name);
2091 AST_LIST_TRAVERSE(&details->documents, doc, next) {
2092 ast_verb(3, " %s\n", doc->filename);
2095 details->caps = AST_FAX_TECH_SEND;
2097 /* check for debug */
2098 if (ast_test_flag(&opts, OPT_DEBUG) || global_fax_debug) {
2099 details->option.debug = AST_FAX_OPTFLAG_TRUE;
2102 /* check for request for status events */
2103 if (ast_test_flag(&opts, OPT_STATUS)) {
2104 details->option.statusevents = AST_FAX_OPTFLAG_TRUE;
2107 if ((ast_channel_get_t38_state(chan) == T38_STATE_UNAVAILABLE) ||
2108 ast_test_flag(&opts, OPT_ALLOWAUDIO) ||
2109 ast_test_flag(&opts, OPT_FORCE_AUDIO)) {
2110 details->option.allow_audio = AST_FAX_OPTFLAG_TRUE;
2113 if (ast_test_flag(&opts, OPT_REQUEST_T38)) {
2114 details->option.request_t38 = AST_FAX_OPTFLAG_TRUE;
2117 if (!(s = fax_session_reserve(details, &token))) {
2118 ast_string_field_set(details, resultstr, "error reserving fax session");
2119 set_channel_variables(chan, details);
2120 ast_log(LOG_ERROR, "Unable to reserve FAX session.\n");
2121 ao2_ref(details, -1);
2125 /* make sure the channel is up */
2126 if (chan->_state != AST_STATE_UP) {
2127 if (ast_answer(chan)) {
2128 ast_string_field_set(details, resultstr, "error answering channel");
2129 set_channel_variables(chan, details);
2130 ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", chan->name);
2131 fax_session_release(s, token);
2133 ao2_ref(details, -1);
2138 if (!ast_test_flag(&opts, OPT_FORCE_AUDIO)) {
2139 if (set_fax_t38_caps(chan, details)) {
2140 ast_string_field_set(details, error, "T38_NEG_ERROR");
2141 ast_string_field_set(details, resultstr, "error negotiating T.38");
2142 set_channel_variables(chan, details);
2143 fax_session_release(s, token);
2145 ao2_ref(details, -1);
2150 if (!ast_test_flag(&opts, OPT_FORCE_AUDIO) && (details->caps & AST_FAX_TECH_T38)) {
2151 if (sendfax_t38_init(chan, details)) {
2152 ast_string_field_set(details, error, "T38_NEG_ERROR");
2153 ast_string_field_set(details, resultstr, "error negotiating T.38");
2154 set_channel_variables(chan, details);
2155 fax_session_release(s, token);
2157 ao2_ref(details, -1);
2158 ast_log(LOG_ERROR, "error initializing channel '%s' in T.38 mode\n", chan->name);
2162 details->option.send_cng = 1;
2165 if ((channel_alive = generic_fax_exec(chan, details, s, token)) < 0) {
2166 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
2169 if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) {
2170 if (disable_t38(chan)) {
2171 ast_debug(1, "error disabling T.38 mode on %s\n", chan->name);
2175 if (!(filenames = generate_filenames_string(details, "FileName: ", "\r\n"))) {
2176 ast_log(LOG_ERROR, "Error generating SendFAX manager event\n");
2178 ao2_ref(details, -1);
2179 return (!channel_alive) ? -1 : 0;
2182 /* send out the AMI completion event */
2183 ast_channel_lock(chan);
2184 get_manager_event_info(chan, &info);
2185 manager_event(EVENT_FLAG_CALL,
2191 "RemoteStationID: %s\r\n"
2192 "LocalStationID: %s\r\n"
2193 "PagesTransferred: %s\r\n"
2194 "Resolution: %s\r\n"
2195 "TransferRate: %s\r\n"
2201 pbx_builtin_getvar_helper(chan, "REMOTESTATIONID"),
2202 pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"),
2203 pbx_builtin_getvar_helper(chan, "FAXPAGES"),
2204 pbx_builtin_getvar_helper(chan, "FAXRESOLUTION"),
2205 pbx_builtin_getvar_helper(chan, "FAXBITRATE"),
2207 ast_channel_unlock(chan);
2209 ast_free(filenames);
2212 ao2_ref(details, -1);
2214 /* If the channel hungup return -1; otherwise, return 0 to continue in the dialplan */
2215 return (!channel_alive) ? -1 : 0;
2218 /*! \brief hash callback for ao2 */
2219 static int session_hash_cb(const void *obj, const int flags)
2221 const struct ast_fax_session *s = obj;
2226 /*! \brief compare callback for ao2 */
2227 static int session_cmp_cb(void *obj, void *arg, int flags)
2229 struct ast_fax_session *lhs = obj, *rhs = arg;
2231 return (lhs->id == rhs->id) ? CMP_MATCH | CMP_STOP : 0;
2234 /*! \brief fax session tab completion */
2235 static char *fax_session_tab_complete(struct ast_cli_args *a)
2240 struct ao2_iterator i;
2241 struct ast_fax_session *s;
2248 tklen = strlen(a->word);
2249 i = ao2_iterator_init(faxregistry.container, 0);
2250 while ((s = ao2_iterator_next(&i))) {
2251 snprintf(tbuf, sizeof(tbuf), "%d", s->id);
2252 if (!strncasecmp(a->word, tbuf, tklen) && ++wordnum > a->n) {
2253 name = ast_strdup(tbuf);
2259 if (ao2_iterator_destroy != NULL) {
2260 ao2_iterator_destroy(&i);
2265 static char *cli_fax_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2267 struct fax_module *fax;
2271 e->command = "fax show version";
2273 "Usage: fax show version\n"
2274 " Show versions of FAX For Asterisk components.\n";
2281 return CLI_SHOWUSAGE;
2284 ast_cli(a->fd, "FAX For Asterisk Components:\n");
2285 ast_cli(a->fd, "\tApplications: %s\n", ast_get_version());
2286 AST_RWLIST_RDLOCK(&faxmodules);
2287 AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
2288 ast_cli(a->fd, "\t%s: %s\n", fax->tech->description, fax->tech->version);
2290 AST_RWLIST_UNLOCK(&faxmodules);
2291 ast_cli(a->fd, "\n");
2296 /*! \brief enable FAX debugging */
2297 static char *cli_fax_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2304 e->command = "fax set debug {on|off}";
2306 "Usage: fax set debug { on | off }\n"
2307 " Enable/Disable FAX debugging on new FAX sessions. The basic FAX debugging will result in\n"
2308 " additional events sent to manager sessions with 'call' class permissions. When\n"
2309 " verbosity is greater than '5' events will be displayed to the console and audio versus\n"
2310 " energy analysis will be performed and displayed to the console.\n";
2316 what = a->argv[e->args-1]; /* guaranteed to exist */
2317 if (!strcasecmp(what, "on")) {
2319 } else if (!strcasecmp(what, "off")) {
2322 return CLI_SHOWUSAGE;
2325 global_fax_debug = flag;
2326 ast_cli(a->fd, "\n\nFAX Debug %s\n\n", (flag) ? "Enabled" : "Disabled");
2331 /*! \brief display registered FAX capabilities */
2332 static char *cli_fax_show_capabilities(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2334 struct fax_module *fax;
2335 unsigned int num_modules = 0;
2339 e->command = "fax show capabilities";
2341 "Usage: fax show capabilities\n"
2342 " Shows the capabilities of the registered FAX technology modules\n";
2348 ast_cli(a->fd, "\n\nRegistered FAX Technology Modules:\n\n");
2349 AST_RWLIST_RDLOCK(&faxmodules);
2350 AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
2351 ast_cli(a->fd, "%-15s : %s\n%-15s : %s\n%-15s : ", "Type", fax->tech->type, "Description", fax->tech->description, "Capabilities");
2352 fax->tech->cli_show_capabilities(a->fd);
2355 AST_RWLIST_UNLOCK(&faxmodules);
2356 ast_cli(a->fd, "%d registered modules\n\n", num_modules);
2361 /*! \brief display global defaults and settings */
2362 static char *cli_fax_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2364 struct fax_module *fax;
2365 char modems[128] = "";
2369 e->command = "fax show settings";
2371 "Usage: fax show settings\n"
2372 " Show the global settings and defaults of both the FAX core and technology modules\n";
2378 ast_cli(a->fd, "FAX For Asterisk Settings:\n");
2379 ast_cli(a->fd, "\tECM: %s\n", general_options.ecm ? "Enabled" : "Disabled");
2380 ast_cli(a->fd, "\tStatus Events: %s\n", general_options.statusevents ? "On" : "Off");
2381 ast_cli(a->fd, "\tMinimum Bit Rate: %d\n", general_options.minrate);
2382 ast_cli(a->fd, "\tMaximum Bit Rate: %d\n", general_options.maxrate);
2383 ast_fax_modem_to_str(general_options.modems, modems, sizeof(modems));
2384 ast_cli(a->fd, "\tModem Modulations Allowed: %s\n", modems);
2385 ast_cli(a->fd, "\n\nFAX Technology Modules:\n\n");
2386 AST_RWLIST_RDLOCK(&faxmodules);
2387 AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
2388 ast_cli(a->fd, "%s (%s) Settings:\n", fax->tech->type, fax->tech->description);
2389 fax->tech->cli_show_settings(a->fd);
2391 AST_RWLIST_UNLOCK(&faxmodules);
2396 /*! \brief display details of a specified fax session */
2397 static char *cli_fax_show_session(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2399 struct ast_fax_session *s, tmp;
2403 e->command = "fax show session";
2405 "Usage: fax show session <session number>\n"
2406 " Shows status of the named FAX session\n";
2409 return fax_session_tab_complete(a);
2413 return CLI_SHOWUSAGE;
2416 if (sscanf(a->argv[3], "%d", &tmp.id) != 1) {
2417 ast_log(LOG_ERROR, "invalid session id: '%s'\n", a->argv[3]);
2418 return RESULT_SUCCESS;
2421 ast_cli(a->fd, "\nFAX Session Details:\n--------------------\n\n");
2422 s = ao2_find(faxregistry.container, &tmp, OBJ_POINTER);
2424 s->tech->cli_show_session(s, a->fd);
2427 ast_cli(a->fd, "\n\n");
2432 /*! \brief display fax stats */
2433 static char *cli_fax_show_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2435 struct fax_module *fax;
2439 e->command = "fax show stats";
2441 "Usage: fax show stats\n"
2442 " Shows a statistical summary of FAX transmissions\n";
2448 ast_cli(a->fd, "\nFAX Statistics:\n---------------\n\n");
2449 ast_cli(a->fd, "%-20.20s : %d\n", "Current Sessions", faxregistry.active_sessions);
2450 ast_cli(a->fd, "%-20.20s : %d\n", "Reserved Sessions", faxregistry.reserved_sessions);
2451 ast_cli(a->fd, "%-20.20s : %d\n", "Transmit Attempts", faxregistry.fax_tx_attempts);
2452 ast_cli(a->fd, "%-20.20s : %d\n", "Receive Attempts", faxregistry.fax_rx_attempts);
2453 ast_cli(a->fd, "%-20.20s : %d\n", "Completed FAXes", faxregistry.fax_complete);
2454 ast_cli(a->fd, "%-20.20s : %d\n", "Failed FAXes", faxregistry.fax_failures);
2455 AST_RWLIST_RDLOCK(&faxmodules);
2456 AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
2457 fax->tech->cli_show_stats(a->fd);
2459 AST_RWLIST_UNLOCK(&faxmodules);
2460 ast_cli(a->fd, "\n\n");
2465 /*! \brief display fax sessions */
2466 static char *cli_fax_show_sessions(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2468 struct ast_fax_session *s;
2469 struct ao2_iterator i;
2475 e->command = "fax show sessions";
2477 "Usage: fax show sessions\n"
2478 " Shows the current FAX sessions\n";
2484 ast_cli(a->fd, "\nCurrent FAX Sessions:\n\n");
2485 ast_cli(a->fd, "%-20.20s %-10.10s %-10.10s %-5.5s %-10.10s %-15.15s %-30.30s\n",
2486 "Channel", "Tech", "FAXID", "Type", "Operation", "State", "File(s)");
2487 i = ao2_iterator_init(faxregistry.container, 0);
2488 while ((s = ao2_iterator_next(&i))) {
2491 if (!(filenames = generate_filenames_string(s->details, "", ", "))) {
2492 ast_log(LOG_ERROR, "error printing filenames for 'fax show sessions' command");
2495 if (ao2_iterator_destroy != NULL) {
2496 ao2_iterator_destroy(&i);
2501 ast_cli(a->fd, "%-20.20s %-10.10s %-10d %-5.5s %-10.10s %-15.15s %-30s\n",
2502 s->channame, s->tech->type, s->id,
2503 (s->details->caps & AST_FAX_TECH_AUDIO) ? "G.711" : "T.38",
2504 (s->details->caps & AST_FAX_TECH_SEND) ? "send" : "receive",
2505 ast_fax_state_to_str(s->state), filenames);
2507 ast_free(filenames);
2511 if (ao2_iterator_destroy != NULL) {
2512 ao2_iterator_destroy(&i);
2514 session_count = ao2_container_count(faxregistry.container);
2515 ast_cli(a->fd, "\n%d FAX sessions\n\n", session_count);
2520 static struct ast_cli_entry fax_cli[] = {
2521 AST_CLI_DEFINE(cli_fax_show_version, "Show versions of FAX For Asterisk components"),
2522 AST_CLI_DEFINE(cli_fax_set_debug, "Enable/Disable FAX debugging on new FAX sessions"),
2523 AST_CLI_DEFINE(cli_fax_show_capabilities, "Show the capabilities of the registered FAX technology modules"),
2524 AST_CLI_DEFINE(cli_fax_show_settings, "Show the global settings and defaults of both the FAX core and technology modules"),
2525 AST_CLI_DEFINE(cli_fax_show_session, "Show the status of the named FAX sessions"),
2526 AST_CLI_DEFINE(cli_fax_show_sessions, "Show the current FAX sessions"),
2527 AST_CLI_DEFINE(cli_fax_show_stats, "Summarize FAX session history"),
2530 /*! \brief configure res_fax */
2531 static int set_config(const char *config_file)
2533 struct ast_config *cfg;
2534 struct ast_variable *v;
2535 struct ast_flags config_flags = { 0 };
2536 char modems[128] = "";
2539 general_options.minrate = RES_FAX_MINRATE;
2540 general_options.maxrate = RES_FAX_MAXRATE;
2541 general_options.statusevents = RES_FAX_STATUSEVENTS;
2542 general_options.modems = RES_FAX_MODEM;
2543 general_options.ecm = AST_FAX_OPTFLAG_TRUE;
2545 /* read configuration */
2546 if (!(cfg = ast_config_load2(config_file, "res_fax", config_flags))) {
2547 ast_log(LOG_NOTICE, "Configuration file '%s' not found, using default options.\n", config_file);
2550 if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
2551 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
2552 cfg = ast_config_load2(config_file, "res_fax", config_flags);
2555 /* create configuration */
2556 for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
2559 if (!strcasecmp(v->name, "minrate")) {
2560 ast_debug(3, "reading minrate '%s' from configuration file\n", v->value);
2561 if ((rate = fax_rate_str_to_int(v->value)) == 0) {
2562 ast_config_destroy(cfg);
2565 general_options.minrate = rate;
2566 } else if (!strcasecmp(v->name, "maxrate")) {
2567 ast_debug(3, "reading maxrate '%s' from configuration file\n", v->value);
2568 if ((rate = fax_rate_str_to_int(v->value)) == 0) {
2569 ast_config_destroy(cfg);
2572 general_options.maxrate = rate;
2573 } else if (!strcasecmp(v->name, "statusevents")) {
2574 ast_debug(3, "reading statusevents '%s' from configuration file\n", v->value);
2575 general_options.statusevents = ast_true(v->value);
2576 } else if (!strcasecmp(v->name, "ecm")) {
2577 ast_debug(3, "reading ecm '%s' from configuration file\n", v->value);
2578 general_options.ecm = ast_true(v->value);
2579 } else if ((!strcasecmp(v->name, "modem")) || (!strcasecmp(v->name, "modems"))) {
2580 general_options.modems = 0;
2581 update_modem_bits(&general_options.modems, v->value);
2585 ast_config_destroy(cfg);
2587 if (general_options.maxrate < general_options.minrate) {
2588 ast_log(LOG_ERROR, "maxrate %d is less than minrate %d\n", general_options.maxrate, general_options.minrate);
2592 if (check_modem_rate(general_options.modems, general_options.minrate)) {
2593 ast_fax_modem_to_str(general_options.modems, modems, sizeof(modems));
2594 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %d\n", modems, general_options.minrate);
2598 if (check_modem_rate(general_options.modems, general_options.maxrate)) {
2599 ast_fax_modem_to_str(general_options.modems, modems, sizeof(modems));
2600 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %d\n", modems, general_options.maxrate);
2607 /*! \brief FAXOPT read function returns the contents of a FAX option */
2608 static int acf_faxopt_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
2610 struct ast_fax_session_details *details = find_details(chan);
2615 ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s) because it has never been written.\n", chan->name, data);
2618 if (!strcasecmp(data, "ecm")) {
2619 ast_copy_string(buf, details->option.ecm ? "yes" : "no", len);
2620 } else if (!strcasecmp(data, "error")) {
2621 ast_copy_string(buf, details->error, len);
2622 } else if (!strcasecmp(data, "filename")) {
2623 if (AST_LIST_EMPTY(&details->documents)) {
2624 ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s) because it has never been written.\n", chan->name, data);
2627 ast_copy_string(buf, AST_LIST_FIRST(&details->documents)->filename, len);
2629 } else if (!strcasecmp(data, "filenames")) {
2630 if (AST_LIST_EMPTY(&details->documents)) {
2631 ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s) because it has never been written.\n", chan->name, data);
2633 } else if ((filenames = generate_filenames_string(details, "", ","))) {
2634 ast_copy_string(buf, filenames, len);
2635 ast_free(filenames);
2637 ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s), there was an error generating the filenames list.\n", chan->name, data);
2640 } else if (!strcasecmp(data, "headerinfo")) {
2641 ast_copy_string(buf, details->headerinfo, len);
2642 } else if (!strcasecmp(data, "localstationid")) {
2643 ast_copy_string(buf, details->localstationid, len);
2644 } else if (!strcasecmp(data, "maxrate")) {
2645 snprintf(buf, len, "%d", details->maxrate);
2646 } else if (!strcasecmp(data, "minrate")) {
2647 snprintf(buf, len, "%d", details->minrate);
2648 } else if (!strcasecmp(data, "pages")) {
2649 snprintf(buf, len, "%d", details->pages_transferred);
2650 } else if (!strcasecmp(data, "rate")) {
2651 ast_copy_string(buf, details->transfer_rate, len);
2652 } else if (!strcasecmp(data, "remotestationid")) {
2653 ast_copy_string(buf, details->remotestationid, len);
2654 } else if (!strcasecmp(data, "resolution")) {
2655 ast_copy_string(buf, details->resolution, len);
2656 } else if (!strcasecmp(data, "sessionid")) {
2657 snprintf(buf, len, "%d", details->id);
2658 } else if (!strcasecmp(data, "status")) {
2659 ast_copy_string(buf, details->result, len);
2660 } else if (!strcasecmp(data, "statusstr")) {
2661 ast_copy_string(buf, details->resultstr, len);
2662 } else if ((!strcasecmp(data, "modem")) || (!strcasecmp(data, "modems"))) {
2663 ast_fax_modem_to_str(details->modems, buf, len);
2665 ast_log(LOG_WARNING, "channel '%s' can't read FAXOPT(%s) because it is unhandled!\n", chan->name, data);
2668 ao2_ref(details, -1);
2673 /*! \brief FAXOPT write function modifies the contents of a FAX option */
2674 static int acf_faxopt_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
2677 struct ast_fax_session_details *details;
2679 if (!(details = find_or_create_details(chan))) {
2680 ast_log(LOG_WARNING, "channel '%s' can't set FAXOPT(%s) to '%s' because it failed to create a datastore.\n", chan->name, data, value);
2683 ast_debug(3, "channel '%s' setting FAXOPT(%s) to '%s'\n", chan->name, data, value);
2685 if (!strcasecmp(data, "ecm")) {
2686 const char *val = ast_skip_blanks(value);
2687 if (ast_true(val)) {
2688 details->option.ecm = AST_FAX_OPTFLAG_TRUE;
2689 } else if (ast_false(val)) {
2690 details->option.ecm = AST_FAX_OPTFLAG_FALSE;
2692 ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(ecm).\n", value);
2694 } else if (!strcasecmp(data, "headerinfo")) {
2695 ast_string_field_set(details, headerinfo, value);
2696 } else if (!strcasecmp(data, "localstationid")) {
2697 ast_string_field_set(details, localstationid, value);
2698 } else if (!strcasecmp(data, "maxrate")) {
2699 details->maxrate = fax_rate_str_to_int(value);
2700 if (!details->maxrate) {
2701 details->maxrate = ast_fax_maxrate();
2703 } else if (!strcasecmp(data, "minrate")) {
2704 details->minrate = fax_rate_str_to_int(value);
2705 if (!details->minrate) {
2706 details->minrate = ast_fax_minrate();
2708 } else if ((!strcasecmp(data, "modem")) || (!strcasecmp(data, "modems"))) {
2709 update_modem_bits(&details->modems, value);
2711 ast_log(LOG_WARNING, "channel '%s' set FAXOPT(%s) to '%s' is unhandled!\n", chan->name, data, value);
2715 ao2_ref(details, -1);
2720 /*! \brief FAXOPT dialplan function */
2721 struct ast_custom_function acf_faxopt = {
2723 .read = acf_faxopt_read,
2724 .write = acf_faxopt_write,
2727 /*! \brief unload res_fax */
2728 static int unload_module(void)
2730 ast_cli_unregister_multiple(fax_cli, ARRAY_LEN(fax_cli));
2732 if (ast_custom_function_unregister(&acf_faxopt) < 0) {
2733 ast_log(LOG_WARNING, "failed to unregister function '%s'\n", acf_faxopt.name);
2736 if (ast_unregister_application(app_sendfax) < 0) {
2737 ast_log(LOG_WARNING, "failed to unregister '%s'\n", app_sendfax);
2740 if (ast_unregister_application(app_receivefax) < 0) {
2741 ast_log(LOG_WARNING, "failed to unregister '%s'\n", app_receivefax);
2744 if (fax_logger_level != -1) {
2745 ast_logger_unregister_level("FAX");
2748 ao2_ref(faxregistry.container, -1);
2753 /*! \brief load res_fax */
2754 static int load_module(void)
2758 /* initialize the registry */
2759 faxregistry.active_sessions = 0;
2760 faxregistry.reserved_sessions = 0;
2761 if (!(faxregistry.container = ao2_container_alloc(FAX_MAXBUCKETS, session_hash_cb, session_cmp_cb))) {
2762 return AST_MODULE_LOAD_DECLINE;
2765 if (set_config(config) < 0) {
2766 ast_log(LOG_ERROR, "failed to load configuration file '%s'\n", config);
2767 ao2_ref(faxregistry.container, -1);
2768 return AST_MODULE_LOAD_DECLINE;
2771 /* register CLI operations and applications */
2772 if (ast_register_application_xml(app_sendfax, sendfax_exec) < 0) {
2773 ast_log(LOG_WARNING, "failed to register '%s'.\n", app_sendfax);
2774 ao2_ref(faxregistry.container, -1);
2775 return AST_MODULE_LOAD_DECLINE;
2777 if (ast_register_application_xml(app_receivefax, receivefax_exec) < 0) {
2778 ast_log(LOG_WARNING, "failed to register '%s'.\n", app_receivefax);
2779 ast_unregister_application(app_sendfax);
2780 ao2_ref(faxregistry.container, -1);
2781 return AST_MODULE_LOAD_DECLINE;
2783 ast_cli_register_multiple(fax_cli, ARRAY_LEN(fax_cli));
2784 res = ast_custom_function_register(&acf_faxopt);
2785 fax_logger_level = ast_logger_register_level("FAX");
2791 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "Generic FAX Applications",
2792 .load = load_module,
2793 .unload = unload_module,
2794 .load_pri = AST_MODPRI_APP_DEPEND,