Sat Apr 26 2014 22:01:40

Asterisk developer's documentation


res_fax.c
Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 2008-2009, Digium, Inc.
00005  *
00006  * Dwayne M. Hubbard <dhubbard@digium.com>
00007  * Kevin P. Fleming <kpfleming@digium.com>
00008  * Matthew Nicholson <mnicholson@digium.com>
00009  *
00010  * Initial T.38-gateway code
00011  * 2008, Daniel Ferenci <daniel.ferenci@nethemba.com>
00012  * Created by Nethemba s.r.o. http://www.nethemba.com
00013  * Sponsored by IPEX a.s. http://www.ipex.cz
00014  *
00015  * T.38-gateway integration into asterisk app_fax and rework
00016  * 2008-2011, Gregory Hinton Nietsky <gregory@distrotech.co.za>
00017  * dns Telecom http://www.dnstelecom.co.za
00018  *
00019  * Modified to make T.38-gateway compatible with Asterisk 1.6.2
00020  * 2010, Anton Verevkin <mymail@verevkin.it>
00021  * ViaNetTV http://www.vianettv.com
00022  *
00023  * Modified to make T.38-gateway work
00024  * 2010, Klaus Darilion, IPCom GmbH, www.ipcom.at
00025  *
00026  * See http://www.asterisk.org for more information about
00027  * the Asterisk project. Please do not directly contact
00028  * any of the maintainers of this project for assistance;
00029  * the project provides a web site, mailing lists and IRC
00030  * channels for your use.
00031  *
00032  * This program is free software, distributed under the terms of
00033  * the GNU General Public License Version 2. See the LICENSE file
00034  * at the top of the source tree.
00035  */
00036 
00037 /*** MODULEINFO
00038    <conflict>app_fax</conflict>
00039    <support_level>core</support_level>
00040 ***/
00041 
00042 /*! \file
00043  *
00044  * \brief Generic FAX Resource for FAX technology resource modules
00045  *
00046  * \author Dwayne M. Hubbard <dhubbard@digium.com>
00047  * \author Kevin P. Fleming <kpfleming@digium.com>
00048  * \author Matthew Nicholson <mnicholson@digium.com>
00049  * \author Gregory H. Nietsky  <gregory@distrotech.co.za>
00050  *
00051  * A generic FAX resource module that provides SendFAX and ReceiveFAX applications.
00052  * This module requires FAX technology modules, like res_fax_spandsp, to register with it
00053  * so it can use the technology modules to perform the actual FAX transmissions.
00054  * \ingroup applications
00055  */
00056 
00057 #include "asterisk.h"
00058 
00059 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 409053 $")
00060 
00061 #include "asterisk/io.h"
00062 #include "asterisk/file.h"
00063 #include "asterisk/logger.h"
00064 #include "asterisk/module.h"
00065 #include "asterisk/app.h"
00066 #include "asterisk/lock.h"
00067 #include "asterisk/options.h"
00068 #include "asterisk/strings.h"
00069 #include "asterisk/cli.h"
00070 #include "asterisk/utils.h"
00071 #include "asterisk/config.h"
00072 #include "asterisk/astobj2.h"
00073 #include "asterisk/res_fax.h"
00074 #include "asterisk/file.h"
00075 #include "asterisk/channel.h"
00076 #include "asterisk/pbx.h"
00077 #include "asterisk/manager.h"
00078 #include "asterisk/dsp.h"
00079 #include "asterisk/indications.h"
00080 #include "asterisk/ast_version.h"
00081 #include "asterisk/translate.h"
00082 
00083 /*** DOCUMENTATION
00084    <application name="ReceiveFAX" language="en_US" module="res_fax">
00085       <synopsis>
00086          Receive a FAX and save as a TIFF/F file.
00087       </synopsis>
00088       <syntax>
00089          <parameter name="filename" required="true" />
00090          <parameter name="options">
00091             <optionlist>
00092                <option name="d">
00093                   <para>Enable FAX debugging.</para>
00094                </option>
00095                <option name="f">
00096                   <para>Allow audio fallback FAX transfer on T.38 capable channels.</para>
00097                </option>
00098                <option name="F">
00099                   <para>Force usage of audio mode on T.38 capable channels.</para>
00100                </option>
00101                <option name="s">
00102                   <para>Send progress Manager events (overrides statusevents setting in res_fax.conf).</para>
00103                </option>
00104             </optionlist>
00105          </parameter>
00106       </syntax>
00107       <description>
00108          <para>This application is provided by res_fax, which is a FAX technology agnostic module
00109          that utilizes FAX technology resource modules to complete a FAX transmission.</para>
00110          <para>Session arguments can be set by the FAXOPT function and to check results of the ReceiveFax() application.</para>
00111       </description>
00112       <see-also>
00113          <ref type="function">FAXOPT</ref>
00114       </see-also>
00115    </application>
00116    <application name="SendFAX" language="en_US" module="res_fax">
00117       <synopsis>
00118          Sends a specified TIFF/F file as a FAX.
00119       </synopsis>
00120       <syntax>
00121          <parameter name="filename" required="true" argsep="&amp;">
00122             <argument name="filename2" multiple="true">
00123                <para>TIFF file to send as a FAX.</para>
00124             </argument>
00125          </parameter>
00126          <parameter name="options">
00127             <optionlist>
00128                <option name="d">
00129                   <para>Enable FAX debugging.</para>
00130                </option>
00131                <option name="f">
00132                   <para>Allow audio fallback FAX transfer on T.38 capable channels.</para>
00133                </option>
00134                <option name="F">
00135                   <para>Force usage of audio mode on T.38 capable channels.</para>
00136                </option>
00137                <option name="s">
00138                   <para>Send progress Manager events (overrides statusevents setting in res_fax.conf).</para>
00139                </option>
00140                <option name="z">
00141                   <para>Initiate a T.38 reinvite on the channel if the remote end does not.</para>
00142                </option>
00143             </optionlist>
00144          </parameter>
00145       </syntax>
00146       <description>
00147          <para>This application is provided by res_fax, which is a FAX technology agnostic module
00148          that utilizes FAX technology resource modules to complete a FAX transmission.</para>
00149          <para>Session arguments can be set by the FAXOPT function and to check results of the SendFax() application.</para>
00150       </description>
00151       <see-also>
00152          <ref type="function">FAXOPT</ref>
00153       </see-also>
00154    </application>
00155    <function name="FAXOPT" language="en_US" module="res_fax">
00156       <synopsis>
00157          Gets/sets various pieces of information about a fax session.
00158       </synopsis>
00159       <syntax>
00160          <parameter name="item" required="true">
00161             <enumlist>
00162                <enum name="ecm">
00163                   <para>R/W Error Correction Mode (ECM) enable with 'yes', disable with 'no'.</para>
00164                </enum>
00165                <enum name="error">
00166                   <para>R/O FAX transmission error code upon failure.</para>
00167                </enum>
00168                <enum name="filename">
00169                   <para>R/O Filename of the first file of the FAX transmission.</para>
00170                </enum>
00171                <enum name="filenames">
00172                   <para>R/O Filenames of all of the files in the FAX transmission (comma separated).</para>
00173                </enum>
00174                <enum name="headerinfo">
00175                   <para>R/W FAX header information.</para>
00176                </enum>
00177                <enum name="localstationid">
00178                   <para>R/W Local Station Identification.</para>
00179                </enum>
00180                <enum name="minrate">
00181                   <para>R/W Minimum transfer rate set before transmission.</para>
00182                </enum>
00183                <enum name="maxrate">
00184                   <para>R/W Maximum transfer rate set before transmission.</para>
00185                </enum>
00186                <enum name="modem">
00187                   <para>R/W Modem type (v17/v27/v29).</para>
00188                </enum>
00189                <enum name="gateway">
00190                   <para>R/W T38 fax gateway, with optional fax activity timeout in seconds (yes[,timeout]/no)</para>
00191                </enum>
00192                <enum name="faxdetect">
00193                   <para>R/W Enable FAX detect with optional timeout in seconds (yes,t38,cng[,timeout]/no)</para>
00194                </enum>
00195                <enum name="pages">
00196                   <para>R/O Number of pages transferred.</para>
00197                </enum>
00198                <enum name="rate">
00199                   <para>R/O Negotiated transmission rate.</para>
00200                </enum>
00201                <enum name="remotestationid">
00202                   <para>R/O Remote Station Identification after transmission.</para>
00203                </enum>
00204                <enum name="resolution">
00205                   <para>R/O Negotiated image resolution after transmission.</para>
00206                </enum>
00207                <enum name="sessionid">
00208                   <para>R/O Session ID of the FAX transmission.</para>
00209                </enum>
00210                <enum name="status">
00211                   <para>R/O Result Status of the FAX transmission.</para>
00212                </enum>
00213                <enum name="statusstr">
00214                   <para>R/O Verbose Result Status of the FAX transmission.</para>
00215                </enum>
00216             </enumlist>
00217          </parameter>
00218       </syntax>
00219       <description>
00220          <para>FAXOPT can be used to override the settings for a FAX session listed in <filename>res_fax.conf</filename>,
00221             it can also be used to retreive information about a FAX session that has finished eg. pages/status.</para>
00222       </description>
00223       <see-also>
00224          <ref type="application">ReceiveFax</ref>
00225          <ref type="application">SendFax</ref>
00226       </see-also>
00227    </function>
00228 ***/
00229 
00230 static const char app_receivefax[] = "ReceiveFAX";
00231 static const char app_sendfax[] = "SendFAX";
00232 
00233 struct debug_info_history {
00234    unsigned int consec_frames;
00235    unsigned int consec_ms;
00236    unsigned char silence;
00237 };
00238 
00239 struct ast_fax_debug_info {
00240    struct timeval base_tv;
00241    struct debug_info_history c2s, s2c;
00242    struct ast_dsp *dsp;
00243 };
00244 
00245 /*! \brief used for gateway framehook */
00246 struct fax_gateway {
00247    /*! \brief FAX Session */
00248    struct ast_fax_session *s;
00249    struct ast_fax_session *peer_v21_session;
00250    struct ast_fax_session *chan_v21_session;
00251    /*! \brief reserved fax session token */
00252    struct ast_fax_tech_token *token;
00253    /*! \brief the start of our timeout counter */
00254    struct timeval timeout_start;
00255    /*! \brief framehook used in gateway mode */
00256    int framehook;
00257    /*! \brief bridged */
00258    int bridged:1;
00259    /*! \brief 1 if a v21 preamble has been detected */
00260    int detected_v21:1;
00261    /*! \brief a flag to track the state of our negotiation */
00262    enum ast_t38_state t38_state;
00263    /*! \brief original audio formats */
00264    struct ast_format chan_read_format;
00265    struct ast_format chan_write_format;
00266    struct ast_format peer_read_format;
00267    struct ast_format peer_write_format;
00268 };
00269 
00270 /*! \brief used for fax detect framehook */
00271 struct fax_detect {
00272    /*! \brief the start of our timeout counter */
00273    struct timeval timeout_start;
00274    /*! \brief faxdetect timeout */
00275    int timeout;
00276    /*! \brief DSP Processor */
00277    struct ast_dsp *dsp;
00278    /*! \brief original audio formats */
00279    struct ast_format orig_format;
00280    /*! \brief fax session details */
00281    struct ast_fax_session_details *details;
00282    /*! \brief mode */
00283    int flags;
00284 };
00285 
00286 /*! \brief FAX Detect flags */
00287 #define FAX_DETECT_MODE_CNG   (1 << 0)
00288 #define FAX_DETECT_MODE_T38   (1 << 1)
00289 #define FAX_DETECT_MODE_BOTH  (FAX_DETECT_MODE_CNG | FAX_DETECT_MODE_T38)
00290 
00291 static int fax_logger_level = -1;
00292 
00293 /*! \brief maximum buckets for res_fax ao2 containers */
00294 #define FAX_MAXBUCKETS 10
00295 
00296 #define RES_FAX_TIMEOUT 10000
00297 #define FAX_GATEWAY_TIMEOUT RES_FAX_TIMEOUT
00298 
00299 /*! \brief The faxregistry is used to manage information and statistics for all FAX sessions. */
00300 static struct {
00301    /*! The number of active FAX sessions */
00302    int active_sessions;
00303    /*! The number of reserved FAX sessions */
00304    int reserved_sessions;
00305    /*! active sessions are astobj2 objects */
00306    struct ao2_container *container;
00307    /*! Total number of Tx FAX attempts */
00308    int fax_tx_attempts;
00309    /*! Total number of Rx FAX attempts */
00310    int fax_rx_attempts;
00311    /*! Number of successful FAX transmissions */
00312    int fax_complete;
00313    /*! Number of failed FAX transmissions */
00314    int fax_failures;
00315    /*! the next unique session name */
00316    int nextsessionname;
00317 } faxregistry;
00318 
00319 /*! \brief registered FAX technology modules are put into this list */
00320 struct fax_module {
00321    const struct ast_fax_tech *tech;
00322    AST_RWLIST_ENTRY(fax_module) list;
00323 };
00324 static AST_RWLIST_HEAD_STATIC(faxmodules, fax_module);
00325 
00326 #define RES_FAX_MINRATE 4800
00327 #define RES_FAX_MAXRATE 14400
00328 #define RES_FAX_STATUSEVENTS 0
00329 #define RES_FAX_MODEM (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V27 | AST_FAX_MODEM_V29)
00330 
00331 struct fax_options {
00332    enum ast_fax_modems modems;
00333    uint32_t statusevents:1;
00334    uint32_t ecm:1;
00335    unsigned int minrate;
00336    unsigned int maxrate;
00337 };
00338 
00339 static struct fax_options general_options;
00340 
00341 static const struct fax_options default_options = {
00342    .minrate = RES_FAX_MINRATE,
00343    .maxrate = RES_FAX_MAXRATE,
00344    .statusevents = RES_FAX_STATUSEVENTS,
00345    .modems = RES_FAX_MODEM,
00346    .ecm = AST_FAX_OPTFLAG_TRUE,
00347 };
00348 
00349 AST_RWLOCK_DEFINE_STATIC(options_lock);
00350 
00351 static void get_general_options(struct fax_options* options);
00352 static void set_general_options(const struct fax_options* options);
00353 
00354 static const char *config = "res_fax.conf";
00355 
00356 static int global_fax_debug = 0;
00357 
00358 enum {
00359    OPT_CALLEDMODE  = (1 << 0),
00360    OPT_CALLERMODE  = (1 << 1),
00361    OPT_DEBUG       = (1 << 2),
00362    OPT_STATUS      = (1 << 3),
00363    OPT_ALLOWAUDIO  = (1 << 5),
00364    OPT_REQUEST_T38 = (1 << 6),
00365    OPT_FORCE_AUDIO = (1 << 7),
00366 };
00367 
00368 AST_APP_OPTIONS(fax_exec_options, BEGIN_OPTIONS
00369    AST_APP_OPTION('a', OPT_CALLEDMODE),
00370    AST_APP_OPTION('c', OPT_CALLERMODE),
00371    AST_APP_OPTION('d', OPT_DEBUG),
00372    AST_APP_OPTION('f', OPT_ALLOWAUDIO),
00373    AST_APP_OPTION('F', OPT_FORCE_AUDIO),
00374    AST_APP_OPTION('s', OPT_STATUS),
00375    AST_APP_OPTION('z', OPT_REQUEST_T38),
00376 END_OPTIONS);
00377 
00378 struct manager_event_info {
00379    char context[AST_MAX_CONTEXT];
00380    char exten[AST_MAX_EXTENSION];
00381    char cid[128];
00382 };
00383 
00384 static void debug_check_frame_for_silence(struct ast_fax_session *s, unsigned int c2s, struct ast_frame *frame)
00385 {
00386    struct debug_info_history *history = c2s ? &s->debug_info->c2s : &s->debug_info->s2c;
00387    int dspsilence;
00388    unsigned int last_consec_frames, last_consec_ms;
00389    unsigned char wassil;
00390    struct timeval diff;
00391 
00392    diff = ast_tvsub(ast_tvnow(), s->debug_info->base_tv);
00393 
00394    ast_dsp_reset(s->debug_info->dsp);
00395    ast_dsp_silence(s->debug_info->dsp, frame, &dspsilence);
00396 
00397    wassil = history->silence;
00398    history->silence = (dspsilence != 0) ? 1 : 0;
00399    if (history->silence != wassil) {
00400       last_consec_frames = history->consec_frames;
00401       last_consec_ms = history->consec_ms;
00402       history->consec_frames = 0;
00403       history->consec_ms = 0;
00404 
00405       if ((last_consec_frames != 0)) {
00406          ast_verb(6, "Channel '%s' fax session '%d', [ %.3ld.%.6ld ], %s sent %d frames (%d ms) of %s.\n",
00407              s->channame, s->id, (long) diff.tv_sec, (long int) diff.tv_usec,
00408              (c2s) ? "channel" : "stack", last_consec_frames, last_consec_ms,
00409              (wassil) ? "silence" : "energy");
00410       }
00411    }
00412 
00413    history->consec_frames++;
00414    history->consec_ms += (frame->samples / 8);
00415 }
00416 
00417 static void destroy_callback(void *data)
00418 {
00419    if (data) {
00420       ao2_ref(data, -1);
00421    }
00422 }
00423 
00424 static const struct ast_datastore_info fax_datastore = {
00425    .type = "res_fax",
00426    .destroy = destroy_callback,
00427 };
00428 
00429 /*! \brief returns a reference counted pointer to a fax datastore, if it exists */
00430 static struct ast_fax_session_details *find_details(struct ast_channel *chan)
00431 {
00432    struct ast_fax_session_details *details;
00433    struct ast_datastore *datastore;
00434 
00435    ast_channel_lock(chan);
00436    if (!(datastore = ast_channel_datastore_find(chan, &fax_datastore, NULL))) {
00437       ast_channel_unlock(chan);
00438       return NULL;
00439    }
00440    if (!(details = datastore->data)) {
00441       ast_log(LOG_WARNING, "Huh?  channel '%s' has a FAX datastore without data!\n", ast_channel_name(chan));
00442       ast_channel_unlock(chan);
00443       return NULL;
00444    }
00445    ao2_ref(details, 1);
00446    ast_channel_unlock(chan);
00447 
00448    return details;
00449 }
00450 
00451 /*! \brief destroy a FAX session details structure */
00452 static void destroy_session_details(void *details)
00453 {
00454    struct ast_fax_session_details *d = details;
00455    struct ast_fax_document *doc;
00456 
00457    while ((doc = AST_LIST_REMOVE_HEAD(&d->documents, next))) {
00458       ast_free(doc);
00459    }
00460    ast_string_field_free_memory(d);
00461 }
00462 
00463 /*! \brief create a FAX session details structure */
00464 static struct ast_fax_session_details *session_details_new(void)
00465 {
00466    struct ast_fax_session_details *d;
00467    struct fax_options options;
00468 
00469    if (!(d = ao2_alloc(sizeof(*d), destroy_session_details))) {
00470       return NULL;
00471    }
00472 
00473    if (ast_string_field_init(d, 512)) {
00474       ao2_ref(d, -1);
00475       return NULL;
00476    }
00477 
00478    get_general_options(&options);
00479 
00480    AST_LIST_HEAD_INIT_NOLOCK(&d->documents);
00481 
00482    /* These options need to be set to the configured default and may be overridden by
00483     * SendFAX, ReceiveFAX, or FAXOPT */
00484    d->option.request_t38 = AST_FAX_OPTFLAG_FALSE;
00485    d->option.send_cng = AST_FAX_OPTFLAG_FALSE;
00486    d->option.send_ced = AST_FAX_OPTFLAG_FALSE;
00487    d->option.ecm = options.ecm;
00488    d->option.statusevents = options.statusevents;
00489    d->modems = options.modems;
00490    d->minrate = options.minrate;
00491    d->maxrate = options.maxrate;
00492    d->gateway_id = -1;
00493    d->faxdetect_id = -1;
00494    d->gateway_timeout = 0;
00495 
00496    return d;
00497 }
00498 
00499 static struct ast_control_t38_parameters our_t38_parameters = {
00500    .version = 0,
00501    .max_ifp = 400,
00502    .rate = AST_T38_RATE_14400,
00503    .rate_management = AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF,
00504 };
00505 
00506 static void t38_parameters_ast_to_fax(struct ast_fax_t38_parameters *dst, const struct ast_control_t38_parameters *src)
00507 {
00508    dst->version = src->version;
00509    dst->max_ifp = src->max_ifp;
00510    dst->rate = src->rate;
00511    dst->rate_management = src->rate_management;
00512    dst->fill_bit_removal = src->fill_bit_removal;
00513    dst->transcoding_mmr = src->transcoding_mmr;
00514    dst->transcoding_jbig = src->transcoding_jbig;
00515 }
00516 
00517 static void t38_parameters_fax_to_ast(struct ast_control_t38_parameters *dst, const struct ast_fax_t38_parameters *src)
00518 {
00519    dst->version = src->version;
00520    dst->max_ifp = src->max_ifp;
00521    dst->rate = src->rate;
00522    dst->rate_management = src->rate_management;
00523    dst->fill_bit_removal = src->fill_bit_removal;
00524    dst->transcoding_mmr = src->transcoding_mmr;
00525    dst->transcoding_jbig = src->transcoding_jbig;
00526 }
00527 
00528 /*! \brief returns a reference counted details structure from the channel's fax datastore.  If the datastore
00529  * does not exist it will be created */
00530 static struct ast_fax_session_details *find_or_create_details(struct ast_channel *chan)
00531 {
00532    struct ast_fax_session_details *details;
00533    struct ast_datastore *datastore;
00534 
00535    if ((details = find_details(chan))) {
00536       return details;
00537    }
00538    /* channel does not have one so we must create one */
00539    if (!(details = session_details_new())) {
00540       ast_log(LOG_WARNING, "channel '%s' can't get a FAX details structure for the datastore!\n", ast_channel_name(chan));
00541       return NULL;
00542    }
00543    if (!(datastore = ast_datastore_alloc(&fax_datastore, NULL))) {
00544       ao2_ref(details, -1);
00545       ast_log(LOG_WARNING, "channel '%s' can't get a datastore!\n", ast_channel_name(chan));
00546       return NULL;
00547    }
00548    /* add the datastore to the channel and increment the refcount */
00549    datastore->data = details;
00550 
00551    /* initialize default T.38 parameters */
00552    t38_parameters_ast_to_fax(&details->our_t38_parameters, &our_t38_parameters);
00553    t38_parameters_ast_to_fax(&details->their_t38_parameters, &our_t38_parameters);
00554 
00555    ao2_ref(details, 1);
00556    ast_channel_lock(chan);
00557    ast_channel_datastore_add(chan, datastore);
00558    ast_channel_unlock(chan);
00559    return details;
00560 }
00561 
00562 unsigned int ast_fax_maxrate(void)
00563 {
00564    struct fax_options options;
00565    get_general_options(&options);
00566 
00567    return options.maxrate;
00568 }
00569 
00570 unsigned int ast_fax_minrate(void)
00571 {
00572    struct fax_options options;
00573    get_general_options(&options);
00574 
00575    return options.minrate;
00576 }
00577 
00578 static int update_modem_bits(enum ast_fax_modems *bits, const char *value)
00579 {
00580    char *m[5], *tok, *v = (char *)value;
00581    int i = 0, j;
00582 
00583    if (!strchr(v, ',')) {
00584       m[i++] = v;
00585       m[i] = NULL;
00586    } else {
00587       tok = strtok(v, ", ");
00588       while (tok && (i < 5)) {
00589          m[i++] = tok;
00590          tok = strtok(NULL, ", ");
00591       }
00592       m[i] = NULL;
00593    }
00594 
00595    *bits = 0;
00596    for (j = 0; j < i; j++) {
00597       if (!strcasecmp(m[j], "v17")) {
00598          *bits |= AST_FAX_MODEM_V17;
00599       } else if (!strcasecmp(m[j], "v27")) {
00600          *bits |= AST_FAX_MODEM_V27;
00601       } else if (!strcasecmp(m[j], "v29")) {
00602          *bits |= AST_FAX_MODEM_V29;
00603       } else if (!strcasecmp(m[j], "v34")) {
00604          *bits |= AST_FAX_MODEM_V34;
00605       } else {
00606          ast_log(LOG_WARNING, "ignoring invalid modem setting: '%s', valid options {v17 | v27 | v29 | v34}\n", m[j]);
00607       }
00608    }
00609    return 0;
00610 }
00611 static char *ast_fax_caps_to_str(enum ast_fax_capabilities caps, char *buf, size_t bufsize)
00612 {
00613    char *out = buf;
00614    size_t size = bufsize;
00615    int first = 1;
00616 
00617    if (caps & AST_FAX_TECH_SEND) {
00618       if (!first) {
00619          ast_build_string(&buf, &size, ",");
00620       }
00621       ast_build_string(&buf, &size, "SEND");
00622       first = 0;
00623    }
00624    if (caps & AST_FAX_TECH_RECEIVE) {
00625       if (!first) {
00626          ast_build_string(&buf, &size, ",");
00627       }
00628       ast_build_string(&buf, &size, "RECEIVE");
00629       first = 0;
00630    }
00631    if (caps & AST_FAX_TECH_AUDIO) {
00632       if (!first) {
00633          ast_build_string(&buf, &size, ",");
00634       }
00635       ast_build_string(&buf, &size, "AUDIO");
00636       first = 0;
00637    }
00638    if (caps & AST_FAX_TECH_T38) {
00639       if (!first) {
00640          ast_build_string(&buf, &size, ",");
00641       }
00642       ast_build_string(&buf, &size, "T38");
00643       first = 0;
00644    }
00645    if (caps & AST_FAX_TECH_MULTI_DOC) {
00646       if (!first) {
00647          ast_build_string(&buf, &size, ",");
00648       }
00649       ast_build_string(&buf, &size, "MULTI_DOC");
00650       first = 0;
00651    }
00652    if (caps & AST_FAX_TECH_GATEWAY) {
00653       if (!first) {
00654          ast_build_string(&buf, &size, ",");
00655       }
00656       ast_build_string(&buf, &size, "GATEWAY");
00657       first = 0;
00658    }
00659    if (caps & AST_FAX_TECH_V21_DETECT) {
00660       if (!first) {
00661          ast_build_string(&buf, &size, ",");
00662       }
00663       ast_build_string(&buf, &size, "V21");
00664       first = 0;
00665    }
00666 
00667    return out;
00668 }
00669 
00670 static int ast_fax_modem_to_str(enum ast_fax_modems bits, char *tbuf, size_t bufsize)
00671 {
00672    int count = 0;
00673 
00674    if (bits & AST_FAX_MODEM_V17) {
00675       strcat(tbuf, "V17");
00676       count++;
00677    }
00678    if (bits & AST_FAX_MODEM_V27) {
00679       if (count) {
00680          strcat(tbuf, ",");
00681       }
00682       strcat(tbuf, "V27");
00683       count++;
00684    }
00685    if (bits & AST_FAX_MODEM_V29) {
00686       if (count) {
00687          strcat(tbuf, ",");
00688       }
00689       strcat(tbuf, "V29");
00690       count++;
00691    }
00692    if (bits & AST_FAX_MODEM_V34) {
00693       if (count) {
00694          strcat(tbuf, ",");
00695       }
00696       strcat(tbuf, "V34");
00697       count++;
00698    }
00699 
00700    return 0;
00701 }
00702 
00703 static int check_modem_rate(enum ast_fax_modems modems, unsigned int rate)
00704 {
00705    switch (rate) {
00706    case 2400:
00707       if (!(modems & (AST_FAX_MODEM_V34))) {
00708          return 1;
00709       }
00710       break;
00711    case 4800:
00712       if (!(modems & (AST_FAX_MODEM_V27 | AST_FAX_MODEM_V34))) {
00713          return 1;
00714       }
00715       break;
00716    case 7200:
00717       if (!(modems & (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V29 | AST_FAX_MODEM_V34))) {
00718          return 1;
00719       }
00720       break;
00721    case 9600:
00722       if (!(modems & (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V27 | AST_FAX_MODEM_V29 | AST_FAX_MODEM_V34))) {
00723          return 1;
00724       }
00725       break;
00726    case 12000:
00727    case 14400:
00728       if (!(modems & (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V34))) {
00729          return 1;
00730       }
00731       break;
00732    case 28800:
00733    case 33600:
00734       if (!(modems & AST_FAX_MODEM_V34)) {
00735          return 1;
00736       }
00737       break;
00738    default:
00739       /* this should never happen */
00740       return 1;
00741    }
00742 
00743    return 0;
00744 }
00745 
00746 /*! \brief register a FAX technology module */
00747 int ast_fax_tech_register(struct ast_fax_tech *tech)
00748 {
00749    struct fax_module *fax;
00750 
00751    if (!(fax = ast_calloc(1, sizeof(*fax)))) {
00752       return -1;
00753    }
00754    fax->tech = tech;
00755    AST_RWLIST_WRLOCK(&faxmodules);
00756    AST_RWLIST_INSERT_TAIL(&faxmodules, fax, list);
00757    AST_RWLIST_UNLOCK(&faxmodules);
00758    ast_module_ref(ast_module_info->self);
00759 
00760    ast_verb(3, "Registered handler for '%s' (%s)\n", fax->tech->type, fax->tech->description);
00761 
00762    return 0;
00763 }
00764 
00765 /*! \brief unregister a FAX technology module */
00766 void ast_fax_tech_unregister(struct ast_fax_tech *tech)
00767 {
00768    struct fax_module *fax;
00769 
00770    ast_verb(3, "Unregistering FAX module type '%s'\n", tech->type);
00771 
00772    AST_RWLIST_WRLOCK(&faxmodules);
00773    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&faxmodules, fax, list) {
00774       if (fax->tech != tech) {
00775          continue;
00776       }
00777       AST_RWLIST_REMOVE_CURRENT(list);
00778       ast_module_unref(ast_module_info->self);
00779       ast_free(fax);
00780       ast_verb(4, "Unregistered FAX module type '%s'\n", tech->type);
00781       break;
00782    }
00783    AST_RWLIST_TRAVERSE_SAFE_END;
00784    AST_RWLIST_UNLOCK(&faxmodules);
00785 }
00786 
00787 /*! \brief convert a ast_fax_state to a string */
00788 const char *ast_fax_state_to_str(enum ast_fax_state state)
00789 {
00790    switch (state) {
00791    case AST_FAX_STATE_UNINITIALIZED:
00792       return "Uninitialized";
00793    case AST_FAX_STATE_INITIALIZED:
00794       return "Initialized";
00795    case AST_FAX_STATE_OPEN:
00796       return "Open";
00797    case AST_FAX_STATE_ACTIVE:
00798       return "Active";
00799    case AST_FAX_STATE_COMPLETE:
00800       return "Complete";
00801    case AST_FAX_STATE_RESERVED:
00802       return "Reserved";
00803    case AST_FAX_STATE_INACTIVE:
00804       return "Inactive";
00805    default:
00806       ast_log(LOG_WARNING, "unhandled FAX state: %d\n", state);
00807       return "Unknown";
00808    }
00809 }
00810 
00811 void ast_fax_log(int level, const char *file, const int line, const char *function, const char *msg)
00812 {
00813    if (fax_logger_level != -1) {
00814       ast_log_dynamic_level(fax_logger_level, "%s", msg);
00815    } else {
00816       ast_log(level, file, line, function, "%s", msg);
00817    }
00818 }
00819 
00820 /*! \brief convert a rate string to a rate */
00821 static unsigned int fax_rate_str_to_int(const char *ratestr)
00822 {
00823    int rate;
00824 
00825    if (sscanf(ratestr, "%d", &rate) != 1) {
00826       ast_log(LOG_ERROR, "failed to sscanf '%s' to rate\n", ratestr);
00827       return 0;
00828    }
00829    switch (rate) {
00830    case 2400:
00831    case 4800:
00832    case 7200:
00833    case 9600:
00834    case 12000:
00835    case 14400:
00836    case 28800:
00837    case 33600:
00838       return rate;
00839    default:
00840       ast_log(LOG_WARNING, "ignoring invalid rate '%s'.  Valid options are {2400 | 4800 | 7200 | 9600 | 12000 | 14400 | 28800 | 33600}\n", ratestr);
00841       return 0;
00842    }
00843 }
00844 
00845 /*! \brief Release a session token.
00846  * \param s a session returned from fax_session_reserve()
00847  * \param token a token generated from fax_session_reserve()
00848  *
00849  * This function releases the given token and marks the given session as no
00850  * longer reserved. It is safe to call on a session that is not actually
00851  * reserved and with a NULL token. This is so that sessions returned by
00852  * technologies that do not support reserved sessions don't require extra logic
00853  * to handle.
00854  *
00855  * \note This function DOES NOT release the given fax session, only the given
00856  * token.
00857  */
00858 static void fax_session_release(struct ast_fax_session *s, struct ast_fax_tech_token *token)
00859 {
00860    if (token) {
00861       s->tech->release_token(token);
00862    }
00863 
00864    if (s->state == AST_FAX_STATE_RESERVED) {
00865       ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, -1);
00866       s->state = AST_FAX_STATE_INACTIVE;
00867    }
00868 }
00869 
00870 /*! \brief destroy a FAX session structure */
00871 static void destroy_session(void *session)
00872 {
00873    struct ast_fax_session *s = session;
00874 
00875    if (s->tech) {
00876       fax_session_release(s, NULL);
00877       if (s->tech_pvt) {
00878          s->tech->destroy_session(s);
00879       }
00880       ast_module_unref(s->tech->module);
00881    }
00882 
00883    if (s->details) {
00884       if (s->details->caps & AST_FAX_TECH_GATEWAY) {
00885          s->details->caps &= ~AST_FAX_TECH_GATEWAY;
00886       }
00887       ao2_ref(s->details, -1);
00888    }
00889 
00890    if (s->debug_info) {
00891       ast_dsp_free(s->debug_info->dsp);
00892       ast_free(s->debug_info);
00893    }
00894 
00895    if (s->smoother) {
00896       ast_smoother_free(s->smoother);
00897    }
00898 
00899    if (s->state != AST_FAX_STATE_INACTIVE) {
00900       ast_atomic_fetchadd_int(&faxregistry.active_sessions, -1);
00901    }
00902 
00903    ast_free(s->channame);
00904    ast_free(s->chan_uniqueid);
00905 }
00906 
00907 /*! \brief Reserve a fax session.
00908  * \param details the fax session details
00909  * \param token a pointer to a place to store a token to be passed to fax_session_new() later
00910  *
00911  * This function reserves a fax session for use later. If the selected fax
00912  * technology does not support reserving sessions a session will still be
00913  * returned but token will not be set.
00914  *
00915  * \note The reference returned by this function does not get consumed by
00916  * fax_session_new() and must always be dereferenced separately.
00917  *
00918  * \return NULL or an uninitialized and possibly reserved session
00919  */
00920 static struct ast_fax_session *fax_session_reserve(struct ast_fax_session_details *details, struct ast_fax_tech_token **token)
00921 {
00922    struct ast_fax_session *s;
00923    struct fax_module *faxmod;
00924 
00925    if (!(s = ao2_alloc(sizeof(*s), destroy_session))) {
00926       return NULL;
00927    }
00928 
00929    s->state = AST_FAX_STATE_INACTIVE;
00930    s->details = details;
00931    ao2_ref(s->details, 1);
00932 
00933    /* locate a FAX technology module that can handle said requirements
00934     * Note: the requirements have not yet been finalized as T.38
00935     * negotiation has not yet occured. */
00936    AST_RWLIST_RDLOCK(&faxmodules);
00937    AST_RWLIST_TRAVERSE(&faxmodules, faxmod, list) {
00938       if ((faxmod->tech->caps & details->caps) != details->caps) {
00939          continue;
00940       }
00941       ast_debug(4, "Reserving a FAX session from '%s'.\n", faxmod->tech->description);
00942       ast_module_ref(faxmod->tech->module);
00943       s->tech = faxmod->tech;
00944       break;
00945    }
00946    AST_RWLIST_UNLOCK(&faxmodules);
00947 
00948    if (!faxmod) {
00949       char caps[128] = "";
00950       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)));
00951       ao2_ref(s, -1);
00952       return NULL;
00953    }
00954 
00955    if (!s->tech->reserve_session) {
00956       ast_debug(1, "Selected FAX technology module (%s) does not support reserving sessions.\n", s->tech->description);
00957       return s;
00958    }
00959 
00960    if (!(*token = s->tech->reserve_session(s))) {
00961       ao2_ref(s, -1);
00962       return NULL;
00963    }
00964 
00965    s->state = AST_FAX_STATE_RESERVED;
00966    ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, 1);
00967 
00968    return s;
00969 }
00970 
00971 /*! \brief create a FAX session
00972  *
00973  * \param details details for the session
00974  * \param chan the channel the session will run on
00975  * \param reserved a reserved session to base this session on (can be NULL)
00976  * \param token the token for a reserved session (can be NULL)
00977  *
00978  * Create a new fax session based on the given details structure.
00979  *
00980  * \note The given token is always consumed (by tech->new_session() or by
00981  * fax_session_release() in the event of a failure). The given reference to a
00982  * reserved session is never consumed and must be dereferenced separately from
00983  * the reference returned by this function.
00984  *
00985  * \return NULL or a reference to a new fax session
00986  */
00987 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)
00988 {
00989    struct ast_fax_session *s = NULL;
00990    struct fax_module *faxmod;
00991 
00992    if (reserved) {
00993       s = reserved;
00994       ao2_ref(reserved, +1);
00995 
00996       /* NOTE: we don't consume the reference to the reserved
00997        * session. The session returned from fax_session_new() is a
00998        * new reference and must be derefed in addition to the
00999        * reserved session.
01000        */
01001 
01002       if (s->state == AST_FAX_STATE_RESERVED) {
01003          ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, -1);
01004          s->state = AST_FAX_STATE_UNINITIALIZED;
01005       }
01006    }
01007 
01008    if (!s && !(s = ao2_alloc(sizeof(*s), destroy_session))) {
01009       return NULL;
01010    }
01011 
01012    ast_atomic_fetchadd_int(&faxregistry.active_sessions, 1);
01013    s->state = AST_FAX_STATE_UNINITIALIZED;
01014 
01015    if (details->option.debug && (details->caps & AST_FAX_TECH_AUDIO)) {
01016       if (!(s->debug_info = ast_calloc(1, sizeof(*(s->debug_info))))) {
01017          fax_session_release(s, token);
01018          ao2_ref(s, -1);
01019          return NULL;
01020       }
01021       if (!(s->debug_info->dsp = ast_dsp_new())) {
01022          ast_free(s->debug_info);
01023          s->debug_info = NULL;
01024          fax_session_release(s, token);
01025          ao2_ref(s, -1);
01026          return NULL;
01027       }
01028       ast_dsp_set_threshold(s->debug_info->dsp, 128);
01029    }
01030 
01031    if (!(s->channame = ast_strdup(ast_channel_name(chan)))) {
01032       fax_session_release(s, token);
01033       ao2_ref(s, -1);
01034       return NULL;
01035    }
01036 
01037    if (!(s->chan_uniqueid = ast_strdup(ast_channel_uniqueid(chan)))) {
01038       fax_session_release(s, token);
01039       ao2_ref(s, -1);
01040       return NULL;
01041    }
01042 
01043    s->chan = chan;
01044    if (!s->details) {
01045       s->details = details;
01046       ao2_ref(s->details, 1);
01047    }
01048 
01049    details->id = s->id = ast_atomic_fetchadd_int(&faxregistry.nextsessionname, 1);
01050 
01051    if (!token) {
01052       /* locate a FAX technology module that can handle said requirements */
01053       AST_RWLIST_RDLOCK(&faxmodules);
01054       AST_RWLIST_TRAVERSE(&faxmodules, faxmod, list) {
01055          if ((faxmod->tech->caps & details->caps) != details->caps) {
01056             continue;
01057          }
01058          ast_debug(4, "Requesting a new FAX session from '%s'.\n", faxmod->tech->description);
01059          ast_module_ref(faxmod->tech->module);
01060          s->tech = faxmod->tech;
01061          break;
01062       }
01063       AST_RWLIST_UNLOCK(&faxmodules);
01064 
01065       if (!faxmod) {
01066          char caps[128] = "";
01067          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)));
01068          ao2_ref(s, -1);
01069          return NULL;
01070       }
01071    }
01072 
01073    if (!(s->tech_pvt = s->tech->new_session(s, token))) {
01074       ast_log(LOG_ERROR, "FAX session failed to initialize.\n");
01075       ao2_ref(s, -1);
01076       return NULL;
01077    }
01078    /* link the session to the session container */
01079    if (!(ao2_link(faxregistry.container, s))) {
01080       ast_log(LOG_ERROR, "failed to add FAX session '%d' to container.\n", s->id);
01081       ao2_ref(s, -1);
01082       return NULL;
01083    }
01084    ast_debug(4, "channel '%s' using FAX session '%d'\n", s->channame, s->id);
01085 
01086    return s;
01087 }
01088 
01089 static void get_manager_event_info(struct ast_channel *chan, struct manager_event_info *info)
01090 {
01091    pbx_substitute_variables_helper(chan, "${CONTEXT}", info->context, sizeof(info->context));
01092    pbx_substitute_variables_helper(chan, "${EXTEN}", info->exten, sizeof(info->exten));
01093    pbx_substitute_variables_helper(chan, "${CALLERID(num)}", info->cid, sizeof(info->cid));
01094 }
01095 
01096 
01097 /* \brief Generate a string of filenames using the given prefix and separator.
01098  * \param details the fax session details
01099  * \param prefix the prefix to each filename
01100  * \param separator the separator between filenames
01101  *
01102  * This function generates a string of filenames from the given details
01103  * structure and using the given prefix and separator.
01104  *
01105  * \retval NULL there was an error generating the string
01106  * \return the string generated string
01107  */
01108 static char *generate_filenames_string(struct ast_fax_session_details *details, char *prefix, char *separator)
01109 {
01110    char *filenames, *c;
01111    size_t size = 0;
01112    int first = 1;
01113    struct ast_fax_document *doc;
01114 
01115    /* don't process empty lists */
01116    if (AST_LIST_EMPTY(&details->documents)) {
01117       return NULL;
01118    }
01119 
01120    /* Calculate the total length of all of the file names */
01121    AST_LIST_TRAVERSE(&details->documents, doc, next) {
01122       size += strlen(separator) + strlen(prefix) + strlen(doc->filename);
01123    }
01124    size += 1; /* add space for the terminating null */
01125 
01126    if (!(filenames = ast_malloc(size))) {
01127       return NULL;
01128    }
01129    c = filenames;
01130 
01131    ast_build_string(&c, &size, "%s%s", prefix, AST_LIST_FIRST(&details->documents)->filename);
01132    AST_LIST_TRAVERSE(&details->documents, doc, next) {
01133       if (first) {
01134          first = 0;
01135          continue;
01136       }
01137 
01138       ast_build_string(&c, &size, "%s%s%s", separator, prefix, doc->filename);
01139    }
01140 
01141    return filenames;
01142 }
01143 
01144 /*! \brief send a FAX status manager event */
01145 static int report_fax_status(struct ast_channel *chan, struct ast_fax_session_details *details, const char *status)
01146 {
01147    char *filenames = generate_filenames_string(details, "FileName: ", "\r\n");
01148 
01149    ast_channel_lock(chan);
01150    if (details->option.statusevents) {
01151       struct manager_event_info info;
01152 
01153       get_manager_event_info(chan, &info);
01154       manager_event(EVENT_FLAG_CALL,
01155                "FAXStatus",
01156                "Operation: %s\r\n"
01157                "Status: %s\r\n"
01158                "Channel: %s\r\n"
01159                "Context: %s\r\n"
01160                "Exten: %s\r\n"
01161                "CallerID: %s\r\n"
01162                "LocalStationID: %s\r\n"
01163                "%s%s",
01164                (details->caps & AST_FAX_TECH_GATEWAY) ? "gateway" : (details->caps & AST_FAX_TECH_RECEIVE) ? "receive" : "send",
01165                status,
01166                ast_channel_name(chan),
01167                info.context,
01168                info.exten,
01169                info.cid,
01170                details->localstationid,
01171                S_OR(filenames, ""),
01172                filenames ? "\r\n" : "");
01173    }
01174    ast_channel_unlock(chan);
01175 
01176    if (filenames) {
01177       ast_free(filenames);
01178    }
01179 
01180    return 0;
01181 }
01182 
01183 /*! \brief Set fax related channel variables. */
01184 static void set_channel_variables(struct ast_channel *chan, struct ast_fax_session_details *details)
01185 {
01186    char buf[10];
01187    pbx_builtin_setvar_helper(chan, "FAXSTATUS", S_OR(details->result, NULL));
01188    pbx_builtin_setvar_helper(chan, "FAXERROR", S_OR(details->error, NULL));
01189    pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", S_OR(details->resultstr, NULL));
01190    pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", S_OR(details->remotestationid, NULL));
01191    pbx_builtin_setvar_helper(chan, "LOCALSTATIONID", S_OR(details->localstationid, NULL));
01192    pbx_builtin_setvar_helper(chan, "FAXBITRATE", S_OR(details->transfer_rate, NULL));
01193    pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", S_OR(details->resolution, NULL));
01194 
01195    snprintf(buf, sizeof(buf), "%d", details->pages_transferred);
01196    pbx_builtin_setvar_helper(chan, "FAXPAGES", buf);
01197 }
01198 
01199 #define GENERIC_FAX_EXEC_SET_VARS(fax, chan, errorstr, reason) \
01200    do {  \
01201       if (ast_strlen_zero(fax->details->result)) \
01202          ast_string_field_set(fax->details, result, "FAILED"); \
01203       if (ast_strlen_zero(fax->details->resultstr)) \
01204          ast_string_field_set(fax->details, resultstr, reason); \
01205       if (ast_strlen_zero(fax->details->error)) \
01206          ast_string_field_set(fax->details, error, errorstr); \
01207       set_channel_variables(chan, fax->details); \
01208    } while (0)
01209 
01210 #define GENERIC_FAX_EXEC_ERROR_QUIET(fax, chan, errorstr, reason) \
01211    do {  \
01212       GENERIC_FAX_EXEC_SET_VARS(fax, chan, errorstr, reason); \
01213    } while (0)
01214 
01215 #define GENERIC_FAX_EXEC_ERROR(fax, chan, errorstr, reason) \
01216    do {  \
01217       ast_log(LOG_ERROR, "channel '%s' FAX session '%d' failure, reason: '%s' (%s)\n", ast_channel_name(chan), fax->id, reason, errorstr); \
01218       GENERIC_FAX_EXEC_ERROR_QUIET(fax, chan, errorstr, reason); \
01219    } while (0)
01220 
01221 static int set_fax_t38_caps(struct ast_channel *chan, struct ast_fax_session_details *details)
01222 {
01223    switch (ast_channel_get_t38_state(chan)) {
01224    case T38_STATE_UNKNOWN:
01225       details->caps |= AST_FAX_TECH_T38;
01226       break;
01227    case T38_STATE_REJECTED:
01228    case T38_STATE_UNAVAILABLE:
01229       details->caps |= AST_FAX_TECH_AUDIO;
01230       break;
01231    case T38_STATE_NEGOTIATED:
01232       /* already in T.38 mode? This should not happen. */
01233    case T38_STATE_NEGOTIATING: {
01234       /* the other end already sent us a T.38 reinvite, so we need to prod the channel
01235        * driver into resending their parameters to us if it supports doing so... if
01236        * not, we can't proceed, because we can't create a proper reply without them.
01237        * if it does work, the channel driver will send an AST_CONTROL_T38_PARAMETERS
01238        * with a request of AST_T38_REQUEST_NEGOTIATE, which will be read by the function
01239        * that gets called after this one completes
01240        */
01241       struct ast_control_t38_parameters parameters = { .request_response = AST_T38_REQUEST_PARMS, };
01242       if (ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &parameters, sizeof(parameters)) != AST_T38_REQUEST_PARMS) {
01243          ast_log(LOG_ERROR, "channel '%s' is in an unsupported T.38 negotiation state, cannot continue.\n", ast_channel_name(chan));
01244          return -1;
01245       }
01246       details->caps |= AST_FAX_TECH_T38;
01247       break;
01248    }
01249    default:
01250       ast_log(LOG_ERROR, "channel '%s' is in an unsupported T.38 negotiation state, cannot continue.\n", ast_channel_name(chan));
01251       return -1;
01252    }
01253 
01254    return 0;
01255 }
01256 
01257 static int disable_t38(struct ast_channel *chan)
01258 {
01259    int timeout_ms;
01260    struct ast_frame *frame = NULL;
01261    struct ast_control_t38_parameters t38_parameters = { .request_response = AST_T38_REQUEST_TERMINATE, };
01262    struct timeval start;
01263    int ms;
01264 
01265    ast_debug(1, "Shutting down T.38 on %s\n", ast_channel_name(chan));
01266    if (ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0) {
01267       ast_debug(1, "error while disabling T.38 on channel '%s'\n", ast_channel_name(chan));
01268       return -1;
01269    }
01270 
01271    /* wait up to five seconds for negotiation to complete */
01272    timeout_ms = 5000;
01273    start = ast_tvnow();
01274    while ((ms = ast_remaining_ms(start, timeout_ms))) {
01275       ms = ast_waitfor(chan, ms);
01276 
01277       if (ms == 0) {
01278          break;
01279       }
01280       if (ms < 0) {
01281          ast_debug(1, "error while disabling T.38 on channel '%s'\n", ast_channel_name(chan));
01282          return -1;
01283       }
01284 
01285       if (!(frame = ast_read(chan))) {
01286          return -1;
01287       }
01288       if ((frame->frametype == AST_FRAME_CONTROL) &&
01289           (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
01290           (frame->datalen == sizeof(t38_parameters))) {
01291          struct ast_control_t38_parameters *parameters = frame->data.ptr;
01292 
01293          switch (parameters->request_response) {
01294          case AST_T38_TERMINATED:
01295             ast_debug(1, "Shut down T.38 on %s\n", ast_channel_name(chan));
01296             break;
01297          case AST_T38_REFUSED:
01298             ast_log(LOG_WARNING, "channel '%s' refused to disable T.38\n", ast_channel_name(chan));
01299             ast_frfree(frame);
01300             return -1;
01301          default:
01302             ast_log(LOG_ERROR, "channel '%s' failed to disable T.38\n", ast_channel_name(chan));
01303             ast_frfree(frame);
01304             return -1;
01305          }
01306          ast_frfree(frame);
01307          break;
01308       }
01309       ast_frfree(frame);
01310    }
01311 
01312    if (ms == 0) { /* all done, nothing happened */
01313       ast_debug(1, "channel '%s' timed-out during T.38 shutdown\n", ast_channel_name(chan));
01314    }
01315 
01316    return 0;
01317 }
01318 
01319 /*! \brief this is the generic FAX session handling function */
01320 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)
01321 {
01322    int ms;
01323    int timeout = RES_FAX_TIMEOUT;
01324    int chancount;
01325    unsigned int expected_frametype = -1;
01326    union ast_frame_subclass expected_framesubclass = { .integer = -1 };
01327    unsigned int t38negotiated = (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED);
01328    struct ast_control_t38_parameters t38_parameters;
01329    const char *tempvar;
01330    struct ast_fax_session *fax = NULL;
01331    struct ast_frame *frame = NULL;
01332    struct ast_channel *c = chan;
01333    struct ast_format orig_write_format;
01334    struct ast_format orig_read_format;
01335    int remaining_time;
01336    struct timeval start;
01337 
01338    ast_format_clear(&orig_write_format);
01339    ast_format_clear(&orig_read_format);
01340    chancount = 1;
01341 
01342    /* create the FAX session */
01343    if (!(fax = fax_session_new(details, chan, reserved, token))) {
01344       ast_log(LOG_ERROR, "Can't create a FAX session, FAX attempt failed.\n");
01345       report_fax_status(chan, details, "No Available Resource");
01346       return -1;
01347    }
01348 
01349    ast_channel_lock(chan);
01350    /* update session details */
01351    if (ast_strlen_zero(details->headerinfo) && (tempvar = pbx_builtin_getvar_helper(chan, "LOCALHEADERINFO"))) {
01352       ast_string_field_set(details, headerinfo, tempvar);
01353    }
01354    if (ast_strlen_zero(details->localstationid)) {
01355       tempvar = pbx_builtin_getvar_helper(chan, "LOCALSTATIONID");
01356       ast_string_field_set(details, localstationid, tempvar ? tempvar : "unknown");
01357    }
01358    ast_channel_unlock(chan);
01359 
01360    report_fax_status(chan, details, "Allocating Resources");
01361 
01362    if (details->caps & AST_FAX_TECH_AUDIO) {
01363       expected_frametype = AST_FRAME_VOICE;;
01364       ast_format_set(&expected_framesubclass.format, AST_FORMAT_SLINEAR, 0);
01365       ast_format_copy(&orig_write_format, ast_channel_writeformat(chan));
01366       if (ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR) < 0) {
01367          ast_log(LOG_ERROR, "channel '%s' failed to set write format to signed linear'.\n", ast_channel_name(chan));
01368          ao2_lock(faxregistry.container);
01369          ao2_unlink(faxregistry.container, fax);
01370          ao2_unlock(faxregistry.container);
01371          ao2_ref(fax, -1);
01372          ast_channel_unlock(chan);
01373          return -1;
01374       }
01375       ast_format_copy(&orig_read_format, ast_channel_readformat(chan));
01376       if (ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR) < 0) {
01377          ast_log(LOG_ERROR, "channel '%s' failed to set read format to signed linear.\n", ast_channel_name(chan));
01378          ao2_lock(faxregistry.container);
01379          ao2_unlink(faxregistry.container, fax);
01380          ao2_unlock(faxregistry.container);
01381          ao2_ref(fax, -1);
01382          ast_channel_unlock(chan);
01383          return -1;
01384       }
01385       if (fax->smoother) {
01386          ast_smoother_free(fax->smoother);
01387          fax->smoother = NULL;
01388       }
01389       if (!(fax->smoother = ast_smoother_new(320))) {
01390          ast_log(LOG_WARNING, "Channel '%s' FAX session '%d' failed to obtain a smoother.\n", ast_channel_name(chan), fax->id);
01391       }
01392    } else {
01393       expected_frametype = AST_FRAME_MODEM;
01394       expected_framesubclass.integer = AST_MODEM_T38;
01395    }
01396 
01397    if (fax->debug_info) {
01398       fax->debug_info->base_tv = ast_tvnow();
01399    }
01400 
01401    /* reset our result fields just in case the fax tech driver wants to
01402     * set custom error messages */
01403    ast_string_field_set(details, result, "");
01404    ast_string_field_set(details, resultstr, "");
01405    ast_string_field_set(details, error, "");
01406    set_channel_variables(chan, details);
01407 
01408    if (fax->tech->start_session(fax) < 0) {
01409       GENERIC_FAX_EXEC_ERROR(fax, chan, "INIT_ERROR", "failed to start FAX session");
01410    }
01411 
01412    report_fax_status(chan, details, "FAX Transmission In Progress");
01413 
01414    ast_debug(5, "channel %s will wait on FAX fd %d\n", ast_channel_name(chan), fax->fd);
01415 
01416    /* handle frames for the session */
01417    remaining_time = timeout;
01418    start = ast_tvnow();
01419    while (remaining_time > 0) {
01420       struct ast_channel *ready_chan;
01421       int ofd, exception;
01422 
01423       ms = 1000;
01424       errno = 0;
01425       ready_chan = ast_waitfor_nandfds(&c, chancount, &fax->fd, 1, &exception, &ofd, &ms);
01426       if (ready_chan) {
01427          if (!(frame = ast_read(chan))) {
01428             /* the channel is probably gone, so lets stop polling on it and let the
01429              * FAX session complete before we exit the application.  if needed,
01430              * send the FAX stack silence so the modems can finish their session without
01431              * any problems */
01432             ast_debug(1, "Channel '%s' did not return a frame; probably hung up.\n", ast_channel_name(chan));
01433             GENERIC_FAX_EXEC_SET_VARS(fax, chan, "HANGUP", "remote channel hungup");
01434             c = NULL;
01435             chancount = 0;
01436             remaining_time = ast_remaining_ms(start, timeout);
01437             fax->tech->cancel_session(fax);
01438             if (fax->tech->generate_silence) {
01439                fax->tech->generate_silence(fax);
01440             }
01441             continue;
01442          }
01443 
01444          if ((frame->frametype == AST_FRAME_CONTROL) &&
01445              (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
01446              (frame->datalen == sizeof(t38_parameters))) {
01447             unsigned int was_t38 = t38negotiated;
01448             struct ast_control_t38_parameters *parameters = frame->data.ptr;
01449 
01450             switch (parameters->request_response) {
01451             case AST_T38_REQUEST_NEGOTIATE:
01452                /* the other end has requested a switch to T.38, so reply that we are willing, if we can
01453                 * do T.38 as well
01454                 */
01455                t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
01456                t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
01457                ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
01458                break;
01459             case AST_T38_NEGOTIATED:
01460                t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
01461                t38negotiated = 1;
01462                break;
01463             default:
01464                break;
01465             }
01466             if (t38negotiated && !was_t38) {
01467                fax->tech->switch_to_t38(fax);
01468                details->caps &= ~AST_FAX_TECH_AUDIO;
01469                expected_frametype = AST_FRAME_MODEM;
01470                expected_framesubclass.integer = AST_MODEM_T38;
01471                if (fax->smoother) {
01472                   ast_smoother_free(fax->smoother);
01473                   fax->smoother = NULL;
01474                }
01475 
01476                report_fax_status(chan, details, "T.38 Negotiated");
01477 
01478                ast_verb(3, "Channel '%s' switched to T.38 FAX session '%d'.\n", ast_channel_name(chan), fax->id);
01479             }
01480          } else if ((frame->frametype == expected_frametype) &&
01481                (!memcmp(&frame->subclass, &expected_framesubclass, sizeof(frame->subclass)))) {
01482             struct ast_frame *f;
01483 
01484             if (fax->smoother) {
01485                /* push the frame into a smoother */
01486                if (ast_smoother_feed(fax->smoother, frame) < 0) {
01487                   GENERIC_FAX_EXEC_ERROR(fax, chan, "UNKNOWN", "Failed to feed the smoother");
01488                }
01489                while ((f = ast_smoother_read(fax->smoother)) && (f->data.ptr)) {
01490                   if (fax->debug_info) {
01491                      debug_check_frame_for_silence(fax, 1, f);
01492                   }
01493                   /* write the frame to the FAX stack */
01494                   fax->tech->write(fax, f);
01495                   fax->frames_received++;
01496                   if (f != frame) {
01497                      ast_frfree(f);
01498                   }
01499                }
01500             } else {
01501                /* write the frame to the FAX stack */
01502                fax->tech->write(fax, frame);
01503                fax->frames_received++;
01504             }
01505             start = ast_tvnow();
01506          }
01507          ast_frfree(frame);
01508       } else if (ofd == fax->fd) {
01509          /* read a frame from the FAX stack and send it out the channel.
01510           * the FAX stack will return a NULL if the FAX session has already completed */
01511          if (!(frame = fax->tech->read(fax))) {
01512             break;
01513          }
01514 
01515          if (fax->debug_info && (frame->frametype == AST_FRAME_VOICE)) {
01516             debug_check_frame_for_silence(fax, 0, frame);
01517          }
01518 
01519          ast_write(chan, frame);
01520          fax->frames_sent++;
01521          ast_frfree(frame);
01522          start = ast_tvnow();
01523       } else {
01524          if (ms && (ofd < 0)) {
01525             if ((errno == 0) || (errno == EINTR)) {
01526                remaining_time = ast_remaining_ms(start, timeout);
01527                if (remaining_time <= 0)
01528                   GENERIC_FAX_EXEC_ERROR(fax, chan, "TIMEOUT", "fax session timed-out");
01529                continue;
01530             } else {
01531                ast_log(LOG_WARNING, "something bad happened while channel '%s' was polling.\n", ast_channel_name(chan));
01532                GENERIC_FAX_EXEC_ERROR(fax, chan, "UNKNOWN", "error polling data");
01533                break;
01534             }
01535          } else {
01536             /* nothing happened */
01537             remaining_time = ast_remaining_ms(start, timeout);
01538             if (remaining_time <= 0) {
01539                GENERIC_FAX_EXEC_ERROR(fax, chan, "TIMEOUT", "fax session timed-out");
01540                break;
01541             }
01542          }
01543       }
01544    }
01545    ast_debug(3, "channel '%s' - event loop stopped { timeout: %d, remaining_time: %d }\n", ast_channel_name(chan), timeout, remaining_time);
01546 
01547    set_channel_variables(chan, details);
01548 
01549    ast_atomic_fetchadd_int(&faxregistry.fax_complete, 1);
01550    if (!strcasecmp(details->result, "FAILED")) {
01551       ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
01552    }
01553 
01554    if (fax) {
01555       ao2_lock(faxregistry.container);
01556       ao2_unlink(faxregistry.container, fax);
01557       ao2_unlock(faxregistry.container);
01558       ao2_ref(fax, -1);
01559    }
01560 
01561    /* if the channel is still alive, and we changed its read/write formats,
01562     * restore them now
01563     */
01564    if (chancount) {
01565       if (orig_read_format.id) {
01566          ast_set_read_format(chan, &orig_read_format);
01567       }
01568       if (orig_write_format.id) {
01569          ast_set_write_format(chan, &orig_write_format);
01570       }
01571    }
01572 
01573    /* return the chancount so the calling function can determine if the channel hungup during this FAX session or not */
01574    return chancount;
01575 }
01576 
01577 static int receivefax_t38_init(struct ast_channel *chan, struct ast_fax_session_details *details)
01578 {
01579    int timeout_ms;
01580    struct ast_frame *frame = NULL;
01581    struct ast_control_t38_parameters t38_parameters;
01582    struct timeval start;
01583    int ms;
01584 
01585    /* don't send any audio if we've already received a T.38 reinvite */
01586    if (ast_channel_get_t38_state(chan) != T38_STATE_NEGOTIATING) {
01587       /* generate 3 seconds of CED */
01588       if (ast_playtones_start(chan, 1024, "!2100/3000", 1)) {
01589          ast_log(LOG_ERROR, "error generating CED tone on %s\n", ast_channel_name(chan));
01590          return -1;
01591       }
01592 
01593       timeout_ms = 3000;
01594       start = ast_tvnow();
01595       while ((ms = ast_remaining_ms(start, timeout_ms))) {
01596          ms = ast_waitfor(chan, ms);
01597 
01598          if (ms < 0) {
01599             ast_log(LOG_ERROR, "error while generating CED tone on %s\n", ast_channel_name(chan));
01600             ast_playtones_stop(chan);
01601             return -1;
01602          }
01603 
01604          if (ms == 0) { /* all done, nothing happened */
01605             break;
01606          }
01607 
01608          if (!(frame = ast_read(chan))) {
01609             ast_log(LOG_ERROR, "error reading frame while generating CED tone on %s\n", ast_channel_name(chan));
01610             ast_playtones_stop(chan);
01611             return -1;
01612          }
01613 
01614          if ((frame->frametype == AST_FRAME_CONTROL) &&
01615              (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
01616              (frame->datalen == sizeof(t38_parameters))) {
01617             struct ast_control_t38_parameters *parameters = frame->data.ptr;
01618 
01619             switch (parameters->request_response) {
01620             case AST_T38_REQUEST_NEGOTIATE:
01621                /* the other end has requested a switch to T.38, so reply that we are willing, if we can
01622                 * do T.38 as well
01623                 */
01624                t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
01625                t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
01626                ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
01627                ast_playtones_stop(chan);
01628                break;
01629             case AST_T38_NEGOTIATED:
01630                ast_debug(1, "Negotiated T.38 for receive on %s\n", ast_channel_name(chan));
01631                t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
01632                details->caps &= ~AST_FAX_TECH_AUDIO;
01633                report_fax_status(chan, details, "T.38 Negotiated");
01634                break;
01635             default:
01636                break;
01637             }
01638          }
01639          ast_frfree(frame);
01640       }
01641 
01642       ast_playtones_stop(chan);
01643    }
01644 
01645    /* if T.38 was negotiated, we are done initializing */
01646    if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) {
01647       return 0;
01648    }
01649 
01650    /* request T.38 */
01651    ast_debug(1, "Negotiating T.38 for receive on %s\n", ast_channel_name(chan));
01652 
01653    /* wait up to five seconds for negotiation to complete */
01654    timeout_ms = 5000;
01655 
01656    /* set parameters based on the session's parameters */
01657    t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
01658    t38_parameters.request_response = AST_T38_REQUEST_NEGOTIATE;
01659    if ((ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0)) {
01660       return -1;
01661    }
01662 
01663    start = ast_tvnow();
01664    while ((ms = ast_remaining_ms(start, timeout_ms))) {
01665       int break_loop = 0;
01666 
01667       ms = ast_waitfor(chan, ms);
01668       if (ms < 0) {
01669          ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", ast_channel_name(chan));
01670          return -1;
01671       }
01672       if (ms == 0) { /* all done, nothing happened */
01673          ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 negotiation.\n", ast_channel_name(chan));
01674          details->caps &= ~AST_FAX_TECH_T38;
01675          break;
01676       }
01677 
01678       if (!(frame = ast_read(chan))) {
01679          ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", ast_channel_name(chan));
01680          return -1;
01681       }
01682 
01683       if ((frame->frametype == AST_FRAME_CONTROL) &&
01684             (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
01685             (frame->datalen == sizeof(t38_parameters))) {
01686          struct ast_control_t38_parameters *parameters = frame->data.ptr;
01687 
01688          switch (parameters->request_response) {
01689          case AST_T38_REQUEST_NEGOTIATE:
01690             t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
01691             t38_parameters.request_response = AST_T38_NEGOTIATED;
01692             ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
01693             break;
01694          case AST_T38_NEGOTIATED:
01695             ast_debug(1, "Negotiated T.38 for receive on %s\n", ast_channel_name(chan));
01696             t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
01697             details->caps &= ~AST_FAX_TECH_AUDIO;
01698             report_fax_status(chan, details, "T.38 Negotiated");
01699             break_loop = 1;
01700             break;
01701          case AST_T38_REFUSED:
01702             ast_log(LOG_WARNING, "channel '%s' refused to negotiate T.38\n", ast_channel_name(chan));
01703             details->caps &= ~AST_FAX_TECH_T38;
01704             break_loop = 1;
01705             break;
01706          default:
01707             ast_log(LOG_ERROR, "channel '%s' failed to negotiate T.38\n", ast_channel_name(chan));
01708             details->caps &= ~AST_FAX_TECH_T38;
01709             break_loop = 1;
01710             break;
01711          }
01712       }
01713       ast_frfree(frame);
01714       if (break_loop) {
01715          break;
01716       }
01717    }
01718 
01719    /* if T.38 was negotiated, we are done initializing */
01720    if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) {
01721       return 0;
01722    }
01723 
01724    /* if we made it here, then T.38 failed, check the 'f' flag */
01725    if (details->option.allow_audio != AST_FAX_OPTFLAG_TRUE) {
01726       ast_log(LOG_WARNING, "Audio FAX not allowed on channel '%s' and T.38 negotiation failed; aborting.\n", ast_channel_name(chan));
01727       return -1;
01728    }
01729 
01730    /* ok, audio fallback is allowed */
01731    details->caps |= AST_FAX_TECH_AUDIO;
01732 
01733    return 0;
01734 }
01735 
01736 /*! \brief initiate a receive FAX session */
01737 static int receivefax_exec(struct ast_channel *chan, const char *data)
01738 {
01739    char *parse, modems[128] = "";
01740    int channel_alive;
01741    struct ast_fax_session_details *details;
01742    struct ast_fax_session *s;
01743    struct ast_fax_tech_token *token = NULL;
01744    struct ast_fax_document *doc;
01745    AST_DECLARE_APP_ARGS(args,
01746       AST_APP_ARG(filename);
01747       AST_APP_ARG(options);
01748    );
01749    struct ast_flags opts = { 0, };
01750    struct manager_event_info info;
01751    enum ast_t38_state t38state;
01752 
01753    /* initialize output channel variables */
01754    pbx_builtin_setvar_helper(chan, "FAXSTATUS", "FAILED");
01755    pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", NULL);
01756    pbx_builtin_setvar_helper(chan, "FAXPAGES", "0");
01757    pbx_builtin_setvar_helper(chan, "FAXBITRATE", NULL);
01758    pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", NULL);
01759 
01760    /* Get a FAX session details structure from the channel's FAX datastore and create one if
01761     * it does not already exist. */
01762    if (!(details = find_or_create_details(chan))) {
01763       pbx_builtin_setvar_helper(chan, "FAXERROR", "MEMORY_ERROR");
01764       pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "error allocating memory");
01765       ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
01766       return -1;
01767    }
01768 
01769    ast_string_field_set(details, result, "FAILED");
01770    ast_string_field_set(details, resultstr, "error starting fax session");
01771    ast_string_field_set(details, error, "INIT_ERROR");
01772    set_channel_variables(chan, details);
01773 
01774    if (details->gateway_id > 0) {
01775       ast_string_field_set(details, resultstr, "can't receive a fax on a channel with a T.38 gateway");
01776       set_channel_variables(chan, details);
01777       ast_log(LOG_ERROR, "executing ReceiveFAX on a channel with a T.38 Gateway is not supported\n");
01778       ao2_ref(details, -1);
01779       return -1;
01780    }
01781 
01782    if (details->maxrate < details->minrate) {
01783       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
01784       ast_string_field_set(details, resultstr, "maxrate is less than minrate");
01785       set_channel_variables(chan, details);
01786       ast_log(LOG_ERROR, "maxrate %d is less than minrate %d\n", details->maxrate, details->minrate);
01787       ao2_ref(details, -1);
01788       return -1;
01789    }
01790 
01791    if (check_modem_rate(details->modems, details->minrate)) {
01792       ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
01793       ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %d\n", modems, details->minrate);
01794       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
01795       ast_string_field_set(details, resultstr, "incompatible 'modems' and 'minrate' settings");
01796       set_channel_variables(chan, details);
01797       ao2_ref(details, -1);
01798       return -1;
01799    }
01800 
01801    if (check_modem_rate(details->modems, details->maxrate)) {
01802       ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
01803       ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %d\n", modems, details->maxrate);
01804       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
01805       ast_string_field_set(details, resultstr, "incompatible 'modems' and 'maxrate' settings");
01806       set_channel_variables(chan, details);
01807       ao2_ref(details, -1);
01808       return -1;
01809    }
01810 
01811    if (ast_strlen_zero(data)) {
01812       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
01813       ast_string_field_set(details, resultstr, "invalid arguments");
01814       set_channel_variables(chan, details);
01815       ast_log(LOG_WARNING, "%s requires an argument (filename[,options])\n", app_receivefax);
01816       ao2_ref(details, -1);
01817       return -1;
01818    }
01819    parse = ast_strdupa(data);
01820    AST_STANDARD_APP_ARGS(args, parse);
01821 
01822    if (!ast_strlen_zero(args.options) &&
01823        ast_app_parse_options(fax_exec_options, &opts, NULL, args.options)) {
01824       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
01825       ast_string_field_set(details, resultstr, "invalid arguments");
01826       set_channel_variables(chan, details);
01827       ao2_ref(details, -1);
01828       return -1;
01829    }
01830    if (ast_strlen_zero(args.filename)) {
01831       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
01832       ast_string_field_set(details, resultstr, "invalid arguments");
01833       set_channel_variables(chan, details);
01834       ast_log(LOG_WARNING, "%s requires an argument (filename[,options])\n", app_receivefax);
01835       ao2_ref(details, -1);
01836       return -1;
01837    }
01838 
01839    /* check for unsupported FAX application options */
01840    if (ast_test_flag(&opts, OPT_CALLERMODE) || ast_test_flag(&opts, OPT_CALLEDMODE)) {
01841       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
01842       ast_string_field_set(details, resultstr, "invalid arguments");
01843       set_channel_variables(chan, details);
01844       ast_log(LOG_WARNING, "%s does not support polling\n", app_receivefax);
01845       ao2_ref(details, -1);
01846       return -1;
01847    }
01848 
01849    ast_atomic_fetchadd_int(&faxregistry.fax_rx_attempts, 1);
01850 
01851    pbx_builtin_setvar_helper(chan, "FAXERROR", "Channel Problems");
01852    pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "Error before FAX transmission started.");
01853 
01854    if (!(doc = ast_calloc(1, sizeof(*doc) + strlen(args.filename) + 1))) {
01855       ast_string_field_set(details, error, "MEMORY_ERROR");
01856       ast_string_field_set(details, resultstr, "error allocating memory");
01857       set_channel_variables(chan, details);
01858       ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
01859       ao2_ref(details, -1);
01860       return -1;
01861    }
01862 
01863    strcpy(doc->filename, args.filename);
01864    AST_LIST_INSERT_TAIL(&details->documents, doc, next);
01865 
01866    ast_verb(3, "Channel '%s' receiving FAX '%s'\n", ast_channel_name(chan), args.filename);
01867 
01868    details->caps = AST_FAX_TECH_RECEIVE;
01869    details->option.send_ced = AST_FAX_OPTFLAG_TRUE;
01870 
01871    /* check for debug */
01872    if (ast_test_flag(&opts, OPT_DEBUG) || global_fax_debug) {
01873       details->option.debug = AST_FAX_OPTFLAG_TRUE;
01874    }
01875 
01876    /* check for request for status events */
01877    if (ast_test_flag(&opts, OPT_STATUS)) {
01878       details->option.statusevents = AST_FAX_OPTFLAG_TRUE;
01879    }
01880 
01881    t38state = ast_channel_get_t38_state(chan);
01882    if ((t38state == T38_STATE_UNAVAILABLE) || (t38state == T38_STATE_REJECTED) ||
01883        ast_test_flag(&opts, OPT_ALLOWAUDIO) ||
01884        ast_test_flag(&opts, OPT_FORCE_AUDIO)) {
01885       details->option.allow_audio = AST_FAX_OPTFLAG_TRUE;
01886    }
01887 
01888    if (!(s = fax_session_reserve(details, &token))) {
01889       ast_string_field_set(details, resultstr, "error reserving fax session");
01890       set_channel_variables(chan, details);
01891       ast_log(LOG_ERROR, "Unable to reserve FAX session.\n");
01892       ao2_ref(details, -1);
01893       return -1;
01894    }
01895 
01896    /* make sure the channel is up */
01897    if (ast_channel_state(chan) != AST_STATE_UP) {
01898       if (ast_answer(chan)) {
01899          ast_string_field_set(details, resultstr, "error answering channel");
01900          set_channel_variables(chan, details);
01901          ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", ast_channel_name(chan));
01902          fax_session_release(s, token);
01903          ao2_ref(s, -1);
01904          ao2_ref(details, -1);
01905          return -1;
01906       }
01907    }
01908 
01909    if (!ast_test_flag(&opts, OPT_FORCE_AUDIO)) {
01910       if (set_fax_t38_caps(chan, details)) {
01911          ast_string_field_set(details, error, "T38_NEG_ERROR");
01912          ast_string_field_set(details, resultstr, "error negotiating T.38");
01913          set_channel_variables(chan, details);
01914          fax_session_release(s, token);
01915          ao2_ref(s, -1);
01916          ao2_ref(details, -1);
01917          return -1;
01918       }
01919    } else {
01920       details->caps |= AST_FAX_TECH_AUDIO;
01921    }
01922 
01923    if (!ast_test_flag(&opts, OPT_FORCE_AUDIO) && (details->caps & AST_FAX_TECH_T38)) {
01924       if (receivefax_t38_init(chan, details)) {
01925          ast_string_field_set(details, error, "T38_NEG_ERROR");
01926          ast_string_field_set(details, resultstr, "error negotiating T.38");
01927          set_channel_variables(chan, details);
01928          fax_session_release(s, token);
01929          ao2_ref(s, -1);
01930          ao2_ref(details, -1);
01931          ast_log(LOG_ERROR, "error initializing channel '%s' in T.38 mode\n", ast_channel_name(chan));
01932          return -1;
01933       }
01934    }
01935 
01936    if ((channel_alive = generic_fax_exec(chan, details, s, token)) < 0) {
01937       ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
01938    }
01939 
01940    if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) {
01941       if (disable_t38(chan)) {
01942          ast_debug(1, "error disabling T.38 mode on %s\n", ast_channel_name(chan));
01943       }
01944    }
01945 
01946    /* send out the AMI completion event */
01947    ast_channel_lock(chan);
01948 
01949    get_manager_event_info(chan, &info);
01950    manager_event(EVENT_FLAG_CALL,
01951             "ReceiveFAX",
01952             "Channel: %s\r\n"
01953             "Context: %s\r\n"
01954             "Exten: %s\r\n"
01955             "CallerID: %s\r\n"
01956             "RemoteStationID: %s\r\n"
01957             "LocalStationID: %s\r\n"
01958             "PagesTransferred: %s\r\n"
01959             "Resolution: %s\r\n"
01960             "TransferRate: %s\r\n"
01961             "FileName: %s\r\n",
01962             ast_channel_name(chan),
01963             info.context,
01964             info.exten,
01965             info.cid,
01966             S_OR(pbx_builtin_getvar_helper(chan, "REMOTESTATIONID"), ""),
01967             S_OR(pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"), ""),
01968             S_OR(pbx_builtin_getvar_helper(chan, "FAXPAGES"), ""),
01969             S_OR(pbx_builtin_getvar_helper(chan, "FAXRESOLUTION"), ""),
01970             S_OR(pbx_builtin_getvar_helper(chan, "FAXBITRATE"), ""),
01971             args.filename);
01972    ast_channel_unlock(chan);
01973 
01974    ao2_ref(s, -1);
01975    ao2_ref(details, -1);
01976 
01977    /* If the channel hungup return -1; otherwise, return 0 to continue in the dialplan */
01978    return (!channel_alive) ? -1 : 0;
01979 }
01980 
01981 static int sendfax_t38_init(struct ast_channel *chan, struct ast_fax_session_details *details)
01982 {
01983    int timeout_ms;
01984    struct ast_frame *frame = NULL;
01985    struct ast_control_t38_parameters t38_parameters;
01986    struct timeval start;
01987    int ms;
01988 
01989    /* send CNG tone while listening for the receiver to initiate a switch
01990     * to T.38 mode; if they do, stop sending the CNG tone and proceed with
01991     * the switch.
01992     *
01993     * 10500 is enough time for 3 CNG tones
01994     */
01995    timeout_ms = 10500;
01996 
01997    /* don't send any audio if we've already received a T.38 reinvite */
01998    if (ast_channel_get_t38_state(chan) != T38_STATE_NEGOTIATING) {
01999       if (ast_playtones_start(chan, 1024, "!1100/500,!0/3000,!1100/500,!0/3000,!1100/500,!0/3000", 1)) {
02000          ast_log(LOG_ERROR, "error generating CNG tone on %s\n", ast_channel_name(chan));
02001          return -1;
02002       }
02003    }
02004 
02005    start = ast_tvnow();
02006    while ((ms = ast_remaining_ms(start, timeout_ms))) {
02007       int break_loop = 0;
02008       ms = ast_waitfor(chan, ms);
02009 
02010       if (ms < 0) {
02011          ast_log(LOG_ERROR, "error while generating CNG tone on %s\n", ast_channel_name(chan));
02012          ast_playtones_stop(chan);
02013          return -1;
02014       }
02015 
02016       if (ms == 0) { /* all done, nothing happened */
02017          break;
02018       }
02019 
02020       if (!(frame = ast_read(chan))) {
02021          ast_log(LOG_ERROR, "error reading frame while generating CNG tone on %s\n", ast_channel_name(chan));
02022          ast_playtones_stop(chan);
02023          return -1;
02024       }
02025 
02026       if ((frame->frametype == AST_FRAME_CONTROL) &&
02027             (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
02028             (frame->datalen == sizeof(t38_parameters))) {
02029          struct ast_control_t38_parameters *parameters = frame->data.ptr;
02030 
02031          switch (parameters->request_response) {
02032          case AST_T38_REQUEST_NEGOTIATE:
02033             /* the other end has requested a switch to T.38, so reply that we are willing, if we can
02034              * do T.38 as well
02035              */
02036             t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
02037             t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
02038             ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
02039             ast_playtones_stop(chan);
02040             break;
02041          case AST_T38_NEGOTIATED:
02042             ast_debug(1, "Negotiated T.38 for send on %s\n", ast_channel_name(chan));
02043             t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
02044             details->caps &= ~AST_FAX_TECH_AUDIO;
02045             report_fax_status(chan, details, "T.38 Negotiated");
02046             break_loop = 1;
02047             break;
02048          default:
02049             break;
02050          }
02051       }
02052       ast_frfree(frame);
02053       if (break_loop) {
02054          break;
02055       }
02056    }
02057 
02058    ast_playtones_stop(chan);
02059 
02060    if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) {
02061       return 0;
02062    }
02063 
02064    /* T.38 negotiation did not happen, initiate a switch if requested */
02065    if (details->option.request_t38 == AST_FAX_OPTFLAG_TRUE) {
02066       ast_debug(1, "Negotiating T.38 for send on %s\n", ast_channel_name(chan));
02067 
02068       /* wait up to five seconds for negotiation to complete */
02069       timeout_ms = 5000;
02070 
02071       /* set parameters based on the session's parameters */
02072       t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
02073       t38_parameters.request_response = AST_T38_REQUEST_NEGOTIATE;
02074       if ((ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0)) {
02075          return -1;
02076       }
02077 
02078       start = ast_tvnow();
02079       while ((ms = ast_remaining_ms(start, timeout_ms))) {
02080          int break_loop = 0;
02081 
02082          ms = ast_waitfor(chan, ms);
02083          if (ms < 0) {
02084             ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", ast_channel_name(chan));
02085             return -1;
02086          }
02087          if (ms == 0) { /* all done, nothing happened */
02088             ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 negotiation.\n", ast_channel_name(chan));
02089             details->caps &= ~AST_FAX_TECH_T38;
02090             break;
02091          }
02092 
02093          if (!(frame = ast_read(chan))) {
02094             ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", ast_channel_name(chan));
02095             return -1;
02096          }
02097 
02098          if ((frame->frametype == AST_FRAME_CONTROL) &&
02099                (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
02100                (frame->datalen == sizeof(t38_parameters))) {
02101             struct ast_control_t38_parameters *parameters = frame->data.ptr;
02102 
02103             switch (parameters->request_response) {
02104             case AST_T38_REQUEST_NEGOTIATE:
02105                t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
02106                t38_parameters.request_response = AST_T38_NEGOTIATED;
02107                ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
02108                break;
02109             case AST_T38_NEGOTIATED:
02110                ast_debug(1, "Negotiated T.38 for receive on %s\n", ast_channel_name(chan));
02111                t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
02112                details->caps &= ~AST_FAX_TECH_AUDIO;
02113                report_fax_status(chan, details, "T.38 Negotiated");
02114                break_loop = 1;
02115                break;
02116             case AST_T38_REFUSED:
02117                ast_log(LOG_WARNING, "channel '%s' refused to negotiate T.38\n", ast_channel_name(chan));
02118                details->caps &= ~AST_FAX_TECH_T38;
02119                break_loop = 1;
02120                break;
02121             default:
02122                ast_log(LOG_ERROR, "channel '%s' failed to negotiate T.38\n", ast_channel_name(chan));
02123                details->caps &= ~AST_FAX_TECH_T38;
02124                break_loop = 1;
02125                break;
02126             }
02127          }
02128          ast_frfree(frame);
02129          if (break_loop) {
02130             break;
02131          }
02132       }
02133 
02134       /* if T.38 was negotiated, we are done initializing */
02135       if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) {
02136          return 0;
02137       }
02138 
02139       /* send one more CNG tone to get audio going again for some
02140        * carriers if we are going to fall back to audio mode */
02141       if (details->option.allow_audio == AST_FAX_OPTFLAG_TRUE) {
02142          if (ast_playtones_start(chan, 1024, "!1100/500,!0/3000", 1)) {
02143             ast_log(LOG_ERROR, "error generating second CNG tone on %s\n", ast_channel_name(chan));
02144             return -1;
02145          }
02146 
02147          timeout_ms = 3500;
02148          start = ast_tvnow();
02149          while ((ms = ast_remaining_ms(start, timeout_ms))) {
02150             int break_loop = 0;
02151 
02152             ms = ast_waitfor(chan, ms);
02153             if (ms < 0) {
02154                ast_log(LOG_ERROR, "error while generating second CNG tone on %s\n", ast_channel_name(chan));
02155                ast_playtones_stop(chan);
02156                return -1;
02157             }
02158             if (ms == 0) { /* all done, nothing happened */
02159                break;
02160             }
02161 
02162             if (!(frame = ast_read(chan))) {
02163                ast_log(LOG_ERROR, "error reading frame while generating second CNG tone on %s\n", ast_channel_name(chan));
02164                ast_playtones_stop(chan);
02165                return -1;
02166             }
02167 
02168             if ((frame->frametype == AST_FRAME_CONTROL) &&
02169                   (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
02170                   (frame->datalen == sizeof(t38_parameters))) {
02171                struct ast_control_t38_parameters *parameters = frame->data.ptr;
02172 
02173                switch (parameters->request_response) {
02174                case AST_T38_REQUEST_NEGOTIATE:
02175                   /* the other end has requested a switch to T.38, so reply that we are willing, if we can
02176                    * do T.38 as well
02177                    */
02178                   t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
02179                   t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
02180                   ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
02181                   ast_playtones_stop(chan);
02182                   break;
02183                case AST_T38_NEGOTIATED:
02184                   ast_debug(1, "Negotiated T.38 for send on %s\n", ast_channel_name(chan));
02185                   t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
02186                   details->caps &= ~AST_FAX_TECH_AUDIO;
02187                   report_fax_status(chan, details, "T.38 Negotiated");
02188                   break_loop = 1;
02189                   break;
02190                default:
02191                   break;
02192                }
02193             }
02194             ast_frfree(frame);
02195             if (break_loop) {
02196                break;
02197             }
02198          }
02199 
02200          ast_playtones_stop(chan);
02201 
02202          /* if T.38 was negotiated, we are done initializing */
02203          if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) {
02204             return 0;
02205          }
02206       }
02207    }
02208 
02209    /* if we made it here, then T.38 failed, check the 'f' flag */
02210    if (details->option.allow_audio == AST_FAX_OPTFLAG_FALSE) {
02211       ast_log(LOG_WARNING, "Audio FAX not allowed on channel '%s' and T.38 negotiation failed; aborting.\n", ast_channel_name(chan));
02212       return -1;
02213    }
02214 
02215    /* ok, audio fallback is allowed */
02216    details->caps |= AST_FAX_TECH_AUDIO;
02217 
02218    return 0;
02219 }
02220 
02221 
02222 /*! \brief initiate a send FAX session */
02223 static int sendfax_exec(struct ast_channel *chan, const char *data)
02224 {
02225    char *parse, *filenames, *c, modems[128] = "";
02226    int channel_alive, file_count;
02227    struct ast_fax_session_details *details;
02228    struct ast_fax_session *s;
02229    struct ast_fax_tech_token *token = NULL;
02230    struct ast_fax_document *doc;
02231    AST_DECLARE_APP_ARGS(args,
02232       AST_APP_ARG(filenames);
02233       AST_APP_ARG(options);
02234    );
02235    struct ast_flags opts = { 0, };
02236    struct manager_event_info info;
02237    enum ast_t38_state t38state;
02238 
02239    /* initialize output channel variables */
02240    pbx_builtin_setvar_helper(chan, "FAXSTATUS", "FAILED");
02241    pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", NULL);
02242    pbx_builtin_setvar_helper(chan, "FAXPAGES", "0");
02243    pbx_builtin_setvar_helper(chan, "FAXBITRATE", NULL);
02244    pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", NULL);
02245 
02246    /* Get a requirement structure and set it.  This structure is used
02247     * to tell the FAX technology module about the higher level FAX session */
02248    if (!(details = find_or_create_details(chan))) {
02249       pbx_builtin_setvar_helper(chan, "FAXERROR", "MEMORY_ERROR");
02250       pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "error allocating memory");
02251       ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
02252       return -1;
02253    }
02254 
02255    ast_string_field_set(details, result, "FAILED");
02256    ast_string_field_set(details, resultstr, "error starting fax session");
02257    ast_string_field_set(details, error, "INIT_ERROR");
02258    set_channel_variables(chan, details);
02259 
02260    if (details->gateway_id > 0) {
02261       ast_string_field_set(details, resultstr, "can't send a fax on a channel with a T.38 gateway");
02262       set_channel_variables(chan, details);
02263       ast_log(LOG_ERROR, "executing SendFAX on a channel with a T.38 Gateway is not supported\n");
02264       ao2_ref(details, -1);
02265       return -1;
02266    }
02267 
02268    if (details->maxrate < details->minrate) {
02269       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
02270       ast_string_field_set(details, resultstr, "maxrate is less than minrate");
02271       set_channel_variables(chan, details);
02272       ast_log(LOG_ERROR, "maxrate %d is less than minrate %d\n", details->maxrate, details->minrate);
02273       ao2_ref(details, -1);
02274       return -1;
02275    }
02276 
02277    if (check_modem_rate(details->modems, details->minrate)) {
02278       ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
02279       ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %d\n", modems, details->minrate);
02280       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
02281       ast_string_field_set(details, resultstr, "incompatible 'modems' and 'minrate' settings");
02282       set_channel_variables(chan, details);
02283       ao2_ref(details, -1);
02284       return -1;
02285    }
02286 
02287    if (check_modem_rate(details->modems, details->maxrate)) {
02288       ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
02289       ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %d\n", modems, details->maxrate);
02290       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
02291       ast_string_field_set(details, resultstr, "incompatible 'modems' and 'maxrate' settings");
02292       set_channel_variables(chan, details);
02293       ao2_ref(details, -1);
02294       return -1;
02295    }
02296 
02297    if (ast_strlen_zero(data)) {
02298       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
02299       ast_string_field_set(details, resultstr, "invalid arguments");
02300       set_channel_variables(chan, details);
02301       ast_log(LOG_WARNING, "%s requires an argument (filename[&filename[&filename]][,options])\n", app_sendfax);
02302       ao2_ref(details, -1);
02303       return -1;
02304    }
02305    parse = ast_strdupa(data);
02306    AST_STANDARD_APP_ARGS(args, parse);
02307 
02308 
02309    if (!ast_strlen_zero(args.options) &&
02310        ast_app_parse_options(fax_exec_options, &opts, NULL, args.options)) {
02311       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
02312       ast_string_field_set(details, resultstr, "invalid arguments");
02313       set_channel_variables(chan, details);
02314       ao2_ref(details, -1);
02315       return -1;
02316    }
02317    if (ast_strlen_zero(args.filenames)) {
02318       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
02319       ast_string_field_set(details, resultstr, "invalid arguments");
02320       set_channel_variables(chan, details);
02321       ast_log(LOG_WARNING, "%s requires an argument (filename[&filename[&filename]],options])\n", app_sendfax);
02322       ao2_ref(details, -1);
02323       return -1;
02324    }
02325 
02326    /* check for unsupported FAX application options */
02327    if (ast_test_flag(&opts, OPT_CALLERMODE) || ast_test_flag(&opts, OPT_CALLEDMODE)) {
02328       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
02329       ast_string_field_set(details, resultstr, "invalid arguments");
02330       set_channel_variables(chan, details);
02331       ast_log(LOG_WARNING, "%s does not support polling\n", app_sendfax);
02332       ao2_ref(details, -1);
02333       return -1;
02334    }
02335 
02336    ast_atomic_fetchadd_int(&faxregistry.fax_tx_attempts, 1);
02337 
02338    file_count = 0;
02339    filenames = args.filenames;
02340    while ((c = strsep(&filenames, "&"))) {
02341       if (access(c, (F_OK | R_OK)) < 0) {
02342          ast_string_field_set(details, error, "FILE_ERROR");
02343          ast_string_field_set(details, resultstr, "error reading file");
02344          set_channel_variables(chan, details);
02345          ast_log(LOG_ERROR, "access failure.  Verify '%s' exists and check permissions.\n", args.filenames);
02346          ao2_ref(details, -1);
02347          return -1;
02348       }
02349 
02350       if (!(doc = ast_calloc(1, sizeof(*doc) + strlen(c) + 1))) {
02351          ast_string_field_set(details, error, "MEMORY_ERROR");
02352          ast_string_field_set(details, resultstr, "error allocating memory");
02353          set_channel_variables(chan, details);
02354          ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
02355          ao2_ref(details, -1);
02356          return -1;
02357       }
02358 
02359       strcpy(doc->filename, c);
02360       AST_LIST_INSERT_TAIL(&details->documents, doc, next);
02361       file_count++;
02362    }
02363 
02364    ast_verb(3, "Channel '%s' sending FAX:\n", ast_channel_name(chan));
02365    AST_LIST_TRAVERSE(&details->documents, doc, next) {
02366       ast_verb(3, "   %s\n", doc->filename);
02367    }
02368 
02369    details->caps = AST_FAX_TECH_SEND;
02370 
02371    if (file_count > 1) {
02372       details->caps |= AST_FAX_TECH_MULTI_DOC;
02373    }
02374 
02375    /* check for debug */
02376    if (ast_test_flag(&opts, OPT_DEBUG) || global_fax_debug) {
02377       details->option.debug = AST_FAX_OPTFLAG_TRUE;
02378    }
02379 
02380    /* check for request for status events */
02381    if (ast_test_flag(&opts, OPT_STATUS)) {
02382       details->option.statusevents = AST_FAX_OPTFLAG_TRUE;
02383    }
02384 
02385    t38state = ast_channel_get_t38_state(chan);
02386    if ((t38state == T38_STATE_UNAVAILABLE) || (t38state == T38_STATE_REJECTED) ||
02387        ast_test_flag(&opts, OPT_ALLOWAUDIO) ||
02388        ast_test_flag(&opts, OPT_FORCE_AUDIO)) {
02389       details->option.allow_audio = AST_FAX_OPTFLAG_TRUE;
02390    }
02391 
02392    if (ast_test_flag(&opts, OPT_REQUEST_T38)) {
02393       details->option.request_t38 = AST_FAX_OPTFLAG_TRUE;
02394    }
02395 
02396    if (!(s = fax_session_reserve(details, &token))) {
02397       ast_string_field_set(details, resultstr, "error reserving fax session");
02398       set_channel_variables(chan, details);
02399       ast_log(LOG_ERROR, "Unable to reserve FAX session.\n");
02400       ao2_ref(details, -1);
02401       return -1;
02402    }
02403 
02404    /* make sure the channel is up */
02405    if (ast_channel_state(chan) != AST_STATE_UP) {
02406       if (ast_answer(chan)) {
02407          ast_string_field_set(details, resultstr, "error answering channel");
02408          set_channel_variables(chan, details);
02409          ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", ast_channel_name(chan));
02410          fax_session_release(s, token);
02411          ao2_ref(s, -1);
02412          ao2_ref(details, -1);
02413          return -1;
02414       }
02415    }
02416 
02417    if (!ast_test_flag(&opts, OPT_FORCE_AUDIO)) {
02418       if (set_fax_t38_caps(chan, details)) {
02419          ast_string_field_set(details, error, "T38_NEG_ERROR");
02420          ast_string_field_set(details, resultstr, "error negotiating T.38");
02421          set_channel_variables(chan, details);
02422          fax_session_release(s, token);
02423          ao2_ref(s, -1);
02424          ao2_ref(details, -1);
02425          return -1;
02426       }
02427    } else {
02428       details->caps |= AST_FAX_TECH_AUDIO;
02429    }
02430 
02431    if (!ast_test_flag(&opts, OPT_FORCE_AUDIO) && (details->caps & AST_FAX_TECH_T38)) {
02432       if (sendfax_t38_init(chan, details)) {
02433          ast_string_field_set(details, error, "T38_NEG_ERROR");
02434          ast_string_field_set(details, resultstr, "error negotiating T.38");
02435          set_channel_variables(chan, details);
02436          fax_session_release(s, token);
02437          ao2_ref(s, -1);
02438          ao2_ref(details, -1);
02439          ast_log(LOG_ERROR, "error initializing channel '%s' in T.38 mode\n", ast_channel_name(chan));
02440          return -1;
02441       }
02442    } else {
02443       details->option.send_cng = 1;
02444    }
02445 
02446    if ((channel_alive = generic_fax_exec(chan, details, s, token)) < 0) {
02447       ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
02448    }
02449 
02450    if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) {
02451       if (disable_t38(chan)) {
02452          ast_debug(1, "error disabling T.38 mode on %s\n", ast_channel_name(chan));
02453       }
02454    }
02455 
02456    if (!(filenames = generate_filenames_string(details, "FileName: ", "\r\n"))) {
02457       ast_log(LOG_ERROR, "Error generating SendFAX manager event\n");
02458       ao2_ref(s, -1);
02459       ao2_ref(details, -1);
02460       return (!channel_alive) ? -1 : 0;
02461    }
02462 
02463    /* send out the AMI completion event */
02464    ast_channel_lock(chan);
02465    get_manager_event_info(chan, &info);
02466    manager_event(EVENT_FLAG_CALL,
02467             "SendFAX",
02468             "Channel: %s\r\n"
02469             "Context: %s\r\n"
02470             "Exten: %s\r\n"
02471             "CallerID: %s\r\n"
02472             "RemoteStationID: %s\r\n"
02473             "LocalStationID: %s\r\n"
02474             "PagesTransferred: %s\r\n"
02475             "Resolution: %s\r\n"
02476             "TransferRate: %s\r\n"
02477             "%s\r\n",
02478             ast_channel_name(chan),
02479             info.context,
02480             info.exten,
02481             info.cid,
02482             S_OR(pbx_builtin_getvar_helper(chan, "REMOTESTATIONID"), ""),
02483             S_OR(pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"), ""),
02484             S_OR(pbx_builtin_getvar_helper(chan, "FAXPAGES"), ""),
02485             S_OR(pbx_builtin_getvar_helper(chan, "FAXRESOLUTION"), ""),
02486             S_OR(pbx_builtin_getvar_helper(chan, "FAXBITRATE"), ""),
02487             filenames);
02488    ast_channel_unlock(chan);
02489 
02490    ast_free(filenames);
02491 
02492    ao2_ref(s, -1);
02493    ao2_ref(details, -1);
02494 
02495    /* If the channel hungup return -1; otherwise, return 0 to continue in the dialplan */
02496    return (!channel_alive) ? -1 : 0;
02497 }
02498 
02499 /*! \brief destroy the v21 detection parts of a fax gateway session */
02500 static void destroy_v21_sessions(struct fax_gateway *gateway)
02501 {
02502    if (gateway->chan_v21_session) {
02503       ao2_lock(faxregistry.container);
02504       ao2_unlink(faxregistry.container, gateway->chan_v21_session);
02505       ao2_unlock(faxregistry.container);
02506 
02507       ao2_ref(gateway->chan_v21_session, -1);
02508       gateway->chan_v21_session = NULL;
02509    }
02510 
02511    if (gateway->peer_v21_session) {
02512       ao2_lock(faxregistry.container);
02513       ao2_unlink(faxregistry.container, gateway->peer_v21_session);
02514       ao2_unlock(faxregistry.container);
02515 
02516       ao2_ref(gateway->peer_v21_session, -1);
02517       gateway->peer_v21_session = NULL;
02518    }
02519 }
02520 
02521 /*! \brief destroy a FAX gateway session structure */
02522 static void destroy_gateway(void *data)
02523 {
02524    struct fax_gateway *gateway = data;
02525 
02526    destroy_v21_sessions(gateway);
02527 
02528    if (gateway->s) {
02529       fax_session_release(gateway->s, gateway->token);
02530       gateway->token = NULL;
02531 
02532       ao2_lock(faxregistry.container);
02533       ao2_unlink(faxregistry.container, gateway->s);
02534       ao2_unlock(faxregistry.container);
02535 
02536       ao2_ref(gateway->s, -1);
02537       gateway->s = NULL;
02538    }
02539 }
02540 
02541 /*! \brief Create a new fax gateway object.
02542  * \param chan the channel the gateway object will be attached to
02543  * \param details the fax session details
02544  * \return NULL or a fax gateway object
02545  */
02546 static struct fax_gateway *fax_gateway_new(struct ast_channel *chan, struct ast_fax_session_details *details)
02547 {
02548    struct fax_gateway *gateway = ao2_alloc(sizeof(*gateway), destroy_gateway);
02549    struct ast_fax_session_details *v21_details;
02550    if (!gateway) {
02551       return NULL;
02552    }
02553 
02554    if (!(v21_details = session_details_new())) {
02555       ao2_ref(gateway, -1);
02556       return NULL;
02557    }
02558 
02559    v21_details->caps = AST_FAX_TECH_V21_DETECT;
02560    if (!(gateway->chan_v21_session = fax_session_new(v21_details, chan, NULL, NULL))) {
02561       ao2_ref(v21_details, -1);
02562       ao2_ref(gateway, -1);
02563       return NULL;
02564    }
02565 
02566    if (!(gateway->peer_v21_session = fax_session_new(v21_details, chan, NULL, NULL))) {
02567       ao2_ref(v21_details, -1);
02568       ao2_ref(gateway, -1);
02569       return NULL;
02570    }
02571    ao2_ref(v21_details, -1);
02572 
02573    gateway->framehook = -1;
02574 
02575    details->caps = AST_FAX_TECH_GATEWAY;
02576    if (details->gateway_timeout && !(gateway->s = fax_session_reserve(details, &gateway->token))) {
02577       details->caps &= ~AST_FAX_TECH_GATEWAY;
02578       ast_log(LOG_ERROR, "Can't reserve a FAX session, gateway attempt failed.\n");
02579       ao2_ref(gateway, -1);
02580       return NULL;
02581    }
02582 
02583    return gateway;
02584 }
02585 
02586 /*! \brief Create a fax session and start T.30<->T.38 gateway mode
02587  * \param gateway a fax gateway object
02588  * \param details fax session details
02589  * \param chan active channel
02590  * \return 0 on error 1 on success*/
02591 static int fax_gateway_start(struct fax_gateway *gateway, struct ast_fax_session_details *details, struct ast_channel *chan)
02592 {
02593    struct ast_fax_session *s;
02594 
02595    /* create the FAX session */
02596    if (!(s = fax_session_new(details, chan, gateway->s, gateway->token))) {
02597       gateway->token = NULL;
02598       ast_string_field_set(details, result, "FAILED");
02599       ast_string_field_set(details, resultstr, "error starting gateway session");
02600       ast_string_field_set(details, error, "INIT_ERROR");
02601       set_channel_variables(chan, details);
02602       report_fax_status(chan, details, "No Available Resource");
02603       ast_log(LOG_ERROR, "Can't create a FAX session, gateway attempt failed.\n");
02604       return -1;
02605    }
02606    /* release the reference for the reserved session and replace it with
02607     * the real session */
02608    if (gateway->s) {
02609       ao2_ref(gateway->s, -1);
02610    }
02611    gateway->s = s;
02612    gateway->token = NULL;
02613 
02614    if (gateway->s->tech->start_session(gateway->s) < 0) {
02615       ast_string_field_set(details, result, "FAILED");
02616       ast_string_field_set(details, resultstr, "error starting gateway session");
02617       ast_string_field_set(details, error, "INIT_ERROR");
02618       set_channel_variables(chan, details);
02619       return -1;
02620    }
02621 
02622    gateway->timeout_start.tv_sec = 0;
02623    gateway->timeout_start.tv_usec = 0;
02624 
02625    report_fax_status(chan, details, "FAX Transmission In Progress");
02626 
02627    return 0;
02628 }
02629 
02630 static struct ast_frame *fax_gateway_request_t38(struct fax_gateway *gateway, struct ast_channel *chan, struct ast_frame *f)
02631 {
02632    struct ast_frame *fp;
02633    struct ast_control_t38_parameters t38_parameters = {
02634       .request_response = AST_T38_REQUEST_NEGOTIATE,
02635    };
02636    struct ast_frame control_frame = {
02637       .src = "res_fax",
02638       .frametype = AST_FRAME_CONTROL,
02639       .datalen = sizeof(t38_parameters),
02640       .subclass.integer = AST_CONTROL_T38_PARAMETERS,
02641       .data.ptr = &t38_parameters,
02642    };
02643 
02644    struct ast_fax_session_details *details = find_details(chan);
02645 
02646    if (!details) {
02647       ast_log(LOG_ERROR, "no FAX session details found on chan %s for T.38 gateway session, odd\n", ast_channel_name(chan));
02648       ast_framehook_detach(chan, gateway->framehook);
02649       return f;
02650    }
02651 
02652    t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
02653    ao2_ref(details, -1);
02654 
02655    if (!(fp = ast_frisolate(&control_frame))) {
02656       ast_log(LOG_ERROR, "error generating T.38 request control frame on chan %s for T.38 gateway session\n", ast_channel_name(chan));
02657       return f;
02658    }
02659 
02660    gateway->t38_state = T38_STATE_NEGOTIATING;
02661    gateway->timeout_start = ast_tvnow();
02662    details->gateway_timeout = FAX_GATEWAY_TIMEOUT;
02663 
02664    ast_debug(1, "requesting T.38 for gateway session for %s\n", ast_channel_name(chan));
02665    return fp;
02666 }
02667 
02668 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)
02669 {
02670    struct ast_channel *other = (active == chan) ? peer : chan;
02671    struct ast_fax_session *active_v21_session = (active == chan) ? gateway->chan_v21_session : gateway->peer_v21_session;
02672 
02673    if (!active_v21_session || gateway->detected_v21) {
02674       return f;
02675    }
02676 
02677    if (active_v21_session->tech->write(active_v21_session, f) == 0 &&
02678        active_v21_session->details->option.v21_detected) {
02679       gateway->detected_v21 = 1;
02680    }
02681 
02682    if (gateway->detected_v21) {
02683       destroy_v21_sessions(gateway);
02684       if (ast_channel_get_t38_state(other) == T38_STATE_UNKNOWN) {
02685          ast_debug(1, "detected v21 preamble from %s\n", ast_channel_name(active));
02686          return fax_gateway_request_t38(gateway, chan, f);
02687       } else {
02688          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));
02689       }
02690    }
02691 
02692    return f;
02693 }
02694 
02695 static int fax_gateway_indicate_t38(struct ast_channel *chan, struct ast_channel *active, struct ast_control_t38_parameters *control_params)
02696 {
02697    if (active == chan) {
02698       return ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, control_params, sizeof(*control_params));
02699    } else {
02700       return ast_queue_control_data(chan, AST_CONTROL_T38_PARAMETERS, control_params, sizeof(*control_params));
02701    }
02702 }
02703 
02704 /*! \brief T38 Gateway Negotiate t38 parameters
02705  * \param gateway gateway object
02706  * \param chan channel running the gateway
02707  * \param peer channel im bridged too
02708  * \param active channel the frame originated on
02709  * \param f the control frame to process
02710  * \return processed control frame or null frame
02711  */
02712 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)
02713 {
02714    struct ast_control_t38_parameters *control_params = f->data.ptr;
02715    struct ast_channel *other = (active == chan) ? peer : chan;
02716    struct ast_fax_session_details *details;
02717 
02718    if (f->datalen != sizeof(struct ast_control_t38_parameters)) {
02719       /* invalaid AST_CONTROL_T38_PARAMETERS frame, we can't
02720        * do anything with it, pass it on */
02721       return f;
02722    }
02723 
02724    /* ignore frames from ourselves */
02725    if ((gateway->t38_state == T38_STATE_NEGOTIATED && control_params->request_response == AST_T38_NEGOTIATED)
02726       || (gateway->t38_state == T38_STATE_REJECTED && control_params->request_response == AST_T38_REFUSED)
02727       || (gateway->t38_state == T38_STATE_NEGOTIATING && control_params->request_response == AST_T38_REQUEST_TERMINATE)) {
02728 
02729       return f;
02730    }
02731 
02732    if (!(details = find_details(chan))) {
02733       ast_log(LOG_ERROR, "no FAX session details found on chan %s for T.38 gateway session, odd\n", ast_channel_name(chan));
02734       ast_framehook_detach(chan, gateway->framehook);
02735       return f;
02736    }
02737 
02738    if (control_params->request_response == AST_T38_REQUEST_NEGOTIATE) {
02739       enum ast_t38_state state = ast_channel_get_t38_state(other);
02740 
02741       if (state == T38_STATE_UNKNOWN) {
02742          /* we detected a request to negotiate T.38 and the
02743           * other channel appears to support T.38, we'll pass
02744           * the request through and only step in if the other
02745           * channel rejects the request */
02746          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));
02747          t38_parameters_ast_to_fax(&details->their_t38_parameters, control_params);
02748          gateway->t38_state = T38_STATE_UNKNOWN;
02749          gateway->timeout_start = ast_tvnow();
02750          details->gateway_timeout = FAX_GATEWAY_TIMEOUT;
02751          ao2_ref(details, -1);
02752          return f;
02753       } else if (state == T38_STATE_UNAVAILABLE || state == T38_STATE_REJECTED) {
02754          /* the other channel does not support T.38, we need to
02755           * step in here */
02756          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));
02757          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));
02758 
02759          t38_parameters_ast_to_fax(&details->their_t38_parameters, control_params);
02760          t38_parameters_fax_to_ast(control_params, &details->our_t38_parameters);
02761 
02762          if (fax_gateway_start(gateway, details, chan)) {
02763             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));
02764             gateway->t38_state = T38_STATE_REJECTED;
02765             control_params->request_response = AST_T38_REFUSED;
02766 
02767             ast_framehook_detach(chan, details->gateway_id);
02768             details->gateway_id = -1;
02769          } else {
02770             gateway->t38_state = T38_STATE_NEGOTIATED;
02771             control_params->request_response = AST_T38_NEGOTIATED;
02772             report_fax_status(chan, details, "T.38 Negotiated");
02773          }
02774 
02775          fax_gateway_indicate_t38(chan, active, control_params);
02776 
02777          ao2_ref(details, -1);
02778          return &ast_null_frame;
02779       } else if (gateway->t38_state == T38_STATE_NEGOTIATING) {
02780          /* we got a request to negotiate T.38 after we already
02781           * sent one to the other party based on v21 preamble
02782           * detection. We'll just pretend we passed this request
02783           * through in the first place. */
02784 
02785          t38_parameters_ast_to_fax(&details->their_t38_parameters, control_params);
02786          gateway->t38_state = T38_STATE_UNKNOWN;
02787          gateway->timeout_start = ast_tvnow();
02788          details->gateway_timeout = FAX_GATEWAY_TIMEOUT;
02789 
02790          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));
02791          ao2_ref(details, -1);
02792          return &ast_null_frame;
02793       } else if (gateway->t38_state == T38_STATE_NEGOTIATED) {
02794          /* we got a request to negotiate T.38 after we already
02795           * sent one to the other party based on v21 preamble
02796           * detection and received a response. We need to
02797           * respond to this and shut down the gateway. */
02798 
02799          t38_parameters_fax_to_ast(control_params, &details->their_t38_parameters);
02800          ast_framehook_detach(chan, details->gateway_id);
02801          details->gateway_id = -1;
02802 
02803          control_params->request_response = AST_T38_NEGOTIATED;
02804 
02805          fax_gateway_indicate_t38(chan, active, control_params);
02806 
02807          ast_string_field_set(details, result, "SUCCESS");
02808          ast_string_field_set(details, resultstr, "no gateway necessary");
02809          ast_string_field_set(details, error, "NATIVE_T38");
02810          set_channel_variables(chan, details);
02811 
02812          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));
02813          ao2_ref(details, -1);
02814          return &ast_null_frame;
02815       } else {
02816          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));
02817          ao2_ref(details, -1);
02818          return f;
02819       }
02820    } else if (gateway->t38_state == T38_STATE_NEGOTIATING
02821       && control_params->request_response == AST_T38_REFUSED) {
02822 
02823       ast_debug(1, "unable to negotiate T.38 on %s for fax gateway\n", ast_channel_name(active));
02824 
02825       /* our request to negotiate T.38 was refused, if the other
02826        * channel supports T.38, they might still reinvite and save
02827        * the day.  Otherwise disable the gateway. */
02828       if (ast_channel_get_t38_state(other) == T38_STATE_UNKNOWN) {
02829          gateway->t38_state = T38_STATE_UNAVAILABLE;
02830       } else {
02831          ast_framehook_detach(chan, details->gateway_id);
02832          details->gateway_id = -1;
02833 
02834          ast_string_field_set(details, result, "FAILED");
02835          ast_string_field_set(details, resultstr, "unable to negotiate T.38");
02836          ast_string_field_set(details, error, "T38_NEG_ERROR");
02837          set_channel_variables(chan, details);
02838       }
02839 
02840       ao2_ref(details, -1);
02841       return &ast_null_frame;
02842    } else if (gateway->t38_state == T38_STATE_NEGOTIATING
02843       && control_params->request_response == AST_T38_NEGOTIATED) {
02844 
02845       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));
02846 
02847       t38_parameters_ast_to_fax(&details->their_t38_parameters, control_params);
02848 
02849       if (fax_gateway_start(gateway, details, chan)) {
02850          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));
02851          gateway->t38_state = T38_STATE_NEGOTIATING;
02852          control_params->request_response = AST_T38_REQUEST_TERMINATE;
02853 
02854          fax_gateway_indicate_t38(chan, active, control_params);
02855       } else {
02856          gateway->t38_state = T38_STATE_NEGOTIATED;
02857          report_fax_status(chan, details, "T.38 Negotiated");
02858       }
02859 
02860       ao2_ref(details, -1);
02861       return &ast_null_frame;
02862    } else if (control_params->request_response == AST_T38_REFUSED) {
02863       /* the other channel refused the request to negotiate T.38,
02864        * we'll step in here and pretend the request was accepted */
02865 
02866       ast_debug(1, "%s attempted to negotiate T.38 but %s refused the request\n", ast_channel_name(other), ast_channel_name(active));
02867       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));
02868 
02869       t38_parameters_fax_to_ast(control_params, &details->our_t38_parameters);
02870 
02871       if (fax_gateway_start(gateway, details, chan)) {
02872          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));
02873          gateway->t38_state = T38_STATE_REJECTED;
02874          control_params->request_response = AST_T38_REFUSED;
02875 
02876          ast_framehook_detach(chan, details->gateway_id);
02877          details->gateway_id = -1;
02878       } else {
02879          gateway->t38_state = T38_STATE_NEGOTIATED;
02880          control_params->request_response = AST_T38_NEGOTIATED;
02881       }
02882 
02883       ao2_ref(details, -1);
02884       return f;
02885    } else if (control_params->request_response == AST_T38_REQUEST_TERMINATE) {
02886       /* the channel wishes to end our short relationship, we shall
02887        * oblige */
02888 
02889       ast_debug(1, "T.38 channel %s is requesting a shutdown of T.38, disabling the gateway\n", ast_channel_name(active));
02890 
02891       ast_framehook_detach(chan, details->gateway_id);
02892       details->gateway_id = -1;
02893 
02894       gateway->t38_state = T38_STATE_REJECTED;
02895       control_params->request_response = AST_T38_TERMINATED;
02896 
02897       fax_gateway_indicate_t38(chan, active, control_params);
02898 
02899       ao2_ref(details, -1);
02900       return &ast_null_frame;
02901    } else if (control_params->request_response == AST_T38_NEGOTIATED) {
02902       ast_debug(1, "T.38 successfully negotiated between %s and %s, no gateway necessary\n", ast_channel_name(active), ast_channel_name(other));
02903 
02904       ast_framehook_detach(chan, details->gateway_id);
02905       details->gateway_id = -1;
02906 
02907       ast_string_field_set(details, result, "SUCCESS");
02908       ast_string_field_set(details, resultstr, "no gateway necessary");
02909       ast_string_field_set(details, error, "NATIVE_T38");
02910       set_channel_variables(chan, details);
02911 
02912       ao2_ref(details, -1);
02913       return f;
02914    } else if (control_params->request_response == AST_T38_TERMINATED) {
02915       ast_debug(1, "T.38 disabled on channel %s\n", ast_channel_name(active));
02916 
02917       ast_framehook_detach(chan, details->gateway_id);
02918       details->gateway_id = -1;
02919 
02920       ao2_ref(details, -1);
02921       return &ast_null_frame;
02922    }
02923 
02924    ao2_ref(details, -1);
02925    return f;
02926 }
02927 
02928 /*! \brief Destroy the gateway data structure when the framehook is detached
02929  * \param data framehook data (gateway data)*/
02930 static void fax_gateway_framehook_destroy(void *data) {
02931    struct fax_gateway *gateway = data;
02932 
02933    if (gateway->s) {
02934       switch (gateway->s->state) {
02935       case AST_FAX_STATE_INITIALIZED:
02936       case AST_FAX_STATE_OPEN:
02937       case AST_FAX_STATE_ACTIVE:
02938       case AST_FAX_STATE_COMPLETE:
02939          if (gateway->s->tech->cancel_session) {
02940             gateway->s->tech->cancel_session(gateway->s);
02941          }
02942          /* fall through */
02943       default:
02944          break;
02945       }
02946    }
02947 
02948    ao2_ref(gateway, -1);
02949 }
02950 
02951 /*! \brief T.30<->T.38 gateway framehook.
02952  *
02953  * Intercept packets on bridged channels and determine if a T.38 gateway is
02954  * required. If a gateway is required, start a gateway and handle T.38
02955  * negotiation if necessary.
02956  *
02957  * \param chan channel running the gateway
02958  * \param f frame to handle may be NULL
02959  * \param event framehook event
02960  * \param data framehook data (struct fax_gateway *)
02961  *
02962  * \return processed frame or NULL when f is NULL or a null frame
02963  */
02964 static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data) {
02965    struct fax_gateway *gateway = data;
02966    struct ast_channel *peer, *active;
02967    struct ast_fax_session_details *details;
02968 
02969    if (gateway->s) {
02970       details = gateway->s->details;
02971       ao2_ref(details, 1);
02972    } else {
02973       if (!(details = find_details(chan))) {
02974          ast_log(LOG_ERROR, "no FAX session details found on chan %s for T.38 gateway session, odd\n", ast_channel_name(chan));
02975          ast_framehook_detach(chan, gateway->framehook);
02976          return f;
02977       }
02978    }
02979 
02980    /* restore audio formats when we are detached */
02981    if (event == AST_FRAMEHOOK_EVENT_DETACHED) {
02982       set_channel_variables(chan, details);
02983 
02984       if (gateway->bridged) {
02985          ast_set_read_format(chan, &gateway->chan_read_format);
02986          ast_set_read_format(chan, &gateway->chan_write_format);
02987 
02988          if ((peer = ast_bridged_channel(chan))) {
02989             ast_set_read_format(peer, &gateway->peer_read_format);
02990             ast_set_read_format(peer, &gateway->peer_write_format);
02991             ast_channel_make_compatible(chan, peer);
02992          }
02993       }
02994 
02995       ao2_ref(details, -1);
02996       return NULL;
02997    }
02998 
02999    if (!f || (event == AST_FRAMEHOOK_EVENT_ATTACHED)) {
03000       ao2_ref(details, -1);
03001       return NULL;
03002    };
03003 
03004    /* this frame was generated by the fax gateway, pass it on */
03005    if (ast_test_flag(f, AST_FAX_FRFLAG_GATEWAY)) {
03006       ao2_ref(details, -1);
03007       return f;
03008    }
03009 
03010    if (!(peer = ast_bridged_channel(chan))) {
03011       /* not bridged, don't do anything */
03012       ao2_ref(details, -1);
03013       return f;
03014    }
03015 
03016    if (!gateway->bridged && peer) {
03017       /* don't start a gateway if neither channel can handle T.38 */
03018       if (ast_channel_get_t38_state(chan) == T38_STATE_UNAVAILABLE && ast_channel_get_t38_state(peer) == T38_STATE_UNAVAILABLE) {
03019          ast_debug(1, "not starting gateway for %s and %s; neither channel supports T.38\n", ast_channel_name(chan), ast_channel_name(peer));
03020          ast_framehook_detach(chan, gateway->framehook);
03021          details->gateway_id = -1;
03022 
03023          ast_string_field_set(details, result, "FAILED");
03024          ast_string_field_set(details, resultstr, "neither channel supports T.38");
03025          ast_string_field_set(details, error, "T38_NEG_ERROR");
03026          set_channel_variables(chan, details);
03027          ao2_ref(details, -1);
03028          return f;
03029       }
03030 
03031       if (details->gateway_timeout) {
03032          gateway->timeout_start = ast_tvnow();
03033       }
03034 
03035       /* we are bridged, change r/w formats to SLIN for v21 preamble
03036        * detection and T.30 */
03037       ast_format_copy(&gateway->chan_read_format, ast_channel_readformat(chan));
03038       ast_format_copy(&gateway->chan_write_format, ast_channel_readformat(chan));
03039 
03040       ast_format_copy(&gateway->peer_read_format, ast_channel_readformat(peer));
03041       ast_format_copy(&gateway->peer_write_format, ast_channel_readformat(peer));
03042 
03043       ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR);
03044       ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR);
03045 
03046       ast_set_read_format_by_id(peer, AST_FORMAT_SLINEAR);
03047       ast_set_write_format_by_id(peer, AST_FORMAT_SLINEAR);
03048 
03049       ast_channel_make_compatible(chan, peer);
03050       gateway->bridged = 1;
03051    }
03052 
03053    if (gateway->bridged && !ast_tvzero(gateway->timeout_start)) {
03054       if (ast_tvdiff_ms(ast_tvnow(), gateway->timeout_start) > details->gateway_timeout) {
03055          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);
03056          ast_framehook_detach(chan, gateway->framehook);
03057          details->gateway_id = -1;
03058 
03059          ast_string_field_set(details, result, "FAILED");
03060          ast_string_field_build(details, resultstr, "no fax activity after %d ms", details->gateway_timeout);
03061          ast_string_field_set(details, error, "TIMEOUT");
03062          set_channel_variables(chan, details);
03063          ao2_ref(details, -1);
03064          return f;
03065       }
03066    }
03067 
03068    /* only handle VOICE, MODEM, and CONTROL frames*/
03069    switch (f->frametype) {
03070    case AST_FRAME_VOICE:
03071       switch (f->subclass.format.id) {
03072       case AST_FORMAT_SLINEAR:
03073       case AST_FORMAT_ALAW:
03074       case AST_FORMAT_ULAW:
03075          break;
03076       default:
03077          ao2_ref(details, -1);
03078          return f;
03079       }
03080       break;
03081    case AST_FRAME_MODEM:
03082       if (f->subclass.integer == AST_MODEM_T38) {
03083          break;
03084       }
03085       ao2_ref(details, -1);
03086       return f;
03087    case AST_FRAME_CONTROL:
03088       if (f->subclass.integer == AST_CONTROL_T38_PARAMETERS) {
03089          break;
03090       }
03091       ao2_ref(details, -1);
03092       return f;
03093    default:
03094       ao2_ref(details, -1);
03095       return f;
03096    }
03097 
03098    /* detect the active channel */
03099    switch (event) {
03100    case AST_FRAMEHOOK_EVENT_WRITE:
03101       active = peer;
03102       break;
03103    case AST_FRAMEHOOK_EVENT_READ:
03104       active = chan;
03105       break;
03106    default:
03107       ast_log(LOG_WARNING, "unhandled framehook event %i\n", event);
03108       ao2_ref(details, -1);
03109       return f;
03110    }
03111 
03112    /* handle control frames */
03113    if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_T38_PARAMETERS) {
03114       ao2_ref(details, -1);
03115       return fax_gateway_detect_t38(gateway, chan, peer, active, f);
03116    }
03117 
03118    if (!gateway->detected_v21 && gateway->t38_state == T38_STATE_UNAVAILABLE && f->frametype == AST_FRAME_VOICE) {
03119       /* not in gateway mode and have not detected v21 yet, listen
03120        * for v21 */
03121       ao2_ref(details, -1);
03122       return fax_gateway_detect_v21(gateway, chan, peer, active, f);
03123    }
03124 
03125    /* in gateway mode, gateway some packets */
03126    if (gateway->t38_state == T38_STATE_NEGOTIATED) {
03127       /* framehooks are called in __ast_read() before frame format
03128        * translation is done, so we need to translate here */
03129       if ((f->frametype == AST_FRAME_VOICE) && (f->subclass.format.id != AST_FORMAT_SLINEAR)) {
03130          if (ast_channel_readtrans(active) && (f = ast_translate(ast_channel_readtrans(active), f, 1)) == NULL) {
03131             f = &ast_null_frame;
03132             ao2_ref(details, -1);
03133             return f;
03134          }
03135       }
03136 
03137       /* XXX we ignore the return value here, perhaps we should
03138        * disable the gateway if a write fails. I am not sure how a
03139        * write would fail, or even if a failure would be fatal so for
03140        * now we'll just ignore the return value. */
03141       gateway->s->tech->write(gateway->s, f);
03142       if ((f->frametype == AST_FRAME_VOICE) && (f->subclass.format.id != AST_FORMAT_SLINEAR) && ast_channel_readtrans(active)) {
03143          /* Only free the frame if we translated / duplicated it - otherwise,
03144           * let whatever is outside the frame hook do it */
03145          ast_frfree(f);
03146       }
03147       f = &ast_null_frame;
03148       ao2_ref(details, -1);
03149       return f;
03150    }
03151 
03152    /* force silence on the line if T.38 negotiation might be taking place */
03153    if (gateway->t38_state != T38_STATE_UNAVAILABLE && gateway->t38_state != T38_STATE_REJECTED) {
03154       if (f->frametype == AST_FRAME_VOICE && f->subclass.format.id == AST_FORMAT_SLINEAR) {
03155          short silence_buf[f->samples];
03156          struct ast_frame silence_frame = {
03157             .frametype = AST_FRAME_VOICE,
03158             .data.ptr = silence_buf,
03159             .samples = f->samples,
03160             .datalen = sizeof(silence_buf),
03161          };
03162          ast_format_set(&silence_frame.subclass.format, AST_FORMAT_SLINEAR, 0);
03163          memset(silence_buf, 0, sizeof(silence_buf));
03164 
03165          ao2_ref(details, -1);
03166          return ast_frisolate(&silence_frame);
03167       } else {
03168          ao2_ref(details, -1);
03169          return &ast_null_frame;
03170       }
03171    }
03172 
03173    ao2_ref(details, -1);
03174    return f;
03175 }
03176 
03177 /*! \brief Attach a gateway framehook object to a channel.
03178  * \param chan the channel to attach to
03179  * \param details fax session details
03180  * \return the framehook id of the attached framehook or -1 on error
03181  * \retval -1 error
03182  */
03183 static int fax_gateway_attach(struct ast_channel *chan, struct ast_fax_session_details *details)
03184 {
03185    struct fax_gateway *gateway;
03186    struct ast_framehook_interface fr_hook = {
03187       .version = AST_FRAMEHOOK_INTERFACE_VERSION,
03188       .event_cb = fax_gateway_framehook,
03189       .destroy_cb = fax_gateway_framehook_destroy,
03190    };
03191 
03192    ast_string_field_set(details, result, "SUCCESS");
03193    ast_string_field_set(details, resultstr, "gateway operation started successfully");
03194    ast_string_field_set(details, error, "NO_ERROR");
03195    set_channel_variables(chan, details);
03196 
03197    /* set up the frame hook*/
03198    gateway = fax_gateway_new(chan, details);
03199    if (!gateway) {
03200       ast_string_field_set(details, result, "FAILED");
03201       ast_string_field_set(details, resultstr, "error initializing gateway session");
03202       ast_string_field_set(details, error, "INIT_ERROR");
03203       set_channel_variables(chan, details);
03204       report_fax_status(chan, details, "No Available Resource");
03205       return -1;
03206    }
03207 
03208    fr_hook.data = gateway;
03209    ast_channel_lock(chan);
03210    gateway->framehook = ast_framehook_attach(chan, &fr_hook);
03211    ast_channel_unlock(chan);
03212 
03213    if (gateway->framehook < 0) {
03214       ao2_ref(gateway, -1);
03215       ast_string_field_set(details, result, "FAILED");
03216       ast_string_field_set(details, resultstr, "error attaching gateway to channel");
03217       ast_string_field_set(details, error, "INIT_ERROR");
03218       set_channel_variables(chan, details);
03219       return -1;
03220    }
03221 
03222    return gateway->framehook;
03223 }
03224 
03225 /*! \brief destroy a FAX detect structure */
03226 static void destroy_faxdetect(void *data)
03227 {
03228    struct fax_detect *faxdetect = data;
03229 
03230    if (faxdetect->dsp) {
03231       ast_dsp_free(faxdetect->dsp);
03232       faxdetect->dsp = NULL;
03233    }
03234    ao2_ref(faxdetect->details, -1);
03235 }
03236 
03237 /*! \brief Create a new fax detect object.
03238  * \param chan the channel attaching to
03239  * \param timeout remove framehook in this time if set
03240  * \param flags required options
03241  * \return NULL or a fax gateway object
03242  */
03243 static struct fax_detect *fax_detect_new(struct ast_channel *chan, int timeout, int flags)
03244 {
03245    struct fax_detect *faxdetect = ao2_alloc(sizeof(*faxdetect), destroy_faxdetect);
03246    if (!faxdetect) {
03247       return NULL;
03248    }
03249 
03250    faxdetect->flags = flags;
03251 
03252    if (timeout) {
03253       faxdetect->timeout_start = ast_tvnow();
03254    } else {
03255       faxdetect->timeout_start.tv_sec = 0;
03256       faxdetect->timeout_start.tv_usec = 0;
03257    }
03258 
03259    if (faxdetect->flags & FAX_DETECT_MODE_CNG) {
03260       faxdetect->dsp = ast_dsp_new();
03261       if (!faxdetect->dsp) {
03262          ao2_ref(faxdetect, -1);
03263          return NULL;
03264       }
03265       ast_dsp_set_features(faxdetect->dsp, DSP_FEATURE_FAX_DETECT);
03266       ast_dsp_set_faxmode(faxdetect->dsp, DSP_FAXMODE_DETECT_CNG | DSP_FAXMODE_DETECT_SQUELCH);
03267    } else {
03268       faxdetect->dsp = NULL;
03269    }
03270 
03271    return faxdetect;
03272 }
03273 
03274 /*! \brief Deref the faxdetect data structure when the faxdetect framehook is detached
03275  * \param data framehook data (faxdetect data)*/
03276 static void fax_detect_framehook_destroy(void *data) {
03277    struct fax_detect *faxdetect = data;
03278 
03279    ao2_ref(faxdetect, -1);
03280 }
03281 
03282 /*! \brief Fax Detect Framehook
03283  *
03284  * Listen for fax tones in audio path and enable jumping to a extension when detected.
03285  *
03286  * \param chan channel
03287  * \param f frame to handle may be NULL
03288  * \param event framehook event
03289  * \param data framehook data (struct fax_detect *)
03290  *
03291  * \return processed frame or NULL when f is NULL or a null frame
03292  */
03293 static struct ast_frame *fax_detect_framehook(struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data) {
03294    struct fax_detect *faxdetect = data;
03295    struct ast_fax_session_details *details;
03296    struct ast_control_t38_parameters *control_params;
03297    struct ast_channel *peer;
03298    int result = 0;
03299 
03300    details = faxdetect->details;
03301 
03302    switch (event) {
03303    case AST_FRAMEHOOK_EVENT_ATTACHED:
03304       /* Setup format for DSP on ATTACH*/
03305       ast_format_copy(&faxdetect->orig_format, ast_channel_readformat(chan));
03306       switch (ast_channel_readformat(chan)->id) {
03307          case AST_FORMAT_SLINEAR:
03308          case AST_FORMAT_ALAW:
03309          case AST_FORMAT_ULAW:
03310             break;
03311          default:
03312             if (ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR)) {
03313                ast_framehook_detach(chan, details->faxdetect_id);
03314                details->faxdetect_id = -1;
03315                return f;
03316             }
03317       }
03318       return NULL;
03319    case AST_FRAMEHOOK_EVENT_DETACHED:
03320       /* restore audio formats when we are detached */
03321       ast_set_read_format(chan, &faxdetect->orig_format);
03322       if ((peer = ast_bridged_channel(chan))) {
03323          ast_channel_make_compatible(chan, peer);
03324       }
03325       return NULL;
03326    case AST_FRAMEHOOK_EVENT_READ:
03327       if (f) {
03328          break;
03329       }
03330    default:
03331       return f;
03332    };
03333 
03334    if (details->faxdetect_id < 0) {
03335       return f;
03336    }
03337 
03338    if ((!ast_tvzero(faxdetect->timeout_start) &&
03339        (ast_tvdiff_ms(ast_tvnow(), faxdetect->timeout_start) > faxdetect->timeout))) {
03340       ast_framehook_detach(chan, details->faxdetect_id);
03341       details->faxdetect_id = -1;
03342       return f;
03343    }
03344 
03345    /* only handle VOICE and CONTROL frames*/
03346    switch (f->frametype) {
03347    case AST_FRAME_VOICE:
03348       /* we have no DSP this means we not detecting CNG */
03349       if (!faxdetect->dsp) {
03350          return f;
03351       }
03352       /* We can only process some formats*/
03353       switch (f->subclass.format.id) {
03354          case AST_FORMAT_SLINEAR:
03355          case AST_FORMAT_ALAW:
03356          case AST_FORMAT_ULAW:
03357             break;
03358          default:
03359             return f;
03360       }
03361       break;
03362    case AST_FRAME_CONTROL:
03363       if ((f->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
03364           (faxdetect->flags & FAX_DETECT_MODE_T38)) {
03365          break;
03366       }
03367       return f;
03368    default:
03369       return f;
03370    }
03371 
03372    if (f->frametype == AST_FRAME_VOICE) {
03373       f = ast_dsp_process(chan, faxdetect->dsp, f);
03374       if (f->frametype == AST_FRAME_DTMF) {
03375          result = f->subclass.integer;
03376       }
03377    } else if ((f->frametype == AST_FRAME_CONTROL) && (f->datalen == sizeof(struct ast_control_t38_parameters))) {
03378       control_params = f->data.ptr;
03379       switch (control_params->request_response) {
03380       case AST_T38_NEGOTIATED:
03381       case AST_T38_REQUEST_NEGOTIATE:
03382          result = 't';
03383          break;
03384       default:
03385          break;
03386       }
03387    }
03388 
03389    if (result) {
03390       const char *target_context = S_OR(ast_channel_macrocontext(chan), ast_channel_context(chan));
03391       switch (result) {
03392       case 'f':
03393       case 't':
03394          ast_channel_unlock(chan);
03395          if (ast_exists_extension(chan, target_context, "fax", 1,
03396              S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
03397             ast_channel_lock(chan);
03398             ast_verb(2, "Redirecting '%s' to fax extension due to %s detection\n",
03399                ast_channel_name(chan), (result == 'f') ? "CNG" : "T38");
03400             pbx_builtin_setvar_helper(chan, "FAXEXTEN", ast_channel_exten(chan));
03401             if (ast_async_goto(chan, target_context, "fax", 1)) {
03402                ast_log(LOG_NOTICE, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(chan), target_context);
03403             }
03404             ast_frfree(f);
03405             f = &ast_null_frame;
03406          } else {
03407             ast_channel_lock(chan);
03408             ast_log(LOG_NOTICE, "FAX %s detected but no fax extension in context (%s)\n",
03409                (result == 'f') ? "CNG" : "T38", target_context);
03410          }
03411       }
03412       ast_framehook_detach(chan, details->faxdetect_id);
03413       details->faxdetect_id = -1;
03414    }
03415 
03416    return f;
03417 }
03418 
03419 /*! \brief Attach a faxdetect framehook object to a channel.
03420  * \param chan the channel to attach to
03421  * \param timeout remove framehook in this time if set
03422  * \return the faxdetect structure or NULL on error
03423  * \param flags required options
03424  * \retval -1 error
03425  */
03426 static int fax_detect_attach(struct ast_channel *chan, int timeout, int flags)
03427 {
03428    struct fax_detect *faxdetect;
03429    struct ast_fax_session_details *details;
03430    struct ast_framehook_interface fr_hook = {
03431       .version = AST_FRAMEHOOK_INTERFACE_VERSION,
03432       .event_cb = fax_detect_framehook,
03433       .destroy_cb = fax_detect_framehook_destroy,
03434    };
03435 
03436    if (!(details = find_or_create_details(chan))) {
03437       ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
03438       return -1;
03439    }
03440 
03441    /* set up the frame hook*/
03442    faxdetect = fax_detect_new(chan, timeout, flags);
03443    if (!faxdetect) {
03444       ao2_ref(details, -1);
03445       return -1;
03446    }
03447 
03448    fr_hook.data = faxdetect;
03449    faxdetect->details = details;
03450    ast_channel_lock(chan);
03451    details->faxdetect_id = ast_framehook_attach(chan, &fr_hook);
03452    ast_channel_unlock(chan);
03453 
03454    if (details->faxdetect_id < 0) {
03455       ao2_ref(faxdetect, -1);
03456    }
03457 
03458    return details->faxdetect_id;
03459 }
03460 
03461 /*! \brief hash callback for ao2 */
03462 static int session_hash_cb(const void *obj, const int flags)
03463 {
03464    const struct ast_fax_session *s = obj;
03465 
03466    return s->id;
03467 }
03468 
03469 /*! \brief compare callback for ao2 */
03470 static int session_cmp_cb(void *obj, void *arg, int flags)
03471 {
03472    struct ast_fax_session *lhs = obj, *rhs = arg;
03473 
03474    return (lhs->id == rhs->id) ? CMP_MATCH | CMP_STOP : 0;
03475 }
03476 
03477 /*! \brief fax session tab completion */
03478 static char *fax_session_tab_complete(struct ast_cli_args *a)
03479 {
03480    int tklen;
03481    int wordnum = 0;
03482    char *name = NULL;
03483    struct ao2_iterator i;
03484    struct ast_fax_session *s;
03485    char tbuf[5];
03486 
03487    if (a->pos != 3) {
03488       return NULL;
03489    }
03490 
03491    tklen = strlen(a->word);
03492    i = ao2_iterator_init(faxregistry.container, 0);
03493    while ((s = ao2_iterator_next(&i))) {
03494       snprintf(tbuf, sizeof(tbuf), "%d", s->id);
03495       if (!strncasecmp(a->word, tbuf, tklen) && ++wordnum > a->n) {
03496          name = ast_strdup(tbuf);
03497          ao2_ref(s, -1);
03498          break;
03499       }
03500       ao2_ref(s, -1);
03501    }
03502    ao2_iterator_destroy(&i);
03503    return name;
03504 }
03505 
03506 static char *cli_fax_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
03507 {
03508    struct fax_module *fax;
03509 
03510    switch(cmd) {
03511    case CLI_INIT:
03512       e->command = "fax show version";
03513       e->usage =
03514          "Usage: fax show version\n"
03515          "       Show versions of FAX For Asterisk components.\n";
03516       return NULL;
03517    case CLI_GENERATE:
03518       return NULL;
03519    }
03520 
03521    if (a->argc != 3) {
03522       return CLI_SHOWUSAGE;
03523    }
03524 
03525    ast_cli(a->fd, "FAX For Asterisk Components:\n");
03526    ast_cli(a->fd, "\tApplications: %s\n", ast_get_version());
03527    AST_RWLIST_RDLOCK(&faxmodules);
03528    AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
03529       ast_cli(a->fd, "\t%s: %s\n", fax->tech->description, fax->tech->version);
03530    }
03531    AST_RWLIST_UNLOCK(&faxmodules);
03532    ast_cli(a->fd, "\n");
03533 
03534    return CLI_SUCCESS;
03535 }
03536 
03537 /*! \brief enable FAX debugging */
03538 static char *cli_fax_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
03539 {
03540    int flag;
03541    const char *what;
03542 
03543    switch (cmd) {
03544    case CLI_INIT:
03545       e->command = "fax set debug {on|off}";
03546       e->usage =
03547          "Usage: fax set debug { on | off }\n"
03548          "       Enable/Disable FAX debugging on new FAX sessions.  The basic FAX debugging will result in\n"
03549          "       additional events sent to manager sessions with 'call' class permissions.  When\n"
03550          "       verbosity is greater than '5' events will be displayed to the console and audio versus\n"
03551          "       energy analysis will be performed and displayed to the console.\n";
03552       return NULL;
03553    case CLI_GENERATE:
03554       return NULL;
03555    }
03556 
03557    what = a->argv[e->args-1];      /* guaranteed to exist */
03558    if (!strcasecmp(what, "on")) {
03559       flag = 1;
03560    } else if (!strcasecmp(what, "off")) {
03561       flag = 0;
03562    } else {
03563       return CLI_SHOWUSAGE;
03564    }
03565 
03566    global_fax_debug = flag;
03567    ast_cli(a->fd, "\n\nFAX Debug %s\n\n", (flag) ? "Enabled" : "Disabled");
03568 
03569    return CLI_SUCCESS;
03570 }
03571 
03572 /*! \brief display registered FAX capabilities */
03573 static char *cli_fax_show_capabilities(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
03574 {
03575    struct fax_module *fax;
03576    unsigned int num_modules = 0;
03577 
03578    switch (cmd) {
03579    case CLI_INIT:
03580       e->command = "fax show capabilities";
03581       e->usage =
03582          "Usage: fax show capabilities\n"
03583          "       Shows the capabilities of the registered FAX technology modules\n";
03584       return NULL;
03585    case CLI_GENERATE:
03586       return NULL;
03587    }
03588 
03589    ast_cli(a->fd, "\n\nRegistered FAX Technology Modules:\n\n");
03590    AST_RWLIST_RDLOCK(&faxmodules);
03591    AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
03592       ast_cli(a->fd, "%-15s : %s\n%-15s : %s\n%-15s : ", "Type", fax->tech->type, "Description", fax->tech->description, "Capabilities");
03593       fax->tech->cli_show_capabilities(a->fd);
03594       num_modules++;
03595    }
03596    AST_RWLIST_UNLOCK(&faxmodules);
03597    ast_cli(a->fd, "%d registered modules\n\n", num_modules);
03598 
03599    return CLI_SUCCESS;
03600 }
03601 
03602 /*! \brief display global defaults and settings */
03603 static char *cli_fax_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
03604 {
03605    struct fax_module *fax;
03606    char modems[128] = "";
03607    struct fax_options options;
03608 
03609    switch (cmd) {
03610    case CLI_INIT:
03611       e->command = "fax show settings";
03612       e->usage =
03613          "Usage: fax show settings\n"
03614          "       Show the global settings and defaults of both the FAX core and technology modules\n";
03615       return NULL;
03616    case CLI_GENERATE:
03617       return NULL;
03618    }
03619 
03620    get_general_options(&options);
03621 
03622    ast_cli(a->fd, "FAX For Asterisk Settings:\n");
03623    ast_cli(a->fd, "\tECM: %s\n", options.ecm ? "Enabled" : "Disabled");
03624    ast_cli(a->fd, "\tStatus Events: %s\n",  options.statusevents ? "On" : "Off");
03625    ast_cli(a->fd, "\tMinimum Bit Rate: %d\n", options.minrate);
03626    ast_cli(a->fd, "\tMaximum Bit Rate: %d\n", options.maxrate);
03627    ast_fax_modem_to_str(options.modems, modems, sizeof(modems));
03628    ast_cli(a->fd, "\tModem Modulations Allowed: %s\n", modems);
03629    ast_cli(a->fd, "\n\nFAX Technology Modules:\n\n");
03630    AST_RWLIST_RDLOCK(&faxmodules);
03631    AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
03632       ast_cli(a->fd, "%s (%s) Settings:\n", fax->tech->type, fax->tech->description);
03633       fax->tech->cli_show_settings(a->fd);
03634    }
03635    AST_RWLIST_UNLOCK(&faxmodules);
03636 
03637    return CLI_SUCCESS;
03638 }
03639 
03640 /*! \brief display details of a specified fax session */
03641 static char *cli_fax_show_session(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
03642 {
03643    struct ast_fax_session *s, tmp;
03644 
03645    switch (cmd) {
03646    case CLI_INIT:
03647       e->command = "fax show session";
03648       e->usage =
03649          "Usage: fax show session <session number>\n"
03650          "       Shows status of the named FAX session\n";
03651       return NULL;
03652    case CLI_GENERATE:
03653       return fax_session_tab_complete(a);
03654    }
03655 
03656    if (a->argc != 4) {
03657       return CLI_SHOWUSAGE;
03658    }
03659 
03660    if (sscanf(a->argv[3], "%d", &tmp.id) != 1) {
03661       ast_log(LOG_ERROR, "invalid session id: '%s'\n", a->argv[3]);
03662       return RESULT_SUCCESS;
03663    }
03664 
03665    ast_cli(a->fd, "\nFAX Session Details:\n--------------------\n\n");
03666    s = ao2_find(faxregistry.container, &tmp, OBJ_POINTER);
03667    if (s) {
03668       s->tech->cli_show_session(s, a->fd);
03669       ao2_ref(s, -1);
03670    }
03671    ast_cli(a->fd, "\n\n");
03672 
03673    return CLI_SUCCESS;
03674 }
03675 
03676 /*! \brief display fax stats */
03677 static char *cli_fax_show_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
03678 {
03679    struct fax_module *fax;
03680 
03681    switch (cmd) {
03682    case CLI_INIT:
03683       e->command = "fax show stats";
03684       e->usage =
03685          "Usage: fax show stats\n"
03686          "       Shows a statistical summary of FAX transmissions\n";
03687       return NULL;
03688    case CLI_GENERATE:
03689       return NULL;
03690    }
03691 
03692    ast_cli(a->fd, "\nFAX Statistics:\n---------------\n\n");
03693    ast_cli(a->fd, "%-20.20s : %d\n", "Current Sessions", faxregistry.active_sessions);
03694    ast_cli(a->fd, "%-20.20s : %d\n", "Reserved Sessions", faxregistry.reserved_sessions);
03695    ast_cli(a->fd, "%-20.20s : %d\n", "Transmit Attempts", faxregistry.fax_tx_attempts);
03696    ast_cli(a->fd, "%-20.20s : %d\n", "Receive Attempts", faxregistry.fax_rx_attempts);
03697    ast_cli(a->fd, "%-20.20s : %d\n", "Completed FAXes", faxregistry.fax_complete);
03698    ast_cli(a->fd, "%-20.20s : %d\n", "Failed FAXes", faxregistry.fax_failures);
03699    AST_RWLIST_RDLOCK(&faxmodules);
03700    AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
03701       fax->tech->cli_show_stats(a->fd);
03702    }
03703    AST_RWLIST_UNLOCK(&faxmodules);
03704    ast_cli(a->fd, "\n\n");
03705 
03706    return CLI_SUCCESS;
03707 }
03708 
03709 static const char *cli_session_type(struct ast_fax_session *s)
03710 {
03711    if (s->details->caps & AST_FAX_TECH_AUDIO) {
03712       return "G.711";
03713    }
03714    if (s->details->caps & AST_FAX_TECH_T38) {
03715       return "T.38";
03716    }
03717 
03718    return "none";
03719 }
03720 
03721 static const char *cli_session_operation(struct ast_fax_session *s)
03722 {
03723    if (s->details->caps & AST_FAX_TECH_GATEWAY) {
03724       return "gateway";
03725    }
03726    if (s->details->caps & AST_FAX_TECH_SEND) {
03727       return "send";
03728    }
03729    if (s->details->caps & AST_FAX_TECH_RECEIVE) {
03730       return "receive";
03731    }
03732    if (s->details->caps & AST_FAX_TECH_V21_DETECT) {
03733       return "V.21";
03734    }
03735 
03736    return "none";
03737 }
03738 
03739 /*! \brief display fax sessions */
03740 static char *cli_fax_show_sessions(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
03741 {
03742    struct ast_fax_session *s;
03743    struct ao2_iterator i;
03744    int session_count;
03745    char *filenames;
03746 
03747    switch (cmd) {
03748    case CLI_INIT:
03749       e->command = "fax show sessions";
03750       e->usage =
03751          "Usage: fax show sessions\n"
03752          "       Shows the current FAX sessions\n";
03753       return NULL;
03754    case CLI_GENERATE:
03755       return NULL;
03756    }
03757 
03758    ast_cli(a->fd, "\nCurrent FAX Sessions:\n\n");
03759    ast_cli(a->fd, "%-20.20s %-10.10s %-10.10s %-5.5s %-10.10s %-15.15s %-30.30s\n",
03760       "Channel", "Tech", "FAXID", "Type", "Operation", "State", "File(s)");
03761    i = ao2_iterator_init(faxregistry.container, 0);
03762    while ((s = ao2_iterator_next(&i))) {
03763       ao2_lock(s);
03764 
03765       filenames = generate_filenames_string(s->details, "", ", ");
03766 
03767       ast_cli(a->fd, "%-20.20s %-10.10s %-10d %-5.5s %-10.10s %-15.15s %-30s\n",
03768          s->channame, s->tech->type, s->id,
03769          cli_session_type(s),
03770          cli_session_operation(s),
03771          ast_fax_state_to_str(s->state), S_OR(filenames, ""));
03772 
03773       ast_free(filenames);
03774       ao2_unlock(s);
03775       ao2_ref(s, -1);
03776    }
03777    ao2_iterator_destroy(&i);
03778    session_count = ao2_container_count(faxregistry.container);
03779    ast_cli(a->fd, "\n%d FAX sessions\n\n", session_count);
03780 
03781    return CLI_SUCCESS;
03782 }
03783 
03784 static struct ast_cli_entry fax_cli[] = {
03785    AST_CLI_DEFINE(cli_fax_show_version, "Show versions of FAX For Asterisk components"),
03786    AST_CLI_DEFINE(cli_fax_set_debug, "Enable/Disable FAX debugging on new FAX sessions"),
03787    AST_CLI_DEFINE(cli_fax_show_capabilities, "Show the capabilities of the registered FAX technology modules"),
03788    AST_CLI_DEFINE(cli_fax_show_settings, "Show the global settings and defaults of both the FAX core and technology modules"),
03789    AST_CLI_DEFINE(cli_fax_show_session, "Show the status of the named FAX sessions"),
03790    AST_CLI_DEFINE(cli_fax_show_sessions, "Show the current FAX sessions"),
03791    AST_CLI_DEFINE(cli_fax_show_stats, "Summarize FAX session history"),
03792 };
03793 
03794 static void set_general_options(const struct fax_options *options)
03795 {
03796    ast_rwlock_wrlock(&options_lock);
03797    general_options = *options;
03798    ast_rwlock_unlock(&options_lock);
03799 }
03800 
03801 static void get_general_options(struct fax_options *options)
03802 {
03803    ast_rwlock_rdlock(&options_lock);
03804    *options = general_options;
03805    ast_rwlock_unlock(&options_lock);
03806 }
03807 
03808 /*! \brief configure res_fax */
03809 static int set_config(int reload)
03810 {
03811    struct ast_config *cfg;
03812    struct ast_variable *v;
03813    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
03814    char modems[128] = "";
03815    struct fax_options options;
03816    int res = 0;
03817 
03818    options = default_options;
03819 
03820    /* When we're not reloading, we have to be certain to set the general options
03821     * to the defaults in case config loading goes wrong at some point. On a reload,
03822     * the general options need to stay the same as what they were prior to the
03823     * reload rather than being reset to the defaults.
03824     */
03825    if (!reload) {
03826       set_general_options(&options);
03827    }
03828 
03829    /* read configuration */
03830    if (!(cfg = ast_config_load2(config, "res_fax", config_flags))) {
03831       ast_log(LOG_NOTICE, "Configuration file '%s' not found, %s options.\n",
03832             config, reload ? "not changing" : "using default");
03833       return 0;
03834    }
03835 
03836    if (cfg == CONFIG_STATUS_FILEINVALID) {
03837       ast_log(LOG_NOTICE, "Configuration file '%s' is invalid, %s options.\n",
03838             config, reload ? "not changing" : "using default");
03839       return 0;
03840    }
03841 
03842    if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
03843       return 0;
03844    }
03845 
03846    if (reload) {
03847       options = default_options;
03848    }
03849 
03850    /* create configuration */
03851    for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
03852       int rate;
03853 
03854       if (!strcasecmp(v->name, "minrate")) {
03855          ast_debug(3, "reading minrate '%s' from configuration file\n", v->value);
03856          if ((rate = fax_rate_str_to_int(v->value)) == 0) {
03857             res = -1;
03858             goto end;
03859          }
03860          options.minrate = rate;
03861       } else if (!strcasecmp(v->name, "maxrate")) {
03862          ast_debug(3, "reading maxrate '%s' from configuration file\n", v->value);
03863          if ((rate = fax_rate_str_to_int(v->value)) == 0) {
03864             res = -1;
03865             goto end;
03866          }
03867          options.maxrate = rate;
03868       } else if (!strcasecmp(v->name, "statusevents")) {
03869          ast_debug(3, "reading statusevents '%s' from configuration file\n", v->value);
03870          options.statusevents = ast_true(v->value);
03871       } else if (!strcasecmp(v->name, "ecm")) {
03872          ast_debug(3, "reading ecm '%s' from configuration file\n", v->value);
03873          options.ecm = ast_true(v->value);
03874       } else if ((!strcasecmp(v->name, "modem")) || (!strcasecmp(v->name, "modems"))) {
03875          options.modems = 0;
03876          update_modem_bits(&options.modems, v->value);
03877       }
03878    }
03879 
03880    if (options.maxrate < options.minrate) {
03881       ast_log(LOG_ERROR, "maxrate %d is less than minrate %d\n", options.maxrate, options.minrate);
03882       res = -1;
03883       goto end;
03884    }
03885 
03886    if (options.minrate == 2400 && (options.modems & AST_FAX_MODEM_V27) && !(options.modems & (AST_FAX_MODEM_V34))) {
03887       ast_fax_modem_to_str(options.modems, modems, sizeof(modems));
03888       ast_log(LOG_WARNING, "'modems' setting '%s' is no longer accepted with 'minrate' setting %d\n", modems, options.minrate);
03889       ast_log(LOG_WARNING, "'minrate' has been reset to 4800, please update res_fax.conf.\n");
03890       options.minrate = 4800;
03891    }
03892 
03893    if (check_modem_rate(options.modems, options.minrate)) {
03894       ast_fax_modem_to_str(options.modems, modems, sizeof(modems));
03895       ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %d\n", modems, options.minrate);
03896       res = -1;
03897       goto end;
03898    }
03899 
03900    if (check_modem_rate(options.modems, options.maxrate)) {
03901       ast_fax_modem_to_str(options.modems, modems, sizeof(modems));
03902       ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %d\n", modems, options.maxrate);
03903       res = -1;
03904       goto end;
03905    }
03906 
03907    set_general_options(&options);
03908 
03909 end:
03910    ast_config_destroy(cfg);
03911    return res;
03912 }
03913 
03914 /*! \brief FAXOPT read function returns the contents of a FAX option */
03915 static int acf_faxopt_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
03916 {
03917    struct ast_fax_session_details *details = find_details(chan);
03918    int res = 0;
03919    char *filenames;
03920 
03921    if (!details) {
03922       ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s) because it has never been written.\n", ast_channel_name(chan), data);
03923       return -1;
03924    }
03925    if (!strcasecmp(data, "ecm")) {
03926       ast_copy_string(buf, details->option.ecm ? "yes" : "no", len);
03927    } else if (!strcasecmp(data, "t38gateway") || !strcasecmp(data, "gateway") ||
03928          !strcasecmp(data, "t38_gateway") || !strcasecmp(data, "faxgateway")) {
03929       ast_copy_string(buf, details->gateway_id != -1 ? "yes" : "no", len);
03930    } else if (!strcasecmp(data, "faxdetect")) {
03931       ast_copy_string(buf, details->faxdetect_id != -1 ? "yes" : "no", len);
03932    } else if (!strcasecmp(data, "error")) {
03933       ast_copy_string(buf, details->error, len);
03934    } else if (!strcasecmp(data, "filename")) {
03935       if (AST_LIST_EMPTY(&details->documents)) {
03936          ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s) because it has never been written.\n", ast_channel_name(chan), data);
03937          res = -1;
03938       } else {
03939          ast_copy_string(buf, AST_LIST_FIRST(&details->documents)->filename, len);
03940       }
03941    } else if (!strcasecmp(data, "filenames")) {
03942       if (AST_LIST_EMPTY(&details->documents)) {
03943          ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s) because it has never been written.\n", ast_channel_name(chan), data);
03944          res = -1;
03945       } else if ((filenames = generate_filenames_string(details, "", ","))) {
03946          ast_copy_string(buf, filenames, len);
03947          ast_free(filenames);
03948       } else {
03949          ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s), there was an error generating the filenames list.\n", ast_channel_name(chan), data);
03950          res = -1;
03951       }
03952    } else if (!strcasecmp(data, "headerinfo")) {
03953       ast_copy_string(buf, details->headerinfo, len);
03954    } else if (!strcasecmp(data, "localstationid")) {
03955       ast_copy_string(buf, details->localstationid, len);
03956    } else if (!strcasecmp(data, "maxrate")) {
03957       snprintf(buf, len, "%d", details->maxrate);
03958    } else if (!strcasecmp(data, "minrate")) {
03959       snprintf(buf, len, "%d", details->minrate);
03960    } else if (!strcasecmp(data, "pages")) {
03961       snprintf(buf, len, "%d", details->pages_transferred);
03962    } else if (!strcasecmp(data, "rate")) {
03963       ast_copy_string(buf, details->transfer_rate, len);
03964    } else if (!strcasecmp(data, "remotestationid")) {
03965       ast_copy_string(buf, details->remotestationid, len);
03966    } else if (!strcasecmp(data, "resolution")) {
03967       ast_copy_string(buf, details->resolution, len);
03968    } else if (!strcasecmp(data, "sessionid")) {
03969       snprintf(buf, len, "%d", details->id);
03970    } else if (!strcasecmp(data, "status")) {
03971       ast_copy_string(buf, details->result, len);
03972    } else if (!strcasecmp(data, "statusstr")) {
03973       ast_copy_string(buf, details->resultstr, len);
03974    } else if ((!strcasecmp(data, "modem")) || (!strcasecmp(data, "modems"))) {
03975       ast_fax_modem_to_str(details->modems, buf, len);
03976    } else {
03977       ast_log(LOG_WARNING, "channel '%s' can't read FAXOPT(%s) because it is unhandled!\n", ast_channel_name(chan), data);
03978       res = -1;
03979    }
03980    ao2_ref(details, -1);
03981 
03982    return res;
03983 }
03984 
03985 /*! \brief FAXOPT write function modifies the contents of a FAX option */
03986 static int acf_faxopt_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
03987 {
03988    int res = 0;
03989    struct ast_fax_session_details *details;
03990 
03991    if (!(details = find_or_create_details(chan))) {
03992       ast_log(LOG_WARNING, "channel '%s' can't set FAXOPT(%s) to '%s' because it failed to create a datastore.\n", ast_channel_name(chan), data, value);
03993       return -1;
03994    }
03995    ast_debug(3, "channel '%s' setting FAXOPT(%s) to '%s'\n", ast_channel_name(chan), data, value);
03996 
03997    if (!strcasecmp(data, "ecm")) {
03998       const char *val = ast_skip_blanks(value);
03999       if (ast_true(val)) {
04000          details->option.ecm = AST_FAX_OPTFLAG_TRUE;
04001       } else if (ast_false(val)) {
04002          details->option.ecm = AST_FAX_OPTFLAG_FALSE;
04003       } else {
04004          ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(ecm).\n", value);
04005       }
04006    } else if (!strcasecmp(data, "t38gateway") || !strcasecmp(data, "gateway") ||
04007          !strcasecmp(data, "t38_gateway") || !strcasecmp(data, "faxgateway")) {
04008       const char *val = ast_skip_blanks(value);
04009       char *timeout = strchr(val, ',');
04010 
04011       if (timeout) {
04012          *timeout++ = '\0';
04013       }
04014 
04015       if (ast_true(val)) {
04016          if (details->gateway_id < 0) {
04017             details->gateway_timeout = 0;
04018             if (timeout) {
04019                unsigned int gwtimeout;
04020                if (sscanf(timeout, "%u", &gwtimeout) == 1) {
04021                   details->gateway_timeout = gwtimeout * 1000;
04022                } else {
04023                   ast_log(LOG_WARNING, "Unsupported timeout '%s' passed to FAXOPT(%s).\n", timeout, data);
04024                }
04025             }
04026 
04027             details->gateway_id = fax_gateway_attach(chan, details);
04028             if (details->gateway_id < 0) {
04029                ast_log(LOG_ERROR, "Error attaching T.38 gateway to channel %s.\n", ast_channel_name(chan));
04030                res = -1;
04031             } else {
04032                ast_debug(1, "Attached T.38 gateway to channel %s.\n", ast_channel_name(chan));
04033             }
04034          } else {
04035             ast_log(LOG_WARNING, "Attempt to attach a T.38 gateway on channel (%s) with gateway already running.\n", ast_channel_name(chan));
04036          }
04037       } else if (ast_false(val)) {
04038          ast_framehook_detach(chan, details->gateway_id);
04039          details->gateway_id = -1;
04040       } else {
04041          ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(%s).\n", value, data);
04042       }
04043    } else if (!strcasecmp(data, "faxdetect")) {
04044       const char *val = ast_skip_blanks(value);
04045       char *timeout = strchr(val, ',');
04046       unsigned int fdtimeout = 0;
04047       int flags;
04048       int faxdetect;
04049 
04050       if (timeout) {
04051          *timeout++ = '\0';
04052       }
04053 
04054       if (ast_true(val) || !strcasecmp(val, "t38") || !strcasecmp(val, "cng")) {
04055          if (details->faxdetect_id < 0) {
04056             if (timeout && (sscanf(timeout, "%u", &fdtimeout) == 1)) {
04057                if (fdtimeout > 0) {
04058                   fdtimeout = fdtimeout * 1000;
04059                } else {
04060                   ast_log(LOG_WARNING, "Timeout cannot be negative ignoring timeout\n");
04061                }
04062             }
04063 
04064             if (!strcasecmp(val, "t38")) {
04065                flags = FAX_DETECT_MODE_T38;
04066             } else if (!strcasecmp(val, "cng")) {
04067                flags = FAX_DETECT_MODE_CNG;
04068             } else {
04069                flags = FAX_DETECT_MODE_BOTH;
04070             }
04071 
04072             faxdetect = fax_detect_attach(chan, fdtimeout, flags);
04073             if (faxdetect < 0) {
04074                ast_log(LOG_ERROR, "Error attaching FAX detect to channel %s.\n", ast_channel_name(chan));
04075                res = -1;
04076             } else {
04077                ast_debug(1, "Attached FAX detect to channel %s.\n", ast_channel_name(chan));
04078             }
04079          } else {
04080             ast_log(LOG_WARNING, "Attempt to attach a FAX detect on channel (%s) with FAX detect already running.\n", ast_channel_name(chan));
04081          }
04082       } else if (ast_false(val)) {
04083          ast_framehook_detach(chan, details->faxdetect_id);
04084          details->faxdetect_id = -1;
04085       } else {
04086          ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(%s).\n", value, data);
04087       }
04088    } else if (!strcasecmp(data, "headerinfo")) {
04089       ast_string_field_set(details, headerinfo, value);
04090    } else if (!strcasecmp(data, "localstationid")) {
04091       ast_string_field_set(details, localstationid, value);
04092    } else if (!strcasecmp(data, "maxrate")) {
04093       details->maxrate = fax_rate_str_to_int(value);
04094       if (!details->maxrate) {
04095          details->maxrate = ast_fax_maxrate();
04096       }
04097    } else if (!strcasecmp(data, "minrate")) {
04098       details->minrate = fax_rate_str_to_int(value);
04099       if (!details->minrate) {
04100          details->minrate = ast_fax_minrate();
04101       }
04102    } else if ((!strcasecmp(data, "modem")) || (!strcasecmp(data, "modems"))) {
04103       update_modem_bits(&details->modems, value);
04104    } else {
04105       ast_log(LOG_WARNING, "channel '%s' set FAXOPT(%s) to '%s' is unhandled!\n", ast_channel_name(chan), data, value);
04106       res = -1;
04107    }
04108 
04109    ao2_ref(details, -1);
04110 
04111    return res;
04112 }
04113 
04114 /*! \brief FAXOPT dialplan function */
04115 struct ast_custom_function acf_faxopt = {
04116    .name = "FAXOPT",
04117    .read = acf_faxopt_read,
04118    .write = acf_faxopt_write,
04119 };
04120 
04121 /*! \brief unload res_fax */
04122 static int unload_module(void)
04123 {
04124    ast_cli_unregister_multiple(fax_cli, ARRAY_LEN(fax_cli));
04125 
04126    if (ast_custom_function_unregister(&acf_faxopt) < 0) {
04127       ast_log(LOG_WARNING, "failed to unregister function '%s'\n", acf_faxopt.name);
04128    }
04129 
04130    if (ast_unregister_application(app_sendfax) < 0) {
04131       ast_log(LOG_WARNING, "failed to unregister '%s'\n", app_sendfax);
04132    }
04133 
04134    if (ast_unregister_application(app_receivefax) < 0) {
04135       ast_log(LOG_WARNING, "failed to unregister '%s'\n", app_receivefax);
04136    }
04137 
04138    if (fax_logger_level != -1) {
04139       ast_logger_unregister_level("FAX");
04140    }
04141 
04142    ao2_ref(faxregistry.container, -1);
04143 
04144    return 0;
04145 }
04146 
04147 /*! \brief load res_fax */
04148 static int load_module(void)
04149 {
04150    int res;
04151 
04152    /* initialize the registry */
04153    faxregistry.active_sessions = 0;
04154    faxregistry.reserved_sessions = 0;
04155    if (!(faxregistry.container = ao2_container_alloc(FAX_MAXBUCKETS, session_hash_cb, session_cmp_cb))) {
04156       return AST_MODULE_LOAD_DECLINE;
04157    }
04158 
04159    if (set_config(0) < 0) {
04160       ast_log(LOG_ERROR, "failed to load configuration file '%s'\n", config);
04161       ao2_ref(faxregistry.container, -1);
04162       return AST_MODULE_LOAD_DECLINE;
04163    }
04164 
04165    /* register CLI operations and applications */
04166    if (ast_register_application_xml(app_sendfax, sendfax_exec) < 0) {
04167       ast_log(LOG_WARNING, "failed to register '%s'.\n", app_sendfax);
04168       ao2_ref(faxregistry.container, -1);
04169       return AST_MODULE_LOAD_DECLINE;
04170    }
04171    if (ast_register_application_xml(app_receivefax, receivefax_exec) < 0) {
04172       ast_log(LOG_WARNING, "failed to register '%s'.\n", app_receivefax);
04173       ast_unregister_application(app_sendfax);
04174       ao2_ref(faxregistry.container, -1);
04175       return AST_MODULE_LOAD_DECLINE;
04176    }
04177 
04178    ast_cli_register_multiple(fax_cli, ARRAY_LEN(fax_cli));
04179    res = ast_custom_function_register(&acf_faxopt);
04180    fax_logger_level = ast_logger_register_level("FAX");
04181 
04182    return res;
04183 }
04184 
04185 static int reload_module(void)
04186 {
04187    set_config(1);
04188    return 0;
04189 }
04190 
04191 
04192 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "Generic FAX Applications",
04193       .load = load_module,
04194       .unload = unload_module,
04195       .reload = reload_module,
04196       .load_pri = AST_MODPRI_APP_DEPEND,
04197           );