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>
8 * Matthew Nicholson <mnicholson@digium.com>
10 * Initial T.38-gateway code
11 * 2008, Daniel Ferenci <daniel.ferenci@nethemba.com>
12 * Created by Nethemba s.r.o. http://www.nethemba.com
13 * Sponsored by IPEX a.s. http://www.ipex.cz
15 * T.38-gateway integration into asterisk app_fax and rework
16 * 2008-2011, Gregory Hinton Nietsky <gregory@distrotech.co.za>
17 * dns Telecom http://www.dnstelecom.co.za
19 * Modified to make T.38-gateway compatible with Asterisk 1.6.2
20 * 2010, Anton Verevkin <mymail@verevkin.it>
21 * ViaNetTV http://www.vianettv.com
23 * Modified to make T.38-gateway work
24 * 2010, Klaus Darilion, IPCom GmbH, www.ipcom.at
26 * See http://www.asterisk.org for more information about
27 * the Asterisk project. Please do not directly contact
28 * any of the maintainers of this project for assistance;
29 * the project provides a web site, mailing lists and IRC
30 * channels for your use.
32 * This program is free software, distributed under the terms of
33 * the GNU General Public License Version 2. See the LICENSE file
34 * at the top of the source tree.
38 <conflict>app_fax</conflict>
39 <support_level>core</support_level>
44 * \brief Generic FAX Resource for FAX technology resource modules
46 * \author Dwayne M. Hubbard <dhubbard@digium.com>
47 * \author Kevin P. Fleming <kpfleming@digium.com>
48 * \author Matthew Nicholson <mnicholson@digium.com>
49 * \author Gregory H. Nietsky <gregory@distrotech.co.za>
51 * A generic FAX resource module that provides SendFAX and ReceiveFAX applications.
52 * This module requires FAX technology modules, like res_fax_spandsp, to register with it
53 * so it can use the technology modules to perform the actual FAX transmissions.
54 * \ingroup applications
57 /*! \li \ref res_fax.c uses the configuration file \ref res_fax.conf
58 * \addtogroup configuration_file Configuration Files
62 * \page res_fax.conf res_fax.conf
63 * \verbinclude res_fax.conf.sample
68 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
70 #include "asterisk/io.h"
71 #include "asterisk/file.h"
72 #include "asterisk/logger.h"
73 #include "asterisk/module.h"
74 #include "asterisk/app.h"
75 #include "asterisk/lock.h"
76 #include "asterisk/options.h"
77 #include "asterisk/strings.h"
78 #include "asterisk/cli.h"
79 #include "asterisk/utils.h"
80 #include "asterisk/config.h"
81 #include "asterisk/astobj2.h"
82 #include "asterisk/res_fax.h"
83 #include "asterisk/file.h"
84 #include "asterisk/channel.h"
85 #include "asterisk/pbx.h"
86 #include "asterisk/manager.h"
87 #include "asterisk/dsp.h"
88 #include "asterisk/indications.h"
89 #include "asterisk/ast_version.h"
90 #include "asterisk/translate.h"
93 <application name="ReceiveFAX" language="en_US" module="res_fax">
95 Receive a FAX and save as a TIFF/F file.
98 <parameter name="filename" required="true" />
99 <parameter name="options">
102 <para>Enable FAX debugging.</para>
105 <para>Allow audio fallback FAX transfer on T.38 capable channels.</para>
108 <para>Force usage of audio mode on T.38 capable channels.</para>
111 <para>Send progress Manager events (overrides statusevents setting in res_fax.conf).</para>
117 <para>This application is provided by res_fax, which is a FAX technology agnostic module
118 that utilizes FAX technology resource modules to complete a FAX transmission.</para>
119 <para>Session arguments can be set by the FAXOPT function and to check results of the ReceiveFax() application.</para>
122 <ref type="function">FAXOPT</ref>
125 <application name="SendFAX" language="en_US" module="res_fax">
127 Sends a specified TIFF/F file as a FAX.
130 <parameter name="filename" required="true" argsep="&">
131 <argument name="filename2" multiple="true">
132 <para>TIFF file to send as a FAX.</para>
135 <parameter name="options">
138 <para>Enable FAX debugging.</para>
141 <para>Allow audio fallback FAX transfer on T.38 capable channels.</para>
144 <para>Force usage of audio mode on T.38 capable channels.</para>
147 <para>Send progress Manager events (overrides statusevents setting in res_fax.conf).</para>
150 <para>Initiate a T.38 reinvite on the channel if the remote end does not.</para>
156 <para>This application is provided by res_fax, which is a FAX technology agnostic module
157 that utilizes FAX technology resource modules to complete a FAX transmission.</para>
158 <para>Session arguments can be set by the FAXOPT function and to check results of the SendFax() application.</para>
161 <ref type="function">FAXOPT</ref>
164 <function name="FAXOPT" language="en_US" module="res_fax">
166 Gets/sets various pieces of information about a fax session.
169 <parameter name="item" required="true">
172 <para>R/W Error Correction Mode (ECM) enable with 'yes', disable with 'no'.</para>
175 <para>R/O FAX transmission error code upon failure.</para>
177 <enum name="filename">
178 <para>R/O Filename of the first file of the FAX transmission.</para>
180 <enum name="filenames">
181 <para>R/O Filenames of all of the files in the FAX transmission (comma separated).</para>
183 <enum name="headerinfo">
184 <para>R/W FAX header information.</para>
186 <enum name="localstationid">
187 <para>R/W Local Station Identification.</para>
189 <enum name="minrate">
190 <para>R/W Minimum transfer rate set before transmission.</para>
192 <enum name="maxrate">
193 <para>R/W Maximum transfer rate set before transmission.</para>
196 <para>R/W Modem type (v17/v27/v29).</para>
198 <enum name="gateway">
199 <para>R/W T38 fax gateway, with optional fax activity timeout in seconds (yes[,timeout]/no)</para>
201 <enum name="faxdetect">
202 <para>R/W Enable FAX detect with optional timeout in seconds (yes,t38,cng[,timeout]/no)</para>
205 <para>R/O Number of pages transferred.</para>
208 <para>R/O Negotiated transmission rate.</para>
210 <enum name="remotestationid">
211 <para>R/O Remote Station Identification after transmission.</para>
213 <enum name="resolution">
214 <para>R/O Negotiated image resolution after transmission.</para>
216 <enum name="sessionid">
217 <para>R/O Session ID of the FAX transmission.</para>
220 <para>R/O Result Status of the FAX transmission.</para>
222 <enum name="statusstr">
223 <para>R/O Verbose Result Status of the FAX transmission.</para>
229 <para>FAXOPT can be used to override the settings for a FAX session listed in <filename>res_fax.conf</filename>,
230 it can also be used to retreive information about a FAX session that has finished eg. pages/status.</para>
233 <ref type="application">ReceiveFax</ref>
234 <ref type="application">SendFax</ref>
239 static const char app_receivefax[] = "ReceiveFAX";
240 static const char app_sendfax[] = "SendFAX";
242 struct debug_info_history {
243 unsigned int consec_frames;
244 unsigned int consec_ms;
245 unsigned char silence;
248 struct ast_fax_debug_info {
249 struct timeval base_tv;
250 struct debug_info_history c2s, s2c;
254 /*! \brief used for gateway framehook */
256 /*! \brief FAX Session */
257 struct ast_fax_session *s;
258 struct ast_fax_session *peer_v21_session;
259 struct ast_fax_session *chan_v21_session;
260 /*! \brief reserved fax session token */
261 struct ast_fax_tech_token *token;
262 /*! \brief the start of our timeout counter */
263 struct timeval timeout_start;
264 /*! \brief framehook used in gateway mode */
266 /*! \brief bridged */
268 /*! \brief 1 if a v21 preamble has been detected */
270 /*! \brief a flag to track the state of our negotiation */
271 enum ast_t38_state t38_state;
272 /*! \brief original audio formats */
273 struct ast_format chan_read_format;
274 struct ast_format chan_write_format;
275 struct ast_format peer_read_format;
276 struct ast_format peer_write_format;
279 /*! \brief used for fax detect framehook */
281 /*! \brief the start of our timeout counter */
282 struct timeval timeout_start;
283 /*! \brief faxdetect timeout */
285 /*! \brief DSP Processor */
287 /*! \brief original audio formats */
288 struct ast_format orig_format;
289 /*! \brief fax session details */
290 struct ast_fax_session_details *details;
295 /*! \brief FAX Detect flags */
296 #define FAX_DETECT_MODE_CNG (1 << 0)
297 #define FAX_DETECT_MODE_T38 (1 << 1)
298 #define FAX_DETECT_MODE_BOTH (FAX_DETECT_MODE_CNG | FAX_DETECT_MODE_T38)
300 static int fax_logger_level = -1;
302 /*! \brief maximum buckets for res_fax ao2 containers */
303 #define FAX_MAXBUCKETS 10
305 #define RES_FAX_TIMEOUT 10000
306 #define FAX_GATEWAY_TIMEOUT RES_FAX_TIMEOUT
308 /*! \brief The faxregistry is used to manage information and statistics for all FAX sessions. */
310 /*! The number of active FAX sessions */
312 /*! The number of reserved FAX sessions */
313 int reserved_sessions;
314 /*! active sessions are astobj2 objects */
315 struct ao2_container *container;
316 /*! Total number of Tx FAX attempts */
318 /*! Total number of Rx FAX attempts */
320 /*! Number of successful FAX transmissions */
322 /*! Number of failed FAX transmissions */
324 /*! the next unique session name */
328 /*! \brief registered FAX technology modules are put into this list */
330 const struct ast_fax_tech *tech;
331 AST_RWLIST_ENTRY(fax_module) list;
333 static AST_RWLIST_HEAD_STATIC(faxmodules, fax_module);
335 #define RES_FAX_MINRATE 2400
336 #define RES_FAX_MAXRATE 14400
337 #define RES_FAX_STATUSEVENTS 0
338 #define RES_FAX_MODEM (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V27 | AST_FAX_MODEM_V29)
341 enum ast_fax_modems modems;
342 uint32_t statusevents:1;
344 unsigned int minrate;
345 unsigned int maxrate;
348 static struct fax_options general_options;
350 static const struct fax_options default_options = {
351 .minrate = RES_FAX_MINRATE,
352 .maxrate = RES_FAX_MAXRATE,
353 .statusevents = RES_FAX_STATUSEVENTS,
354 .modems = RES_FAX_MODEM,
355 .ecm = AST_FAX_OPTFLAG_TRUE,
358 AST_RWLOCK_DEFINE_STATIC(options_lock);
360 static void get_general_options(struct fax_options* options);
361 static void set_general_options(const struct fax_options* options);
363 static const char *config = "res_fax.conf";
365 static int global_fax_debug = 0;
368 OPT_CALLEDMODE = (1 << 0),
369 OPT_CALLERMODE = (1 << 1),
370 OPT_DEBUG = (1 << 2),
371 OPT_STATUS = (1 << 3),
372 OPT_ALLOWAUDIO = (1 << 5),
373 OPT_REQUEST_T38 = (1 << 6),
374 OPT_FORCE_AUDIO = (1 << 7),
377 AST_APP_OPTIONS(fax_exec_options, BEGIN_OPTIONS
378 AST_APP_OPTION('a', OPT_CALLEDMODE),
379 AST_APP_OPTION('c', OPT_CALLERMODE),
380 AST_APP_OPTION('d', OPT_DEBUG),
381 AST_APP_OPTION('f', OPT_ALLOWAUDIO),
382 AST_APP_OPTION('F', OPT_FORCE_AUDIO),
383 AST_APP_OPTION('s', OPT_STATUS),
384 AST_APP_OPTION('z', OPT_REQUEST_T38),
387 struct manager_event_info {
388 char context[AST_MAX_CONTEXT];
389 char exten[AST_MAX_EXTENSION];
393 static void debug_check_frame_for_silence(struct ast_fax_session *s, unsigned int c2s, struct ast_frame *frame)
395 struct debug_info_history *history = c2s ? &s->debug_info->c2s : &s->debug_info->s2c;
397 unsigned int last_consec_frames, last_consec_ms;
398 unsigned char wassil;
401 diff = ast_tvsub(ast_tvnow(), s->debug_info->base_tv);
403 ast_dsp_reset(s->debug_info->dsp);
404 ast_dsp_silence(s->debug_info->dsp, frame, &dspsilence);
406 wassil = history->silence;
407 history->silence = (dspsilence != 0) ? 1 : 0;
408 if (history->silence != wassil) {
409 last_consec_frames = history->consec_frames;
410 last_consec_ms = history->consec_ms;
411 history->consec_frames = 0;
412 history->consec_ms = 0;
414 if ((last_consec_frames != 0)) {
415 ast_verb(6, "Channel '%s' fax session '%d', [ %.3ld.%.6ld ], %s sent %d frames (%d ms) of %s.\n",
416 s->channame, s->id, (long) diff.tv_sec, (long int) diff.tv_usec,
417 (c2s) ? "channel" : "stack", last_consec_frames, last_consec_ms,
418 (wassil) ? "silence" : "energy");
422 history->consec_frames++;
423 history->consec_ms += (frame->samples / 8);
426 static void destroy_callback(void *data)
433 static const struct ast_datastore_info fax_datastore = {
435 .destroy = destroy_callback,
438 /*! \brief returns a reference counted pointer to a fax datastore, if it exists */
439 static struct ast_fax_session_details *find_details(struct ast_channel *chan)
441 struct ast_fax_session_details *details;
442 struct ast_datastore *datastore;
444 ast_channel_lock(chan);
445 if (!(datastore = ast_channel_datastore_find(chan, &fax_datastore, NULL))) {
446 ast_channel_unlock(chan);
449 if (!(details = datastore->data)) {
450 ast_log(LOG_WARNING, "Huh? channel '%s' has a FAX datastore without data!\n", ast_channel_name(chan));
451 ast_channel_unlock(chan);
455 ast_channel_unlock(chan);
460 /*! \brief destroy a FAX session details structure */
461 static void destroy_session_details(void *details)
463 struct ast_fax_session_details *d = details;
464 struct ast_fax_document *doc;
466 while ((doc = AST_LIST_REMOVE_HEAD(&d->documents, next))) {
469 ast_string_field_free_memory(d);
472 /*! \brief create a FAX session details structure */
473 static struct ast_fax_session_details *session_details_new(void)
475 struct ast_fax_session_details *d;
476 struct fax_options options;
478 if (!(d = ao2_alloc(sizeof(*d), destroy_session_details))) {
482 if (ast_string_field_init(d, 512)) {
487 get_general_options(&options);
489 AST_LIST_HEAD_INIT_NOLOCK(&d->documents);
491 /* These options need to be set to the configured default and may be overridden by
492 * SendFAX, ReceiveFAX, or FAXOPT */
493 d->option.request_t38 = AST_FAX_OPTFLAG_FALSE;
494 d->option.send_cng = AST_FAX_OPTFLAG_FALSE;
495 d->option.send_ced = AST_FAX_OPTFLAG_FALSE;
496 d->option.ecm = options.ecm;
497 d->option.statusevents = options.statusevents;
498 d->modems = options.modems;
499 d->minrate = options.minrate;
500 d->maxrate = options.maxrate;
502 d->faxdetect_id = -1;
503 d->gateway_timeout = 0;
508 static struct ast_control_t38_parameters our_t38_parameters = {
511 .rate = AST_T38_RATE_14400,
512 .rate_management = AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF,
515 static void t38_parameters_ast_to_fax(struct ast_fax_t38_parameters *dst, const struct ast_control_t38_parameters *src)
517 dst->version = src->version;
518 dst->max_ifp = src->max_ifp;
519 dst->rate = src->rate;
520 dst->rate_management = src->rate_management;
521 dst->fill_bit_removal = src->fill_bit_removal;
522 dst->transcoding_mmr = src->transcoding_mmr;
523 dst->transcoding_jbig = src->transcoding_jbig;
526 static void t38_parameters_fax_to_ast(struct ast_control_t38_parameters *dst, const struct ast_fax_t38_parameters *src)
528 dst->version = src->version;
529 dst->max_ifp = src->max_ifp;
530 dst->rate = src->rate;
531 dst->rate_management = src->rate_management;
532 dst->fill_bit_removal = src->fill_bit_removal;
533 dst->transcoding_mmr = src->transcoding_mmr;
534 dst->transcoding_jbig = src->transcoding_jbig;
537 /*! \brief returns a reference counted details structure from the channel's fax datastore. If the datastore
538 * does not exist it will be created */
539 static struct ast_fax_session_details *find_or_create_details(struct ast_channel *chan)
541 struct ast_fax_session_details *details;
542 struct ast_datastore *datastore;
544 if ((details = find_details(chan))) {
547 /* channel does not have one so we must create one */
548 if (!(details = session_details_new())) {
549 ast_log(LOG_WARNING, "channel '%s' can't get a FAX details structure for the datastore!\n", ast_channel_name(chan));
552 if (!(datastore = ast_datastore_alloc(&fax_datastore, NULL))) {
553 ao2_ref(details, -1);
554 ast_log(LOG_WARNING, "channel '%s' can't get a datastore!\n", ast_channel_name(chan));
557 /* add the datastore to the channel and increment the refcount */
558 datastore->data = details;
560 /* initialize default T.38 parameters */
561 t38_parameters_ast_to_fax(&details->our_t38_parameters, &our_t38_parameters);
562 t38_parameters_ast_to_fax(&details->their_t38_parameters, &our_t38_parameters);
565 ast_channel_lock(chan);
566 ast_channel_datastore_add(chan, datastore);
567 ast_channel_unlock(chan);
571 unsigned int ast_fax_maxrate(void)
573 struct fax_options options;
574 get_general_options(&options);
576 return options.maxrate;
579 unsigned int ast_fax_minrate(void)
581 struct fax_options options;
582 get_general_options(&options);
584 return options.minrate;
587 static int update_modem_bits(enum ast_fax_modems *bits, const char *value)
589 char *m[5], *tok, *v = (char *)value;
592 if (!strchr(v, ',')) {
596 tok = strtok(v, ", ");
597 while (tok && (i < 5)) {
599 tok = strtok(NULL, ", ");
605 for (j = 0; j < i; j++) {
606 if (!strcasecmp(m[j], "v17")) {
607 *bits |= AST_FAX_MODEM_V17;
608 } else if (!strcasecmp(m[j], "v27")) {
609 *bits |= AST_FAX_MODEM_V27;
610 } else if (!strcasecmp(m[j], "v29")) {
611 *bits |= AST_FAX_MODEM_V29;
612 } else if (!strcasecmp(m[j], "v34")) {
613 *bits |= AST_FAX_MODEM_V34;
615 ast_log(LOG_WARNING, "ignoring invalid modem setting: '%s', valid options {v17 | v27 | v29 | v34}\n", m[j]);
620 static char *ast_fax_caps_to_str(enum ast_fax_capabilities caps, char *buf, size_t bufsize)
623 size_t size = bufsize;
626 if (caps & AST_FAX_TECH_SEND) {
628 ast_build_string(&buf, &size, ",");
630 ast_build_string(&buf, &size, "SEND");
633 if (caps & AST_FAX_TECH_RECEIVE) {
635 ast_build_string(&buf, &size, ",");
637 ast_build_string(&buf, &size, "RECEIVE");
640 if (caps & AST_FAX_TECH_AUDIO) {
642 ast_build_string(&buf, &size, ",");
644 ast_build_string(&buf, &size, "AUDIO");
647 if (caps & AST_FAX_TECH_T38) {
649 ast_build_string(&buf, &size, ",");
651 ast_build_string(&buf, &size, "T38");
654 if (caps & AST_FAX_TECH_MULTI_DOC) {
656 ast_build_string(&buf, &size, ",");
658 ast_build_string(&buf, &size, "MULTI_DOC");
661 if (caps & AST_FAX_TECH_GATEWAY) {
663 ast_build_string(&buf, &size, ",");
665 ast_build_string(&buf, &size, "GATEWAY");
668 if (caps & AST_FAX_TECH_V21_DETECT) {
670 ast_build_string(&buf, &size, ",");
672 ast_build_string(&buf, &size, "V21");
679 static int ast_fax_modem_to_str(enum ast_fax_modems bits, char *tbuf, size_t bufsize)
683 if (bits & AST_FAX_MODEM_V17) {
687 if (bits & AST_FAX_MODEM_V27) {
694 if (bits & AST_FAX_MODEM_V29) {
701 if (bits & AST_FAX_MODEM_V34) {
712 static int check_modem_rate(enum ast_fax_modems modems, unsigned int rate)
716 if (!(modems & (AST_FAX_MODEM_V27 | AST_FAX_MODEM_V34))) {
721 if (!(modems & (AST_FAX_MODEM_V27 | AST_FAX_MODEM_V34))) {
727 if (!(modems & (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V29 | AST_FAX_MODEM_V34))) {
733 if (!(modems & (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V34))) {
739 if (!(modems & AST_FAX_MODEM_V34)) {
744 /* this should never happen */
751 /*! \brief register a FAX technology module */
752 int ast_fax_tech_register(struct ast_fax_tech *tech)
754 struct fax_module *fax;
756 if (!(fax = ast_calloc(1, sizeof(*fax)))) {
760 AST_RWLIST_WRLOCK(&faxmodules);
761 AST_RWLIST_INSERT_TAIL(&faxmodules, fax, list);
762 AST_RWLIST_UNLOCK(&faxmodules);
763 ast_module_ref(ast_module_info->self);
765 ast_verb(3, "Registered handler for '%s' (%s)\n", fax->tech->type, fax->tech->description);
770 /*! \brief unregister a FAX technology module */
771 void ast_fax_tech_unregister(struct ast_fax_tech *tech)
773 struct fax_module *fax;
775 ast_verb(3, "Unregistering FAX module type '%s'\n", tech->type);
777 AST_RWLIST_WRLOCK(&faxmodules);
778 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&faxmodules, fax, list) {
779 if (fax->tech != tech) {
782 AST_RWLIST_REMOVE_CURRENT(list);
783 ast_module_unref(ast_module_info->self);
785 ast_verb(4, "Unregistered FAX module type '%s'\n", tech->type);
788 AST_RWLIST_TRAVERSE_SAFE_END;
789 AST_RWLIST_UNLOCK(&faxmodules);
792 /*! \brief convert a ast_fax_state to a string */
793 const char *ast_fax_state_to_str(enum ast_fax_state state)
796 case AST_FAX_STATE_UNINITIALIZED:
797 return "Uninitialized";
798 case AST_FAX_STATE_INITIALIZED:
799 return "Initialized";
800 case AST_FAX_STATE_OPEN:
802 case AST_FAX_STATE_ACTIVE:
804 case AST_FAX_STATE_COMPLETE:
806 case AST_FAX_STATE_RESERVED:
808 case AST_FAX_STATE_INACTIVE:
811 ast_log(LOG_WARNING, "unhandled FAX state: %d\n", state);
816 void ast_fax_log(int level, const char *file, const int line, const char *function, const char *msg)
818 if (fax_logger_level != -1) {
819 ast_log_dynamic_level(fax_logger_level, "%s", msg);
821 ast_log(level, file, line, function, "%s", msg);
825 /*! \brief convert a rate string to a rate */
826 static unsigned int fax_rate_str_to_int(const char *ratestr)
830 if (sscanf(ratestr, "%d", &rate) != 1) {
831 ast_log(LOG_ERROR, "failed to sscanf '%s' to rate\n", ratestr);
845 ast_log(LOG_WARNING, "ignoring invalid rate '%s'. Valid options are {2400 | 4800 | 7200 | 9600 | 12000 | 14400 | 28800 | 33600}\n", ratestr);
850 /*! \brief Release a session token.
851 * \param s a session returned from fax_session_reserve()
852 * \param token a token generated from fax_session_reserve()
854 * This function releases the given token and marks the given session as no
855 * longer reserved. It is safe to call on a session that is not actually
856 * reserved and with a NULL token. This is so that sessions returned by
857 * technologies that do not support reserved sessions don't require extra logic
860 * \note This function DOES NOT release the given fax session, only the given
863 static void fax_session_release(struct ast_fax_session *s, struct ast_fax_tech_token *token)
866 s->tech->release_token(token);
869 if (s->state == AST_FAX_STATE_RESERVED) {
870 ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, -1);
871 s->state = AST_FAX_STATE_INACTIVE;
875 /*! \brief destroy a FAX session structure */
876 static void destroy_session(void *session)
878 struct ast_fax_session *s = session;
881 fax_session_release(s, NULL);
883 s->tech->destroy_session(s);
885 ast_module_unref(s->tech->module);
889 if (s->details->caps & AST_FAX_TECH_GATEWAY) {
890 s->details->caps &= ~AST_FAX_TECH_GATEWAY;
892 ao2_ref(s->details, -1);
896 ast_dsp_free(s->debug_info->dsp);
897 ast_free(s->debug_info);
901 ast_smoother_free(s->smoother);
904 if (s->state != AST_FAX_STATE_INACTIVE) {
905 ast_atomic_fetchadd_int(&faxregistry.active_sessions, -1);
908 ast_free(s->channame);
909 ast_free(s->chan_uniqueid);
912 /*! \brief Reserve a fax session.
913 * \param details the fax session details
914 * \param token a pointer to a place to store a token to be passed to fax_session_new() later
916 * This function reserves a fax session for use later. If the selected fax
917 * technology does not support reserving sessions a session will still be
918 * returned but token will not be set.
920 * \note The reference returned by this function does not get consumed by
921 * fax_session_new() and must always be dereferenced separately.
923 * \return NULL or an uninitialized and possibly reserved session
925 static struct ast_fax_session *fax_session_reserve(struct ast_fax_session_details *details, struct ast_fax_tech_token **token)
927 struct ast_fax_session *s;
928 struct fax_module *faxmod;
930 if (!(s = ao2_alloc(sizeof(*s), destroy_session))) {
934 s->state = AST_FAX_STATE_INACTIVE;
935 s->details = details;
936 ao2_ref(s->details, 1);
938 /* locate a FAX technology module that can handle said requirements
939 * Note: the requirements have not yet been finalized as T.38
940 * negotiation has not yet occured. */
941 AST_RWLIST_RDLOCK(&faxmodules);
942 AST_RWLIST_TRAVERSE(&faxmodules, faxmod, list) {
943 if ((faxmod->tech->caps & details->caps) != details->caps) {
946 ast_debug(4, "Reserving a FAX session from '%s'.\n", faxmod->tech->description);
947 ast_module_ref(faxmod->tech->module);
948 s->tech = faxmod->tech;
951 AST_RWLIST_UNLOCK(&faxmodules);
955 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)));
960 if (!s->tech->reserve_session) {
961 ast_debug(1, "Selected FAX technology module (%s) does not support reserving sessions.\n", s->tech->description);
965 if (!(*token = s->tech->reserve_session(s))) {
970 s->state = AST_FAX_STATE_RESERVED;
971 ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, 1);
976 /*! \brief create a FAX session
978 * \param details details for the session
979 * \param chan the channel the session will run on
980 * \param reserved a reserved session to base this session on (can be NULL)
981 * \param token the token for a reserved session (can be NULL)
983 * Create a new fax session based on the given details structure.
985 * \note The given token is always consumed (by tech->new_session() or by
986 * fax_session_release() in the event of a failure). The given reference to a
987 * reserved session is never consumed and must be dereferenced separately from
988 * the reference returned by this function.
990 * \return NULL or a reference to a new fax session
992 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)
994 struct ast_fax_session *s = NULL;
995 struct fax_module *faxmod;
999 ao2_ref(reserved, +1);
1001 /* NOTE: we don't consume the reference to the reserved
1002 * session. The session returned from fax_session_new() is a
1003 * new reference and must be derefed in addition to the
1007 if (s->state == AST_FAX_STATE_RESERVED) {
1008 ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, -1);
1009 s->state = AST_FAX_STATE_UNINITIALIZED;
1013 if (!s && !(s = ao2_alloc(sizeof(*s), destroy_session))) {
1017 ast_atomic_fetchadd_int(&faxregistry.active_sessions, 1);
1018 s->state = AST_FAX_STATE_UNINITIALIZED;
1020 if (details->option.debug && (details->caps & AST_FAX_TECH_AUDIO)) {
1021 if (!(s->debug_info = ast_calloc(1, sizeof(*(s->debug_info))))) {
1022 fax_session_release(s, token);
1026 if (!(s->debug_info->dsp = ast_dsp_new())) {
1027 ast_free(s->debug_info);
1028 s->debug_info = NULL;
1029 fax_session_release(s, token);
1033 ast_dsp_set_threshold(s->debug_info->dsp, 128);
1036 if (!(s->channame = ast_strdup(ast_channel_name(chan)))) {
1037 fax_session_release(s, token);
1042 if (!(s->chan_uniqueid = ast_strdup(ast_channel_uniqueid(chan)))) {
1043 fax_session_release(s, token);
1050 s->details = details;
1051 ao2_ref(s->details, 1);
1054 details->id = s->id = ast_atomic_fetchadd_int(&faxregistry.nextsessionname, 1);
1057 /* locate a FAX technology module that can handle said requirements */
1058 AST_RWLIST_RDLOCK(&faxmodules);
1059 AST_RWLIST_TRAVERSE(&faxmodules, faxmod, list) {
1060 if ((faxmod->tech->caps & details->caps) != details->caps) {
1063 ast_debug(4, "Requesting a new FAX session from '%s'.\n", faxmod->tech->description);
1064 ast_module_ref(faxmod->tech->module);
1065 s->tech = faxmod->tech;
1068 AST_RWLIST_UNLOCK(&faxmodules);
1071 char caps[128] = "";
1072 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)));
1078 if (!(s->tech_pvt = s->tech->new_session(s, token))) {
1079 ast_log(LOG_ERROR, "FAX session failed to initialize.\n");
1083 /* link the session to the session container */
1084 if (!(ao2_link(faxregistry.container, s))) {
1085 ast_log(LOG_ERROR, "failed to add FAX session '%d' to container.\n", s->id);
1089 ast_debug(4, "channel '%s' using FAX session '%d'\n", s->channame, s->id);
1094 static void get_manager_event_info(struct ast_channel *chan, struct manager_event_info *info)
1096 pbx_substitute_variables_helper(chan, "${CONTEXT}", info->context, sizeof(info->context));
1097 pbx_substitute_variables_helper(chan, "${EXTEN}", info->exten, sizeof(info->exten));
1098 pbx_substitute_variables_helper(chan, "${CALLERID(num)}", info->cid, sizeof(info->cid));
1102 /* \brief Generate a string of filenames using the given prefix and separator.
1103 * \param details the fax session details
1104 * \param prefix the prefix to each filename
1105 * \param separator the separator between filenames
1107 * This function generates a string of filenames from the given details
1108 * structure and using the given prefix and separator.
1110 * \retval NULL there was an error generating the string
1111 * \return the string generated string
1113 static char *generate_filenames_string(struct ast_fax_session_details *details, char *prefix, char *separator)
1115 char *filenames, *c;
1118 struct ast_fax_document *doc;
1120 /* don't process empty lists */
1121 if (AST_LIST_EMPTY(&details->documents)) {
1125 /* Calculate the total length of all of the file names */
1126 AST_LIST_TRAVERSE(&details->documents, doc, next) {
1127 size += strlen(separator) + strlen(prefix) + strlen(doc->filename);
1129 size += 1; /* add space for the terminating null */
1131 if (!(filenames = ast_malloc(size))) {
1136 ast_build_string(&c, &size, "%s%s", prefix, AST_LIST_FIRST(&details->documents)->filename);
1137 AST_LIST_TRAVERSE(&details->documents, doc, next) {
1143 ast_build_string(&c, &size, "%s%s%s", separator, prefix, doc->filename);
1149 /*! \brief send a FAX status manager event */
1150 static int report_fax_status(struct ast_channel *chan, struct ast_fax_session_details *details, const char *status)
1152 char *filenames = generate_filenames_string(details, "FileName: ", "\r\n");
1154 ast_channel_lock(chan);
1155 if (details->option.statusevents) {
1156 struct manager_event_info info;
1158 get_manager_event_info(chan, &info);
1159 manager_event(EVENT_FLAG_CALL,
1167 "LocalStationID: %s\r\n"
1169 (details->caps & AST_FAX_TECH_GATEWAY) ? "gateway" : (details->caps & AST_FAX_TECH_RECEIVE) ? "receive" : "send",
1171 ast_channel_name(chan),
1175 details->localstationid,
1176 S_OR(filenames, ""),
1177 filenames ? "\r\n" : "");
1179 ast_channel_unlock(chan);
1182 ast_free(filenames);
1188 /*! \brief Set fax related channel variables. */
1189 static void set_channel_variables(struct ast_channel *chan, struct ast_fax_session_details *details)
1192 pbx_builtin_setvar_helper(chan, "FAXSTATUS", S_OR(details->result, NULL));
1193 pbx_builtin_setvar_helper(chan, "FAXERROR", S_OR(details->error, NULL));
1194 pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", S_OR(details->resultstr, NULL));
1195 pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", S_OR(details->remotestationid, NULL));
1196 pbx_builtin_setvar_helper(chan, "LOCALSTATIONID", S_OR(details->localstationid, NULL));
1197 pbx_builtin_setvar_helper(chan, "FAXBITRATE", S_OR(details->transfer_rate, NULL));
1198 pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", S_OR(details->resolution, NULL));
1200 snprintf(buf, sizeof(buf), "%d", details->pages_transferred);
1201 pbx_builtin_setvar_helper(chan, "FAXPAGES", buf);
1204 #define GENERIC_FAX_EXEC_SET_VARS(fax, chan, errorstr, reason) \
1206 if (ast_strlen_zero(fax->details->result)) \
1207 ast_string_field_set(fax->details, result, "FAILED"); \
1208 if (ast_strlen_zero(fax->details->resultstr)) \
1209 ast_string_field_set(fax->details, resultstr, reason); \
1210 if (ast_strlen_zero(fax->details->error)) \
1211 ast_string_field_set(fax->details, error, errorstr); \
1212 set_channel_variables(chan, fax->details); \
1215 #define GENERIC_FAX_EXEC_ERROR_QUIET(fax, chan, errorstr, reason) \
1217 GENERIC_FAX_EXEC_SET_VARS(fax, chan, errorstr, reason); \
1220 #define GENERIC_FAX_EXEC_ERROR(fax, chan, errorstr, reason) \
1222 ast_log(LOG_ERROR, "channel '%s' FAX session '%d' failure, reason: '%s' (%s)\n", ast_channel_name(chan), fax->id, reason, errorstr); \
1223 GENERIC_FAX_EXEC_ERROR_QUIET(fax, chan, errorstr, reason); \
1226 static int set_fax_t38_caps(struct ast_channel *chan, struct ast_fax_session_details *details)
1228 switch (ast_channel_get_t38_state(chan)) {
1229 case T38_STATE_UNKNOWN:
1230 details->caps |= AST_FAX_TECH_T38;
1232 case T38_STATE_REJECTED:
1233 case T38_STATE_UNAVAILABLE:
1234 details->caps |= AST_FAX_TECH_AUDIO;
1236 case T38_STATE_NEGOTIATED:
1237 /* already in T.38 mode? This should not happen. */
1238 case T38_STATE_NEGOTIATING: {
1239 /* the other end already sent us a T.38 reinvite, so we need to prod the channel
1240 * driver into resending their parameters to us if it supports doing so... if
1241 * not, we can't proceed, because we can't create a proper reply without them.
1242 * if it does work, the channel driver will send an AST_CONTROL_T38_PARAMETERS
1243 * with a request of AST_T38_REQUEST_NEGOTIATE, which will be read by the function
1244 * that gets called after this one completes
1246 struct ast_control_t38_parameters parameters = { .request_response = AST_T38_REQUEST_PARMS, };
1247 if (ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, ¶meters, sizeof(parameters)) != AST_T38_REQUEST_PARMS) {
1248 ast_log(LOG_ERROR, "channel '%s' is in an unsupported T.38 negotiation state, cannot continue.\n", ast_channel_name(chan));
1251 details->caps |= AST_FAX_TECH_T38;
1255 ast_log(LOG_ERROR, "channel '%s' is in an unsupported T.38 negotiation state, cannot continue.\n", ast_channel_name(chan));
1262 static int disable_t38(struct ast_channel *chan)
1265 struct ast_frame *frame = NULL;
1266 struct ast_control_t38_parameters t38_parameters = { .request_response = AST_T38_REQUEST_TERMINATE, };
1267 struct timeval start;
1270 ast_debug(1, "Shutting down T.38 on %s\n", ast_channel_name(chan));
1271 if (ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0) {
1272 ast_debug(1, "error while disabling T.38 on channel '%s'\n", ast_channel_name(chan));
1276 /* wait up to five seconds for negotiation to complete */
1278 start = ast_tvnow();
1279 while ((ms = ast_remaining_ms(start, timeout_ms))) {
1280 ms = ast_waitfor(chan, ms);
1286 ast_debug(1, "error while disabling T.38 on channel '%s'\n", ast_channel_name(chan));
1290 if (!(frame = ast_read(chan))) {
1293 if ((frame->frametype == AST_FRAME_CONTROL) &&
1294 (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
1295 (frame->datalen == sizeof(t38_parameters))) {
1296 struct ast_control_t38_parameters *parameters = frame->data.ptr;
1298 switch (parameters->request_response) {
1299 case AST_T38_TERMINATED:
1300 ast_debug(1, "Shut down T.38 on %s\n", ast_channel_name(chan));
1302 case AST_T38_REFUSED:
1303 ast_log(LOG_WARNING, "channel '%s' refused to disable T.38\n", ast_channel_name(chan));
1307 ast_log(LOG_ERROR, "channel '%s' failed to disable T.38\n", ast_channel_name(chan));
1317 if (ms == 0) { /* all done, nothing happened */
1318 ast_debug(1, "channel '%s' timed-out during T.38 shutdown\n", ast_channel_name(chan));
1324 /*! \brief this is the generic FAX session handling function */
1325 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)
1328 int timeout = RES_FAX_TIMEOUT;
1330 unsigned int expected_frametype = -1;
1331 union ast_frame_subclass expected_framesubclass = { .integer = -1 };
1332 unsigned int t38negotiated = (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED);
1333 struct ast_control_t38_parameters t38_parameters;
1334 const char *tempvar;
1335 struct ast_fax_session *fax = NULL;
1336 struct ast_frame *frame = NULL;
1337 struct ast_channel *c = chan;
1338 struct ast_format orig_write_format;
1339 struct ast_format orig_read_format;
1341 struct timeval start;
1343 ast_format_clear(&orig_write_format);
1344 ast_format_clear(&orig_read_format);
1347 /* create the FAX session */
1348 if (!(fax = fax_session_new(details, chan, reserved, token))) {
1349 ast_log(LOG_ERROR, "Can't create a FAX session, FAX attempt failed.\n");
1350 report_fax_status(chan, details, "No Available Resource");
1354 ast_channel_lock(chan);
1355 /* update session details */
1356 if (ast_strlen_zero(details->headerinfo) && (tempvar = pbx_builtin_getvar_helper(chan, "LOCALHEADERINFO"))) {
1357 ast_string_field_set(details, headerinfo, tempvar);
1359 if (ast_strlen_zero(details->localstationid)) {
1360 tempvar = pbx_builtin_getvar_helper(chan, "LOCALSTATIONID");
1361 ast_string_field_set(details, localstationid, tempvar ? tempvar : "unknown");
1363 ast_channel_unlock(chan);
1365 report_fax_status(chan, details, "Allocating Resources");
1367 if (details->caps & AST_FAX_TECH_AUDIO) {
1368 expected_frametype = AST_FRAME_VOICE;;
1369 ast_format_set(&expected_framesubclass.format, AST_FORMAT_SLINEAR, 0);
1370 ast_format_copy(&orig_write_format, ast_channel_writeformat(chan));
1371 if (ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR) < 0) {
1372 ast_log(LOG_ERROR, "channel '%s' failed to set write format to signed linear'.\n", ast_channel_name(chan));
1373 ao2_lock(faxregistry.container);
1374 ao2_unlink(faxregistry.container, fax);
1375 ao2_unlock(faxregistry.container);
1377 ast_channel_unlock(chan);
1380 ast_format_copy(&orig_read_format, ast_channel_readformat(chan));
1381 if (ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR) < 0) {
1382 ast_log(LOG_ERROR, "channel '%s' failed to set read format to signed linear.\n", ast_channel_name(chan));
1383 ao2_lock(faxregistry.container);
1384 ao2_unlink(faxregistry.container, fax);
1385 ao2_unlock(faxregistry.container);
1387 ast_channel_unlock(chan);
1390 if (fax->smoother) {
1391 ast_smoother_free(fax->smoother);
1392 fax->smoother = NULL;
1394 if (!(fax->smoother = ast_smoother_new(320))) {
1395 ast_log(LOG_WARNING, "Channel '%s' FAX session '%d' failed to obtain a smoother.\n", ast_channel_name(chan), fax->id);
1398 expected_frametype = AST_FRAME_MODEM;
1399 expected_framesubclass.integer = AST_MODEM_T38;
1402 if (fax->debug_info) {
1403 fax->debug_info->base_tv = ast_tvnow();
1406 /* reset our result fields just in case the fax tech driver wants to
1407 * set custom error messages */
1408 ast_string_field_set(details, result, "");
1409 ast_string_field_set(details, resultstr, "");
1410 ast_string_field_set(details, error, "");
1411 set_channel_variables(chan, details);
1413 if (fax->tech->start_session(fax) < 0) {
1414 GENERIC_FAX_EXEC_ERROR(fax, chan, "INIT_ERROR", "failed to start FAX session");
1417 report_fax_status(chan, details, "FAX Transmission In Progress");
1419 ast_debug(5, "channel %s will wait on FAX fd %d\n", ast_channel_name(chan), fax->fd);
1421 /* handle frames for the session */
1422 remaining_time = timeout;
1423 start = ast_tvnow();
1424 while (remaining_time > 0) {
1425 struct ast_channel *ready_chan;
1430 ready_chan = ast_waitfor_nandfds(&c, chancount, &fax->fd, 1, &exception, &ofd, &ms);
1432 if (!(frame = ast_read(chan))) {
1433 /* the channel is probably gone, so lets stop polling on it and let the
1434 * FAX session complete before we exit the application. if needed,
1435 * send the FAX stack silence so the modems can finish their session without
1437 ast_debug(1, "Channel '%s' did not return a frame; probably hung up.\n", ast_channel_name(chan));
1438 GENERIC_FAX_EXEC_SET_VARS(fax, chan, "HANGUP", "remote channel hungup");
1441 remaining_time = ast_remaining_ms(start, timeout);
1442 fax->tech->cancel_session(fax);
1443 if (fax->tech->generate_silence) {
1444 fax->tech->generate_silence(fax);
1449 if ((frame->frametype == AST_FRAME_CONTROL) &&
1450 (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
1451 (frame->datalen == sizeof(t38_parameters))) {
1452 unsigned int was_t38 = t38negotiated;
1453 struct ast_control_t38_parameters *parameters = frame->data.ptr;
1455 switch (parameters->request_response) {
1456 case AST_T38_REQUEST_NEGOTIATE:
1457 /* the other end has requested a switch to T.38, so reply that we are willing, if we can
1460 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
1461 t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
1462 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
1464 case AST_T38_NEGOTIATED:
1465 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
1471 if (t38negotiated && !was_t38) {
1472 fax->tech->switch_to_t38(fax);
1473 details->caps &= ~AST_FAX_TECH_AUDIO;
1474 expected_frametype = AST_FRAME_MODEM;
1475 expected_framesubclass.integer = AST_MODEM_T38;
1476 if (fax->smoother) {
1477 ast_smoother_free(fax->smoother);
1478 fax->smoother = NULL;
1481 report_fax_status(chan, details, "T.38 Negotiated");
1483 ast_verb(3, "Channel '%s' switched to T.38 FAX session '%d'.\n", ast_channel_name(chan), fax->id);
1485 } else if ((frame->frametype == expected_frametype) &&
1486 (!memcmp(&frame->subclass, &expected_framesubclass, sizeof(frame->subclass)))) {
1487 struct ast_frame *f;
1489 if (fax->smoother) {
1490 /* push the frame into a smoother */
1491 if (ast_smoother_feed(fax->smoother, frame) < 0) {
1492 GENERIC_FAX_EXEC_ERROR(fax, chan, "UNKNOWN", "Failed to feed the smoother");
1494 while ((f = ast_smoother_read(fax->smoother)) && (f->data.ptr)) {
1495 if (fax->debug_info) {
1496 debug_check_frame_for_silence(fax, 1, f);
1498 /* write the frame to the FAX stack */
1499 fax->tech->write(fax, f);
1500 fax->frames_received++;
1506 /* write the frame to the FAX stack */
1507 fax->tech->write(fax, frame);
1508 fax->frames_received++;
1510 start = ast_tvnow();
1513 } else if (ofd == fax->fd) {
1514 /* read a frame from the FAX stack and send it out the channel.
1515 * the FAX stack will return a NULL if the FAX session has already completed */
1516 if (!(frame = fax->tech->read(fax))) {
1520 if (fax->debug_info && (frame->frametype == AST_FRAME_VOICE)) {
1521 debug_check_frame_for_silence(fax, 0, frame);
1524 ast_write(chan, frame);
1527 start = ast_tvnow();
1529 if (ms && (ofd < 0)) {
1530 if ((errno == 0) || (errno == EINTR)) {
1531 remaining_time = ast_remaining_ms(start, timeout);
1532 if (remaining_time <= 0)
1533 GENERIC_FAX_EXEC_ERROR(fax, chan, "TIMEOUT", "fax session timed-out");
1536 ast_log(LOG_WARNING, "something bad happened while channel '%s' was polling.\n", ast_channel_name(chan));
1537 GENERIC_FAX_EXEC_ERROR(fax, chan, "UNKNOWN", "error polling data");
1541 /* nothing happened */
1542 remaining_time = ast_remaining_ms(start, timeout);
1543 if (remaining_time <= 0) {
1544 GENERIC_FAX_EXEC_ERROR(fax, chan, "TIMEOUT", "fax session timed-out");
1550 ast_debug(3, "channel '%s' - event loop stopped { timeout: %d, remaining_time: %d }\n", ast_channel_name(chan), timeout, remaining_time);
1552 set_channel_variables(chan, details);
1554 ast_atomic_fetchadd_int(&faxregistry.fax_complete, 1);
1555 if (!strcasecmp(details->result, "FAILED")) {
1556 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1560 ao2_lock(faxregistry.container);
1561 ao2_unlink(faxregistry.container, fax);
1562 ao2_unlock(faxregistry.container);
1566 /* if the channel is still alive, and we changed its read/write formats,
1570 if (orig_read_format.id) {
1571 ast_set_read_format(chan, &orig_read_format);
1573 if (orig_write_format.id) {
1574 ast_set_write_format(chan, &orig_write_format);
1578 /* return the chancount so the calling function can determine if the channel hungup during this FAX session or not */
1582 static int receivefax_t38_init(struct ast_channel *chan, struct ast_fax_session_details *details)
1585 struct ast_frame *frame = NULL;
1586 struct ast_control_t38_parameters t38_parameters;
1587 struct timeval start;
1590 /* don't send any audio if we've already received a T.38 reinvite */
1591 if (ast_channel_get_t38_state(chan) != T38_STATE_NEGOTIATING) {
1592 /* generate 3 seconds of CED */
1593 if (ast_playtones_start(chan, 1024, "!2100/3000", 1)) {
1594 ast_log(LOG_ERROR, "error generating CED tone on %s\n", ast_channel_name(chan));
1599 start = ast_tvnow();
1600 while ((ms = ast_remaining_ms(start, timeout_ms))) {
1601 ms = ast_waitfor(chan, ms);
1604 ast_log(LOG_ERROR, "error while generating CED tone on %s\n", ast_channel_name(chan));
1605 ast_playtones_stop(chan);
1609 if (ms == 0) { /* all done, nothing happened */
1613 if (!(frame = ast_read(chan))) {
1614 ast_log(LOG_ERROR, "error reading frame while generating CED tone on %s\n", ast_channel_name(chan));
1615 ast_playtones_stop(chan);
1619 if ((frame->frametype == AST_FRAME_CONTROL) &&
1620 (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
1621 (frame->datalen == sizeof(t38_parameters))) {
1622 struct ast_control_t38_parameters *parameters = frame->data.ptr;
1624 switch (parameters->request_response) {
1625 case AST_T38_REQUEST_NEGOTIATE:
1626 /* the other end has requested a switch to T.38, so reply that we are willing, if we can
1629 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
1630 t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
1631 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
1632 ast_playtones_stop(chan);
1634 case AST_T38_NEGOTIATED:
1635 ast_debug(1, "Negotiated T.38 for receive on %s\n", ast_channel_name(chan));
1636 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
1637 details->caps &= ~AST_FAX_TECH_AUDIO;
1638 report_fax_status(chan, details, "T.38 Negotiated");
1647 ast_playtones_stop(chan);
1650 /* if T.38 was negotiated, we are done initializing */
1651 if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) {
1656 ast_debug(1, "Negotiating T.38 for receive on %s\n", ast_channel_name(chan));
1658 /* wait up to five seconds for negotiation to complete */
1661 /* set parameters based on the session's parameters */
1662 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
1663 t38_parameters.request_response = AST_T38_REQUEST_NEGOTIATE;
1664 if ((ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0)) {
1668 start = ast_tvnow();
1669 while ((ms = ast_remaining_ms(start, timeout_ms))) {
1672 ms = ast_waitfor(chan, ms);
1674 ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", ast_channel_name(chan));
1677 if (ms == 0) { /* all done, nothing happened */
1678 ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 negotiation.\n", ast_channel_name(chan));
1679 details->caps &= ~AST_FAX_TECH_T38;
1683 if (!(frame = ast_read(chan))) {
1684 ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", ast_channel_name(chan));
1688 if ((frame->frametype == AST_FRAME_CONTROL) &&
1689 (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
1690 (frame->datalen == sizeof(t38_parameters))) {
1691 struct ast_control_t38_parameters *parameters = frame->data.ptr;
1693 switch (parameters->request_response) {
1694 case AST_T38_REQUEST_NEGOTIATE:
1695 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
1696 t38_parameters.request_response = AST_T38_NEGOTIATED;
1697 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
1699 case AST_T38_NEGOTIATED:
1700 ast_debug(1, "Negotiated T.38 for receive on %s\n", ast_channel_name(chan));
1701 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
1702 details->caps &= ~AST_FAX_TECH_AUDIO;
1703 report_fax_status(chan, details, "T.38 Negotiated");
1706 case AST_T38_REFUSED:
1707 ast_log(LOG_WARNING, "channel '%s' refused to negotiate T.38\n", ast_channel_name(chan));
1708 details->caps &= ~AST_FAX_TECH_T38;
1712 ast_log(LOG_ERROR, "channel '%s' failed to negotiate T.38\n", ast_channel_name(chan));
1713 details->caps &= ~AST_FAX_TECH_T38;
1724 /* if T.38 was negotiated, we are done initializing */
1725 if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) {
1729 /* if we made it here, then T.38 failed, check the 'f' flag */
1730 if (details->option.allow_audio != AST_FAX_OPTFLAG_TRUE) {
1731 ast_log(LOG_WARNING, "Audio FAX not allowed on channel '%s' and T.38 negotiation failed; aborting.\n", ast_channel_name(chan));
1735 /* ok, audio fallback is allowed */
1736 details->caps |= AST_FAX_TECH_AUDIO;
1741 /*! \brief initiate a receive FAX session */
1742 static int receivefax_exec(struct ast_channel *chan, const char *data)
1744 char *parse, modems[128] = "";
1746 struct ast_fax_session_details *details;
1747 struct ast_fax_session *s;
1748 struct ast_fax_tech_token *token = NULL;
1749 struct ast_fax_document *doc;
1750 AST_DECLARE_APP_ARGS(args,
1751 AST_APP_ARG(filename);
1752 AST_APP_ARG(options);
1754 struct ast_flags opts = { 0, };
1755 struct manager_event_info info;
1756 enum ast_t38_state t38state;
1758 /* initialize output channel variables */
1759 pbx_builtin_setvar_helper(chan, "FAXSTATUS", "FAILED");
1760 pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", NULL);
1761 pbx_builtin_setvar_helper(chan, "FAXPAGES", "0");
1762 pbx_builtin_setvar_helper(chan, "FAXBITRATE", NULL);
1763 pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", NULL);
1765 /* Get a FAX session details structure from the channel's FAX datastore and create one if
1766 * it does not already exist. */
1767 if (!(details = find_or_create_details(chan))) {
1768 pbx_builtin_setvar_helper(chan, "FAXERROR", "MEMORY_ERROR");
1769 pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "error allocating memory");
1770 ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
1774 ast_string_field_set(details, result, "FAILED");
1775 ast_string_field_set(details, resultstr, "error starting fax session");
1776 ast_string_field_set(details, error, "INIT_ERROR");
1777 set_channel_variables(chan, details);
1779 if (details->gateway_id > 0) {
1780 ast_string_field_set(details, resultstr, "can't receive a fax on a channel with a T.38 gateway");
1781 set_channel_variables(chan, details);
1782 ast_log(LOG_ERROR, "executing ReceiveFAX on a channel with a T.38 Gateway is not supported\n");
1783 ao2_ref(details, -1);
1787 if (details->maxrate < details->minrate) {
1788 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
1789 ast_string_field_set(details, resultstr, "maxrate is less than minrate");
1790 set_channel_variables(chan, details);
1791 ast_log(LOG_ERROR, "maxrate %d is less than minrate %d\n", details->maxrate, details->minrate);
1792 ao2_ref(details, -1);
1796 if (check_modem_rate(details->modems, details->minrate)) {
1797 ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
1798 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %d\n", modems, details->minrate);
1799 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
1800 ast_string_field_set(details, resultstr, "incompatible 'modems' and 'minrate' settings");
1801 set_channel_variables(chan, details);
1802 ao2_ref(details, -1);
1806 if (check_modem_rate(details->modems, details->maxrate)) {
1807 ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
1808 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %d\n", modems, details->maxrate);
1809 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
1810 ast_string_field_set(details, resultstr, "incompatible 'modems' and 'maxrate' settings");
1811 set_channel_variables(chan, details);
1812 ao2_ref(details, -1);
1816 if (ast_strlen_zero(data)) {
1817 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
1818 ast_string_field_set(details, resultstr, "invalid arguments");
1819 set_channel_variables(chan, details);
1820 ast_log(LOG_WARNING, "%s requires an argument (filename[,options])\n", app_receivefax);
1821 ao2_ref(details, -1);
1824 parse = ast_strdupa(data);
1825 AST_STANDARD_APP_ARGS(args, parse);
1827 if (!ast_strlen_zero(args.options) &&
1828 ast_app_parse_options(fax_exec_options, &opts, NULL, args.options)) {
1829 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
1830 ast_string_field_set(details, resultstr, "invalid arguments");
1831 set_channel_variables(chan, details);
1832 ao2_ref(details, -1);
1835 if (ast_strlen_zero(args.filename)) {
1836 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
1837 ast_string_field_set(details, resultstr, "invalid arguments");
1838 set_channel_variables(chan, details);
1839 ast_log(LOG_WARNING, "%s requires an argument (filename[,options])\n", app_receivefax);
1840 ao2_ref(details, -1);
1844 /* check for unsupported FAX application options */
1845 if (ast_test_flag(&opts, OPT_CALLERMODE) || ast_test_flag(&opts, OPT_CALLEDMODE)) {
1846 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
1847 ast_string_field_set(details, resultstr, "invalid arguments");
1848 set_channel_variables(chan, details);
1849 ast_log(LOG_WARNING, "%s does not support polling\n", app_receivefax);
1850 ao2_ref(details, -1);
1854 ast_atomic_fetchadd_int(&faxregistry.fax_rx_attempts, 1);
1856 pbx_builtin_setvar_helper(chan, "FAXERROR", "Channel Problems");
1857 pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "Error before FAX transmission started.");
1859 if (!(doc = ast_calloc(1, sizeof(*doc) + strlen(args.filename) + 1))) {
1860 ast_string_field_set(details, error, "MEMORY_ERROR");
1861 ast_string_field_set(details, resultstr, "error allocating memory");
1862 set_channel_variables(chan, details);
1863 ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
1864 ao2_ref(details, -1);
1868 strcpy(doc->filename, args.filename);
1869 AST_LIST_INSERT_TAIL(&details->documents, doc, next);
1871 ast_verb(3, "Channel '%s' receiving FAX '%s'\n", ast_channel_name(chan), args.filename);
1873 details->caps = AST_FAX_TECH_RECEIVE;
1875 /* check for debug */
1876 if (ast_test_flag(&opts, OPT_DEBUG) || global_fax_debug) {
1877 details->option.debug = AST_FAX_OPTFLAG_TRUE;
1880 /* check for request for status events */
1881 if (ast_test_flag(&opts, OPT_STATUS)) {
1882 details->option.statusevents = AST_FAX_OPTFLAG_TRUE;
1885 t38state = ast_channel_get_t38_state(chan);
1886 if ((t38state == T38_STATE_UNAVAILABLE) || (t38state == T38_STATE_REJECTED) ||
1887 ast_test_flag(&opts, OPT_ALLOWAUDIO) ||
1888 ast_test_flag(&opts, OPT_FORCE_AUDIO)) {
1889 details->option.allow_audio = AST_FAX_OPTFLAG_TRUE;
1892 if (!(s = fax_session_reserve(details, &token))) {
1893 ast_string_field_set(details, resultstr, "error reserving fax session");
1894 set_channel_variables(chan, details);
1895 ast_log(LOG_ERROR, "Unable to reserve FAX session.\n");
1896 ao2_ref(details, -1);
1900 /* make sure the channel is up */
1901 if (ast_channel_state(chan) != AST_STATE_UP) {
1902 if (ast_answer(chan)) {
1903 ast_string_field_set(details, resultstr, "error answering channel");
1904 set_channel_variables(chan, details);
1905 ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", ast_channel_name(chan));
1906 fax_session_release(s, token);
1908 ao2_ref(details, -1);
1913 if (!ast_test_flag(&opts, OPT_FORCE_AUDIO)) {
1914 if (set_fax_t38_caps(chan, details)) {
1915 ast_string_field_set(details, error, "T38_NEG_ERROR");
1916 ast_string_field_set(details, resultstr, "error negotiating T.38");
1917 set_channel_variables(chan, details);
1918 fax_session_release(s, token);
1920 ao2_ref(details, -1);
1924 details->caps |= AST_FAX_TECH_AUDIO;
1927 if (!ast_test_flag(&opts, OPT_FORCE_AUDIO) && (details->caps & AST_FAX_TECH_T38)) {
1928 if (receivefax_t38_init(chan, details)) {
1929 ast_string_field_set(details, error, "T38_NEG_ERROR");
1930 ast_string_field_set(details, resultstr, "error negotiating T.38");
1931 set_channel_variables(chan, details);
1932 fax_session_release(s, token);
1934 ao2_ref(details, -1);
1935 ast_log(LOG_ERROR, "error initializing channel '%s' in T.38 mode\n", ast_channel_name(chan));
1939 details->option.send_ced = 1;
1942 if ((channel_alive = generic_fax_exec(chan, details, s, token)) < 0) {
1943 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1946 if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) {
1947 if (disable_t38(chan)) {
1948 ast_debug(1, "error disabling T.38 mode on %s\n", ast_channel_name(chan));
1952 /* send out the AMI completion event */
1953 ast_channel_lock(chan);
1955 get_manager_event_info(chan, &info);
1956 manager_event(EVENT_FLAG_CALL,
1962 "RemoteStationID: %s\r\n"
1963 "LocalStationID: %s\r\n"
1964 "PagesTransferred: %s\r\n"
1965 "Resolution: %s\r\n"
1966 "TransferRate: %s\r\n"
1968 ast_channel_name(chan),
1972 S_OR(pbx_builtin_getvar_helper(chan, "REMOTESTATIONID"), ""),
1973 S_OR(pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"), ""),
1974 S_OR(pbx_builtin_getvar_helper(chan, "FAXPAGES"), ""),
1975 S_OR(pbx_builtin_getvar_helper(chan, "FAXRESOLUTION"), ""),
1976 S_OR(pbx_builtin_getvar_helper(chan, "FAXBITRATE"), ""),
1978 ast_channel_unlock(chan);
1981 ao2_ref(details, -1);
1983 /* If the channel hungup return -1; otherwise, return 0 to continue in the dialplan */
1984 return (!channel_alive) ? -1 : 0;
1987 static int sendfax_t38_init(struct ast_channel *chan, struct ast_fax_session_details *details)
1990 struct ast_frame *frame = NULL;
1991 struct ast_control_t38_parameters t38_parameters;
1992 struct timeval start;
1995 /* send CNG tone while listening for the receiver to initiate a switch
1996 * to T.38 mode; if they do, stop sending the CNG tone and proceed with
1999 * 10500 is enough time for 3 CNG tones
2003 /* don't send any audio if we've already received a T.38 reinvite */
2004 if (ast_channel_get_t38_state(chan) != T38_STATE_NEGOTIATING) {
2005 if (ast_playtones_start(chan, 1024, "!1100/500,!0/3000,!1100/500,!0/3000,!1100/500,!0/3000", 1)) {
2006 ast_log(LOG_ERROR, "error generating CNG tone on %s\n", ast_channel_name(chan));
2011 start = ast_tvnow();
2012 while ((ms = ast_remaining_ms(start, timeout_ms))) {
2014 ms = ast_waitfor(chan, ms);
2017 ast_log(LOG_ERROR, "error while generating CNG tone on %s\n", ast_channel_name(chan));
2018 ast_playtones_stop(chan);
2022 if (ms == 0) { /* all done, nothing happened */
2026 if (!(frame = ast_read(chan))) {
2027 ast_log(LOG_ERROR, "error reading frame while generating CNG tone on %s\n", ast_channel_name(chan));
2028 ast_playtones_stop(chan);
2032 if ((frame->frametype == AST_FRAME_CONTROL) &&
2033 (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
2034 (frame->datalen == sizeof(t38_parameters))) {
2035 struct ast_control_t38_parameters *parameters = frame->data.ptr;
2037 switch (parameters->request_response) {
2038 case AST_T38_REQUEST_NEGOTIATE:
2039 /* the other end has requested a switch to T.38, so reply that we are willing, if we can
2042 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
2043 t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
2044 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
2045 ast_playtones_stop(chan);
2047 case AST_T38_NEGOTIATED:
2048 ast_debug(1, "Negotiated T.38 for send on %s\n", ast_channel_name(chan));
2049 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
2050 details->caps &= ~AST_FAX_TECH_AUDIO;
2051 report_fax_status(chan, details, "T.38 Negotiated");
2064 ast_playtones_stop(chan);
2066 if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) {
2070 /* T.38 negotiation did not happen, initiate a switch if requested */
2071 if (details->option.request_t38 == AST_FAX_OPTFLAG_TRUE) {
2072 ast_debug(1, "Negotiating T.38 for send on %s\n", ast_channel_name(chan));
2074 /* wait up to five seconds for negotiation to complete */
2077 /* set parameters based on the session's parameters */
2078 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
2079 t38_parameters.request_response = AST_T38_REQUEST_NEGOTIATE;
2080 if ((ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0)) {
2084 start = ast_tvnow();
2085 while ((ms = ast_remaining_ms(start, timeout_ms))) {
2088 ms = ast_waitfor(chan, ms);
2090 ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", ast_channel_name(chan));
2093 if (ms == 0) { /* all done, nothing happened */
2094 ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 negotiation.\n", ast_channel_name(chan));
2095 details->caps &= ~AST_FAX_TECH_T38;
2099 if (!(frame = ast_read(chan))) {
2100 ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", ast_channel_name(chan));
2104 if ((frame->frametype == AST_FRAME_CONTROL) &&
2105 (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
2106 (frame->datalen == sizeof(t38_parameters))) {
2107 struct ast_control_t38_parameters *parameters = frame->data.ptr;
2109 switch (parameters->request_response) {
2110 case AST_T38_REQUEST_NEGOTIATE:
2111 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
2112 t38_parameters.request_response = AST_T38_NEGOTIATED;
2113 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
2115 case AST_T38_NEGOTIATED:
2116 ast_debug(1, "Negotiated T.38 for receive on %s\n", ast_channel_name(chan));
2117 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
2118 details->caps &= ~AST_FAX_TECH_AUDIO;
2119 report_fax_status(chan, details, "T.38 Negotiated");
2122 case AST_T38_REFUSED:
2123 ast_log(LOG_WARNING, "channel '%s' refused to negotiate T.38\n", ast_channel_name(chan));
2124 details->caps &= ~AST_FAX_TECH_T38;
2128 ast_log(LOG_ERROR, "channel '%s' failed to negotiate T.38\n", ast_channel_name(chan));
2129 details->caps &= ~AST_FAX_TECH_T38;
2140 /* if T.38 was negotiated, we are done initializing */
2141 if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) {
2145 /* send one more CNG tone to get audio going again for some
2146 * carriers if we are going to fall back to audio mode */
2147 if (details->option.allow_audio == AST_FAX_OPTFLAG_TRUE) {
2148 if (ast_playtones_start(chan, 1024, "!1100/500,!0/3000", 1)) {
2149 ast_log(LOG_ERROR, "error generating second CNG tone on %s\n", ast_channel_name(chan));
2154 start = ast_tvnow();
2155 while ((ms = ast_remaining_ms(start, timeout_ms))) {
2158 ms = ast_waitfor(chan, ms);
2160 ast_log(LOG_ERROR, "error while generating second CNG tone on %s\n", ast_channel_name(chan));
2161 ast_playtones_stop(chan);
2164 if (ms == 0) { /* all done, nothing happened */
2168 if (!(frame = ast_read(chan))) {
2169 ast_log(LOG_ERROR, "error reading frame while generating second CNG tone on %s\n", ast_channel_name(chan));
2170 ast_playtones_stop(chan);
2174 if ((frame->frametype == AST_FRAME_CONTROL) &&
2175 (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
2176 (frame->datalen == sizeof(t38_parameters))) {
2177 struct ast_control_t38_parameters *parameters = frame->data.ptr;
2179 switch (parameters->request_response) {
2180 case AST_T38_REQUEST_NEGOTIATE:
2181 /* the other end has requested a switch to T.38, so reply that we are willing, if we can
2184 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
2185 t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
2186 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
2187 ast_playtones_stop(chan);
2189 case AST_T38_NEGOTIATED:
2190 ast_debug(1, "Negotiated T.38 for send on %s\n", ast_channel_name(chan));
2191 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
2192 details->caps &= ~AST_FAX_TECH_AUDIO;
2193 report_fax_status(chan, details, "T.38 Negotiated");
2206 ast_playtones_stop(chan);
2208 /* if T.38 was negotiated, we are done initializing */
2209 if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) {
2215 /* if we made it here, then T.38 failed, check the 'f' flag */
2216 if (details->option.allow_audio == AST_FAX_OPTFLAG_FALSE) {
2217 ast_log(LOG_WARNING, "Audio FAX not allowed on channel '%s' and T.38 negotiation failed; aborting.\n", ast_channel_name(chan));
2221 /* ok, audio fallback is allowed */
2222 details->caps |= AST_FAX_TECH_AUDIO;
2228 /*! \brief initiate a send FAX session */
2229 static int sendfax_exec(struct ast_channel *chan, const char *data)
2231 char *parse, *filenames, *c, modems[128] = "";
2232 int channel_alive, file_count;
2233 struct ast_fax_session_details *details;
2234 struct ast_fax_session *s;
2235 struct ast_fax_tech_token *token = NULL;
2236 struct ast_fax_document *doc;
2237 AST_DECLARE_APP_ARGS(args,
2238 AST_APP_ARG(filenames);
2239 AST_APP_ARG(options);
2241 struct ast_flags opts = { 0, };
2242 struct manager_event_info info;
2243 enum ast_t38_state t38state;
2245 /* initialize output channel variables */
2246 pbx_builtin_setvar_helper(chan, "FAXSTATUS", "FAILED");
2247 pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", NULL);
2248 pbx_builtin_setvar_helper(chan, "FAXPAGES", "0");
2249 pbx_builtin_setvar_helper(chan, "FAXBITRATE", NULL);
2250 pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", NULL);
2252 /* Get a requirement structure and set it. This structure is used
2253 * to tell the FAX technology module about the higher level FAX session */
2254 if (!(details = find_or_create_details(chan))) {
2255 pbx_builtin_setvar_helper(chan, "FAXERROR", "MEMORY_ERROR");
2256 pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "error allocating memory");
2257 ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
2261 ast_string_field_set(details, result, "FAILED");
2262 ast_string_field_set(details, resultstr, "error starting fax session");
2263 ast_string_field_set(details, error, "INIT_ERROR");
2264 set_channel_variables(chan, details);
2266 if (details->gateway_id > 0) {
2267 ast_string_field_set(details, resultstr, "can't send a fax on a channel with a T.38 gateway");
2268 set_channel_variables(chan, details);
2269 ast_log(LOG_ERROR, "executing SendFAX on a channel with a T.38 Gateway is not supported\n");
2270 ao2_ref(details, -1);
2274 if (details->maxrate < details->minrate) {
2275 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2276 ast_string_field_set(details, resultstr, "maxrate is less than minrate");
2277 set_channel_variables(chan, details);
2278 ast_log(LOG_ERROR, "maxrate %d is less than minrate %d\n", details->maxrate, details->minrate);
2279 ao2_ref(details, -1);
2283 if (check_modem_rate(details->modems, details->minrate)) {
2284 ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
2285 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %d\n", modems, details->minrate);
2286 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2287 ast_string_field_set(details, resultstr, "incompatible 'modems' and 'minrate' settings");
2288 set_channel_variables(chan, details);
2289 ao2_ref(details, -1);
2293 if (check_modem_rate(details->modems, details->maxrate)) {
2294 ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
2295 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %d\n", modems, details->maxrate);
2296 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2297 ast_string_field_set(details, resultstr, "incompatible 'modems' and 'maxrate' settings");
2298 set_channel_variables(chan, details);
2299 ao2_ref(details, -1);
2303 if (ast_strlen_zero(data)) {
2304 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2305 ast_string_field_set(details, resultstr, "invalid arguments");
2306 set_channel_variables(chan, details);
2307 ast_log(LOG_WARNING, "%s requires an argument (filename[&filename[&filename]][,options])\n", app_sendfax);
2308 ao2_ref(details, -1);
2311 parse = ast_strdupa(data);
2312 AST_STANDARD_APP_ARGS(args, parse);
2315 if (!ast_strlen_zero(args.options) &&
2316 ast_app_parse_options(fax_exec_options, &opts, NULL, args.options)) {
2317 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2318 ast_string_field_set(details, resultstr, "invalid arguments");
2319 set_channel_variables(chan, details);
2320 ao2_ref(details, -1);
2323 if (ast_strlen_zero(args.filenames)) {
2324 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2325 ast_string_field_set(details, resultstr, "invalid arguments");
2326 set_channel_variables(chan, details);
2327 ast_log(LOG_WARNING, "%s requires an argument (filename[&filename[&filename]],options])\n", app_sendfax);
2328 ao2_ref(details, -1);
2332 /* check for unsupported FAX application options */
2333 if (ast_test_flag(&opts, OPT_CALLERMODE) || ast_test_flag(&opts, OPT_CALLEDMODE)) {
2334 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2335 ast_string_field_set(details, resultstr, "invalid arguments");
2336 set_channel_variables(chan, details);
2337 ast_log(LOG_WARNING, "%s does not support polling\n", app_sendfax);
2338 ao2_ref(details, -1);
2342 ast_atomic_fetchadd_int(&faxregistry.fax_tx_attempts, 1);
2345 filenames = args.filenames;
2346 while ((c = strsep(&filenames, "&"))) {
2347 if (access(c, (F_OK | R_OK)) < 0) {
2348 ast_string_field_set(details, error, "FILE_ERROR");
2349 ast_string_field_set(details, resultstr, "error reading file");
2350 set_channel_variables(chan, details);
2351 ast_log(LOG_ERROR, "access failure. Verify '%s' exists and check permissions.\n", args.filenames);
2352 ao2_ref(details, -1);
2356 if (!(doc = ast_calloc(1, sizeof(*doc) + strlen(c) + 1))) {
2357 ast_string_field_set(details, error, "MEMORY_ERROR");
2358 ast_string_field_set(details, resultstr, "error allocating memory");
2359 set_channel_variables(chan, details);
2360 ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
2361 ao2_ref(details, -1);
2365 strcpy(doc->filename, c);
2366 AST_LIST_INSERT_TAIL(&details->documents, doc, next);
2370 ast_verb(3, "Channel '%s' sending FAX:\n", ast_channel_name(chan));
2371 AST_LIST_TRAVERSE(&details->documents, doc, next) {
2372 ast_verb(3, " %s\n", doc->filename);
2375 details->caps = AST_FAX_TECH_SEND;
2377 if (file_count > 1) {
2378 details->caps |= AST_FAX_TECH_MULTI_DOC;
2381 /* check for debug */
2382 if (ast_test_flag(&opts, OPT_DEBUG) || global_fax_debug) {
2383 details->option.debug = AST_FAX_OPTFLAG_TRUE;
2386 /* check for request for status events */
2387 if (ast_test_flag(&opts, OPT_STATUS)) {
2388 details->option.statusevents = AST_FAX_OPTFLAG_TRUE;
2391 t38state = ast_channel_get_t38_state(chan);
2392 if ((t38state == T38_STATE_UNAVAILABLE) || (t38state == T38_STATE_REJECTED) ||
2393 ast_test_flag(&opts, OPT_ALLOWAUDIO) ||
2394 ast_test_flag(&opts, OPT_FORCE_AUDIO)) {
2395 details->option.allow_audio = AST_FAX_OPTFLAG_TRUE;
2398 if (ast_test_flag(&opts, OPT_REQUEST_T38)) {
2399 details->option.request_t38 = AST_FAX_OPTFLAG_TRUE;
2402 if (!(s = fax_session_reserve(details, &token))) {
2403 ast_string_field_set(details, resultstr, "error reserving fax session");
2404 set_channel_variables(chan, details);
2405 ast_log(LOG_ERROR, "Unable to reserve FAX session.\n");
2406 ao2_ref(details, -1);
2410 /* make sure the channel is up */
2411 if (ast_channel_state(chan) != AST_STATE_UP) {
2412 if (ast_answer(chan)) {
2413 ast_string_field_set(details, resultstr, "error answering channel");
2414 set_channel_variables(chan, details);
2415 ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", ast_channel_name(chan));
2416 fax_session_release(s, token);
2418 ao2_ref(details, -1);
2423 if (!ast_test_flag(&opts, OPT_FORCE_AUDIO)) {
2424 if (set_fax_t38_caps(chan, details)) {
2425 ast_string_field_set(details, error, "T38_NEG_ERROR");
2426 ast_string_field_set(details, resultstr, "error negotiating T.38");
2427 set_channel_variables(chan, details);
2428 fax_session_release(s, token);
2430 ao2_ref(details, -1);
2434 details->caps |= AST_FAX_TECH_AUDIO;
2437 if (!ast_test_flag(&opts, OPT_FORCE_AUDIO) && (details->caps & AST_FAX_TECH_T38)) {
2438 if (sendfax_t38_init(chan, details)) {
2439 ast_string_field_set(details, error, "T38_NEG_ERROR");
2440 ast_string_field_set(details, resultstr, "error negotiating T.38");
2441 set_channel_variables(chan, details);
2442 fax_session_release(s, token);
2444 ao2_ref(details, -1);
2445 ast_log(LOG_ERROR, "error initializing channel '%s' in T.38 mode\n", ast_channel_name(chan));
2449 details->option.send_cng = 1;
2452 if ((channel_alive = generic_fax_exec(chan, details, s, token)) < 0) {
2453 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
2456 if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) {
2457 if (disable_t38(chan)) {
2458 ast_debug(1, "error disabling T.38 mode on %s\n", ast_channel_name(chan));
2462 if (!(filenames = generate_filenames_string(details, "FileName: ", "\r\n"))) {
2463 ast_log(LOG_ERROR, "Error generating SendFAX manager event\n");
2465 ao2_ref(details, -1);
2466 return (!channel_alive) ? -1 : 0;
2469 /* send out the AMI completion event */
2470 ast_channel_lock(chan);
2471 get_manager_event_info(chan, &info);
2472 manager_event(EVENT_FLAG_CALL,
2478 "RemoteStationID: %s\r\n"
2479 "LocalStationID: %s\r\n"
2480 "PagesTransferred: %s\r\n"
2481 "Resolution: %s\r\n"
2482 "TransferRate: %s\r\n"
2484 ast_channel_name(chan),
2488 S_OR(pbx_builtin_getvar_helper(chan, "REMOTESTATIONID"), ""),
2489 S_OR(pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"), ""),
2490 S_OR(pbx_builtin_getvar_helper(chan, "FAXPAGES"), ""),
2491 S_OR(pbx_builtin_getvar_helper(chan, "FAXRESOLUTION"), ""),
2492 S_OR(pbx_builtin_getvar_helper(chan, "FAXBITRATE"), ""),
2494 ast_channel_unlock(chan);
2496 ast_free(filenames);
2499 ao2_ref(details, -1);
2501 /* If the channel hungup return -1; otherwise, return 0 to continue in the dialplan */
2502 return (!channel_alive) ? -1 : 0;
2505 /*! \brief destroy the v21 detection parts of a fax gateway session */
2506 static void destroy_v21_sessions(struct fax_gateway *gateway)
2508 if (gateway->chan_v21_session) {
2509 ao2_lock(faxregistry.container);
2510 ao2_unlink(faxregistry.container, gateway->chan_v21_session);
2511 ao2_unlock(faxregistry.container);
2513 ao2_ref(gateway->chan_v21_session, -1);
2514 gateway->chan_v21_session = NULL;
2517 if (gateway->peer_v21_session) {
2518 ao2_lock(faxregistry.container);
2519 ao2_unlink(faxregistry.container, gateway->peer_v21_session);
2520 ao2_unlock(faxregistry.container);
2522 ao2_ref(gateway->peer_v21_session, -1);
2523 gateway->peer_v21_session = NULL;
2527 /*! \brief destroy a FAX gateway session structure */
2528 static void destroy_gateway(void *data)
2530 struct fax_gateway *gateway = data;
2532 destroy_v21_sessions(gateway);
2535 fax_session_release(gateway->s, gateway->token);
2536 gateway->token = NULL;
2538 ao2_lock(faxregistry.container);
2539 ao2_unlink(faxregistry.container, gateway->s);
2540 ao2_unlock(faxregistry.container);
2542 ao2_ref(gateway->s, -1);
2547 /*! \brief Create a new fax gateway object.
2548 * \param chan the channel the gateway object will be attached to
2549 * \param details the fax session details
2550 * \return NULL or a fax gateway object
2552 static struct fax_gateway *fax_gateway_new(struct ast_channel *chan, struct ast_fax_session_details *details)
2554 struct fax_gateway *gateway = ao2_alloc(sizeof(*gateway), destroy_gateway);
2555 struct ast_fax_session_details *v21_details;
2560 if (!(v21_details = session_details_new())) {
2561 ao2_ref(gateway, -1);
2565 v21_details->caps = AST_FAX_TECH_V21_DETECT;
2566 if (!(gateway->chan_v21_session = fax_session_new(v21_details, chan, NULL, NULL))) {
2567 ao2_ref(v21_details, -1);
2568 ao2_ref(gateway, -1);
2572 if (!(gateway->peer_v21_session = fax_session_new(v21_details, chan, NULL, NULL))) {
2573 ao2_ref(v21_details, -1);
2574 ao2_ref(gateway, -1);
2577 ao2_ref(v21_details, -1);
2579 gateway->framehook = -1;
2581 details->caps = AST_FAX_TECH_GATEWAY;
2582 if (details->gateway_timeout && !(gateway->s = fax_session_reserve(details, &gateway->token))) {
2583 details->caps &= ~AST_FAX_TECH_GATEWAY;
2584 ast_log(LOG_ERROR, "Can't reserve a FAX session, gateway attempt failed.\n");
2585 ao2_ref(gateway, -1);
2592 /*! \brief Create a fax session and start T.30<->T.38 gateway mode
2593 * \param gateway a fax gateway object
2594 * \param details fax session details
2595 * \param chan active channel
2596 * \return 0 on error 1 on success*/
2597 static int fax_gateway_start(struct fax_gateway *gateway, struct ast_fax_session_details *details, struct ast_channel *chan)
2599 struct ast_fax_session *s;
2601 /* create the FAX session */
2602 if (!(s = fax_session_new(details, chan, gateway->s, gateway->token))) {
2603 gateway->token = NULL;
2604 ast_string_field_set(details, result, "FAILED");
2605 ast_string_field_set(details, resultstr, "error starting gateway session");
2606 ast_string_field_set(details, error, "INIT_ERROR");
2607 set_channel_variables(chan, details);
2608 report_fax_status(chan, details, "No Available Resource");
2609 ast_log(LOG_ERROR, "Can't create a FAX session, gateway attempt failed.\n");
2612 /* release the reference for the reserved session and replace it with
2613 * the real session */
2615 ao2_ref(gateway->s, -1);
2618 gateway->token = NULL;
2620 if (gateway->s->tech->start_session(gateway->s) < 0) {
2621 ast_string_field_set(details, result, "FAILED");
2622 ast_string_field_set(details, resultstr, "error starting gateway session");
2623 ast_string_field_set(details, error, "INIT_ERROR");
2624 set_channel_variables(chan, details);
2628 gateway->timeout_start.tv_sec = 0;
2629 gateway->timeout_start.tv_usec = 0;
2631 report_fax_status(chan, details, "FAX Transmission In Progress");
2636 static struct ast_frame *fax_gateway_request_t38(struct fax_gateway *gateway, struct ast_channel *chan, struct ast_frame *f)
2638 struct ast_frame *fp;
2639 struct ast_control_t38_parameters t38_parameters = {
2640 .request_response = AST_T38_REQUEST_NEGOTIATE,
2642 struct ast_frame control_frame = {
2644 .frametype = AST_FRAME_CONTROL,
2645 .datalen = sizeof(t38_parameters),
2646 .subclass.integer = AST_CONTROL_T38_PARAMETERS,
2647 .data.ptr = &t38_parameters,
2650 struct ast_fax_session_details *details = find_details(chan);
2653 ast_log(LOG_ERROR, "no FAX session details found on chan %s for T.38 gateway session, odd\n", ast_channel_name(chan));
2654 ast_framehook_detach(chan, gateway->framehook);
2658 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
2659 ao2_ref(details, -1);
2661 if (!(fp = ast_frisolate(&control_frame))) {
2662 ast_log(LOG_ERROR, "error generating T.38 request control frame on chan %s for T.38 gateway session\n", ast_channel_name(chan));
2666 gateway->t38_state = T38_STATE_NEGOTIATING;
2667 gateway->timeout_start = ast_tvnow();
2668 details->gateway_timeout = FAX_GATEWAY_TIMEOUT;
2670 ast_debug(1, "requesting T.38 for gateway session for %s\n", ast_channel_name(chan));
2674 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)
2676 struct ast_channel *other = (active == chan) ? peer : chan;
2677 struct ast_fax_session *active_v21_session = (active == chan) ? gateway->chan_v21_session : gateway->peer_v21_session;
2679 if (!active_v21_session || gateway->detected_v21) {
2683 if (active_v21_session->tech->write(active_v21_session, f) == 0 &&
2684 active_v21_session->details->option.v21_detected) {
2685 gateway->detected_v21 = 1;
2688 if (gateway->detected_v21) {
2689 destroy_v21_sessions(gateway);
2690 if (ast_channel_get_t38_state(other) == T38_STATE_UNKNOWN) {
2691 ast_debug(1, "detected v21 preamble from %s\n", ast_channel_name(active));
2692 return fax_gateway_request_t38(gateway, chan, f);
2694 ast_debug(1, "detected v21 preamble on %s, but %s does not support T.38 for T.38 gateway session\n", ast_channel_name(active), ast_channel_name(other));
2701 static int fax_gateway_indicate_t38(struct ast_channel *chan, struct ast_channel *active, struct ast_control_t38_parameters *control_params)
2703 if (active == chan) {
2704 return ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, control_params, sizeof(*control_params));
2706 return ast_queue_control_data(chan, AST_CONTROL_T38_PARAMETERS, control_params, sizeof(*control_params));
2710 /*! \brief T38 Gateway Negotiate t38 parameters
2711 * \param gateway gateway object
2712 * \param chan channel running the gateway
2713 * \param peer channel im bridged too
2714 * \param active channel the frame originated on
2715 * \param f the control frame to process
2716 * \return processed control frame or null frame
2718 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)
2720 struct ast_control_t38_parameters *control_params = f->data.ptr;
2721 struct ast_channel *other = (active == chan) ? peer : chan;
2722 struct ast_fax_session_details *details;
2724 if (f->datalen != sizeof(struct ast_control_t38_parameters)) {
2725 /* invalaid AST_CONTROL_T38_PARAMETERS frame, we can't
2726 * do anything with it, pass it on */
2730 /* ignore frames from ourselves */
2731 if ((gateway->t38_state == T38_STATE_NEGOTIATED && control_params->request_response == AST_T38_NEGOTIATED)
2732 || (gateway->t38_state == T38_STATE_REJECTED && control_params->request_response == AST_T38_REFUSED)
2733 || (gateway->t38_state == T38_STATE_NEGOTIATING && control_params->request_response == AST_T38_REQUEST_TERMINATE)) {
2738 if (!(details = find_details(chan))) {
2739 ast_log(LOG_ERROR, "no FAX session details found on chan %s for T.38 gateway session, odd\n", ast_channel_name(chan));
2740 ast_framehook_detach(chan, gateway->framehook);
2744 if (control_params->request_response == AST_T38_REQUEST_NEGOTIATE) {
2745 enum ast_t38_state state = ast_channel_get_t38_state(other);
2747 if (state == T38_STATE_UNKNOWN) {
2748 /* we detected a request to negotiate T.38 and the
2749 * other channel appears to support T.38, we'll pass
2750 * the request through and only step in if the other
2751 * channel rejects the request */
2752 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));
2753 t38_parameters_ast_to_fax(&details->their_t38_parameters, control_params);
2754 gateway->t38_state = T38_STATE_UNKNOWN;
2755 gateway->timeout_start = ast_tvnow();
2756 details->gateway_timeout = FAX_GATEWAY_TIMEOUT;
2757 ao2_ref(details, -1);
2759 } else if (state == T38_STATE_UNAVAILABLE || state == T38_STATE_REJECTED) {
2760 /* the other channel does not support T.38, we need to
2762 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));
2763 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));
2765 t38_parameters_ast_to_fax(&details->their_t38_parameters, control_params);
2766 t38_parameters_fax_to_ast(control_params, &details->our_t38_parameters);
2768 if (fax_gateway_start(gateway, details, chan)) {
2769 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));
2770 gateway->t38_state = T38_STATE_REJECTED;
2771 control_params->request_response = AST_T38_REFUSED;
2773 ast_framehook_detach(chan, details->gateway_id);
2774 details->gateway_id = -1;
2776 gateway->t38_state = T38_STATE_NEGOTIATED;
2777 control_params->request_response = AST_T38_NEGOTIATED;
2778 report_fax_status(chan, details, "T.38 Negotiated");
2781 fax_gateway_indicate_t38(chan, active, control_params);
2783 ao2_ref(details, -1);
2784 return &ast_null_frame;
2785 } else if (gateway->t38_state == T38_STATE_NEGOTIATING) {
2786 /* we got a request to negotiate T.38 after we already
2787 * sent one to the other party based on v21 preamble
2788 * detection. We'll just pretend we passed this request
2789 * through in the first place. */
2791 t38_parameters_ast_to_fax(&details->their_t38_parameters, control_params);
2792 gateway->t38_state = T38_STATE_UNKNOWN;
2793 gateway->timeout_start = ast_tvnow();
2794 details->gateway_timeout = FAX_GATEWAY_TIMEOUT;
2796 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));
2797 ao2_ref(details, -1);
2798 return &ast_null_frame;
2799 } else if (gateway->t38_state == T38_STATE_NEGOTIATED) {
2800 /* we got a request to negotiate T.38 after we already
2801 * sent one to the other party based on v21 preamble
2802 * detection and received a response. We need to
2803 * respond to this and shut down the gateway. */
2805 t38_parameters_fax_to_ast(control_params, &details->their_t38_parameters);
2806 ast_framehook_detach(chan, details->gateway_id);
2807 details->gateway_id = -1;
2809 control_params->request_response = AST_T38_NEGOTIATED;
2811 fax_gateway_indicate_t38(chan, active, control_params);
2813 ast_string_field_set(details, result, "SUCCESS");
2814 ast_string_field_set(details, resultstr, "no gateway necessary");
2815 ast_string_field_set(details, error, "NATIVE_T38");
2816 set_channel_variables(chan, details);
2818 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));
2819 ao2_ref(details, -1);
2820 return &ast_null_frame;
2822 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));
2823 ao2_ref(details, -1);
2826 } else if (gateway->t38_state == T38_STATE_NEGOTIATING
2827 && control_params->request_response == AST_T38_REFUSED) {
2829 ast_debug(1, "unable to negotiate T.38 on %s for fax gateway\n", ast_channel_name(active));
2831 /* our request to negotiate T.38 was refused, if the other
2832 * channel supports T.38, they might still reinvite and save
2833 * the day. Otherwise disable the gateway. */
2834 if (ast_channel_get_t38_state(other) == T38_STATE_UNKNOWN) {
2835 gateway->t38_state = T38_STATE_UNAVAILABLE;
2837 ast_framehook_detach(chan, details->gateway_id);
2838 details->gateway_id = -1;
2840 ast_string_field_set(details, result, "FAILED");
2841 ast_string_field_set(details, resultstr, "unable to negotiate T.38");
2842 ast_string_field_set(details, error, "T38_NEG_ERROR");
2843 set_channel_variables(chan, details);
2846 ao2_ref(details, -1);
2847 return &ast_null_frame;
2848 } else if (gateway->t38_state == T38_STATE_NEGOTIATING
2849 && control_params->request_response == AST_T38_NEGOTIATED) {
2851 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));
2853 t38_parameters_ast_to_fax(&details->their_t38_parameters, control_params);
2855 if (fax_gateway_start(gateway, details, chan)) {
2856 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));
2857 gateway->t38_state = T38_STATE_NEGOTIATING;
2858 control_params->request_response = AST_T38_REQUEST_TERMINATE;
2860 fax_gateway_indicate_t38(chan, active, control_params);
2862 gateway->t38_state = T38_STATE_NEGOTIATED;
2863 report_fax_status(chan, details, "T.38 Negotiated");
2866 ao2_ref(details, -1);
2867 return &ast_null_frame;
2868 } else if (control_params->request_response == AST_T38_REFUSED) {
2869 /* the other channel refused the request to negotiate T.38,
2870 * we'll step in here and pretend the request was accepted */
2872 ast_debug(1, "%s attempted to negotiate T.38 but %s refused the request\n", ast_channel_name(other), ast_channel_name(active));
2873 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));
2875 t38_parameters_fax_to_ast(control_params, &details->our_t38_parameters);
2877 if (fax_gateway_start(gateway, details, chan)) {
2878 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));
2879 gateway->t38_state = T38_STATE_REJECTED;
2880 control_params->request_response = AST_T38_REFUSED;
2882 ast_framehook_detach(chan, details->gateway_id);
2883 details->gateway_id = -1;
2885 gateway->t38_state = T38_STATE_NEGOTIATED;
2886 control_params->request_response = AST_T38_NEGOTIATED;
2889 ao2_ref(details, -1);
2891 } else if (control_params->request_response == AST_T38_REQUEST_TERMINATE) {
2892 /* the channel wishes to end our short relationship, we shall
2895 ast_debug(1, "T.38 channel %s is requesting a shutdown of T.38, disabling the gateway\n", ast_channel_name(active));
2897 ast_framehook_detach(chan, details->gateway_id);
2898 details->gateway_id = -1;
2900 gateway->t38_state = T38_STATE_REJECTED;
2901 control_params->request_response = AST_T38_TERMINATED;
2903 fax_gateway_indicate_t38(chan, active, control_params);
2905 ao2_ref(details, -1);
2906 return &ast_null_frame;
2907 } else if (control_params->request_response == AST_T38_NEGOTIATED) {
2908 ast_debug(1, "T.38 successfully negotiated between %s and %s, no gateway necessary\n", ast_channel_name(active), ast_channel_name(other));
2910 ast_framehook_detach(chan, details->gateway_id);
2911 details->gateway_id = -1;
2913 ast_string_field_set(details, result, "SUCCESS");
2914 ast_string_field_set(details, resultstr, "no gateway necessary");
2915 ast_string_field_set(details, error, "NATIVE_T38");
2916 set_channel_variables(chan, details);
2918 ao2_ref(details, -1);
2920 } else if (control_params->request_response == AST_T38_TERMINATED) {
2921 ast_debug(1, "T.38 disabled on channel %s\n", ast_channel_name(active));
2923 ast_framehook_detach(chan, details->gateway_id);
2924 details->gateway_id = -1;
2926 ao2_ref(details, -1);
2927 return &ast_null_frame;
2930 ao2_ref(details, -1);
2934 /*! \brief Destroy the gateway data structure when the framehook is detached
2935 * \param data framehook data (gateway data)*/
2936 static void fax_gateway_framehook_destroy(void *data) {
2937 struct fax_gateway *gateway = data;
2940 switch (gateway->s->state) {
2941 case AST_FAX_STATE_INITIALIZED:
2942 case AST_FAX_STATE_OPEN:
2943 case AST_FAX_STATE_ACTIVE:
2944 case AST_FAX_STATE_COMPLETE:
2945 if (gateway->s->tech->cancel_session) {
2946 gateway->s->tech->cancel_session(gateway->s);
2954 ao2_ref(gateway, -1);
2957 /*! \brief T.30<->T.38 gateway framehook.
2959 * Intercept packets on bridged channels and determine if a T.38 gateway is
2960 * required. If a gateway is required, start a gateway and handle T.38
2961 * negotiation if necessary.
2963 * \param chan channel running the gateway
2964 * \param f frame to handle may be NULL
2965 * \param event framehook event
2966 * \param data framehook data (struct fax_gateway *)
2968 * \return processed frame or NULL when f is NULL or a null frame
2970 static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data) {
2971 struct fax_gateway *gateway = data;
2972 struct ast_channel *peer, *active;
2973 struct ast_fax_session_details *details;
2976 details = gateway->s->details;
2977 ao2_ref(details, 1);
2979 if (!(details = find_details(chan))) {
2980 ast_log(LOG_ERROR, "no FAX session details found on chan %s for T.38 gateway session, odd\n", ast_channel_name(chan));
2981 ast_framehook_detach(chan, gateway->framehook);
2986 /* restore audio formats when we are detached */
2987 if (event == AST_FRAMEHOOK_EVENT_DETACHED) {
2988 set_channel_variables(chan, details);
2990 if (gateway->bridged) {
2991 ast_set_read_format(chan, &gateway->chan_read_format);
2992 ast_set_read_format(chan, &gateway->chan_write_format);
2994 if ((peer = ast_bridged_channel(chan))) {
2995 ast_set_read_format(peer, &gateway->peer_read_format);
2996 ast_set_read_format(peer, &gateway->peer_write_format);
2997 ast_channel_make_compatible(chan, peer);
3001 ao2_ref(details, -1);
3005 if (!f || (event == AST_FRAMEHOOK_EVENT_ATTACHED)) {
3006 ao2_ref(details, -1);
3010 /* this frame was generated by the fax gateway, pass it on */
3011 if (ast_test_flag(f, AST_FAX_FRFLAG_GATEWAY)) {
3012 ao2_ref(details, -1);
3016 if (!(peer = ast_bridged_channel(chan))) {
3017 /* not bridged, don't do anything */
3018 ao2_ref(details, -1);
3022 if (!gateway->bridged && peer) {
3023 /* don't start a gateway if neither channel can handle T.38 */
3024 if (ast_channel_get_t38_state(chan) == T38_STATE_UNAVAILABLE && ast_channel_get_t38_state(peer) == T38_STATE_UNAVAILABLE) {
3025 ast_debug(1, "not starting gateway for %s and %s; neither channel supports T.38\n", ast_channel_name(chan), ast_channel_name(peer));
3026 ast_framehook_detach(chan, gateway->framehook);
3027 details->gateway_id = -1;
3029 ast_string_field_set(details, result, "FAILED");
3030 ast_string_field_set(details, resultstr, "neither channel supports T.38");
3031 ast_string_field_set(details, error, "T38_NEG_ERROR");
3032 set_channel_variables(chan, details);
3033 ao2_ref(details, -1);
3037 if (details->gateway_timeout) {
3038 gateway->timeout_start = ast_tvnow();
3041 /* we are bridged, change r/w formats to SLIN for v21 preamble
3042 * detection and T.30 */
3043 ast_format_copy(&gateway->chan_read_format, ast_channel_readformat(chan));
3044 ast_format_copy(&gateway->chan_write_format, ast_channel_readformat(chan));
3046 ast_format_copy(&gateway->peer_read_format, ast_channel_readformat(peer));
3047 ast_format_copy(&gateway->peer_write_format, ast_channel_readformat(peer));
3049 ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR);
3050 ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR);
3052 ast_set_read_format_by_id(peer, AST_FORMAT_SLINEAR);
3053 ast_set_write_format_by_id(peer, AST_FORMAT_SLINEAR);
3055 ast_channel_make_compatible(chan, peer);
3056 gateway->bridged = 1;
3059 if (gateway->bridged && !ast_tvzero(gateway->timeout_start)) {
3060 if (ast_tvdiff_ms(ast_tvnow(), gateway->timeout_start) > details->gateway_timeout) {
3061 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);
3062 ast_framehook_detach(chan, gateway->framehook);
3063 details->gateway_id = -1;
3065 ast_string_field_set(details, result, "FAILED");
3066 ast_string_field_build(details, resultstr, "no fax activity after %d ms", details->gateway_timeout);
3067 ast_string_field_set(details, error, "TIMEOUT");
3068 set_channel_variables(chan, details);
3069 ao2_ref(details, -1);
3074 /* only handle VOICE, MODEM, and CONTROL frames*/
3075 switch (f->frametype) {
3076 case AST_FRAME_VOICE:
3077 switch (f->subclass.format.id) {
3078 case AST_FORMAT_SLINEAR:
3079 case AST_FORMAT_ALAW:
3080 case AST_FORMAT_ULAW:
3083 ao2_ref(details, -1);
3087 case AST_FRAME_MODEM:
3088 if (f->subclass.integer == AST_MODEM_T38) {
3091 ao2_ref(details, -1);
3093 case AST_FRAME_CONTROL:
3094 if (f->subclass.integer == AST_CONTROL_T38_PARAMETERS) {
3097 ao2_ref(details, -1);
3100 ao2_ref(details, -1);
3104 /* detect the active channel */
3106 case AST_FRAMEHOOK_EVENT_WRITE:
3109 case AST_FRAMEHOOK_EVENT_READ:
3113 ast_log(LOG_WARNING, "unhandled framehook event %i\n", event);
3114 ao2_ref(details, -1);
3118 /* handle control frames */
3119 if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_T38_PARAMETERS) {
3120 ao2_ref(details, -1);
3121 return fax_gateway_detect_t38(gateway, chan, peer, active, f);
3124 if (!gateway->detected_v21 && gateway->t38_state == T38_STATE_UNAVAILABLE && f->frametype == AST_FRAME_VOICE) {
3125 /* not in gateway mode and have not detected v21 yet, listen
3127 ao2_ref(details, -1);
3128 return fax_gateway_detect_v21(gateway, chan, peer, active, f);
3131 /* in gateway mode, gateway some packets */
3132 if (gateway->t38_state == T38_STATE_NEGOTIATED) {
3133 /* framehooks are called in __ast_read() before frame format
3134 * translation is done, so we need to translate here */
3135 if ((f->frametype == AST_FRAME_VOICE) && (f->subclass.format.id != AST_FORMAT_SLINEAR)) {
3136 if (ast_channel_readtrans(active) && (f = ast_translate(ast_channel_readtrans(active), f, 1)) == NULL) {
3137 f = &ast_null_frame;
3138 ao2_ref(details, -1);
3143 /* XXX we ignore the return value here, perhaps we should
3144 * disable the gateway if a write fails. I am not sure how a
3145 * write would fail, or even if a failure would be fatal so for
3146 * now we'll just ignore the return value. */
3147 gateway->s->tech->write(gateway->s, f);
3148 if ((f->frametype == AST_FRAME_VOICE) && (f->subclass.format.id != AST_FORMAT_SLINEAR) && ast_channel_readtrans(active)) {
3149 /* Only free the frame if we translated / duplicated it - otherwise,
3150 * let whatever is outside the frame hook do it */
3153 f = &ast_null_frame;
3154 ao2_ref(details, -1);
3158 /* force silence on the line if T.38 negotiation might be taking place */
3159 if (gateway->t38_state != T38_STATE_UNAVAILABLE && gateway->t38_state != T38_STATE_REJECTED) {
3160 if (f->frametype == AST_FRAME_VOICE && f->subclass.format.id == AST_FORMAT_SLINEAR) {
3161 short silence_buf[f->samples];
3162 struct ast_frame silence_frame = {
3163 .frametype = AST_FRAME_VOICE,
3164 .data.ptr = silence_buf,
3165 .samples = f->samples,
3166 .datalen = sizeof(silence_buf),
3168 ast_format_set(&silence_frame.subclass.format, AST_FORMAT_SLINEAR, 0);
3169 memset(silence_buf, 0, sizeof(silence_buf));
3171 ao2_ref(details, -1);
3172 return ast_frisolate(&silence_frame);
3174 ao2_ref(details, -1);
3175 return &ast_null_frame;
3179 ao2_ref(details, -1);
3183 /*! \brief Attach a gateway framehook object to a channel.
3184 * \param chan the channel to attach to
3185 * \param details fax session details
3186 * \return the framehook id of the attached framehook or -1 on error
3189 static int fax_gateway_attach(struct ast_channel *chan, struct ast_fax_session_details *details)
3191 struct fax_gateway *gateway;
3192 struct ast_framehook_interface fr_hook = {
3193 .version = AST_FRAMEHOOK_INTERFACE_VERSION,
3194 .event_cb = fax_gateway_framehook,
3195 .destroy_cb = fax_gateway_framehook_destroy,
3198 ast_string_field_set(details, result, "SUCCESS");
3199 ast_string_field_set(details, resultstr, "gateway operation started successfully");
3200 ast_string_field_set(details, error, "NO_ERROR");
3201 set_channel_variables(chan, details);
3203 /* set up the frame hook*/
3204 gateway = fax_gateway_new(chan, details);
3206 ast_string_field_set(details, result, "FAILED");
3207 ast_string_field_set(details, resultstr, "error initializing gateway session");
3208 ast_string_field_set(details, error, "INIT_ERROR");
3209 set_channel_variables(chan, details);
3210 report_fax_status(chan, details, "No Available Resource");
3214 fr_hook.data = gateway;
3215 ast_channel_lock(chan);
3216 gateway->framehook = ast_framehook_attach(chan, &fr_hook);
3217 ast_channel_unlock(chan);
3219 if (gateway->framehook < 0) {
3220 ao2_ref(gateway, -1);
3221 ast_string_field_set(details, result, "FAILED");
3222 ast_string_field_set(details, resultstr, "error attaching gateway to channel");
3223 ast_string_field_set(details, error, "INIT_ERROR");
3224 set_channel_variables(chan, details);
3228 return gateway->framehook;
3231 /*! \brief destroy a FAX detect structure */
3232 static void destroy_faxdetect(void *data)
3234 struct fax_detect *faxdetect = data;
3236 if (faxdetect->dsp) {
3237 ast_dsp_free(faxdetect->dsp);
3238 faxdetect->dsp = NULL;
3240 ao2_ref(faxdetect->details, -1);
3243 /*! \brief Create a new fax detect object.
3244 * \param chan the channel attaching to
3245 * \param timeout remove framehook in this time if set
3246 * \param flags required options
3247 * \return NULL or a fax gateway object
3249 static struct fax_detect *fax_detect_new(struct ast_channel *chan, int timeout, int flags)
3251 struct fax_detect *faxdetect = ao2_alloc(sizeof(*faxdetect), destroy_faxdetect);
3256 faxdetect->flags = flags;
3259 faxdetect->timeout_start = ast_tvnow();
3261 faxdetect->timeout_start.tv_sec = 0;
3262 faxdetect->timeout_start.tv_usec = 0;
3265 if (faxdetect->flags & FAX_DETECT_MODE_CNG) {
3266 faxdetect->dsp = ast_dsp_new();
3267 if (!faxdetect->dsp) {
3268 ao2_ref(faxdetect, -1);
3271 ast_dsp_set_features(faxdetect->dsp, DSP_FEATURE_FAX_DETECT);
3272 ast_dsp_set_faxmode(faxdetect->dsp, DSP_FAXMODE_DETECT_CNG | DSP_FAXMODE_DETECT_SQUELCH);
3274 faxdetect->dsp = NULL;
3280 /*! \brief Deref the faxdetect data structure when the faxdetect framehook is detached
3281 * \param data framehook data (faxdetect data)*/
3282 static void fax_detect_framehook_destroy(void *data) {
3283 struct fax_detect *faxdetect = data;
3285 ao2_ref(faxdetect, -1);
3288 /*! \brief Fax Detect Framehook
3290 * Listen for fax tones in audio path and enable jumping to a extension when detected.
3292 * \param chan channel
3293 * \param f frame to handle may be NULL
3294 * \param event framehook event
3295 * \param data framehook data (struct fax_detect *)
3297 * \return processed frame or NULL when f is NULL or a null frame
3299 static struct ast_frame *fax_detect_framehook(struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data) {
3300 struct fax_detect *faxdetect = data;
3301 struct ast_fax_session_details *details;
3302 struct ast_control_t38_parameters *control_params;
3303 struct ast_channel *peer;
3306 details = faxdetect->details;
3309 case AST_FRAMEHOOK_EVENT_ATTACHED:
3310 /* Setup format for DSP on ATTACH*/
3311 ast_format_copy(&faxdetect->orig_format, ast_channel_readformat(chan));
3312 switch (ast_channel_readformat(chan)->id) {
3313 case AST_FORMAT_SLINEAR:
3314 case AST_FORMAT_ALAW:
3315 case AST_FORMAT_ULAW:
3318 if (ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR)) {
3319 ast_framehook_detach(chan, details->faxdetect_id);
3320 details->faxdetect_id = -1;
3325 case AST_FRAMEHOOK_EVENT_DETACHED:
3326 /* restore audio formats when we are detached */
3327 ast_set_read_format(chan, &faxdetect->orig_format);
3328 if ((peer = ast_bridged_channel(chan))) {
3329 ast_channel_make_compatible(chan, peer);
3332 case AST_FRAMEHOOK_EVENT_READ:
3340 if (details->faxdetect_id < 0) {
3344 if ((!ast_tvzero(faxdetect->timeout_start) &&
3345 (ast_tvdiff_ms(ast_tvnow(), faxdetect->timeout_start) > faxdetect->timeout))) {
3346 ast_framehook_detach(chan, details->faxdetect_id);
3347 details->faxdetect_id = -1;
3351 /* only handle VOICE and CONTROL frames*/
3352 switch (f->frametype) {
3353 case AST_FRAME_VOICE:
3354 /* we have no DSP this means we not detecting CNG */
3355 if (!faxdetect->dsp) {
3358 /* We can only process some formats*/
3359 switch (f->subclass.format.id) {
3360 case AST_FORMAT_SLINEAR:
3361 case AST_FORMAT_ALAW:
3362 case AST_FORMAT_ULAW:
3368 case AST_FRAME_CONTROL:
3369 if ((f->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
3370 (faxdetect->flags & FAX_DETECT_MODE_T38)) {
3378 if (f->frametype == AST_FRAME_VOICE) {
3379 f = ast_dsp_process(chan, faxdetect->dsp, f);
3380 if (f->frametype == AST_FRAME_DTMF) {
3381 result = f->subclass.integer;
3383 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->datalen == sizeof(struct ast_control_t38_parameters))) {
3384 control_params = f->data.ptr;
3385 switch (control_params->request_response) {
3386 case AST_T38_NEGOTIATED:
3387 case AST_T38_REQUEST_NEGOTIATE:
3396 const char *target_context = S_OR(ast_channel_macrocontext(chan), ast_channel_context(chan));
3400 ast_channel_unlock(chan);
3401 if (ast_exists_extension(chan, target_context, "fax", 1,
3402 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
3403 ast_channel_lock(chan);
3404 ast_verb(2, "Redirecting '%s' to fax extension due to %s detection\n",
3405 ast_channel_name(chan), (result == 'f') ? "CNG" : "T38");
3406 pbx_builtin_setvar_helper(chan, "FAXEXTEN", ast_channel_exten(chan));
3407 if (ast_async_goto(chan, target_context, "fax", 1)) {
3408 ast_log(LOG_NOTICE, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(chan), target_context);
3411 f = &ast_null_frame;
3413 ast_channel_lock(chan);
3414 ast_log(LOG_NOTICE, "FAX %s detected but no fax extension in context (%s)\n",
3415 (result == 'f') ? "CNG" : "T38", target_context);
3418 ast_framehook_detach(chan, details->faxdetect_id);
3419 details->faxdetect_id = -1;
3425 /*! \brief Attach a faxdetect framehook object to a channel.
3426 * \param chan the channel to attach to
3427 * \param timeout remove framehook in this time if set
3428 * \return the faxdetect structure or NULL on error
3429 * \param flags required options
3432 static int fax_detect_attach(struct ast_channel *chan, int timeout, int flags)
3434 struct fax_detect *faxdetect;
3435 struct ast_fax_session_details *details;
3436 struct ast_framehook_interface fr_hook = {
3437 .version = AST_FRAMEHOOK_INTERFACE_VERSION,
3438 .event_cb = fax_detect_framehook,
3439 .destroy_cb = fax_detect_framehook_destroy,
3442 if (!(details = find_or_create_details(chan))) {
3443 ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
3447 /* set up the frame hook*/
3448 faxdetect = fax_detect_new(chan, timeout, flags);
3450 ao2_ref(details, -1);
3454 fr_hook.data = faxdetect;
3455 faxdetect->details = details;
3456 ast_channel_lock(chan);
3457 details->faxdetect_id = ast_framehook_attach(chan, &fr_hook);
3458 ast_channel_unlock(chan);
3460 if (details->faxdetect_id < 0) {
3461 ao2_ref(faxdetect, -1);
3464 return details->faxdetect_id;
3467 /*! \brief hash callback for ao2 */
3468 static int session_hash_cb(const void *obj, const int flags)
3470 const struct ast_fax_session *s = obj;
3475 /*! \brief compare callback for ao2 */
3476 static int session_cmp_cb(void *obj, void *arg, int flags)
3478 struct ast_fax_session *lhs = obj, *rhs = arg;
3480 return (lhs->id == rhs->id) ? CMP_MATCH | CMP_STOP : 0;
3483 /*! \brief fax session tab completion */
3484 static char *fax_session_tab_complete(struct ast_cli_args *a)
3489 struct ao2_iterator i;
3490 struct ast_fax_session *s;
3497 tklen = strlen(a->word);
3498 i = ao2_iterator_init(faxregistry.container, 0);
3499 while ((s = ao2_iterator_next(&i))) {
3500 snprintf(tbuf, sizeof(tbuf), "%d", s->id);
3501 if (!strncasecmp(a->word, tbuf, tklen) && ++wordnum > a->n) {
3502 name = ast_strdup(tbuf);
3508 ao2_iterator_destroy(&i);
3512 static char *cli_fax_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)