Fri Aug 17 00:17:18 2018

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  *
00009  * See http://www.asterisk.org for more information about
00010  * the Asterisk project. Please do not directly contact
00011  * any of the maintainers of this project for assistance;
00012  * the project provides a web site, mailing lists and IRC
00013  * channels for your use.
00014  *
00015  * This program is free software, distributed under the terms of
00016  * the GNU General Public License Version 2. See the LICENSE file
00017  * at the top of the source tree.
00018  */
00019 
00020 /*** MODULEINFO
00021    <support_level>core</support_level>
00022    <conflict>app_fax</conflict>
00023 ***/
00024 
00025 /*! \file
00026  *
00027  * \brief Generic FAX Resource for FAX technology resource modules
00028  *
00029  * \author Dwayne M. Hubbard <dhubbard@digium.com>
00030  * \author Kevin P. Fleming <kpfleming@digium.com>
00031  *
00032  * A generic FAX resource module that provides SendFAX and ReceiveFAX applications.
00033  * This module requires FAX technology modules, like res_fax_spandsp, to register with it
00034  * so it can use the technology modules to perform the actual FAX transmissions.
00035  * \ingroup applications
00036  */
00037 
00038 #include "asterisk.h"
00039 
00040 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 425405 $")
00041 
00042 #include "asterisk/io.h"
00043 #include "asterisk/file.h"
00044 #include "asterisk/logger.h"
00045 #include "asterisk/module.h"
00046 #include "asterisk/app.h"
00047 #include "asterisk/lock.h"
00048 #include "asterisk/options.h"
00049 #include "asterisk/strings.h"
00050 #include "asterisk/cli.h"
00051 #include "asterisk/utils.h"
00052 #include "asterisk/config.h"
00053 #include "asterisk/astobj2.h"
00054 #include "asterisk/res_fax.h"
00055 #include "asterisk/file.h"
00056 #include "asterisk/channel.h"
00057 #include "asterisk/pbx.h"
00058 #include "asterisk/manager.h"
00059 #include "asterisk/dsp.h"
00060 #include "asterisk/indications.h"
00061 #include "asterisk/ast_version.h"
00062 
00063 /*** DOCUMENTATION
00064    <application name="ReceiveFAX" language="en_US" module="res_fax">
00065       <synopsis>
00066          Receive a FAX and save as a TIFF/F file.
00067       </synopsis>
00068       <syntax>
00069          <parameter name="filename" required="true" />
00070          <parameter name="options">
00071             <optionlist>
00072                <option name="d">
00073                   <para>Enable FAX debugging.</para>
00074                </option>
00075                <option name="f">
00076                   <para>Allow audio fallback FAX transfer on T.38 capable channels.</para>
00077                </option>
00078                <option name="s">
00079                   <para>Send progress Manager events (overrides statusevents setting in res_fax.conf).</para>
00080                </option>
00081             </optionlist>
00082          </parameter>
00083       </syntax>
00084       <description>
00085          <para>This application is provided by res_fax, which is a FAX technology agnostic module
00086          that utilizes FAX technology resource modules to complete a FAX transmission.</para>
00087          <para>Session arguments can be set by the FAXOPT function and to check results of the ReceiveFax() application.</para>
00088       </description>
00089       <see-also>
00090          <ref type="function">FAXOPT</ref>
00091       </see-also>
00092    </application>
00093    <application name="SendFAX" language="en_US" module="res_fax">
00094       <synopsis>
00095          Sends a specified TIFF/F file as a FAX.
00096       </synopsis>
00097       <syntax>
00098          <parameter name="filename" required="true" argsep="&amp;">
00099             <argument name="filename2" multiple="true">
00100                <para>TIFF file to send as a FAX.</para>
00101             </argument>
00102          </parameter>
00103          <parameter name="options">
00104             <optionlist>
00105                <option name="d">
00106                   <para>Enable FAX debugging.</para>
00107                </option>
00108                <option name="f">
00109                   <para>Allow audio fallback FAX transfer on T.38 capable channels.</para>
00110                </option>
00111                <option name="s">
00112                   <para>Send progress Manager events (overrides statusevents setting in res_fax.conf).</para>
00113                </option>
00114                <option name="z">
00115                   <para>Initiate a T.38 reinvite on the channel if the remote end does not.</para>
00116                </option>
00117             </optionlist>
00118          </parameter>
00119       </syntax>
00120       <description>
00121          <para>This application is provided by res_fax, which is a FAX technology agnostic module
00122          that utilizes FAX technology resource modules to complete a FAX transmission.</para>
00123          <para>Session arguments can be set by the FAXOPT function and to check results of the SendFax() application.</para>
00124       </description>
00125       <see-also>
00126          <ref type="function">FAXOPT</ref>
00127       </see-also>
00128    </application>
00129    <function name="FAXOPT" language="en_US" module="res_fax">
00130       <synopsis>
00131          Gets/sets various pieces of information about a fax session.
00132       </synopsis>
00133       <syntax>
00134          <parameter name="item" required="true">
00135             <enumlist>
00136                <enum name="ecm">
00137                   <para>R/W Error Correction Mode (ECM) enable with 'yes', disable with 'no'.</para>
00138                </enum>
00139                <enum name="error">
00140                   <para>R/O FAX transmission error code upon failure.</para>
00141                </enum>
00142                <enum name="filename">
00143                   <para>R/O Filename of the first file of the FAX transmission.</para>
00144                </enum>
00145                <enum name="filenames">
00146                   <para>R/O Filenames of all of the files in the FAX transmission (comma separated).</para>
00147                </enum>
00148                <enum name="headerinfo">
00149                   <para>R/W FAX header information.</para>
00150                </enum>
00151                <enum name="localstationid">
00152                   <para>R/W Local Station Identification.</para>
00153                </enum>
00154                <enum name="minrate">
00155                   <para>R/W Minimum transfer rate set before transmission.</para>
00156                </enum>
00157                <enum name="maxrate">
00158                   <para>R/W Maximum transfer rate set before transmission.</para>
00159                </enum>
00160                <enum name="modem">
00161                   <para>R/W Modem type (v17/v27/v29).</para>
00162                </enum>
00163                <enum name="pages">
00164                   <para>R/O Number of pages transferred.</para>
00165                </enum>
00166                <enum name="rate">
00167                   <para>R/O Negotiated transmission rate.</para>
00168                </enum>
00169                <enum name="remotestationid">
00170                   <para>R/O Remote Station Identification after transmission.</para>
00171                </enum>
00172                <enum name="resolution">
00173                   <para>R/O Negotiated image resolution after transmission.</para>
00174                </enum>
00175                <enum name="sessionid">
00176                   <para>R/O Session ID of the FAX transmission.</para>
00177                </enum>
00178                <enum name="status">
00179                   <para>R/O Result Status of the FAX transmission.</para>
00180                </enum>
00181                <enum name="statusstr">
00182                   <para>R/O Verbose Result Status of the FAX transmission.</para>
00183                </enum>
00184             </enumlist>
00185          </parameter>
00186       </syntax>
00187       <description>
00188          <para>FAXOPT can be used to override the settings for a FAX session listed in <filename>res_fax.conf</filename>,
00189             it can also be used to retreive information about a FAX session that has finished eg. pages/status.</para>
00190       </description>
00191       <see-also>
00192          <ref type="application">ReceiveFax</ref>
00193          <ref type="application">SendFax</ref>
00194       </see-also>
00195    </function>
00196 ***/
00197 
00198 static const char app_receivefax[] = "ReceiveFAX";
00199 static const char app_sendfax[] = "SendFAX";
00200 
00201 struct debug_info_history {
00202    unsigned int consec_frames;
00203    unsigned int consec_ms;
00204    unsigned char silence;
00205 };
00206 
00207 struct ast_fax_debug_info {
00208    struct timeval base_tv;
00209    struct debug_info_history c2s, s2c;
00210    struct ast_dsp *dsp;
00211 };
00212 
00213 static int fax_logger_level = -1;
00214 
00215 /*! \brief maximum buckets for res_fax ao2 containers */
00216 #define FAX_MAXBUCKETS 10
00217 
00218 #define RES_FAX_TIMEOUT 10000
00219 
00220 /*! \brief The faxregistry is used to manage information and statistics for all FAX sessions. */
00221 static struct {
00222    /*! The number of active FAX sessions */
00223    int active_sessions;
00224    /*! The number of reserved FAX sessions */
00225    int reserved_sessions;
00226    /*! active sessions are astobj2 objects */
00227    struct ao2_container *container;
00228    /*! Total number of Tx FAX attempts */
00229    int fax_tx_attempts;
00230    /*! Total number of Rx FAX attempts */
00231    int fax_rx_attempts;
00232    /*! Number of successful FAX transmissions */
00233    int fax_complete;
00234    /*! Number of failed FAX transmissions */
00235    int fax_failures;
00236    /*! the next unique session name */
00237    int nextsessionname;
00238 } faxregistry;
00239 
00240 /*! \brief registered FAX technology modules are put into this list */
00241 struct fax_module {
00242    const struct ast_fax_tech *tech;
00243    AST_RWLIST_ENTRY(fax_module) list;
00244 };
00245 static AST_RWLIST_HEAD_STATIC(faxmodules, fax_module);
00246 
00247 #define RES_FAX_MINRATE 4800
00248 #define RES_FAX_MAXRATE 14400
00249 #define RES_FAX_STATUSEVENTS 0
00250 #define RES_FAX_MODEM (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V27 | AST_FAX_MODEM_V29)
00251 
00252 struct fax_options {
00253    enum ast_fax_modems modems;
00254    uint32_t statusevents:1;
00255    uint32_t ecm:1;
00256    unsigned int minrate;   
00257    unsigned int maxrate;
00258 };
00259 
00260 static struct fax_options general_options;
00261 
00262 static const struct fax_options default_options = {
00263    .minrate = RES_FAX_MINRATE,
00264    .maxrate = RES_FAX_MAXRATE,
00265    .statusevents = RES_FAX_STATUSEVENTS,
00266    .modems = RES_FAX_MODEM,
00267    .ecm = AST_FAX_OPTFLAG_TRUE,
00268 };
00269 
00270 AST_RWLOCK_DEFINE_STATIC(options_lock);
00271 
00272 static void get_general_options(struct fax_options* options);
00273 static void set_general_options(const struct fax_options* options);
00274 
00275 static const char *config = "res_fax.conf";
00276 
00277 static int global_fax_debug = 0;
00278 
00279 enum {
00280    OPT_CALLEDMODE  = (1 << 0),
00281    OPT_CALLERMODE  = (1 << 1),
00282    OPT_DEBUG       = (1 << 2),
00283    OPT_STATUS      = (1 << 3),
00284    OPT_ALLOWAUDIO  = (1 << 5),
00285    OPT_REQUEST_T38 = (1 << 6),
00286 };
00287 
00288 AST_APP_OPTIONS(fax_exec_options, BEGIN_OPTIONS
00289    AST_APP_OPTION('a', OPT_CALLEDMODE),
00290    AST_APP_OPTION('c', OPT_CALLERMODE),
00291    AST_APP_OPTION('d', OPT_DEBUG),
00292    AST_APP_OPTION('f', OPT_ALLOWAUDIO),
00293    AST_APP_OPTION('s', OPT_STATUS),
00294    AST_APP_OPTION('z', OPT_REQUEST_T38),
00295 END_OPTIONS);
00296 
00297 struct manager_event_info {
00298    char context[AST_MAX_CONTEXT];
00299    char exten[AST_MAX_EXTENSION];
00300    char cid[128];
00301 };
00302 
00303 static void debug_check_frame_for_silence(struct ast_fax_session *s, unsigned int c2s, struct ast_frame *frame)
00304 {  
00305    struct debug_info_history *history = c2s ? &s->debug_info->c2s : &s->debug_info->s2c;
00306    int dspsilence;
00307    unsigned int last_consec_frames, last_consec_ms;
00308    unsigned char wassil;
00309    struct timeval diff;
00310 
00311    diff = ast_tvsub(ast_tvnow(), s->debug_info->base_tv);
00312 
00313    ast_dsp_reset(s->debug_info->dsp);
00314    ast_dsp_silence(s->debug_info->dsp, frame, &dspsilence);
00315 
00316    wassil = history->silence;
00317    history->silence = (dspsilence != 0) ? 1 : 0;
00318    if (history->silence != wassil) {
00319       last_consec_frames = history->consec_frames;
00320       last_consec_ms = history->consec_ms;
00321       history->consec_frames = 0;
00322       history->consec_ms = 0;
00323 
00324       if ((last_consec_frames != 0)) {
00325          ast_verb(6, "Channel '%s' fax session '%u', [ %.3ld.%.6ld ], %s sent %u frames (%u ms) of %s.\n",
00326              s->channame, s->id, (long) diff.tv_sec, (long int) diff.tv_usec,
00327              (c2s) ? "channel" : "stack", last_consec_frames, last_consec_ms,
00328              (wassil) ? "silence" : "energy");
00329       }
00330    }
00331 
00332    history->consec_frames++;
00333    history->consec_ms += (frame->samples / 8);
00334 }
00335 
00336 static void destroy_callback(void *data) 
00337 {
00338    if (data) {
00339       ao2_ref(data, -1);
00340    }
00341 }
00342 
00343 static const struct ast_datastore_info fax_datastore = {
00344    .type = "res_fax",
00345    .destroy = destroy_callback,
00346 };
00347 
00348 /*! \brief returns a reference counted pointer to a fax datastore, if it exists */
00349 static struct ast_fax_session_details *find_details(struct ast_channel *chan)
00350 {
00351    struct ast_fax_session_details *details;
00352    struct ast_datastore *datastore;
00353 
00354    ast_channel_lock(chan); 
00355    if (!(datastore = ast_channel_datastore_find(chan, &fax_datastore, NULL))) {
00356       ast_channel_unlock(chan);  
00357       return NULL;
00358    }
00359    if (!(details = datastore->data)) {
00360       ast_log(LOG_WARNING, "Huh?  channel '%s' has a FAX datastore without data!\n", chan->name);
00361       ast_channel_unlock(chan);
00362       return NULL;
00363    }
00364    ao2_ref(details, 1); 
00365    ast_channel_unlock(chan);  
00366 
00367    return details;
00368 }
00369 
00370 /*! \brief destroy a FAX session details structure */
00371 static void destroy_session_details(void *details)
00372 {
00373    struct ast_fax_session_details *d = details;
00374    struct ast_fax_document *doc;
00375    
00376    while ((doc = AST_LIST_REMOVE_HEAD(&d->documents, next))) {
00377       ast_free(doc);
00378    }
00379    ast_string_field_free_memory(d); 
00380 }
00381 
00382 /*! \brief create a FAX session details structure */
00383 static struct ast_fax_session_details *session_details_new(void)
00384 {
00385    struct ast_fax_session_details *d;
00386    struct fax_options options;
00387 
00388    if (!(d = ao2_alloc(sizeof(*d), destroy_session_details))) {
00389       return NULL;
00390    }
00391    
00392    if (ast_string_field_init(d, 512)) {
00393       ao2_ref(d, -1);
00394       return NULL;
00395    }
00396 
00397    get_general_options(&options);
00398 
00399    AST_LIST_HEAD_INIT_NOLOCK(&d->documents);
00400 
00401    /* These options need to be set to the configured default and may be overridden by
00402     * SendFAX, ReceiveFAX, or FAXOPT */
00403    d->option.request_t38 = AST_FAX_OPTFLAG_FALSE;
00404    d->option.send_cng = AST_FAX_OPTFLAG_FALSE;
00405    d->option.send_ced = AST_FAX_OPTFLAG_FALSE;
00406    d->option.ecm = options.ecm;
00407    d->option.statusevents = options.statusevents;
00408    d->modems = options.modems;
00409    d->minrate = options.minrate;
00410    d->maxrate = options.maxrate;
00411 
00412    return d;
00413 }
00414 
00415 /*! \brief returns a reference counted details structure from the channel's fax datastore.  If the datastore
00416  * does not exist it will be created */   
00417 static struct ast_fax_session_details *find_or_create_details(struct ast_channel *chan)
00418 {
00419    struct ast_fax_session_details *details;
00420    struct ast_datastore *datastore;
00421 
00422    if ((details = find_details(chan))) {
00423       return details;
00424    }
00425    /* channel does not have one so we must create one */
00426    if (!(details = session_details_new())) {
00427       ast_log(LOG_WARNING, "channel '%s' can't get a FAX details structure for the datastore!\n", chan->name);
00428       return NULL;
00429    }
00430    if (!(datastore = ast_datastore_alloc(&fax_datastore, NULL))) {
00431       ao2_ref(details, -1);
00432       ast_log(LOG_WARNING, "channel '%s' can't get a datastore!\n", chan->name);
00433       return NULL;
00434    }
00435    /* add the datastore to the channel and increment the refcount */
00436    datastore->data = details;
00437    ao2_ref(details, 1);
00438    ast_channel_lock(chan);
00439    ast_channel_datastore_add(chan, datastore);
00440    ast_channel_unlock(chan);
00441    return details;
00442 }
00443 
00444 unsigned int ast_fax_maxrate(void)
00445 {
00446    struct fax_options options;
00447    get_general_options(&options);
00448 
00449    return options.maxrate;
00450 }
00451 
00452 unsigned int ast_fax_minrate(void)
00453 {
00454    struct fax_options options;
00455    get_general_options(&options);
00456 
00457    return options.minrate;
00458 }
00459 
00460 static int update_modem_bits(enum ast_fax_modems *bits, const char *value)
00461 {     
00462    char *m[5], *tok, *v = (char *)value;
00463    int i = 0, j;
00464 
00465    if (!strchr(v, ',')) {
00466       m[i++] = v;
00467       m[i] = NULL;
00468    } else {
00469       tok = strtok(v, ", ");
00470       while (tok && i < ARRAY_LEN(m) - 1) {
00471          m[i++] = tok;
00472          tok = strtok(NULL, ", ");
00473       }
00474       m[i] = NULL;
00475    }
00476 
00477    *bits = 0;
00478    for (j = 0; j < i; j++) {
00479       if (!strcasecmp(m[j], "v17")) {
00480          *bits |= AST_FAX_MODEM_V17;
00481       } else if (!strcasecmp(m[j], "v27")) {
00482          *bits |= AST_FAX_MODEM_V27;
00483       } else if (!strcasecmp(m[j], "v29")) {
00484          *bits |= AST_FAX_MODEM_V29;
00485       } else if (!strcasecmp(m[j], "v34")) {
00486          *bits |= AST_FAX_MODEM_V34;
00487       } else {
00488          ast_log(LOG_WARNING, "ignoring invalid modem setting: '%s', valid options {v17 | v27 | v29 | v34}\n", m[j]);
00489       }
00490    }
00491    return 0;
00492 }
00493 
00494 static char *ast_fax_caps_to_str(enum ast_fax_capabilities caps, char *buf, size_t bufsize)
00495 {
00496    char *out = buf;
00497    size_t size = bufsize;
00498    int first = 1;
00499 
00500    if (caps & AST_FAX_TECH_SEND) {
00501       if (!first) {
00502          ast_build_string(&buf, &size, ",");
00503       }
00504       ast_build_string(&buf, &size, "SEND");
00505       first = 0;
00506    }
00507    if (caps & AST_FAX_TECH_RECEIVE) {
00508       if (!first) {
00509          ast_build_string(&buf, &size, ",");
00510       }
00511       ast_build_string(&buf, &size, "RECEIVE");
00512       first = 0;
00513    }
00514    if (caps & AST_FAX_TECH_AUDIO) {
00515       if (!first) {
00516          ast_build_string(&buf, &size, ",");
00517       }
00518       ast_build_string(&buf, &size, "AUDIO");
00519       first = 0;
00520    }
00521    if (caps & AST_FAX_TECH_T38) {
00522       if (!first) {
00523          ast_build_string(&buf, &size, ",");
00524       }
00525       ast_build_string(&buf, &size, "T38");
00526       first = 0;
00527    }
00528    if (caps & AST_FAX_TECH_MULTI_DOC) {
00529       if (!first) {
00530          ast_build_string(&buf, &size, ",");
00531       }
00532       ast_build_string(&buf, &size, "MULTI_DOC");
00533       first = 0;
00534    }
00535 
00536    return out;
00537 }
00538 
00539 static int ast_fax_modem_to_str(enum ast_fax_modems bits, char *tbuf, size_t bufsize)
00540 {
00541    int count = 0;
00542 
00543    if (bits & AST_FAX_MODEM_V17) {
00544       strcat(tbuf, "V17");
00545       count++;
00546    }
00547    if (bits & AST_FAX_MODEM_V27) {
00548       if (count) {
00549          strcat(tbuf, ",");
00550       }
00551       strcat(tbuf, "V27");
00552       count++;
00553    }
00554    if (bits & AST_FAX_MODEM_V29) {
00555       if (count) {
00556          strcat(tbuf, ",");
00557       }
00558       strcat(tbuf, "V29");
00559       count++;
00560    }
00561    if (bits & AST_FAX_MODEM_V34) {
00562       if (count) {
00563          strcat(tbuf, ",");
00564       }
00565       strcat(tbuf, "V34");
00566       count++;
00567    }
00568 
00569    return 0;
00570 }
00571 
00572 static int check_modem_rate(enum ast_fax_modems modems, unsigned int rate)
00573 {
00574    switch (rate) {
00575    case 2400:
00576       if (!(modems & (AST_FAX_MODEM_V34))) {
00577          return 1;
00578       }
00579       break;
00580    case 4800:
00581       if (!(modems & (AST_FAX_MODEM_V27 | AST_FAX_MODEM_V34))) {
00582          return 1;
00583       }
00584       break;
00585    case 7200:
00586       if (!(modems & (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V29 | AST_FAX_MODEM_V34))) {
00587          return 1;
00588       }
00589       break;
00590    case 9600:
00591       if (!(modems & (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V27 | AST_FAX_MODEM_V29 | AST_FAX_MODEM_V34))) {
00592          return 1;
00593       }
00594       break;
00595    case 12000:
00596    case 14400:
00597       if (!(modems & (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V34))) {
00598          return 1;
00599       }
00600       break;
00601    case 28800:
00602    case 33600:
00603       if (!(modems & AST_FAX_MODEM_V34)) {
00604          return 1;
00605       }
00606       break;
00607    default:
00608       /* this should never happen */
00609       return 1;
00610    }
00611 
00612    return 0;
00613 }
00614 
00615 /*! \brief register a FAX technology module */
00616 int ast_fax_tech_register(struct ast_fax_tech *tech)
00617 {
00618    struct fax_module *fax;
00619 
00620    if (!(fax = ast_calloc(1, sizeof(*fax)))) {
00621       return -1;
00622    }
00623    fax->tech = tech;
00624    AST_RWLIST_WRLOCK(&faxmodules);
00625    AST_RWLIST_INSERT_TAIL(&faxmodules, fax, list);
00626    AST_RWLIST_UNLOCK(&faxmodules);
00627    ast_module_ref(ast_module_info->self);
00628 
00629    ast_verb(3, "Registered handler for '%s' (%s)\n", fax->tech->type, fax->tech->description);
00630 
00631    return 0;
00632 }
00633 
00634 /*! \brief unregister a FAX technology module */
00635 void ast_fax_tech_unregister(struct ast_fax_tech *tech)
00636 {
00637    struct fax_module *fax;
00638 
00639    ast_verb(3, "Unregistering FAX module type '%s'\n", tech->type);
00640 
00641    AST_RWLIST_WRLOCK(&faxmodules);
00642    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&faxmodules, fax, list) {
00643       if (fax->tech != tech) {
00644          continue;
00645       }
00646       AST_RWLIST_REMOVE_CURRENT(list);
00647       ast_module_unref(ast_module_info->self);
00648       ast_free(fax);
00649       ast_verb(4, "Unregistered FAX module type '%s'\n", tech->type);
00650       break;   
00651    }
00652    AST_RWLIST_TRAVERSE_SAFE_END;
00653    AST_RWLIST_UNLOCK(&faxmodules);
00654 }
00655 
00656 /*! \brief convert a ast_fax_state to a string */
00657 const char *ast_fax_state_to_str(enum ast_fax_state state)
00658 {
00659    switch (state) {
00660    case AST_FAX_STATE_UNINITIALIZED:
00661       return "Uninitialized";
00662    case AST_FAX_STATE_INITIALIZED:
00663       return "Initialized";
00664    case AST_FAX_STATE_OPEN:
00665       return "Open";
00666    case AST_FAX_STATE_ACTIVE:
00667       return "Active";
00668    case AST_FAX_STATE_COMPLETE:
00669       return "Complete";
00670    case AST_FAX_STATE_RESERVED:
00671       return "Reserved";
00672    case AST_FAX_STATE_INACTIVE:
00673       return "Inactive";
00674    default:
00675       ast_log(LOG_WARNING, "unhandled FAX state: %u\n", state);
00676       return "Unknown";
00677    }
00678 }
00679 
00680 void ast_fax_log(int level, const char *file, const int line, const char *function, const char *msg)
00681 {
00682    if (fax_logger_level != -1) {
00683       ast_log_dynamic_level(fax_logger_level, "%s", msg);
00684    } else {
00685       ast_log(level, file, line, function, "%s", msg);
00686    }
00687 }
00688 
00689 /*! \brief convert a rate string to a rate */
00690 static unsigned int fax_rate_str_to_int(const char *ratestr)
00691 {
00692    int rate;
00693 
00694    if (sscanf(ratestr, "%d", &rate) != 1) {
00695       ast_log(LOG_ERROR, "failed to sscanf '%s' to rate\n", ratestr);
00696       return 0;
00697    }
00698    switch (rate) {
00699    case 2400:
00700    case 4800:
00701    case 7200:
00702    case 9600:
00703    case 12000:
00704    case 14400:
00705    case 28800:
00706    case 33600:
00707       return rate;
00708    default:
00709       ast_log(LOG_WARNING, "ignoring invalid rate '%s'.  Valid options are {2400 | 4800 | 7200 | 9600 | 12000 | 14400 | 28800 | 33600}\n", ratestr);
00710       return 0;
00711    }
00712 }
00713 
00714 static void fax_session_release(struct ast_fax_session *s, struct ast_fax_tech_token *token)
00715 {
00716    if (token) {
00717       s->tech->release_token(token);
00718    }
00719 
00720    if (s->state == AST_FAX_STATE_RESERVED) {
00721       ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, -1);
00722       s->state = AST_FAX_STATE_INACTIVE;
00723    }
00724 }
00725 
00726 /*! \brief destroy a FAX session structure */
00727 static void destroy_session(void *session)
00728 {
00729    struct ast_fax_session *s = session;
00730 
00731    if (s->tech) {
00732       fax_session_release(s, NULL);
00733       if (s->tech_pvt) {
00734          s->tech->destroy_session(s);
00735       }
00736       ast_module_unref(s->tech->module);
00737    }
00738 
00739    if (s->details) {
00740       ao2_ref(s->details, -1);
00741    }
00742    
00743    if (s->debug_info) {
00744       ast_dsp_free(s->debug_info->dsp);
00745       ast_free(s->debug_info);
00746    }
00747 
00748    if (s->smoother) {
00749       ast_smoother_free(s->smoother);
00750    }
00751 
00752    if (s->state != AST_FAX_STATE_INACTIVE) {
00753       ast_atomic_fetchadd_int(&faxregistry.active_sessions, -1);
00754    }
00755 
00756    ast_free(s->channame);
00757    ast_free(s->chan_uniqueid);
00758 }
00759 
00760 static struct ast_fax_session *fax_session_reserve(struct ast_fax_session_details *details, struct ast_fax_tech_token **token)
00761 {
00762    struct ast_fax_session *s;
00763    struct fax_module *faxmod;
00764    char caps[128] = "";
00765 
00766    if (!(s = ao2_alloc(sizeof(*s), destroy_session))) {
00767       return NULL;
00768    }
00769 
00770    s->state = AST_FAX_STATE_INACTIVE;
00771 
00772    /* locate a FAX technology module that can handle said requirements
00773     * Note: the requirements have not yet been finalized as T.38
00774     * negotiation has not yet occured. */
00775    AST_RWLIST_RDLOCK(&faxmodules);
00776    AST_RWLIST_TRAVERSE(&faxmodules, faxmod, list) {
00777       if ((faxmod->tech->caps & details->caps) != details->caps) {
00778          continue;
00779       }
00780       ast_debug(4, "Reserving a FAX session from '%s'.\n", faxmod->tech->description);
00781       ast_module_ref(faxmod->tech->module);
00782       s->tech = faxmod->tech;
00783       break;
00784    }
00785    AST_RWLIST_UNLOCK(&faxmodules);
00786 
00787    if (!faxmod) {
00788       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)));
00789       ao2_ref(s, -1);
00790       return NULL;
00791    }
00792 
00793    if (!s->tech->reserve_session) {
00794       ast_debug(1, "Selected FAX technology module (%s) does not support reserving sessions.\n", s->tech->description);
00795       return s;
00796    }
00797 
00798    if (!(*token = s->tech->reserve_session(s))) {
00799       ao2_ref(s, -1);
00800       return NULL;
00801    }
00802 
00803    s->state = AST_FAX_STATE_RESERVED;
00804    ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, 1);
00805 
00806    return s;
00807 }
00808 
00809 /*! \brief create a FAX session */
00810 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)
00811 {
00812    struct ast_fax_session *s = NULL;
00813    struct fax_module *faxmod;
00814    char caps[128] = "";
00815 
00816    if (reserved) {
00817       s = reserved;
00818       ao2_ref(reserved, +1);
00819 
00820       if (s->state == AST_FAX_STATE_RESERVED) {
00821          ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, -1);
00822          s->state = AST_FAX_STATE_UNINITIALIZED;
00823       }
00824    }
00825 
00826    if (!s && !(s = ao2_alloc(sizeof(*s), destroy_session))) {
00827       return NULL;
00828    }
00829 
00830    ast_atomic_fetchadd_int(&faxregistry.active_sessions, 1);
00831    s->state = AST_FAX_STATE_UNINITIALIZED;
00832 
00833    if (details->option.debug && (details->caps & AST_FAX_TECH_AUDIO)) {
00834       if (!(s->debug_info = ast_calloc(1, sizeof(*(s->debug_info))))) {
00835          fax_session_release(s, token);
00836          ao2_ref(s, -1);
00837          return NULL;
00838       }
00839       if (!(s->debug_info->dsp = ast_dsp_new())) {
00840          ast_free(s->debug_info);
00841          s->debug_info = NULL;
00842          fax_session_release(s, token);
00843          ao2_ref(s, -1);
00844          return NULL;
00845       }
00846       ast_dsp_set_threshold(s->debug_info->dsp, 128);
00847    }  
00848 
00849    if (!(s->channame = ast_strdup(chan->name))) {
00850       fax_session_release(s, token);
00851       ao2_ref(s, -1);
00852       return NULL;
00853    }
00854 
00855    if (!(s->chan_uniqueid = ast_strdup(chan->uniqueid))) {
00856       fax_session_release(s, token);
00857       ao2_ref(s, -1);
00858       return NULL;
00859    }
00860 
00861    s->chan = chan;
00862    s->details = details;
00863    ao2_ref(s->details, 1);
00864 
00865    details->id = s->id = ast_atomic_fetchadd_int(&faxregistry.nextsessionname, 1);
00866 
00867    if (!token) {
00868       /* locate a FAX technology module that can handle said requirements */
00869       AST_RWLIST_RDLOCK(&faxmodules);
00870       AST_RWLIST_TRAVERSE(&faxmodules, faxmod, list) {
00871          if ((faxmod->tech->caps & details->caps) != details->caps) {
00872             continue;
00873          }
00874          ast_debug(4, "Requesting a new FAX session from '%s'.\n", faxmod->tech->description);
00875          ast_module_ref(faxmod->tech->module);
00876          if (reserved) {
00877             /* Balance module ref from reserved session */
00878             ast_module_unref(reserved->tech->module);
00879          }
00880          s->tech = faxmod->tech;
00881          break;
00882       }
00883       AST_RWLIST_UNLOCK(&faxmodules);
00884 
00885       if (!faxmod) {
00886          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)));
00887          ao2_ref(s, -1);
00888          return NULL;
00889       }
00890    }
00891 
00892    if (!(s->tech_pvt = s->tech->new_session(s, token))) {
00893       ast_log(LOG_ERROR, "FAX session failed to initialize.\n");
00894       ao2_ref(s, -1);
00895       return NULL;
00896    }
00897    /* link the session to the session container */
00898    if (!(ao2_link(faxregistry.container, s))) {
00899       ast_log(LOG_ERROR, "failed to add FAX session '%u' to container.\n", s->id);
00900       ao2_ref(s, -1);
00901       return NULL;
00902    }
00903    ast_debug(4, "channel '%s' using FAX session '%u'\n", s->channame, s->id);
00904 
00905    return s;
00906 }
00907 
00908 static void get_manager_event_info(struct ast_channel *chan, struct manager_event_info *info)
00909 {
00910    pbx_substitute_variables_helper(chan, "${CONTEXT}", info->context, sizeof(info->context));
00911    pbx_substitute_variables_helper(chan, "${EXTEN}", info->exten, sizeof(info->exten));
00912    pbx_substitute_variables_helper(chan, "${CALLERID(num)}", info->cid, sizeof(info->cid));
00913 }
00914 
00915 
00916 /* \brief Generate a string of filenames using the given prefix and separator.
00917  * \param details the fax session details
00918  * \param prefix the prefix to each filename
00919  * \param separator the separator between filenames
00920  *
00921  * This function generates a string of filenames from the given details
00922  * structure and using the given prefix and separator.
00923  *
00924  * \retval NULL there was an error generating the string
00925  * \return the string generated string
00926  */
00927 static char *generate_filenames_string(struct ast_fax_session_details *details, char *prefix, char *separator)
00928 {
00929    char *filenames, *c;
00930    size_t size = 0;
00931    int first = 1;
00932    struct ast_fax_document *doc;
00933 
00934    /* don't process empty lists */
00935    if (AST_LIST_EMPTY(&details->documents)) {
00936       return NULL;
00937    }
00938 
00939    /* Calculate the total length of all of the file names */
00940    AST_LIST_TRAVERSE(&details->documents, doc, next) {
00941       size += strlen(separator) + strlen(prefix) + strlen(doc->filename);
00942    }
00943    size += 1; /* add space for the terminating null */
00944 
00945    if (!(filenames = ast_malloc(size))) {
00946       return NULL;
00947    }
00948    c = filenames;
00949 
00950    ast_build_string(&c, &size, "%s%s", prefix, AST_LIST_FIRST(&details->documents)->filename);
00951    AST_LIST_TRAVERSE(&details->documents, doc, next) {
00952       if (first) {
00953          first = 0;
00954          continue;
00955       }
00956 
00957       ast_build_string(&c, &size, "%s%s%s", separator, prefix, doc->filename);
00958    }
00959 
00960    return filenames;
00961 }
00962 
00963 /*! \brief send a FAX status manager event */
00964 static int report_fax_status(struct ast_channel *chan, struct ast_fax_session_details *details, const char *status)
00965 {
00966    char *filenames = generate_filenames_string(details, "FileName: ", "\r\n");
00967    if (!filenames) {
00968       return 1;
00969    }
00970 
00971    ast_channel_lock(chan);
00972    if (details->option.statusevents) {
00973       struct manager_event_info info;
00974 
00975       get_manager_event_info(chan, &info);
00976       manager_event(EVENT_FLAG_CALL,
00977                (details->caps & AST_FAX_TECH_RECEIVE) ? "ReceiveFAXStatus" : "SendFAXStatus",
00978                "Status: %s\r\n"
00979                "Channel: %s\r\n"
00980                "Context: %s\r\n"
00981                "Exten: %s\r\n"
00982                "CallerID: %s\r\n"
00983                "LocalStationID: %s\r\n"
00984                "%s\r\n",
00985                status,
00986                chan->name,
00987                info.context,
00988                info.exten,
00989                info.cid,
00990                details->localstationid,
00991                filenames);
00992    }
00993    ast_channel_unlock(chan);
00994    ast_free(filenames);
00995 
00996    return 0;
00997 }
00998 
00999 /*! \brief Set fax related channel variables. */
01000 static void set_channel_variables(struct ast_channel *chan, struct ast_fax_session_details *details)
01001 {
01002    char buf[10];
01003    pbx_builtin_setvar_helper(chan, "FAXSTATUS", S_OR(details->result, NULL));
01004    pbx_builtin_setvar_helper(chan, "FAXERROR", S_OR(details->error, NULL));
01005    pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", S_OR(details->resultstr, NULL));
01006    pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", S_OR(details->remotestationid, NULL));
01007    pbx_builtin_setvar_helper(chan, "LOCALSTATIONID", S_OR(details->localstationid, NULL));
01008    pbx_builtin_setvar_helper(chan, "FAXBITRATE", S_OR(details->transfer_rate, NULL));
01009    pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", S_OR(details->resolution, NULL));
01010 
01011    snprintf(buf, sizeof(buf), "%u", details->pages_transferred);
01012    pbx_builtin_setvar_helper(chan, "FAXPAGES", buf);
01013 }
01014 
01015 #define GENERIC_FAX_EXEC_SET_VARS(fax, chan, errorstr, reason) \
01016    do {  \
01017       if (ast_strlen_zero(fax->details->result)) \
01018          ast_string_field_set(fax->details, result, "FAILED"); \
01019       if (ast_strlen_zero(fax->details->resultstr)) \
01020          ast_string_field_set(fax->details, resultstr, reason); \
01021       if (ast_strlen_zero(fax->details->error)) \
01022          ast_string_field_set(fax->details, error, errorstr); \
01023       set_channel_variables(chan, fax->details); \
01024    } while (0)
01025 
01026 #define GENERIC_FAX_EXEC_ERROR_QUIET(fax, chan, errorstr, reason) \
01027    do {  \
01028       GENERIC_FAX_EXEC_SET_VARS(fax, chan, errorstr, reason); \
01029    } while (0)
01030 
01031 #define GENERIC_FAX_EXEC_ERROR(fax, chan, errorstr, reason) \
01032    do {  \
01033       ast_log(LOG_ERROR, "channel '%s' FAX session '%u' failure, reason: '%s' (%s)\n", chan->name, fax->id, reason, errorstr); \
01034       GENERIC_FAX_EXEC_ERROR_QUIET(fax, chan, errorstr, reason); \
01035    } while (0)
01036 
01037 static void t38_parameters_ast_to_fax(struct ast_fax_t38_parameters *dst, const struct ast_control_t38_parameters *src)
01038 {
01039    dst->version = src->version;
01040    dst->max_ifp = src->max_ifp;
01041    dst->rate = src->rate;
01042    dst->rate_management = src->rate_management;
01043    dst->fill_bit_removal = src->fill_bit_removal;
01044    dst->transcoding_mmr = src->transcoding_mmr;
01045    dst->transcoding_jbig = src->transcoding_jbig;
01046 }
01047 
01048 static void t38_parameters_fax_to_ast(struct ast_control_t38_parameters *dst, const struct ast_fax_t38_parameters *src)
01049 {
01050    dst->version = src->version;
01051    dst->max_ifp = src->max_ifp;
01052    dst->rate = src->rate;
01053    dst->rate_management = src->rate_management;
01054    dst->fill_bit_removal = src->fill_bit_removal;
01055    dst->transcoding_mmr = src->transcoding_mmr;
01056    dst->transcoding_jbig = src->transcoding_jbig;
01057 }
01058 
01059 static int set_fax_t38_caps(struct ast_channel *chan, struct ast_fax_session_details *details)
01060 {
01061    switch (ast_channel_get_t38_state(chan)) {
01062    case T38_STATE_UNKNOWN:
01063       details->caps |= AST_FAX_TECH_T38;
01064       break;
01065    case T38_STATE_UNAVAILABLE:
01066       details->caps |= AST_FAX_TECH_AUDIO;
01067       break;
01068    case T38_STATE_NEGOTIATING: {
01069       /* the other end already sent us a T.38 reinvite, so we need to prod the channel
01070        * driver into resending their parameters to us if it supports doing so... if
01071        * not, we can't proceed, because we can't create a proper reply without them.
01072        * if it does work, the channel driver will send an AST_CONTROL_T38_PARAMETERS
01073        * with a request of AST_T38_REQUEST_NEGOTIATE, which will be read by the function
01074        * that gets called after this one completes
01075        */
01076       struct ast_control_t38_parameters parameters = { .request_response = AST_T38_REQUEST_PARMS, };
01077       if (ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &parameters, sizeof(parameters)) != AST_T38_REQUEST_PARMS) {
01078          ast_log(LOG_ERROR, "channel '%s' is in an unsupported T.38 negotiation state, cannot continue.\n", chan->name);
01079          return -1;
01080       }
01081       details->caps |= AST_FAX_TECH_T38;
01082       break;
01083    }
01084    default:
01085       ast_log(LOG_ERROR, "channel '%s' is in an unsupported T.38 negotiation state, cannot continue.\n", chan->name);
01086       return -1;
01087    }
01088 
01089    return 0;
01090 }
01091 
01092 static int disable_t38(struct ast_channel *chan)
01093 {
01094    int timeout_ms;
01095    struct ast_frame *frame = NULL;
01096    struct ast_control_t38_parameters t38_parameters = { .request_response = AST_T38_REQUEST_TERMINATE, };
01097    struct timeval start;
01098    int ms;
01099 
01100    ast_debug(1, "Shutting down T.38 on %s\n", chan->name);
01101    if (ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0) {
01102       ast_debug(1, "error while disabling T.38 on channel '%s'\n", chan->name);
01103       return -1;
01104    }
01105 
01106    /* wait up to five seconds for negotiation to complete */
01107    timeout_ms = 5000;
01108    start = ast_tvnow();
01109    while ((ms = ast_remaining_ms(start, timeout_ms))) {
01110       ms = ast_waitfor(chan, ms);
01111 
01112       if (ms == 0) {
01113          break;
01114       }
01115       if (ms < 0) {
01116          ast_debug(1, "error while disabling T.38 on channel '%s'\n", chan->name);
01117          return -1;
01118       }
01119 
01120       if (!(frame = ast_read(chan))) {
01121          return -1;
01122       }
01123       if ((frame->frametype == AST_FRAME_CONTROL) &&
01124           (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
01125           (frame->datalen == sizeof(t38_parameters))) {
01126          struct ast_control_t38_parameters *parameters = frame->data.ptr;
01127 
01128          switch (parameters->request_response) {
01129          case AST_T38_TERMINATED:
01130             ast_debug(1, "Shut down T.38 on %s\n", chan->name);
01131             break;
01132          case AST_T38_REFUSED:
01133             ast_log(LOG_WARNING, "channel '%s' refused to disable T.38\n", chan->name);
01134             ast_frfree(frame);
01135             return -1;
01136          default:
01137             ast_log(LOG_ERROR, "channel '%s' failed to disable T.38\n", chan->name);
01138             ast_frfree(frame);
01139             return -1;
01140          }
01141          ast_frfree(frame);
01142          break;
01143       }
01144       ast_frfree(frame);
01145    }
01146 
01147    if (ms == 0) { /* all done, nothing happened */
01148       ast_debug(1, "channel '%s' timed-out during T.38 shutdown\n", chan->name);
01149    }
01150 
01151    return 0;
01152 }
01153 
01154 static struct ast_control_t38_parameters our_t38_parameters = {
01155    .version = 0,
01156    .max_ifp = 400,
01157    .rate = AST_T38_RATE_14400,
01158    .rate_management = AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF,
01159 };
01160 
01161 /*! \brief this is the generic FAX session handling function */
01162 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)
01163 {
01164    int ms;
01165    int timeout = RES_FAX_TIMEOUT;
01166    int chancount;
01167    unsigned int expected_frametype = -1;
01168    union ast_frame_subclass expected_framesubclass = { .integer = -1 };
01169    unsigned int t38negotiated = (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED);
01170    struct ast_control_t38_parameters t38_parameters;
01171    const char *tempvar;
01172    struct ast_fax_session *fax = NULL;
01173    struct ast_frame *frame = NULL;
01174    struct ast_channel *c = chan;
01175    unsigned int orig_write_format = 0, orig_read_format = 0;
01176    int remaining_time;
01177    struct timeval start;
01178 
01179    chancount = 1;
01180 
01181    /* create the FAX session */
01182    if (!(fax = fax_session_new(details, chan, reserved, token))) {
01183       ast_log(LOG_ERROR, "Can't create a FAX session, FAX attempt failed.\n");
01184       report_fax_status(chan, details, "No Available Resource");
01185       return -1;
01186    }
01187 
01188    ast_channel_lock(chan);
01189    /* update session details */  
01190    if (ast_strlen_zero(details->headerinfo) && (tempvar = pbx_builtin_getvar_helper(chan, "LOCALHEADERINFO"))) {
01191       ast_string_field_set(details, headerinfo, tempvar);
01192    }
01193    if (ast_strlen_zero(details->localstationid)) {
01194       tempvar = pbx_builtin_getvar_helper(chan, "LOCALSTATIONID");
01195       ast_string_field_set(details, localstationid, tempvar ? tempvar : "unknown");
01196    }
01197    ast_channel_unlock(chan);
01198 
01199    report_fax_status(chan, details, "Allocating Resources");
01200 
01201    if (details->caps & AST_FAX_TECH_AUDIO) {
01202       expected_frametype = AST_FRAME_VOICE;;
01203       expected_framesubclass.codec = AST_FORMAT_SLINEAR;
01204       orig_write_format = chan->writeformat;
01205       if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
01206          ast_log(LOG_ERROR, "channel '%s' failed to set write format to signed linear'.\n", chan->name);
01207          ao2_lock(faxregistry.container);
01208          ao2_unlink(faxregistry.container, fax);
01209          ao2_unlock(faxregistry.container);
01210          ao2_ref(fax, -1);
01211          ast_channel_unlock(chan);
01212          return -1;
01213       }
01214       orig_read_format = chan->readformat;
01215       if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0) {
01216          ast_log(LOG_ERROR, "channel '%s' failed to set read format to signed linear.\n", chan->name);
01217          ao2_lock(faxregistry.container);
01218          ao2_unlink(faxregistry.container, fax);
01219          ao2_unlock(faxregistry.container);
01220          ao2_ref(fax, -1);
01221          ast_channel_unlock(chan);
01222          return -1;
01223       }
01224       if (fax->smoother) {
01225          ast_smoother_free(fax->smoother);
01226          fax->smoother = NULL;
01227       }
01228       if (!(fax->smoother = ast_smoother_new(320))) {
01229          ast_log(LOG_WARNING, "Channel '%s' FAX session '%u' failed to obtain a smoother.\n", chan->name, fax->id);
01230       }
01231    } else {
01232       expected_frametype = AST_FRAME_MODEM;
01233       expected_framesubclass.codec = AST_MODEM_T38;
01234    }
01235 
01236    if (fax->debug_info) {
01237       fax->debug_info->base_tv = ast_tvnow();
01238    }
01239 
01240    /* reset our result fields just in case the fax tech driver wants to
01241     * set custom error messages */
01242    ast_string_field_set(details, result, "");
01243    ast_string_field_set(details, resultstr, "");
01244    ast_string_field_set(details, error, "");
01245    set_channel_variables(chan, details);
01246 
01247    if (fax->tech->start_session(fax) < 0) {
01248       GENERIC_FAX_EXEC_ERROR(fax, chan, "INIT_ERROR", "failed to start FAX session");
01249    }
01250 
01251    report_fax_status(chan, details, "FAX Transmission In Progress");
01252 
01253    ast_debug(5, "channel %s will wait on FAX fd %d\n", chan->name, fax->fd);
01254 
01255    /* handle frames for the session */
01256    remaining_time = timeout;
01257    start = ast_tvnow();
01258    while (remaining_time > 0) {
01259       struct ast_channel *ready_chan;
01260       int ofd, exception;
01261 
01262       ms = 1000;
01263       errno = 0;
01264       ready_chan = ast_waitfor_nandfds(&c, chancount, &fax->fd, 1, &exception, &ofd, &ms);
01265       if (ready_chan) {
01266          if (!(frame = ast_read(chan))) {
01267             /* the channel is probably gone, so lets stop polling on it and let the
01268              * FAX session complete before we exit the application.  if needed,
01269              * send the FAX stack silence so the modems can finish their session without
01270              * any problems */
01271             ast_debug(1, "Channel '%s' did not return a frame; probably hung up.\n", chan->name);
01272             GENERIC_FAX_EXEC_SET_VARS(fax, chan, "HANGUP", "remote channel hungup");
01273             c = NULL;
01274             chancount = 0;
01275             remaining_time = ast_remaining_ms(start, timeout);
01276             fax->tech->cancel_session(fax);
01277             if (fax->tech->generate_silence) {
01278                fax->tech->generate_silence(fax);
01279             }
01280             continue;
01281          }
01282 
01283          if ((frame->frametype == AST_FRAME_CONTROL) &&
01284              (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
01285              (frame->datalen == sizeof(t38_parameters))) {
01286             unsigned int was_t38 = t38negotiated;
01287             struct ast_control_t38_parameters *parameters = frame->data.ptr;
01288             
01289             switch (parameters->request_response) {
01290             case AST_T38_REQUEST_NEGOTIATE:
01291                /* the other end has requested a switch to T.38, so reply that we are willing, if we can
01292                 * do T.38 as well
01293                 */
01294                t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
01295                t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
01296                ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
01297                break;
01298             case AST_T38_NEGOTIATED:
01299                t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
01300                t38negotiated = 1;
01301                break;
01302             default:
01303                break;
01304             }
01305             if (t38negotiated && !was_t38) {
01306                fax->tech->switch_to_t38(fax);
01307                details->caps &= ~AST_FAX_TECH_AUDIO;
01308                expected_frametype = AST_FRAME_MODEM;
01309                expected_framesubclass.codec = AST_MODEM_T38;
01310                if (fax->smoother) {
01311                   ast_smoother_free(fax->smoother);
01312                   fax->smoother = NULL;
01313                }
01314                
01315                report_fax_status(chan, details, "T.38 Negotiated");
01316                
01317                ast_verb(3, "Channel '%s' switched to T.38 FAX session '%u'.\n", chan->name, fax->id);
01318             }
01319          } else if ((frame->frametype == expected_frametype) &&
01320                (!memcmp(&frame->subclass, &expected_framesubclass, sizeof(frame->subclass)))) {
01321             struct ast_frame *f;
01322             
01323             if (fax->smoother) {
01324                /* push the frame into a smoother */
01325                if (ast_smoother_feed(fax->smoother, frame) < 0) {
01326                   GENERIC_FAX_EXEC_ERROR(fax, chan, "UNKNOWN", "Failed to feed the smoother");
01327                }
01328                while ((f = ast_smoother_read(fax->smoother)) && (f->data.ptr)) {
01329                   if (fax->debug_info) {
01330                      debug_check_frame_for_silence(fax, 1, f);
01331                   }
01332                   /* write the frame to the FAX stack */
01333                   fax->tech->write(fax, f);
01334                   fax->frames_received++;
01335                   if (f != frame) {
01336                      ast_frfree(f);
01337                   }
01338                }
01339             } else {
01340                /* write the frame to the FAX stack */
01341                fax->tech->write(fax, frame);
01342                fax->frames_received++;
01343             }
01344             start = ast_tvnow();
01345          }
01346          ast_frfree(frame);
01347       } else if (ofd == fax->fd) {
01348          /* read a frame from the FAX stack and send it out the channel.
01349           * the FAX stack will return a NULL if the FAX session has already completed */
01350          if (!(frame = fax->tech->read(fax))) {
01351             break;
01352          }
01353 
01354          if (fax->debug_info && (frame->frametype == AST_FRAME_VOICE)) {
01355             debug_check_frame_for_silence(fax, 0, frame);
01356          }
01357 
01358          ast_write(chan, frame);
01359          fax->frames_sent++;
01360          ast_frfree(frame);
01361          start = ast_tvnow();
01362       } else {
01363          if (ms && (ofd < 0)) {
01364             if ((errno == 0) || (errno == EINTR)) {
01365                remaining_time = ast_remaining_ms(start, timeout);
01366                if (remaining_time <= 0)
01367                   GENERIC_FAX_EXEC_ERROR(fax, chan, "TIMEOUT", "fax session timed-out");
01368                continue;
01369             } else {
01370                ast_log(LOG_WARNING, "something bad happened while channel '%s' was polling.\n", chan->name);
01371                GENERIC_FAX_EXEC_ERROR(fax, chan, "UNKNOWN", "error polling data");
01372                break;
01373             }
01374          } else {
01375             /* nothing happened */
01376             remaining_time = ast_remaining_ms(start, timeout);
01377             if (remaining_time <= 0) {
01378                GENERIC_FAX_EXEC_ERROR(fax, chan, "TIMEOUT", "fax session timed-out");
01379                break;
01380             }
01381          }
01382       }
01383    }
01384    ast_debug(3, "channel '%s' - event loop stopped { timeout: %d, remaining_time: %d }\n", chan->name, timeout, remaining_time);
01385 
01386    set_channel_variables(chan, details);
01387 
01388    if (!strcasecmp(details->result, "FAILED")) {
01389       ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
01390    } else {
01391       ast_atomic_fetchadd_int(&faxregistry.fax_complete, 1);
01392    }
01393 
01394    if (fax) {
01395       ao2_lock(faxregistry.container);
01396       ao2_unlink(faxregistry.container, fax);
01397       ao2_unlock(faxregistry.container);
01398       ao2_ref(fax, -1);
01399    }
01400 
01401    /* if the channel is still alive, and we changed its read/write formats,
01402     * restore them now
01403     */
01404    if (chancount) {
01405       if (orig_read_format) {
01406          ast_set_read_format(chan, orig_read_format);
01407       }
01408       if (orig_write_format) {
01409          ast_set_write_format(chan, orig_write_format);
01410       }
01411    }
01412 
01413    /* return the chancount so the calling function can determine if the channel hungup during this FAX session or not */
01414    return chancount;
01415 }
01416 
01417 static int receivefax_t38_init(struct ast_channel *chan, struct ast_fax_session_details *details)
01418 {
01419    int timeout_ms;
01420    struct ast_frame *frame = NULL;
01421    struct ast_control_t38_parameters t38_parameters;
01422    struct timeval start;
01423    int ms;
01424 
01425    t38_parameters_ast_to_fax(&details->our_t38_parameters, &our_t38_parameters);
01426 
01427    /* don't send any audio if we've already received a T.38 reinvite */
01428    if (ast_channel_get_t38_state(chan) != T38_STATE_NEGOTIATING) {
01429       /* generate 3 seconds of CED */
01430       if (ast_playtones_start(chan, 1024, "!2100/3000", 1)) {
01431          ast_log(LOG_ERROR, "error generating CED tone on %s\n", chan->name);
01432          return -1;
01433       }
01434 
01435       timeout_ms = 3000;
01436       start = ast_tvnow();
01437       while ((ms = ast_remaining_ms(start, timeout_ms))) {
01438          ms = ast_waitfor(chan, ms);
01439 
01440          if (ms < 0) {
01441             ast_log(LOG_ERROR, "error while generating CED tone on %s\n", chan->name);
01442             ast_playtones_stop(chan);
01443             return -1;
01444          }
01445 
01446          if (ms == 0) { /* all done, nothing happened */
01447             break;
01448          }
01449 
01450          if (!(frame = ast_read(chan))) {
01451             ast_log(LOG_ERROR, "error reading frame while generating CED tone on %s\n", chan->name);
01452             ast_playtones_stop(chan);
01453             return -1;
01454          }
01455 
01456          if ((frame->frametype == AST_FRAME_CONTROL) &&
01457              (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
01458              (frame->datalen == sizeof(t38_parameters))) {
01459             struct ast_control_t38_parameters *parameters = frame->data.ptr;
01460 
01461             switch (parameters->request_response) {
01462             case AST_T38_REQUEST_NEGOTIATE:
01463                /* the other end has requested a switch to T.38, so reply that we are willing, if we can
01464                 * do T.38 as well
01465                 */
01466                t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
01467                t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
01468                ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
01469                ast_playtones_stop(chan);
01470                break;
01471             case AST_T38_NEGOTIATED:
01472                ast_debug(1, "Negotiated T.38 for receive on %s\n", chan->name);
01473                t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
01474                details->caps &= ~AST_FAX_TECH_AUDIO;
01475                report_fax_status(chan, details, "T.38 Negotiated");
01476                break;
01477             default:
01478                break;
01479             }
01480          }
01481          ast_frfree(frame);
01482       }
01483 
01484       ast_playtones_stop(chan);
01485    }
01486 
01487    /* if T.38 was negotiated, we are done initializing */
01488    if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) {
01489       return 0;
01490    }
01491 
01492    /* request T.38 */
01493    ast_debug(1, "Negotiating T.38 for receive on %s\n", chan->name);
01494 
01495    /* wait up to five seconds for negotiation to complete */
01496    timeout_ms = 5000;
01497 
01498    /* set parameters based on the session's parameters */
01499    t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
01500    t38_parameters.request_response = AST_T38_REQUEST_NEGOTIATE;
01501    if ((ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0)) {
01502       return -1;
01503    }
01504 
01505    start = ast_tvnow();
01506    while ((ms = ast_remaining_ms(start, timeout_ms))) {
01507       int break_loop = 0;
01508 
01509       ms = ast_waitfor(chan, ms);
01510       if (ms < 0) {
01511          ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", chan->name);
01512          return -1;
01513       }
01514       if (ms == 0) { /* all done, nothing happened */
01515          ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 negotiation.\n", chan->name);
01516          details->caps &= ~AST_FAX_TECH_T38;
01517          break;
01518       }
01519 
01520       if (!(frame = ast_read(chan))) {
01521          ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", chan->name);
01522          return -1;
01523       }
01524 
01525       if ((frame->frametype == AST_FRAME_CONTROL) &&
01526             (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
01527             (frame->datalen == sizeof(t38_parameters))) {
01528          struct ast_control_t38_parameters *parameters = frame->data.ptr;
01529 
01530          switch (parameters->request_response) {
01531          case AST_T38_REQUEST_NEGOTIATE:
01532             t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
01533             t38_parameters.request_response = AST_T38_NEGOTIATED;
01534             ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
01535             break;
01536          case AST_T38_NEGOTIATED:
01537             ast_debug(1, "Negotiated T.38 for receive on %s\n", chan->name);
01538             t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
01539             details->caps &= ~AST_FAX_TECH_AUDIO;
01540             report_fax_status(chan, details, "T.38 Negotiated");
01541             break_loop = 1;
01542             break;
01543          case AST_T38_REFUSED:
01544             ast_log(LOG_WARNING, "channel '%s' refused to negotiate T.38\n", chan->name);
01545             details->caps &= ~AST_FAX_TECH_T38;
01546             break_loop = 1;
01547             break;
01548          default:
01549             ast_log(LOG_ERROR, "channel '%s' failed to negotiate T.38\n", chan->name);
01550             details->caps &= ~AST_FAX_TECH_T38;
01551             break_loop = 1;
01552             break;
01553          }
01554       }
01555       ast_frfree(frame);
01556       if (break_loop) {
01557          break;
01558       }
01559    }
01560 
01561    /* if T.38 was negotiated, we are done initializing */
01562    if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) {
01563       return 0;
01564    }
01565 
01566    /* if we made it here, then T.38 failed, check the 'f' flag */
01567    if (details->option.allow_audio != AST_FAX_OPTFLAG_TRUE) {
01568       ast_log(LOG_WARNING, "Audio FAX not allowed on channel '%s' and T.38 negotiation failed; aborting.\n", chan->name);
01569       return -1;
01570    }
01571 
01572    /* ok, audio fallback is allowed */
01573    details->caps |= AST_FAX_TECH_AUDIO;
01574 
01575    return 0;
01576 }
01577 
01578 /*! \brief initiate a receive FAX session */
01579 static int receivefax_exec(struct ast_channel *chan, const char *data)
01580 {
01581    char *parse, modems[128] = "";
01582    int channel_alive;
01583    struct ast_fax_session_details *details;
01584    struct ast_fax_session *s;
01585    struct ast_fax_tech_token *token = NULL;
01586    struct ast_fax_document *doc;
01587    AST_DECLARE_APP_ARGS(args,
01588       AST_APP_ARG(filename);
01589       AST_APP_ARG(options);
01590    );
01591    struct ast_flags opts = { 0, };
01592    struct manager_event_info info;
01593 
01594    /* initialize output channel variables */
01595    pbx_builtin_setvar_helper(chan, "FAXSTATUS", "FAILED");
01596    pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", NULL);
01597    pbx_builtin_setvar_helper(chan, "FAXPAGES", "0");
01598    pbx_builtin_setvar_helper(chan, "FAXBITRATE", NULL);
01599    pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", NULL);
01600 
01601    /* if we ran receivefax then we attempted to receive a fax, even if we
01602     * never start a fax session */
01603    ast_atomic_fetchadd_int(&faxregistry.fax_rx_attempts, 1);
01604 
01605    /* Get a FAX session details structure from the channel's FAX datastore and create one if
01606     * it does not already exist. */
01607    if (!(details = find_or_create_details(chan))) {
01608       ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
01609       pbx_builtin_setvar_helper(chan, "FAXERROR", "MEMORY_ERROR");
01610       pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "error allocating memory");
01611       ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
01612       return -1;
01613    }
01614 
01615    ast_string_field_set(details, result, "FAILED");
01616    ast_string_field_set(details, resultstr, "error starting fax session");
01617    ast_string_field_set(details, error, "INIT_ERROR");
01618    set_channel_variables(chan, details);
01619 
01620    if (details->maxrate < details->minrate) {
01621       ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
01622       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
01623       ast_string_field_set(details, resultstr, "maxrate is less than minrate");
01624       set_channel_variables(chan, details);
01625       ast_log(LOG_ERROR, "maxrate %u is less than minrate %u\n", details->maxrate, details->minrate);
01626       ao2_ref(details, -1);
01627       return -1;
01628    }
01629 
01630    if (check_modem_rate(details->modems, details->minrate)) {
01631       ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
01632       ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
01633       ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %u\n", modems, details->minrate);
01634       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
01635       ast_string_field_set(details, resultstr, "incompatible 'modems' and 'minrate' settings");
01636       set_channel_variables(chan, details);
01637       ao2_ref(details, -1);
01638       return -1;
01639    }
01640 
01641    if (check_modem_rate(details->modems, details->maxrate)) {
01642       ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
01643       ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
01644       ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %u\n", modems, details->maxrate);
01645       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
01646       ast_string_field_set(details, resultstr, "incompatible 'modems' and 'maxrate' settings");
01647       set_channel_variables(chan, details);
01648       ao2_ref(details, -1);
01649       return -1;
01650    }
01651 
01652    if (ast_strlen_zero(data)) {
01653       ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
01654       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
01655       ast_string_field_set(details, resultstr, "invalid arguments");
01656       set_channel_variables(chan, details);
01657       ast_log(LOG_WARNING, "%s requires an argument (filename[,options])\n", app_receivefax);
01658       ao2_ref(details, -1);
01659       return -1;
01660    }
01661    parse = ast_strdupa(data);
01662    AST_STANDARD_APP_ARGS(args, parse);
01663 
01664    if (!ast_strlen_zero(args.options) &&
01665        ast_app_parse_options(fax_exec_options, &opts, NULL, args.options)) {
01666       ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
01667       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
01668       ast_string_field_set(details, resultstr, "invalid arguments");
01669       set_channel_variables(chan, details);
01670       ao2_ref(details, -1);
01671       return -1;
01672    }
01673    if (ast_strlen_zero(args.filename)) {
01674       ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
01675       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
01676       ast_string_field_set(details, resultstr, "invalid arguments");
01677       set_channel_variables(chan, details);
01678       ast_log(LOG_WARNING, "%s requires an argument (filename[,options])\n", app_receivefax);
01679       ao2_ref(details, -1);
01680       return -1;
01681    }
01682 
01683    /* check for unsupported FAX application options */
01684    if (ast_test_flag(&opts, OPT_CALLERMODE) || ast_test_flag(&opts, OPT_CALLEDMODE)) {
01685       ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
01686       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
01687       ast_string_field_set(details, resultstr, "invalid arguments");
01688       set_channel_variables(chan, details);
01689       ast_log(LOG_WARNING, "%s does not support polling\n", app_receivefax);
01690       ao2_ref(details, -1);
01691       return -1;
01692    }
01693 
01694    pbx_builtin_setvar_helper(chan, "FAXERROR", "Channel Problems");
01695    pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "Error before FAX transmission started.");
01696 
01697    if (!(doc = ast_calloc(1, sizeof(*doc) + strlen(args.filename) + 1))) {
01698       ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
01699       ast_string_field_set(details, error, "MEMORY_ERROR");
01700       ast_string_field_set(details, resultstr, "error allocating memory");
01701       set_channel_variables(chan, details);
01702       ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
01703       ao2_ref(details, -1);
01704       return -1;
01705    }
01706 
01707    strcpy(doc->filename, args.filename);
01708    AST_LIST_INSERT_TAIL(&details->documents, doc, next);
01709 
01710    ast_verb(3, "Channel '%s' receiving FAX '%s'\n", chan->name, args.filename);
01711 
01712    details->caps = AST_FAX_TECH_RECEIVE;
01713    details->option.send_ced = AST_FAX_OPTFLAG_TRUE;
01714 
01715    /* check for debug */
01716    if (ast_test_flag(&opts, OPT_DEBUG) || global_fax_debug) {
01717       details->option.debug = AST_FAX_OPTFLAG_TRUE;
01718    }
01719 
01720    /* check for request for status events */
01721    if (ast_test_flag(&opts, OPT_STATUS)) {
01722       details->option.statusevents = AST_FAX_OPTFLAG_TRUE;
01723    }
01724 
01725    if ((ast_channel_get_t38_state(chan) == T38_STATE_UNAVAILABLE) ||
01726        ast_test_flag(&opts, OPT_ALLOWAUDIO)) {
01727       details->option.allow_audio = AST_FAX_OPTFLAG_TRUE;
01728    }
01729 
01730    if (!(s = fax_session_reserve(details, &token))) {
01731       ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
01732       ast_string_field_set(details, resultstr, "error reserving fax session");
01733       set_channel_variables(chan, details);
01734       ast_log(LOG_ERROR, "Unable to reserve FAX session.\n");
01735       ao2_ref(details, -1);
01736       return -1;
01737    }
01738 
01739    /* make sure the channel is up */
01740    if (chan->_state != AST_STATE_UP) {
01741       if (ast_answer(chan)) {
01742          ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
01743          ast_string_field_set(details, resultstr, "error answering channel");
01744          set_channel_variables(chan, details);
01745          ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", chan->name);
01746          fax_session_release(s, token);
01747          ao2_ref(s, -1);
01748          ao2_ref(details, -1);
01749          return -1;
01750       }
01751    }
01752 
01753    if (set_fax_t38_caps(chan, details)) {
01754       ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
01755       ast_string_field_set(details, error, "T38_NEG_ERROR");
01756       ast_string_field_set(details, resultstr, "error negotiating T.38");
01757       set_channel_variables(chan, details);
01758       fax_session_release(s, token);
01759       ao2_ref(s, -1);
01760       ao2_ref(details, -1);
01761       return -1;
01762    }
01763 
01764    if (details->caps & AST_FAX_TECH_T38) {
01765       if (receivefax_t38_init(chan, details)) {
01766          ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
01767          ast_string_field_set(details, error, "T38_NEG_ERROR");
01768          ast_string_field_set(details, resultstr, "error negotiating T.38");
01769          set_channel_variables(chan, details);
01770          fax_session_release(s, token);
01771          ao2_ref(s, -1);
01772          ao2_ref(details, -1);
01773          ast_log(LOG_ERROR, "error initializing channel '%s' in T.38 mode\n", chan->name);
01774          return -1;
01775       }
01776    }
01777 
01778    if ((channel_alive = generic_fax_exec(chan, details, s, token)) < 0) {
01779       ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
01780    }
01781 
01782    if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) {
01783       if (disable_t38(chan)) {
01784          ast_debug(1, "error disabling T.38 mode on %s\n", chan->name);
01785       }
01786    }
01787 
01788    /* send out the AMI completion event */
01789    ast_channel_lock(chan);
01790 
01791    get_manager_event_info(chan, &info);
01792    manager_event(EVENT_FLAG_CALL,
01793             "ReceiveFAX", 
01794             "Channel: %s\r\n"
01795             "Context: %s\r\n"
01796             "Exten: %s\r\n"
01797             "CallerID: %s\r\n"
01798             "RemoteStationID: %s\r\n"
01799             "LocalStationID: %s\r\n"
01800             "PagesTransferred: %s\r\n"
01801             "Resolution: %s\r\n"
01802             "TransferRate: %s\r\n"
01803             "FileName: %s\r\n",
01804             chan->name,
01805             info.context,
01806             info.exten,
01807             info.cid,
01808             S_OR(pbx_builtin_getvar_helper(chan, "REMOTESTATIONID"), ""),
01809             S_OR(pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"), ""),
01810             S_OR(pbx_builtin_getvar_helper(chan, "FAXPAGES"), ""),
01811             S_OR(pbx_builtin_getvar_helper(chan, "FAXRESOLUTION"), ""),
01812             S_OR(pbx_builtin_getvar_helper(chan, "FAXBITRATE"), ""),
01813             args.filename);
01814    ast_channel_unlock(chan);
01815 
01816    ao2_ref(s, -1);
01817    ao2_ref(details, -1);
01818 
01819    /* If the channel hungup return -1; otherwise, return 0 to continue in the dialplan */
01820    return (!channel_alive) ? -1 : 0;
01821 }
01822 
01823 static int sendfax_t38_init(struct ast_channel *chan, struct ast_fax_session_details *details)
01824 {
01825    int timeout_ms;
01826    struct ast_frame *frame = NULL;
01827    struct ast_control_t38_parameters t38_parameters;
01828    struct timeval start;
01829    int ms;
01830 
01831    t38_parameters_ast_to_fax(&details->our_t38_parameters, &our_t38_parameters);
01832 
01833    /* send CNG tone while listening for the receiver to initiate a switch
01834     * to T.38 mode; if they do, stop sending the CNG tone and proceed with
01835     * the switch.
01836     *
01837     * 10500 is enough time for 3 CNG tones
01838     */
01839    timeout_ms = 10500;
01840 
01841    /* don't send any audio if we've already received a T.38 reinvite */
01842    if (ast_channel_get_t38_state(chan) != T38_STATE_NEGOTIATING) {
01843       if (ast_playtones_start(chan, 1024, "!1100/500,!0/3000,!1100/500,!0/3000,!1100/500,!0/3000", 1)) {
01844          ast_log(LOG_ERROR, "error generating CNG tone on %s\n", chan->name);
01845          return -1;
01846       }
01847    }
01848 
01849    start = ast_tvnow();
01850    while ((ms = ast_remaining_ms(start, timeout_ms))) {
01851       int break_loop = 0;
01852       ms = ast_waitfor(chan, ms);
01853 
01854       if (ms < 0) {
01855          ast_log(LOG_ERROR, "error while generating CNG tone on %s\n", chan->name);
01856          ast_playtones_stop(chan);
01857          return -1;
01858       }
01859 
01860       if (ms == 0) { /* all done, nothing happened */
01861          break;
01862       }
01863 
01864       if (!(frame = ast_read(chan))) {
01865          ast_log(LOG_ERROR, "error reading frame while generating CNG tone on %s\n", chan->name);
01866          ast_playtones_stop(chan);
01867          return -1;
01868       }
01869 
01870       if ((frame->frametype == AST_FRAME_CONTROL) &&
01871             (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
01872             (frame->datalen == sizeof(t38_parameters))) {
01873          struct ast_control_t38_parameters *parameters = frame->data.ptr;
01874 
01875          switch (parameters->request_response) {
01876          case AST_T38_REQUEST_NEGOTIATE:
01877             /* the other end has requested a switch to T.38, so reply that we are willing, if we can
01878              * do T.38 as well
01879              */
01880             t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
01881             t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
01882             ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
01883             ast_playtones_stop(chan);
01884             break;
01885          case AST_T38_NEGOTIATED:
01886             ast_debug(1, "Negotiated T.38 for send on %s\n", chan->name);
01887             t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
01888             details->caps &= ~AST_FAX_TECH_AUDIO;
01889             report_fax_status(chan, details, "T.38 Negotiated");
01890             break_loop = 1;
01891             break;
01892          default:
01893             break;
01894          }
01895       }
01896       ast_frfree(frame);
01897       if (break_loop) {
01898          break;
01899       }
01900    }
01901 
01902    ast_playtones_stop(chan);
01903 
01904    if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) {
01905       return 0;
01906    }
01907 
01908    /* T.38 negotiation did not happen, initiate a switch if requested */
01909    if (details->option.request_t38 == AST_FAX_OPTFLAG_TRUE) {
01910       ast_debug(1, "Negotiating T.38 for send on %s\n", chan->name);
01911 
01912       /* wait up to five seconds for negotiation to complete */
01913       timeout_ms = 5000;
01914 
01915       /* set parameters based on the session's parameters */
01916       t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
01917       t38_parameters.request_response = AST_T38_REQUEST_NEGOTIATE;
01918       if ((ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0)) {
01919          return -1;
01920       }
01921 
01922       start = ast_tvnow();
01923       while ((ms = ast_remaining_ms(start, timeout_ms))) {
01924          int break_loop = 0;
01925 
01926          ms = ast_waitfor(chan, ms);
01927          if (ms < 0) {
01928             ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", chan->name);
01929             return -1;
01930          }
01931          if (ms == 0) { /* all done, nothing happened */
01932             ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 negotiation.\n", chan->name);
01933             details->caps &= ~AST_FAX_TECH_T38;
01934             break;
01935          }
01936 
01937          if (!(frame = ast_read(chan))) {
01938             ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", chan->name);
01939             return -1;
01940          }
01941 
01942          if ((frame->frametype == AST_FRAME_CONTROL) &&
01943                (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
01944                (frame->datalen == sizeof(t38_parameters))) {
01945             struct ast_control_t38_parameters *parameters = frame->data.ptr;
01946 
01947             switch (parameters->request_response) {
01948             case AST_T38_REQUEST_NEGOTIATE:
01949                t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
01950                t38_parameters.request_response = AST_T38_NEGOTIATED;
01951                ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
01952                break;
01953             case AST_T38_NEGOTIATED:
01954                ast_debug(1, "Negotiated T.38 for receive on %s\n", chan->name);
01955                t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
01956                details->caps &= ~AST_FAX_TECH_AUDIO;
01957                report_fax_status(chan, details, "T.38 Negotiated");
01958                break_loop = 1;
01959                break;
01960             case AST_T38_REFUSED:
01961                ast_log(LOG_WARNING, "channel '%s' refused to negotiate T.38\n", chan->name);
01962                details->caps &= ~AST_FAX_TECH_T38;
01963                break_loop = 1;
01964                break;
01965             default:
01966                ast_log(LOG_ERROR, "channel '%s' failed to negotiate T.38\n", chan->name);
01967                details->caps &= ~AST_FAX_TECH_T38;
01968                break_loop = 1;
01969                break;
01970             }
01971          }
01972          ast_frfree(frame);
01973          if (break_loop) {
01974             break;
01975          }
01976       }
01977 
01978       /* if T.38 was negotiated, we are done initializing */
01979       if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) {
01980          return 0;
01981       }
01982 
01983       /* send one more CNG tone to get audio going again for some
01984        * carriers if we are going to fall back to audio mode */
01985       if (details->option.allow_audio == AST_FAX_OPTFLAG_TRUE) {
01986          if (ast_playtones_start(chan, 1024, "!1100/500,!0/3000", 1)) {
01987             ast_log(LOG_ERROR, "error generating second CNG tone on %s\n", chan->name);
01988             return -1;
01989          }
01990 
01991          timeout_ms = 3500;
01992          start = ast_tvnow();
01993          while ((ms = ast_remaining_ms(start, timeout_ms))) {
01994             int break_loop = 0;
01995 
01996             ms = ast_waitfor(chan, ms);
01997             if (ms < 0) {
01998                ast_log(LOG_ERROR, "error while generating second CNG tone on %s\n", chan->name);
01999                ast_playtones_stop(chan);
02000                return -1;
02001             }
02002             if (ms == 0) { /* all done, nothing happened */
02003                break;
02004             }
02005 
02006             if (!(frame = ast_read(chan))) {
02007                ast_log(LOG_ERROR, "error reading frame while generating second CNG tone on %s\n", chan->name);
02008                ast_playtones_stop(chan);
02009                return -1;
02010             }
02011 
02012             if ((frame->frametype == AST_FRAME_CONTROL) &&
02013                   (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
02014                   (frame->datalen == sizeof(t38_parameters))) {
02015                struct ast_control_t38_parameters *parameters = frame->data.ptr;
02016 
02017                switch (parameters->request_response) {
02018                case AST_T38_REQUEST_NEGOTIATE:
02019                   /* the other end has requested a switch to T.38, so reply that we are willing, if we can
02020                    * do T.38 as well
02021                    */
02022                   t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
02023                   t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
02024                   ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
02025                   ast_playtones_stop(chan);
02026                   break;
02027                case AST_T38_NEGOTIATED:
02028                   ast_debug(1, "Negotiated T.38 for send on %s\n", chan->name);
02029                   t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
02030                   details->caps &= ~AST_FAX_TECH_AUDIO;
02031                   report_fax_status(chan, details, "T.38 Negotiated");
02032                   break_loop = 1;
02033                   break;
02034                default:
02035                   break;
02036                }
02037             }
02038             ast_frfree(frame);
02039             if (break_loop) {
02040                break;
02041             }
02042          }
02043 
02044          ast_playtones_stop(chan);
02045 
02046          /* if T.38 was negotiated, we are done initializing */
02047          if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) {
02048             return 0;
02049          }
02050       }
02051    }
02052 
02053    /* if we made it here, then T.38 failed, check the 'f' flag */
02054    if (details->option.allow_audio == AST_FAX_OPTFLAG_FALSE) {
02055       ast_log(LOG_WARNING, "Audio FAX not allowed on channel '%s' and T.38 negotiation failed; aborting.\n", chan->name);
02056       return -1;
02057    }
02058 
02059    /* ok, audio fallback is allowed */
02060    details->caps |= AST_FAX_TECH_AUDIO;
02061 
02062    return 0;
02063 }
02064 
02065 
02066 /*! \brief initiate a send FAX session */
02067 static int sendfax_exec(struct ast_channel *chan, const char *data)
02068 {
02069    char *parse, *filenames, *c, modems[128] = "";
02070    int channel_alive, file_count;
02071    struct ast_fax_session_details *details;
02072    struct ast_fax_session *s;
02073    struct ast_fax_tech_token *token = NULL;
02074    struct ast_fax_document *doc;
02075    AST_DECLARE_APP_ARGS(args,
02076       AST_APP_ARG(filenames);
02077       AST_APP_ARG(options);
02078    );
02079    struct ast_flags opts = { 0, };
02080    struct manager_event_info info;
02081 
02082    /* initialize output channel variables */
02083    pbx_builtin_setvar_helper(chan, "FAXSTATUS", "FAILED");
02084    pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", NULL);
02085    pbx_builtin_setvar_helper(chan, "FAXPAGES", "0");
02086    pbx_builtin_setvar_helper(chan, "FAXBITRATE", NULL);
02087    pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", NULL);
02088 
02089    /* if we ran sendfax then we attempted to send a fax, even if we never
02090     * start a fax session */
02091    ast_atomic_fetchadd_int(&faxregistry.fax_tx_attempts, 1);
02092 
02093    /* Get a requirement structure and set it.  This structure is used
02094     * to tell the FAX technology module about the higher level FAX session */
02095    if (!(details = find_or_create_details(chan))) {
02096       ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
02097       pbx_builtin_setvar_helper(chan, "FAXERROR", "MEMORY_ERROR");
02098       pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "error allocating memory");
02099       ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
02100       return -1;
02101    }
02102 
02103    ast_string_field_set(details, result, "FAILED");
02104    ast_string_field_set(details, resultstr, "error starting fax session");
02105    ast_string_field_set(details, error, "INIT_ERROR");
02106    set_channel_variables(chan, details);
02107 
02108    if (details->maxrate < details->minrate) {
02109       ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
02110       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
02111       ast_string_field_set(details, resultstr, "maxrate is less than minrate");
02112       set_channel_variables(chan, details);
02113       ast_log(LOG_ERROR, "maxrate %u is less than minrate %u\n", details->maxrate, details->minrate);
02114       ao2_ref(details, -1);
02115       return -1;
02116    }
02117 
02118    if (check_modem_rate(details->modems, details->minrate)) {
02119       ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
02120       ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
02121       ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %u\n", modems, details->minrate);
02122       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
02123       ast_string_field_set(details, resultstr, "incompatible 'modems' and 'minrate' settings");
02124       set_channel_variables(chan, details);
02125       ao2_ref(details, -1);
02126       return -1;
02127    }
02128 
02129    if (check_modem_rate(details->modems, details->maxrate)) {
02130       ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
02131       ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
02132       ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %u\n", modems, details->maxrate);
02133       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
02134       ast_string_field_set(details, resultstr, "incompatible 'modems' and 'maxrate' settings");
02135       set_channel_variables(chan, details);
02136       ao2_ref(details, -1);
02137       return -1;
02138    }
02139 
02140    if (ast_strlen_zero(data)) {
02141       ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
02142       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
02143       ast_string_field_set(details, resultstr, "invalid arguments");
02144       set_channel_variables(chan, details);
02145       ast_log(LOG_WARNING, "%s requires an argument (filename[&filename[&filename]][,options])\n", app_sendfax);
02146       ao2_ref(details, -1);
02147       return -1;
02148    }
02149    parse = ast_strdupa(data);
02150    AST_STANDARD_APP_ARGS(args, parse);
02151 
02152 
02153    if (!ast_strlen_zero(args.options) &&
02154        ast_app_parse_options(fax_exec_options, &opts, NULL, args.options)) {
02155       ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
02156       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
02157       ast_string_field_set(details, resultstr, "invalid arguments");
02158       set_channel_variables(chan, details);
02159       ao2_ref(details, -1);
02160       return -1;
02161    }
02162    if (ast_strlen_zero(args.filenames)) {
02163       ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
02164       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
02165       ast_string_field_set(details, resultstr, "invalid arguments");
02166       set_channel_variables(chan, details);
02167       ast_log(LOG_WARNING, "%s requires an argument (filename[&filename[&filename]],options])\n", app_sendfax);
02168       ao2_ref(details, -1);
02169       return -1;
02170    }
02171    
02172    /* check for unsupported FAX application options */
02173    if (ast_test_flag(&opts, OPT_CALLERMODE) || ast_test_flag(&opts, OPT_CALLEDMODE)) {
02174       ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
02175       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
02176       ast_string_field_set(details, resultstr, "invalid arguments");
02177       set_channel_variables(chan, details);
02178       ast_log(LOG_WARNING, "%s does not support polling\n", app_sendfax);
02179       ao2_ref(details, -1);
02180       return -1;
02181    }
02182 
02183    file_count = 0;
02184    filenames = args.filenames;
02185    while ((c = strsep(&filenames, "&"))) {
02186       if (access(c, (F_OK | R_OK)) < 0) {
02187          ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
02188          ast_string_field_set(details, error, "FILE_ERROR");
02189          ast_string_field_set(details, resultstr, "error reading file");
02190          set_channel_variables(chan, details);
02191          ast_log(LOG_ERROR, "access failure.  Verify '%s' exists and check permissions.\n", args.filenames);
02192          ao2_ref(details, -1);
02193          return -1;
02194       }
02195 
02196       if (!(doc = ast_calloc(1, sizeof(*doc) + strlen(c) + 1))) {
02197          ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
02198          ast_string_field_set(details, error, "MEMORY_ERROR");
02199          ast_string_field_set(details, resultstr, "error allocating memory");
02200          set_channel_variables(chan, details);
02201          ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
02202          ao2_ref(details, -1);
02203          return -1;
02204       }
02205 
02206       strcpy(doc->filename, c);
02207       AST_LIST_INSERT_TAIL(&details->documents, doc, next);
02208       file_count++;
02209    }
02210 
02211    if (file_count > 1) {
02212       details->caps |= AST_FAX_TECH_MULTI_DOC;
02213    }
02214 
02215    ast_verb(3, "Channel '%s' sending FAX:\n", chan->name);
02216    AST_LIST_TRAVERSE(&details->documents, doc, next) {
02217       ast_verb(3, "   %s\n", doc->filename);
02218    }
02219 
02220    details->caps = AST_FAX_TECH_SEND;
02221 
02222    /* check for debug */
02223    if (ast_test_flag(&opts, OPT_DEBUG) || global_fax_debug) {
02224       details->option.debug = AST_FAX_OPTFLAG_TRUE;
02225    }
02226 
02227    /* check for request for status events */
02228    if (ast_test_flag(&opts, OPT_STATUS)) {
02229       details->option.statusevents = AST_FAX_OPTFLAG_TRUE;
02230    }
02231 
02232    if ((ast_channel_get_t38_state(chan) == T38_STATE_UNAVAILABLE) ||
02233        ast_test_flag(&opts, OPT_ALLOWAUDIO)) {
02234       details->option.allow_audio = AST_FAX_OPTFLAG_TRUE;
02235    }
02236 
02237    if (ast_test_flag(&opts, OPT_REQUEST_T38)) {
02238       details->option.request_t38 = AST_FAX_OPTFLAG_TRUE;
02239    }
02240 
02241    if (!(s = fax_session_reserve(details, &token))) {
02242       ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
02243       ast_string_field_set(details, resultstr, "error reserving fax session");
02244       set_channel_variables(chan, details);
02245       ast_log(LOG_ERROR, "Unable to reserve FAX session.\n");
02246       ao2_ref(details, -1);
02247       return -1;
02248    }
02249 
02250    /* make sure the channel is up */
02251    if (chan->_state != AST_STATE_UP) {
02252       if (ast_answer(chan)) {
02253          ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
02254          ast_string_field_set(details, resultstr, "error answering channel");
02255          set_channel_variables(chan, details);
02256          ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", chan->name);
02257          fax_session_release(s, token);
02258          ao2_ref(s, -1);
02259          ao2_ref(details, -1);
02260          return -1;
02261       }
02262    }
02263 
02264    if (set_fax_t38_caps(chan, details)) {
02265       ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
02266       ast_string_field_set(details, error, "T38_NEG_ERROR");
02267       ast_string_field_set(details, resultstr, "error negotiating T.38");
02268       set_channel_variables(chan, details);
02269       fax_session_release(s, token);
02270       ao2_ref(s, -1);
02271       ao2_ref(details, -1);
02272       return -1;
02273    }
02274 
02275    if (details->caps & AST_FAX_TECH_T38) {
02276       if (sendfax_t38_init(chan, details)) {
02277          ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
02278          ast_string_field_set(details, error, "T38_NEG_ERROR");
02279          ast_string_field_set(details, resultstr, "error negotiating T.38");
02280          set_channel_variables(chan, details);
02281          fax_session_release(s, token);
02282          ao2_ref(s, -1);
02283          ao2_ref(details, -1);
02284          ast_log(LOG_ERROR, "error initializing channel '%s' in T.38 mode\n", chan->name);
02285          return -1;
02286       }
02287    } else {
02288       details->option.send_cng = 1;
02289    }
02290 
02291    if ((channel_alive = generic_fax_exec(chan, details, s, token)) < 0) {
02292       ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
02293    }
02294 
02295    if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) {
02296       if (disable_t38(chan)) {
02297          ast_debug(1, "error disabling T.38 mode on %s\n", chan->name);
02298       }
02299    }
02300 
02301    if (!(filenames = generate_filenames_string(details, "FileName: ", "\r\n"))) {
02302       ast_log(LOG_ERROR, "Error generating SendFAX manager event\n");
02303       ao2_ref(s, -1);
02304       ao2_ref(details, -1);
02305       return (!channel_alive) ? -1 : 0;
02306    }
02307 
02308    /* send out the AMI completion event */
02309    ast_channel_lock(chan);
02310    get_manager_event_info(chan, &info);
02311    manager_event(EVENT_FLAG_CALL,
02312             "SendFAX", 
02313             "Channel: %s\r\n"
02314             "Context: %s\r\n"
02315             "Exten: %s\r\n"
02316             "CallerID: %s\r\n"
02317             "RemoteStationID: %s\r\n"
02318             "LocalStationID: %s\r\n"
02319             "PagesTransferred: %s\r\n"
02320             "Resolution: %s\r\n"
02321             "TransferRate: %s\r\n"
02322             "%s\r\n",
02323             chan->name,
02324             info.context,
02325             info.exten,
02326             info.cid,
02327             S_OR(pbx_builtin_getvar_helper(chan, "REMOTESTATIONID"), ""),
02328             S_OR(pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"), ""),
02329             S_OR(pbx_builtin_getvar_helper(chan, "FAXPAGES"), ""),
02330             S_OR(pbx_builtin_getvar_helper(chan, "FAXRESOLUTION"), ""),
02331             S_OR(pbx_builtin_getvar_helper(chan, "FAXBITRATE"), ""),
02332             filenames);
02333    ast_channel_unlock(chan);
02334 
02335    ast_free(filenames);
02336 
02337    ao2_ref(s, -1);
02338    ao2_ref(details, -1);
02339 
02340    /* If the channel hungup return -1; otherwise, return 0 to continue in the dialplan */
02341    return (!channel_alive) ? -1 : 0;
02342 }
02343 
02344 /*! \brief hash callback for ao2 */
02345 static int session_hash_cb(const void *obj, const int flags)
02346 {
02347    const struct ast_fax_session *s = obj;
02348 
02349    return s->id;
02350 }
02351 
02352 /*! \brief compare callback for ao2 */
02353 static int session_cmp_cb(void *obj, void *arg, int flags)
02354 {
02355    struct ast_fax_session *lhs = obj, *rhs = arg;
02356 
02357    return (lhs->id == rhs->id) ? CMP_MATCH | CMP_STOP : 0;
02358 }
02359 
02360 /*! \brief fax session tab completion */
02361 static char *fax_session_tab_complete(struct ast_cli_args *a)
02362 {
02363    int tklen;
02364    int wordnum = 0;
02365    char *name = NULL;
02366    struct ao2_iterator i;
02367    struct ast_fax_session *s;
02368    char tbuf[5];
02369 
02370    if (a->pos != 3) {
02371       return NULL;
02372    }
02373 
02374    tklen = strlen(a->word);
02375    i = ao2_iterator_init(faxregistry.container, 0);
02376    while ((s = ao2_iterator_next(&i))) {
02377       snprintf(tbuf, sizeof(tbuf), "%u", s->id);
02378       if (!strncasecmp(a->word, tbuf, tklen) && ++wordnum > a->n) {
02379          name = ast_strdup(tbuf);
02380          ao2_ref(s, -1);
02381          break;
02382       }
02383       ao2_ref(s, -1);
02384    }
02385    ao2_iterator_destroy(&i);
02386    return name;
02387 }
02388 
02389 static char *cli_fax_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02390 {
02391    struct fax_module *fax;
02392 
02393    switch(cmd) {
02394    case CLI_INIT:
02395       e->command = "fax show version";
02396       e->usage =
02397          "Usage: fax show version\n"
02398          "       Show versions of FAX For Asterisk components.\n";
02399       return NULL;
02400    case CLI_GENERATE:
02401       return NULL;
02402    }
02403 
02404    if (a->argc != 3) {
02405       return CLI_SHOWUSAGE;
02406    }
02407 
02408    ast_cli(a->fd, "FAX For Asterisk Components:\n");
02409    ast_cli(a->fd, "\tApplications: %s\n", ast_get_version());
02410    AST_RWLIST_RDLOCK(&faxmodules);
02411    AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
02412       ast_cli(a->fd, "\t%s: %s\n", fax->tech->description, fax->tech->version);
02413    }
02414    AST_RWLIST_UNLOCK(&faxmodules);
02415    ast_cli(a->fd, "\n");
02416 
02417    return CLI_SUCCESS;
02418 }
02419 
02420 /*! \brief enable FAX debugging */
02421 static char *cli_fax_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02422 {
02423    int flag;
02424    const char *what;
02425 
02426    switch (cmd) {
02427    case CLI_INIT:
02428       e->command = "fax set debug {on|off}";
02429       e->usage = 
02430          "Usage: fax set debug { on | off }\n"
02431          "       Enable/Disable FAX debugging on new FAX sessions.  The basic FAX debugging will result in\n"
02432          "       additional events sent to manager sessions with 'call' class permissions.  When\n"
02433          "       verbosity is greater than '5' events will be displayed to the console and audio versus\n"
02434          "       energy analysis will be performed and displayed to the console.\n";
02435       return NULL;
02436    case CLI_GENERATE:
02437       return NULL;
02438    }
02439 
02440    what = a->argv[e->args-1];      /* guaranteed to exist */
02441    if (!strcasecmp(what, "on")) {
02442       flag = 1;
02443    } else if (!strcasecmp(what, "off")) {
02444       flag = 0;
02445    } else {
02446       return CLI_SHOWUSAGE;
02447    }
02448 
02449    global_fax_debug = flag;
02450    ast_cli(a->fd, "\n\nFAX Debug %s\n\n", (flag) ? "Enabled" : "Disabled");
02451 
02452    return CLI_SUCCESS;
02453 }
02454 
02455 /*! \brief display registered FAX capabilities */
02456 static char *cli_fax_show_capabilities(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02457 {
02458    struct fax_module *fax;
02459    unsigned int num_modules = 0;
02460    
02461    switch (cmd) {
02462    case CLI_INIT:
02463       e->command = "fax show capabilities";
02464       e->usage = 
02465          "Usage: fax show capabilities\n"
02466          "       Shows the capabilities of the registered FAX technology modules\n";
02467       return NULL;
02468    case CLI_GENERATE:
02469       return NULL;
02470    }
02471 
02472    ast_cli(a->fd, "\n\nRegistered FAX Technology Modules:\n\n");
02473    AST_RWLIST_RDLOCK(&faxmodules);
02474    AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
02475       ast_cli(a->fd, "%-15s : %s\n%-15s : %s\n%-15s : ", "Type", fax->tech->type, "Description", fax->tech->description, "Capabilities");
02476       fax->tech->cli_show_capabilities(a->fd);
02477       num_modules++;
02478    }
02479    AST_RWLIST_UNLOCK(&faxmodules);
02480    ast_cli(a->fd, "%u registered modules\n\n", num_modules);
02481 
02482    return CLI_SUCCESS;
02483 }
02484 
02485 /*! \brief display global defaults and settings */
02486 static char *cli_fax_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02487 {
02488    struct fax_module *fax;
02489    char modems[128] = "";
02490    struct fax_options options;
02491 
02492    switch (cmd) {
02493    case CLI_INIT:
02494       e->command = "fax show settings";
02495       e->usage =
02496          "Usage: fax show settings\n"
02497          "       Show the global settings and defaults of both the FAX core and technology modules\n";
02498       return NULL;
02499    case CLI_GENERATE:
02500       return NULL;
02501    }
02502 
02503    get_general_options(&options);
02504 
02505    ast_cli(a->fd, "FAX For Asterisk Settings:\n");
02506    ast_cli(a->fd, "\tECM: %s\n", options.ecm ? "Enabled" : "Disabled");
02507    ast_cli(a->fd, "\tStatus Events: %s\n",  options.statusevents ? "On" : "Off");
02508    ast_cli(a->fd, "\tMinimum Bit Rate: %u\n", options.minrate);
02509    ast_cli(a->fd, "\tMaximum Bit Rate: %u\n", options.maxrate);
02510    ast_fax_modem_to_str(options.modems, modems, sizeof(modems));
02511    ast_cli(a->fd, "\tModem Modulations Allowed: %s\n", modems);
02512    ast_cli(a->fd, "\n\nFAX Technology Modules:\n\n");
02513    AST_RWLIST_RDLOCK(&faxmodules);
02514    AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
02515       ast_cli(a->fd, "%s (%s) Settings:\n", fax->tech->type, fax->tech->description);
02516       fax->tech->cli_show_settings(a->fd);
02517    }
02518    AST_RWLIST_UNLOCK(&faxmodules);
02519 
02520    return CLI_SUCCESS;
02521 }
02522 
02523 /*! \brief display details of a specified fax session */
02524 static char *cli_fax_show_session(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02525 {
02526    struct ast_fax_session *s, tmp;
02527 
02528    switch (cmd) {
02529    case CLI_INIT:
02530       e->command = "fax show session";
02531       e->usage =
02532          "Usage: fax show session <session number>\n"
02533          "       Shows status of the named FAX session\n";
02534       return NULL;
02535    case CLI_GENERATE:
02536       return fax_session_tab_complete(a);
02537    }
02538 
02539    if (a->argc != 4) {
02540       return CLI_SHOWUSAGE;
02541    }
02542 
02543    if (sscanf(a->argv[3], "%u", &tmp.id) != 1) {
02544       ast_log(LOG_ERROR, "invalid session id: '%s'\n", a->argv[3]);
02545       return RESULT_SUCCESS;
02546    }
02547 
02548    ast_cli(a->fd, "\nFAX Session Details:\n--------------------\n\n");
02549    s = ao2_find(faxregistry.container, &tmp, OBJ_POINTER);
02550    if (s) {
02551       s->tech->cli_show_session(s, a->fd);
02552       ao2_ref(s, -1);
02553    }
02554    ast_cli(a->fd, "\n\n");
02555 
02556    return CLI_SUCCESS;
02557 }
02558    
02559 /*! \brief display fax stats */
02560 static char *cli_fax_show_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02561 {
02562    struct fax_module *fax;
02563    
02564    switch (cmd) {
02565    case CLI_INIT:
02566       e->command = "fax show stats";
02567       e->usage =
02568          "Usage: fax show stats\n"
02569          "       Shows a statistical summary of FAX transmissions\n";
02570       return NULL;
02571    case CLI_GENERATE:
02572       return NULL;
02573    }
02574 
02575    ast_cli(a->fd, "\nFAX Statistics:\n---------------\n\n");
02576    ast_cli(a->fd, "%-20.20s : %d\n", "Current Sessions", faxregistry.active_sessions);
02577    ast_cli(a->fd, "%-20.20s : %d\n", "Reserved Sessions", faxregistry.reserved_sessions);
02578    ast_cli(a->fd, "%-20.20s : %d\n", "Transmit Attempts", faxregistry.fax_tx_attempts);
02579    ast_cli(a->fd, "%-20.20s : %d\n", "Receive Attempts", faxregistry.fax_rx_attempts);
02580    ast_cli(a->fd, "%-20.20s : %d\n", "Completed FAXes", faxregistry.fax_complete);
02581    ast_cli(a->fd, "%-20.20s : %d\n", "Failed FAXes", faxregistry.fax_failures);
02582    AST_RWLIST_RDLOCK(&faxmodules);
02583    AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
02584       fax->tech->cli_show_stats(a->fd);
02585    }
02586    AST_RWLIST_UNLOCK(&faxmodules);
02587    ast_cli(a->fd, "\n\n");
02588 
02589    return CLI_SUCCESS;
02590 }
02591 
02592 /*! \brief display fax sessions */
02593 static char *cli_fax_show_sessions(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02594 {
02595    struct ast_fax_session *s;
02596    struct ao2_iterator i;
02597    int session_count;
02598    char *filenames;
02599 
02600    switch (cmd) {
02601    case CLI_INIT:
02602       e->command = "fax show sessions";
02603       e->usage =
02604          "Usage: fax show sessions\n"
02605          "       Shows the current FAX sessions\n";
02606       return NULL;
02607    case CLI_GENERATE:
02608       return NULL;
02609    }
02610 
02611    ast_cli(a->fd, "\nCurrent FAX Sessions:\n\n");
02612    ast_cli(a->fd, "%-20.20s %-10.10s %-10.10s %-5.5s %-10.10s %-15.15s %-30.30s\n",
02613       "Channel", "Tech", "FAXID", "Type", "Operation", "State", "File(s)");
02614    i = ao2_iterator_init(faxregistry.container, 0);
02615    while ((s = ao2_iterator_next(&i))) {
02616       ao2_lock(s);
02617 
02618       if (!(filenames = generate_filenames_string(s->details, "", ", "))) {
02619          ast_log(LOG_ERROR, "Error printing filenames for 'fax show sessions' command\n");
02620          ao2_unlock(s);
02621          ao2_ref(s, -1);
02622          ao2_iterator_destroy(&i);
02623          return CLI_FAILURE;
02624       }
02625 
02626       ast_cli(a->fd, "%-20.20s %-10.10s %-10u %-5.5s %-10.10s %-15.15s %-30s\n",
02627          s->channame, s->tech->type, s->id,
02628          (s->details->caps & AST_FAX_TECH_AUDIO) ? "G.711" : "T.38",
02629          (s->details->caps & AST_FAX_TECH_SEND) ? "send" : "receive",
02630          ast_fax_state_to_str(s->state), filenames);
02631 
02632       ast_free(filenames);
02633       ao2_unlock(s);
02634       ao2_ref(s, -1);
02635    }
02636    ao2_iterator_destroy(&i);
02637    session_count = ao2_container_count(faxregistry.container);
02638    ast_cli(a->fd, "\n%d FAX sessions\n\n", session_count);
02639 
02640    return CLI_SUCCESS;
02641 }
02642 
02643 static struct ast_cli_entry fax_cli[] = {
02644    AST_CLI_DEFINE(cli_fax_show_version, "Show versions of FAX For Asterisk components"),
02645    AST_CLI_DEFINE(cli_fax_set_debug, "Enable/Disable FAX debugging on new FAX sessions"),
02646    AST_CLI_DEFINE(cli_fax_show_capabilities, "Show the capabilities of the registered FAX technology modules"),
02647    AST_CLI_DEFINE(cli_fax_show_settings, "Show the global settings and defaults of both the FAX core and technology modules"),
02648    AST_CLI_DEFINE(cli_fax_show_session, "Show the status of the named FAX sessions"),
02649    AST_CLI_DEFINE(cli_fax_show_sessions, "Show the current FAX sessions"),
02650    AST_CLI_DEFINE(cli_fax_show_stats, "Summarize FAX session history"),
02651 };
02652 
02653 static void set_general_options(const struct fax_options *options)
02654 {
02655    ast_rwlock_wrlock(&options_lock);
02656    general_options = *options;
02657    ast_rwlock_unlock(&options_lock);
02658 }
02659 
02660 static void get_general_options(struct fax_options *options)
02661 {
02662    ast_rwlock_rdlock(&options_lock);
02663    *options = general_options;
02664    ast_rwlock_unlock(&options_lock);
02665 }
02666 
02667 /*! \brief configure res_fax */
02668 static int set_config(int reload)
02669 {
02670    struct ast_config *cfg;
02671    struct ast_variable *v;
02672    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
02673    char modems[128] = "";
02674    struct fax_options options;
02675    int res = 0;
02676 
02677    options = default_options;
02678 
02679    /* When we're not reloading, we have to be certain to set the general options
02680     * to the defaults in case config loading goes wrong at some point. On a reload,
02681     * the general options need to stay the same as what they were prior to the
02682     * reload rather than being reset to the defaults.
02683     */
02684    if (!reload) {
02685       set_general_options(&options);
02686    }
02687 
02688    /* read configuration */
02689    if (!(cfg = ast_config_load2(config, "res_fax", config_flags))) {
02690       ast_log(LOG_NOTICE, "Configuration file '%s' not found, %s options.\n",
02691             config, reload ? "not changing" : "using default");
02692       return 0;
02693    }
02694 
02695    if (cfg == CONFIG_STATUS_FILEINVALID) {
02696       ast_log(LOG_NOTICE, "Configuration file '%s' is invalid, %s options.\n",
02697             config, reload ? "not changing" : "using default");
02698       return 0;
02699    }
02700 
02701    if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
02702       return 0;
02703    }
02704 
02705    if (reload) {
02706       options = default_options;
02707    }
02708 
02709    /* create configuration */
02710    for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
02711       int rate;
02712 
02713       if (!strcasecmp(v->name, "minrate")) {
02714          ast_debug(3, "reading minrate '%s' from configuration file\n", v->value);
02715          if ((rate = fax_rate_str_to_int(v->value)) == 0) {
02716             res = -1;
02717             goto end;
02718          }
02719          options.minrate = rate;
02720       } else if (!strcasecmp(v->name, "maxrate")) {
02721          ast_debug(3, "reading maxrate '%s' from configuration file\n", v->value);
02722          if ((rate = fax_rate_str_to_int(v->value)) == 0) {
02723             res = -1;
02724             goto end;
02725          }
02726          options.maxrate = rate;
02727       } else if (!strcasecmp(v->name, "statusevents")) {
02728          ast_debug(3, "reading statusevents '%s' from configuration file\n", v->value);
02729          options.statusevents = ast_true(v->value);
02730       } else if (!strcasecmp(v->name, "ecm")) {
02731          ast_debug(3, "reading ecm '%s' from configuration file\n", v->value);
02732          options.ecm = ast_true(v->value);
02733       } else if ((!strcasecmp(v->name, "modem")) || (!strcasecmp(v->name, "modems"))) {
02734          options.modems = 0;
02735          update_modem_bits(&options.modems, v->value);
02736       }
02737    }
02738 
02739    if (options.maxrate < options.minrate) {
02740       ast_log(LOG_ERROR, "maxrate %u is less than minrate %u\n", options.maxrate, options.minrate);
02741       res = -1;
02742       goto end;
02743    }
02744 
02745    if (options.minrate == 2400 && (options.modems & AST_FAX_MODEM_V27) && !(options.modems & (AST_FAX_MODEM_V34))) {
02746       ast_fax_modem_to_str(options.modems, modems, sizeof(modems));
02747       ast_log(LOG_WARNING, "'modems' setting '%s' is no longer accepted with 'minrate' setting %u\n", modems, options.minrate);
02748       ast_log(LOG_WARNING, "'minrate' has been reset to 4800, please update res_fax.conf.\n");
02749       options.minrate = 4800;
02750    }
02751 
02752    if (check_modem_rate(options.modems, options.minrate)) {
02753       ast_fax_modem_to_str(options.modems, modems, sizeof(modems));
02754       ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %u\n", modems, options.minrate);
02755       res = -1;
02756       goto end;
02757    }
02758 
02759    if (check_modem_rate(options.modems, options.maxrate)) {
02760       ast_fax_modem_to_str(options.modems, modems, sizeof(modems));
02761       ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %u\n", modems, options.maxrate);
02762       res = -1;
02763       goto end;
02764    }
02765 
02766    set_general_options(&options);
02767 
02768 end:
02769    ast_config_destroy(cfg);
02770    return res;
02771 }
02772 
02773 /*! \brief FAXOPT read function returns the contents of a FAX option */
02774 static int acf_faxopt_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
02775 {
02776    struct ast_fax_session_details *details = find_details(chan);
02777    int res = 0;
02778    char *filenames;
02779 
02780    if (!details) {
02781       ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s) because it has never been written.\n", chan->name, data);
02782       return -1;
02783    }
02784    if (!strcasecmp(data, "ecm")) {
02785       ast_copy_string(buf, details->option.ecm ? "yes" : "no", len);
02786    } else if (!strcasecmp(data, "error")) {
02787       ast_copy_string(buf, details->error, len);
02788    } else if (!strcasecmp(data, "filename")) {
02789       if (AST_LIST_EMPTY(&details->documents)) {
02790          ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s) because it has never been written.\n", chan->name, data);
02791          res = -1;
02792       } else {
02793          ast_copy_string(buf, AST_LIST_FIRST(&details->documents)->filename, len);
02794       }
02795    } else if (!strcasecmp(data, "filenames")) {
02796       if (AST_LIST_EMPTY(&details->documents)) {
02797          ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s) because it has never been written.\n", chan->name, data);
02798          res = -1;
02799       } else if ((filenames = generate_filenames_string(details, "", ","))) {
02800          ast_copy_string(buf, filenames, len);
02801          ast_free(filenames);
02802       } else {
02803          ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s), there was an error generating the filenames list.\n", chan->name, data);
02804          res = -1;
02805       }
02806    } else if (!strcasecmp(data, "headerinfo")) {
02807       ast_copy_string(buf, details->headerinfo, len);
02808    } else if (!strcasecmp(data, "localstationid")) {
02809       ast_copy_string(buf, details->localstationid, len);
02810    } else if (!strcasecmp(data, "maxrate")) {
02811       snprintf(buf, len, "%u", details->maxrate);
02812    } else if (!strcasecmp(data, "minrate")) {
02813       snprintf(buf, len, "%u", details->minrate);
02814    } else if (!strcasecmp(data, "pages")) {
02815       snprintf(buf, len, "%u", details->pages_transferred);
02816    } else if (!strcasecmp(data, "rate")) {
02817       ast_copy_string(buf, details->transfer_rate, len);
02818    } else if (!strcasecmp(data, "remotestationid")) {
02819       ast_copy_string(buf, details->remotestationid, len);
02820    } else if (!strcasecmp(data, "resolution")) {
02821       ast_copy_string(buf, details->resolution, len);
02822    } else if (!strcasecmp(data, "sessionid")) {
02823       snprintf(buf, len, "%u", details->id);
02824    } else if (!strcasecmp(data, "status")) {
02825       ast_copy_string(buf, details->result, len);
02826    } else if (!strcasecmp(data, "statusstr")) {
02827       ast_copy_string(buf, details->resultstr, len);
02828    } else if ((!strcasecmp(data, "modem")) || (!strcasecmp(data, "modems"))) {
02829       ast_fax_modem_to_str(details->modems, buf, len);
02830    } else {
02831       ast_log(LOG_WARNING, "channel '%s' can't read FAXOPT(%s) because it is unhandled!\n", chan->name, data);
02832       res = -1;
02833    }
02834    ao2_ref(details, -1);
02835 
02836    return res;
02837 }
02838 
02839 /*! \brief FAXOPT write function modifies the contents of a FAX option */
02840 static int acf_faxopt_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
02841 {
02842    int res = 0;
02843    struct ast_fax_session_details *details;
02844 
02845    if (!(details = find_or_create_details(chan))) {
02846       ast_log(LOG_WARNING, "channel '%s' can't set FAXOPT(%s) to '%s' because it failed to create a datastore.\n", chan->name, data, value);
02847       return -1;
02848    }
02849    ast_debug(3, "channel '%s' setting FAXOPT(%s) to '%s'\n", chan->name, data, value);
02850 
02851    if (!strcasecmp(data, "ecm")) {
02852       const char *val = ast_skip_blanks(value);
02853       if (ast_true(val)) {
02854          details->option.ecm = AST_FAX_OPTFLAG_TRUE;
02855       } else if (ast_false(val)) {
02856          details->option.ecm = AST_FAX_OPTFLAG_FALSE;
02857       } else {
02858          ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(ecm).\n", value);
02859       }
02860    } else if (!strcasecmp(data, "headerinfo")) {
02861       ast_string_field_set(details, headerinfo, value);
02862    } else if (!strcasecmp(data, "localstationid")) {
02863       ast_string_field_set(details, localstationid, value);
02864    } else if (!strcasecmp(data, "maxrate")) {
02865       details->maxrate = fax_rate_str_to_int(value);
02866       if (!details->maxrate) {
02867          details->maxrate = ast_fax_maxrate();
02868       }
02869    } else if (!strcasecmp(data, "minrate")) {
02870       details->minrate = fax_rate_str_to_int(value);
02871       if (!details->minrate) {
02872          details->minrate = ast_fax_minrate();
02873       }
02874    } else if ((!strcasecmp(data, "modem")) || (!strcasecmp(data, "modems"))) {
02875       update_modem_bits(&details->modems, value);
02876    } else {
02877       ast_log(LOG_WARNING, "channel '%s' set FAXOPT(%s) to '%s' is unhandled!\n", chan->name, data, value);
02878       res = -1;
02879    }
02880 
02881    ao2_ref(details, -1);
02882 
02883    return res;
02884 }
02885 
02886 /*! \brief FAXOPT dialplan function */
02887 struct ast_custom_function acf_faxopt = {
02888    .name = "FAXOPT",
02889    .read = acf_faxopt_read,
02890    .write = acf_faxopt_write,
02891 };
02892 
02893 /*! \brief unload res_fax */
02894 static int unload_module(void)
02895 {
02896    ast_cli_unregister_multiple(fax_cli, ARRAY_LEN(fax_cli));
02897    
02898    if (ast_custom_function_unregister(&acf_faxopt) < 0) {
02899       ast_log(LOG_WARNING, "failed to unregister function '%s'\n", acf_faxopt.name);
02900    }
02901 
02902    if (ast_unregister_application(app_sendfax) < 0) {
02903       ast_log(LOG_WARNING, "failed to unregister '%s'\n", app_sendfax);
02904    }
02905 
02906    if (ast_unregister_application(app_receivefax) < 0) {
02907       ast_log(LOG_WARNING, "failed to unregister '%s'\n", app_receivefax);
02908    }
02909 
02910    if (fax_logger_level != -1) {
02911       ast_logger_unregister_level("FAX");
02912    }
02913 
02914    ao2_ref(faxregistry.container, -1);
02915 
02916    return 0;
02917 }
02918 
02919 /*! \brief load res_fax */
02920 static int load_module(void)
02921 {
02922    int res;
02923 
02924    /* initialize the registry */
02925    faxregistry.active_sessions = 0;
02926    faxregistry.reserved_sessions = 0;
02927    if (!(faxregistry.container = ao2_container_alloc(FAX_MAXBUCKETS, session_hash_cb, session_cmp_cb))) {
02928       return AST_MODULE_LOAD_DECLINE;
02929    }
02930    
02931    if (set_config(0) < 0) {
02932       ast_log(LOG_ERROR, "failed to load configuration file '%s'\n", config);
02933       ao2_ref(faxregistry.container, -1);
02934       return AST_MODULE_LOAD_DECLINE;
02935    }
02936 
02937    /* register CLI operations and applications */
02938    if (ast_register_application_xml(app_sendfax, sendfax_exec) < 0) {
02939       ast_log(LOG_WARNING, "failed to register '%s'.\n", app_sendfax);
02940       ao2_ref(faxregistry.container, -1);
02941       return AST_MODULE_LOAD_DECLINE;
02942    }
02943    if (ast_register_application_xml(app_receivefax, receivefax_exec) < 0) {
02944       ast_log(LOG_WARNING, "failed to register '%s'.\n", app_receivefax);
02945       ast_unregister_application(app_sendfax);
02946       ao2_ref(faxregistry.container, -1);
02947       return AST_MODULE_LOAD_DECLINE;
02948    }
02949    ast_cli_register_multiple(fax_cli, ARRAY_LEN(fax_cli));
02950    res = ast_custom_function_register(&acf_faxopt);   
02951    fax_logger_level = ast_logger_register_level("FAX");
02952 
02953    return res;
02954 }
02955 
02956 static int reload_module(void)
02957 {
02958    set_config(1);
02959    return 0;
02960 }
02961 
02962 
02963 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "Generic FAX Applications",
02964       .load = load_module,
02965       .unload = unload_module,
02966       .reload = reload_module,
02967       .load_pri = AST_MODPRI_APP_DEPEND,
02968           );

Generated on 17 Aug 2018 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1