res_fax.c File Reference

Generic FAX Resource for FAX technology resource modules. More...

#include "asterisk.h"
#include "asterisk/io.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/app.h"
#include "asterisk/lock.h"
#include "asterisk/options.h"
#include "asterisk/strings.h"
#include "asterisk/cli.h"
#include "asterisk/utils.h"
#include "asterisk/config.h"
#include "asterisk/astobj2.h"
#include "asterisk/res_fax.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/dsp.h"
#include "asterisk/indications.h"
#include "asterisk/ast_version.h"
#include "asterisk/translate.h"
#include "asterisk/stasis.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/smoother.h"
#include "asterisk/format_cache.h"

Include dependency graph for res_fax.c:

Go to the source code of this file.

Data Structures

struct  ast_fax_debug_info
struct  debug_info_history
struct  fax_detect
 used for fax detect framehook More...
struct  fax_gateway
 used for gateway framehook More...
struct  fax_module
 registered FAX technology modules are put into this list More...
struct  fax_options
struct  faxmodules

Defines

#define FAX_DETECT_MODE_BOTH   (FAX_DETECT_MODE_CNG | FAX_DETECT_MODE_T38)
#define FAX_DETECT_MODE_CNG   (1 << 0)
 FAX Detect flags.
#define FAX_DETECT_MODE_T38   (1 << 1)
#define FAX_GATEWAY_TIMEOUT   RES_FAX_TIMEOUT
#define FAX_MAXBUCKETS   10
 maximum buckets for res_fax ao2 containers
#define GENERIC_FAX_EXEC_ERROR(fax, chan, errorstr, reason)
#define GENERIC_FAX_EXEC_ERROR_QUIET(fax, chan, errorstr, reason)
#define GENERIC_FAX_EXEC_SET_VARS(fax, chan, errorstr, reason)
#define RES_FAX_MAXRATE   14400
#define RES_FAX_MINRATE   4800
#define RES_FAX_MODEM   (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V27 | AST_FAX_MODEM_V29)
#define RES_FAX_STATUSEVENTS   0
#define RES_FAX_T38TIMEOUT   5000
#define RES_FAX_TIMEOUT   10000

Enumerations

enum  {
  OPT_CALLEDMODE = (1 << 0), OPT_CALLERMODE = (1 << 1), OPT_DEBUG = (1 << 2), OPT_STATUS = (1 << 3),
  OPT_ALLOWAUDIO = (1 << 5), OPT_REQUEST_T38 = (1 << 6), OPT_FORCE_AUDIO = (1 << 7)
}

Functions

static void __fini_faxmodules (void)
static void __init_faxmodules (void)
static void __reg_module (void)
static void __unreg_module (void)
static int acf_faxopt_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 FAXOPT read function returns the contents of a FAX option.
static int acf_faxopt_write (struct ast_channel *chan, const char *cmd, char *data, const char *value)
 FAXOPT write function modifies the contents of a FAX option.
static char * ast_fax_caps_to_str (enum ast_fax_capabilities caps, char *buf, size_t bufsize)
void ast_fax_log (int level, const char *file, const int line, const char *function, const char *msg)
 Log message at FAX or recommended level.
unsigned int ast_fax_maxrate (void)
 get the maxiumum supported fax rate
unsigned int ast_fax_minrate (void)
 get the minimum supported fax rate
static int ast_fax_modem_to_str (enum ast_fax_modems bits, char *tbuf, size_t bufsize)
const char * ast_fax_session_operation_str (struct ast_fax_session *s)
 get string representation of a FAX session's operation
const char * ast_fax_state_to_str (enum ast_fax_state state)
 convert a ast_fax_state to a string
int ast_fax_tech_register (struct ast_fax_tech *tech)
 register a FAX technology module
void ast_fax_tech_unregister (struct ast_fax_tech *tech)
 unregister a FAX technology module
static int check_modem_rate (enum ast_fax_modems modems, unsigned int rate)
static char * cli_fax_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 enable FAX debugging
static char * cli_fax_show_capabilities (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 display registered FAX capabilities
static char * cli_fax_show_session (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 display details of a specified fax session
static char * cli_fax_show_sessions (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 display fax sessions
static char * cli_fax_show_settings (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 display global defaults and settings
static char * cli_fax_show_stats (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 display fax stats
static char * cli_fax_show_version (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static void debug_check_frame_for_silence (struct ast_fax_session *s, unsigned int c2s, struct ast_frame *frame)
static void destroy_callback (void *data)
static void destroy_faxdetect (void *data)
 destroy a FAX detect structure
static void destroy_gateway (void *data)
 destroy a FAX gateway session structure
static void destroy_session (void *session)
 destroy a FAX session structure
static void destroy_session_details (void *details)
 destroy a FAX session details structure
static void destroy_v21_sessions (struct fax_gateway *gateway)
 destroy the v21 detection parts of a fax gateway session
static int disable_t38 (struct ast_channel *chan)
static int fax_detect_attach (struct ast_channel *chan, int timeout, int flags)
 Attach a faxdetect framehook object to a channel.
static struct ast_framefax_detect_framehook (struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data)
 Fax Detect Framehook.
static void fax_detect_framehook_destroy (void *data)
 Deref the faxdetect data structure when the faxdetect framehook is detached.
static struct fax_detectfax_detect_new (struct ast_channel *chan, int timeout, int flags)
 Create a new fax detect object.
static int fax_gateway_attach (struct ast_channel *chan, struct ast_fax_session_details *details)
 Attach a gateway framehook object to a channel.
static struct ast_framefax_gateway_detect_t38 (struct fax_gateway *gateway, struct ast_channel *chan, struct ast_channel *peer, struct ast_channel *active, struct ast_frame *f)
 T38 Gateway Negotiate t38 parameters.
static struct ast_framefax_gateway_detect_v21 (struct fax_gateway *gateway, struct ast_channel *chan, struct ast_channel *peer, struct ast_channel *active, struct ast_frame *f)
static struct ast_framefax_gateway_framehook (struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data)
 T.30<->T.38 gateway framehook.
static void fax_gateway_framehook_destroy (void *data)
 Destroy the gateway data structure when the framehook is detached.
static int fax_gateway_indicate_t38 (struct ast_channel *chan, struct ast_channel *active, struct ast_control_t38_parameters *control_params)
static struct fax_gatewayfax_gateway_new (struct ast_channel *chan, struct ast_fax_session_details *details)
 Create a new fax gateway object.
static struct ast_framefax_gateway_request_t38 (struct fax_gateway *gateway, struct ast_channel *chan, struct ast_frame *f)
static int fax_gateway_start (struct fax_gateway *gateway, struct ast_fax_session_details *details, struct ast_channel *chan)
 Create a fax session and start T.30<->T.38 gateway mode.
static unsigned int fax_rate_str_to_int (const char *ratestr)
 convert a rate string to a rate
static struct ast_fax_sessionfax_session_new (struct ast_fax_session_details *details, struct ast_channel *chan, struct ast_fax_session *reserved, struct ast_fax_tech_token *token)
 create a FAX session
static void fax_session_release (struct ast_fax_session *s, struct ast_fax_tech_token *token)
 Release a session token.
static struct ast_fax_sessionfax_session_reserve (struct ast_fax_session_details *details, struct ast_fax_tech_token **token)
 Reserve a fax session.
static char * fax_session_tab_complete (struct ast_cli_args *a)
 fax session tab completion
static const char * fax_session_type (struct ast_fax_session *s)
static struct
ast_fax_session_details
find_details (struct ast_channel *chan)
 returns a reference counted pointer to a fax datastore, if it exists
static struct
ast_fax_session_details
find_or_create_details (struct ast_channel *chan)
 returns a reference counted details structure from the channel's fax datastore. If the datastore does not exist it will be created
static void fixup_callback (void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
 Copies fax detection and gateway framehooks during masquerades.
static struct ast_jsongenerate_filenames_json (struct ast_fax_session_details *details)
static char * generate_filenames_string (struct ast_fax_session_details *details, char *prefix, char *separator)
 Generate a string of filenames using the given prefix and separator.
static int generic_fax_exec (struct ast_channel *chan, struct ast_fax_session_details *details, struct ast_fax_session *reserved, struct ast_fax_tech_token *token)
 this is the generic FAX session handling function
static void get_general_options (struct fax_options *options)
static int load_module (void)
 Load the module.
static int manager_fax_session (struct mansession *s, const struct message *m)
static int manager_fax_sessions (struct mansession *s, const struct message *m)
static int manager_fax_sessions_entry (struct mansession *s, struct ast_fax_session *session, const char *id_text)
static int manager_fax_stats (struct mansession *s, const struct message *m)
static int receivefax_exec (struct ast_channel *chan, const char *data)
 initiate a receive FAX session
static int receivefax_t38_init (struct ast_channel *chan, struct ast_fax_session_details *details)
static int reload_module (void)
static int report_fax_status (struct ast_channel *chan, struct ast_fax_session_details *details, const char *status)
 send a FAX status manager event
static int report_receive_fax_status (struct ast_channel *chan, const char *filename)
 Report on the final state of a receive fax operation.
static int report_send_fax_status (struct ast_channel *chan, struct ast_fax_session_details *details)
 Report on the status of a completed fax send attempt.
static int sendfax_exec (struct ast_channel *chan, const char *data)
 initiate a send FAX session
static int sendfax_t38_init (struct ast_channel *chan, struct ast_fax_session_details *details)
static int session_cmp_cb (void *obj, void *arg, int flags)
 compare callback for ao2
static struct
ast_fax_session_details
session_details_new (void)
 create a FAX session details structure
static int session_hash_cb (const void *obj, const int flags)
 hash callback for ao2
static void set_channel_variables (struct ast_channel *chan, struct ast_fax_session_details *details)
 Set fax related channel variables.
static int set_config (int reload)
 configure res_fax
static int set_fax_t38_caps (struct ast_channel *chan, struct ast_fax_session_details *details)
static void set_general_options (const struct fax_options *options)
static int set_t38timeout (const char *value, unsigned int *t38timeout)
static void t38_parameters_ast_to_fax (struct ast_fax_t38_parameters *dst, const struct ast_control_t38_parameters *src)
static void t38_parameters_fax_to_ast (struct ast_control_t38_parameters *dst, const struct ast_fax_t38_parameters *src)
static int unload_module (void)
 unload res_fax
static int update_modem_bits (enum ast_fax_modems *bits, const char *value)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "Generic FAX Applications" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_APP_DEPEND, }
struct ast_custom_function acf_faxopt
 FAXOPT dialplan function.
static const char app_receivefax [] = "ReceiveFAX"
static const char app_sendfax [] = "SendFAX"
static struct ast_module_infoast_module_info = &__mod_info
static const char * config = "res_fax.conf"
static struct fax_options default_options
static struct ast_cli_entry fax_cli []
static struct ast_datastore_info fax_datastore
static struct ast_app_option fax_exec_options [128] = { [ 'a' ] = { .flag = OPT_CALLEDMODE }, [ 'c' ] = { .flag = OPT_CALLERMODE }, [ 'd' ] = { .flag = OPT_DEBUG }, [ 'f' ] = { .flag = OPT_ALLOWAUDIO }, [ 'F' ] = { .flag = OPT_FORCE_AUDIO }, [ 's' ] = { .flag = OPT_STATUS }, [ 'z' ] = { .flag = OPT_REQUEST_T38 }, }
static int fax_logger_level = -1
struct {
   int   active_sessions
   struct ao2_container *   container
   int   fax_complete
   int   fax_failures
   int   fax_rx_attempts
   int   fax_tx_attempts
   int   nextsessionname
   int   reserved_sessions
faxregistry
 The faxregistry is used to manage information and statistics for all FAX sessions.
static struct fax_options general_options
static int global_fax_debug = 0
static ast_rwlock_t options_lock = { {0} , NULL, 1 }
static struct
ast_control_t38_parameters 
our_t38_parameters


Detailed Description

Generic FAX Resource for FAX technology resource modules.

Author:
Dwayne M. Hubbard <dhubbard@digium.com>

Kevin P. Fleming <kpfleming@digium.com>

Matthew Nicholson <mnicholson@digium.com>

Gregory H. Nietsky <gregory@distrotech.co.za>

A generic FAX resource module that provides SendFAX and ReceiveFAX applications. This module requires FAX technology modules, like res_fax_spandsp, to register with it so it can use the technology modules to perform the actual FAX transmissions.

Definition in file res_fax.c.


Define Documentation

#define FAX_DETECT_MODE_BOTH   (FAX_DETECT_MODE_CNG | FAX_DETECT_MODE_T38)

Definition at line 486 of file res_fax.c.

Referenced by acf_faxopt_write().

#define FAX_DETECT_MODE_CNG   (1 << 0)

FAX Detect flags.

Definition at line 484 of file res_fax.c.

Referenced by acf_faxopt_write(), and fax_detect_new().

#define FAX_DETECT_MODE_T38   (1 << 1)

Definition at line 485 of file res_fax.c.

Referenced by acf_faxopt_write(), and fax_detect_framehook().

#define FAX_GATEWAY_TIMEOUT   RES_FAX_TIMEOUT

Definition at line 494 of file res_fax.c.

Referenced by fax_gateway_detect_t38(), and fax_gateway_request_t38().

#define FAX_MAXBUCKETS   10

maximum buckets for res_fax ao2 containers

Definition at line 491 of file res_fax.c.

Referenced by load_module().

#define GENERIC_FAX_EXEC_ERROR ( fax,
chan,
errorstr,
reason   ) 

Value:

do {  \
      ast_log(LOG_ERROR, "channel '%s' FAX session '%u' failure, reason: '%s' (%s)\n", ast_channel_name(chan), fax->id, reason, errorstr); \
      GENERIC_FAX_EXEC_ERROR_QUIET(fax, chan, errorstr, reason); \
   } while (0)

Definition at line 1478 of file res_fax.c.

Referenced by generic_fax_exec().

#define GENERIC_FAX_EXEC_ERROR_QUIET ( fax,
chan,
errorstr,
reason   ) 

Value:

do {  \
      GENERIC_FAX_EXEC_SET_VARS(fax, chan, errorstr, reason); \
   } while (0)

Definition at line 1473 of file res_fax.c.

#define GENERIC_FAX_EXEC_SET_VARS ( fax,
chan,
errorstr,
reason   ) 

Definition at line 1462 of file res_fax.c.

Referenced by generic_fax_exec().

#define RES_FAX_MAXRATE   14400

Definition at line 524 of file res_fax.c.

#define RES_FAX_MINRATE   4800

Definition at line 523 of file res_fax.c.

#define RES_FAX_MODEM   (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V27 | AST_FAX_MODEM_V29)

Definition at line 526 of file res_fax.c.

#define RES_FAX_STATUSEVENTS   0

Definition at line 525 of file res_fax.c.

#define RES_FAX_T38TIMEOUT   5000

Definition at line 527 of file res_fax.c.

#define RES_FAX_TIMEOUT   10000

Definition at line 493 of file res_fax.c.

Referenced by generic_fax_exec().


Enumeration Type Documentation

anonymous enum

Enumerator:
OPT_CALLEDMODE 
OPT_CALLERMODE 
OPT_DEBUG 
OPT_STATUS 
OPT_ALLOWAUDIO 
OPT_REQUEST_T38 
OPT_FORCE_AUDIO 

Definition at line 558 of file res_fax.c.

00558      {
00559    OPT_CALLEDMODE  = (1 << 0),
00560    OPT_CALLERMODE  = (1 << 1),
00561    OPT_DEBUG       = (1 << 2),
00562    OPT_STATUS      = (1 << 3),
00563    OPT_ALLOWAUDIO  = (1 << 5),
00564    OPT_REQUEST_T38 = (1 << 6),
00565    OPT_FORCE_AUDIO = (1 << 7),
00566 };


Function Documentation

static void __fini_faxmodules ( void   )  [static]

Definition at line 521 of file res_fax.c.

00529 {

static void __init_faxmodules ( void   )  [static]

Definition at line 521 of file res_fax.c.

00529 {

static void __reg_module ( void   )  [static]

Definition at line 4692 of file res_fax.c.

static void __unreg_module ( void   )  [static]

Definition at line 4692 of file res_fax.c.

static int acf_faxopt_read ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
) [static]

FAXOPT read function returns the contents of a FAX option.

Definition at line 4363 of file res_fax.c.

References ao2_ref, ast_channel_name(), ast_copy_string(), ast_fax_modem_to_str(), ast_free, AST_LIST_EMPTY, AST_LIST_FIRST, ast_log, ast_fax_session_details::documents, ast_fax_session_details::ecm, ast_fax_session_details::error, ast_fax_session_details::faxdetect_id, find_details(), ast_fax_session_details::gateway_id, generate_filenames_string(), ast_fax_session_details::headerinfo, ast_fax_session_details::id, ast_fax_session_details::localstationid, LOG_ERROR, LOG_WARNING, ast_fax_session_details::maxrate, ast_fax_session_details::minrate, ast_fax_session_details::modems, ast_fax_session_details::option, ast_fax_session_details::pages_transferred, ast_fax_session_details::remotestationid, ast_fax_session_details::resolution, ast_fax_session_details::result, ast_fax_session_details::resultstr, ast_fax_session_details::t38timeout, and ast_fax_session_details::transfer_rate.

04364 {
04365    struct ast_fax_session_details *details = find_details(chan);
04366    int res = 0;
04367    char *filenames;
04368 
04369    if (!details) {
04370       ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s) because it has never been written.\n", ast_channel_name(chan), data);
04371       return -1;
04372    }
04373    if (!strcasecmp(data, "ecm")) {
04374       ast_copy_string(buf, details->option.ecm ? "yes" : "no", len);
04375    } else if (!strcasecmp(data, "t38gateway") || !strcasecmp(data, "gateway") ||
04376          !strcasecmp(data, "t38_gateway") || !strcasecmp(data, "faxgateway")) {
04377       ast_copy_string(buf, details->gateway_id != -1 ? "yes" : "no", len);
04378    } else if (!strcasecmp(data, "faxdetect")) {
04379       ast_copy_string(buf, details->faxdetect_id != -1 ? "yes" : "no", len);
04380    } else if (!strcasecmp(data, "error")) {
04381       ast_copy_string(buf, details->error, len);
04382    } else if (!strcasecmp(data, "filename")) {
04383       if (AST_LIST_EMPTY(&details->documents)) {
04384          ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s) because it has never been written.\n", ast_channel_name(chan), data);
04385          res = -1;
04386       } else {
04387          ast_copy_string(buf, AST_LIST_FIRST(&details->documents)->filename, len);
04388       }
04389    } else if (!strcasecmp(data, "filenames")) {
04390       if (AST_LIST_EMPTY(&details->documents)) {
04391          ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s) because it has never been written.\n", ast_channel_name(chan), data);
04392          res = -1;
04393       } else if ((filenames = generate_filenames_string(details, "", ","))) {
04394          ast_copy_string(buf, filenames, len);
04395          ast_free(filenames);
04396       } else {
04397          ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s), there was an error generating the filenames list.\n", ast_channel_name(chan), data);
04398          res = -1;
04399       }
04400    } else if (!strcasecmp(data, "headerinfo")) {
04401       ast_copy_string(buf, details->headerinfo, len);
04402    } else if (!strcasecmp(data, "localstationid")) {
04403       ast_copy_string(buf, details->localstationid, len);
04404    } else if (!strcasecmp(data, "maxrate")) {
04405       snprintf(buf, len, "%u", details->maxrate);
04406    } else if (!strcasecmp(data, "minrate")) {
04407       snprintf(buf, len, "%u", details->minrate);
04408    } else if (!strcasecmp(data, "pages")) {
04409       snprintf(buf, len, "%u", details->pages_transferred);
04410    } else if (!strcasecmp(data, "rate")) {
04411       ast_copy_string(buf, details->transfer_rate, len);
04412    } else if (!strcasecmp(data, "remotestationid")) {
04413       ast_copy_string(buf, details->remotestationid, len);
04414    } else if (!strcasecmp(data, "resolution")) {
04415       ast_copy_string(buf, details->resolution, len);
04416    } else if (!strcasecmp(data, "sessionid")) {
04417       snprintf(buf, len, "%u", details->id);
04418    } else if (!strcasecmp(data, "status")) {
04419       ast_copy_string(buf, details->result, len);
04420    } else if (!strcasecmp(data, "statusstr")) {
04421       ast_copy_string(buf, details->resultstr, len);
04422    } else if ((!strcasecmp(data, "modem")) || (!strcasecmp(data, "modems"))) {
04423       ast_fax_modem_to_str(details->modems, buf, len);
04424    } else if (!strcasecmp(data, "t38timeout")) {
04425       snprintf(buf, len, "%u", details->t38timeout);
04426    } else {
04427       ast_log(LOG_WARNING, "channel '%s' can't read FAXOPT(%s) because it is unhandled!\n", ast_channel_name(chan), data);
04428       res = -1;
04429    }
04430    ao2_ref(details, -1);
04431 
04432    return res;
04433 }

static int acf_faxopt_write ( struct ast_channel chan,
const char *  cmd,
char *  data,
const char *  value 
) [static]

FAXOPT write function modifies the contents of a FAX option.

Definition at line 4436 of file res_fax.c.

References ao2_ref, ast_channel_name(), ast_debug, ast_false(), ast_fax_maxrate(), ast_fax_minrate(), AST_FAX_OPTFLAG_FALSE, AST_FAX_OPTFLAG_TRUE, ast_framehook_detach(), ast_log, ast_skip_blanks(), ast_string_field_set, ast_true(), ast_fax_session_details::ecm, fax_detect_attach(), FAX_DETECT_MODE_BOTH, FAX_DETECT_MODE_CNG, FAX_DETECT_MODE_T38, fax_gateway_attach(), fax_rate_str_to_int(), ast_fax_session_details::faxdetect_id, fdtimeout, find_or_create_details(), ast_fax_session_details::gateway_id, ast_fax_session_details::gateway_timeout, ast_fax_session_details::headerinfo, ast_fax_session_details::localstationid, LOG_ERROR, LOG_WARNING, ast_fax_session_details::maxrate, ast_fax_session_details::minrate, ast_fax_session_details::modems, ast_fax_session_details::option, set_t38timeout(), ast_fax_session_details::t38timeout, timeout, and update_modem_bits().

04437 {
04438    int res = 0;
04439    struct ast_fax_session_details *details;
04440 
04441    if (!(details = find_or_create_details(chan))) {
04442       ast_log(LOG_WARNING, "channel '%s' can't set FAXOPT(%s) to '%s' because it failed to create a datastore.\n", ast_channel_name(chan), data, value);
04443       return -1;
04444    }
04445    ast_debug(3, "channel '%s' setting FAXOPT(%s) to '%s'\n", ast_channel_name(chan), data, value);
04446 
04447    if (!strcasecmp(data, "ecm")) {
04448       const char *val = ast_skip_blanks(value);
04449       if (ast_true(val)) {
04450          details->option.ecm = AST_FAX_OPTFLAG_TRUE;
04451       } else if (ast_false(val)) {
04452          details->option.ecm = AST_FAX_OPTFLAG_FALSE;
04453       } else {
04454          ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(ecm).\n", value);
04455       }
04456    } else if (!strcasecmp(data, "t38gateway") || !strcasecmp(data, "gateway") ||
04457          !strcasecmp(data, "t38_gateway") || !strcasecmp(data, "faxgateway")) {
04458       const char *val = ast_skip_blanks(value);
04459       char *timeout = strchr(val, ',');
04460 
04461       if (timeout) {
04462          *timeout++ = '\0';
04463       }
04464 
04465       if (ast_true(val)) {
04466          if (details->gateway_id < 0) {
04467             details->gateway_timeout = 0;
04468             if (timeout) {
04469                unsigned int gwtimeout;
04470                if (sscanf(timeout, "%u", &gwtimeout) == 1) {
04471                   details->gateway_timeout = gwtimeout * 1000;
04472                } else {
04473                   ast_log(LOG_WARNING, "Unsupported timeout '%s' passed to FAXOPT(%s).\n", timeout, data);
04474                }
04475             }
04476 
04477             details->gateway_id = fax_gateway_attach(chan, details);
04478             if (details->gateway_id < 0) {
04479                ast_log(LOG_ERROR, "Error attaching T.38 gateway to channel %s.\n", ast_channel_name(chan));
04480                res = -1;
04481             } else {
04482                ast_debug(1, "Attached T.38 gateway to channel %s.\n", ast_channel_name(chan));
04483             }
04484          } else {
04485             ast_log(LOG_WARNING, "Attempt to attach a T.38 gateway on channel (%s) with gateway already running.\n", ast_channel_name(chan));
04486          }
04487       } else if (ast_false(val)) {
04488          ast_framehook_detach(chan, details->gateway_id);
04489          details->gateway_id = -1;
04490       } else {
04491          ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(%s).\n", value, data);
04492       }
04493    } else if (!strcasecmp(data, "faxdetect")) {
04494       const char *val = ast_skip_blanks(value);
04495       char *timeout = strchr(val, ',');
04496       unsigned int fdtimeout = 0;
04497       int flags;
04498       int faxdetect;
04499 
04500       if (timeout) {
04501          *timeout++ = '\0';
04502       }
04503 
04504       if (ast_true(val) || !strcasecmp(val, "t38") || !strcasecmp(val, "cng")) {
04505          if (details->faxdetect_id < 0) {
04506             if (timeout && (sscanf(timeout, "%u", &fdtimeout) == 1)) {
04507                if (fdtimeout > 0) {
04508                   fdtimeout = fdtimeout * 1000;
04509                } else {
04510                   ast_log(LOG_WARNING, "Timeout cannot be negative ignoring timeout\n");
04511                }
04512             }
04513 
04514             if (!strcasecmp(val, "t38")) {
04515                flags = FAX_DETECT_MODE_T38;
04516             } else if (!strcasecmp(val, "cng")) {
04517                flags = FAX_DETECT_MODE_CNG;
04518             } else {
04519                flags = FAX_DETECT_MODE_BOTH;
04520             }
04521 
04522             faxdetect = fax_detect_attach(chan, fdtimeout, flags);
04523             if (faxdetect < 0) {
04524                ast_log(LOG_ERROR, "Error attaching FAX detect to channel %s.\n", ast_channel_name(chan));
04525                res = -1;
04526             } else {
04527                ast_debug(1, "Attached FAX detect to channel %s.\n", ast_channel_name(chan));
04528             }
04529          } else {
04530             ast_log(LOG_WARNING, "Attempt to attach a FAX detect on channel (%s) with FAX detect already running.\n", ast_channel_name(chan));
04531          }
04532       } else if (ast_false(val)) {
04533          ast_framehook_detach(chan, details->faxdetect_id);
04534          details->faxdetect_id = -1;
04535       } else {
04536          ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(%s).\n", value, data);
04537       }
04538    } else if (!strcasecmp(data, "headerinfo")) {
04539       ast_string_field_set(details, headerinfo, value);
04540    } else if (!strcasecmp(data, "localstationid")) {
04541       ast_string_field_set(details, localstationid, value);
04542    } else if (!strcasecmp(data, "maxrate")) {
04543       details->maxrate = fax_rate_str_to_int(value);
04544       if (!details->maxrate) {
04545          details->maxrate = ast_fax_maxrate();
04546       }
04547    } else if (!strcasecmp(data, "minrate")) {
04548       details->minrate = fax_rate_str_to_int(value);
04549       if (!details->minrate) {
04550          details->minrate = ast_fax_minrate();
04551       }
04552    } else if (!strcasecmp(data, "t38timeout")) {
04553       if (set_t38timeout(value, &details->t38timeout)) {
04554          res = -1;
04555       }
04556    } else if ((!strcasecmp(data, "modem")) || (!strcasecmp(data, "modems"))) {
04557       update_modem_bits(&details->modems, value);
04558    } else {
04559       ast_log(LOG_WARNING, "channel '%s' set FAXOPT(%s) to '%s' is unhandled!\n", ast_channel_name(chan), data, value);
04560       res = -1;
04561    }
04562 
04563    ao2_ref(details, -1);
04564 
04565    return res;
04566 }

static char* ast_fax_caps_to_str ( enum ast_fax_capabilities  caps,
char *  buf,
size_t  bufsize 
) [static]

Definition at line 843 of file res_fax.c.

References ast_build_string(), AST_FAX_TECH_AUDIO, AST_FAX_TECH_GATEWAY, AST_FAX_TECH_MULTI_DOC, AST_FAX_TECH_RECEIVE, AST_FAX_TECH_SEND, AST_FAX_TECH_T38, AST_FAX_TECH_V21_DETECT, first, and out.

Referenced by fax_session_new(), and fax_session_reserve().

00844 {
00845    char *out = buf;
00846    size_t size = bufsize;
00847    int first = 1;
00848 
00849    if (caps & AST_FAX_TECH_SEND) {
00850       if (!first) {
00851          ast_build_string(&buf, &size, ",");
00852       }
00853       ast_build_string(&buf, &size, "SEND");
00854       first = 0;
00855    }
00856    if (caps & AST_FAX_TECH_RECEIVE) {
00857       if (!first) {
00858          ast_build_string(&buf, &size, ",");
00859       }
00860       ast_build_string(&buf, &size, "RECEIVE");
00861       first = 0;
00862    }
00863    if (caps & AST_FAX_TECH_AUDIO) {
00864       if (!first) {
00865          ast_build_string(&buf, &size, ",");
00866       }
00867       ast_build_string(&buf, &size, "AUDIO");
00868       first = 0;
00869    }
00870    if (caps & AST_FAX_TECH_T38) {
00871       if (!first) {
00872          ast_build_string(&buf, &size, ",");
00873       }
00874       ast_build_string(&buf, &size, "T38");
00875       first = 0;
00876    }
00877    if (caps & AST_FAX_TECH_MULTI_DOC) {
00878       if (!first) {
00879          ast_build_string(&buf, &size, ",");
00880       }
00881       ast_build_string(&buf, &size, "MULTI_DOC");
00882       first = 0;
00883    }
00884    if (caps & AST_FAX_TECH_GATEWAY) {
00885       if (!first) {
00886          ast_build_string(&buf, &size, ",");
00887       }
00888       ast_build_string(&buf, &size, "GATEWAY");
00889       first = 0;
00890    }
00891    if (caps & AST_FAX_TECH_V21_DETECT) {
00892       if (!first) {
00893          ast_build_string(&buf, &size, ",");
00894       }
00895       ast_build_string(&buf, &size, "V21");
00896       first = 0;
00897    }
00898 
00899    return out;
00900 }

void ast_fax_log ( int  level,
const char *  file,
const int  line,
const char *  function,
const char *  msg 
)

Log message at FAX or recommended level.

The first four parameters can be represented with Asterisk's LOG_* levels. In other words, this function may be called like

ast_fax_log(LOG_DEBUG, msg);

Definition at line 1043 of file res_fax.c.

References ast_log, and ast_log_dynamic_level.

Referenced by spandsp_log().

01044 {
01045    if (fax_logger_level != -1) {
01046       ast_log_dynamic_level(fax_logger_level, "%s", msg);
01047    } else {
01048       ast_log(level, file, line, function, "%s", msg);
01049    }
01050 }

unsigned int ast_fax_maxrate ( void   ) 

get the maxiumum supported fax rate

Definition at line 793 of file res_fax.c.

References get_general_options(), and fax_options::maxrate.

Referenced by acf_faxopt_write().

00794 {
00795    struct fax_options options;
00796    get_general_options(&options);
00797 
00798    return options.maxrate;
00799 }

unsigned int ast_fax_minrate ( void   ) 

get the minimum supported fax rate

Definition at line 801 of file res_fax.c.

References get_general_options(), and fax_options::minrate.

Referenced by acf_faxopt_write().

00802 {
00803    struct fax_options options;
00804    get_general_options(&options);
00805 
00806    return options.minrate;
00807 }

static int ast_fax_modem_to_str ( enum ast_fax_modems  bits,
char *  tbuf,
size_t  bufsize 
) [static]

Definition at line 902 of file res_fax.c.

References AST_FAX_MODEM_V17, AST_FAX_MODEM_V27, AST_FAX_MODEM_V29, and AST_FAX_MODEM_V34.

Referenced by acf_faxopt_read(), cli_fax_show_settings(), receivefax_exec(), sendfax_exec(), and set_config().

00903 {
00904    int count = 0;
00905 
00906    if (bits & AST_FAX_MODEM_V17) {
00907       strcat(tbuf, "V17");
00908       count++;
00909    }
00910    if (bits & AST_FAX_MODEM_V27) {
00911       if (count) {
00912          strcat(tbuf, ",");
00913       }
00914       strcat(tbuf, "V27");
00915       count++;
00916    }
00917    if (bits & AST_FAX_MODEM_V29) {
00918       if (count) {
00919          strcat(tbuf, ",");
00920       }
00921       strcat(tbuf, "V29");
00922       count++;
00923    }
00924    if (bits & AST_FAX_MODEM_V34) {
00925       if (count) {
00926          strcat(tbuf, ",");
00927       }
00928       strcat(tbuf, "V34");
00929       count++;
00930    }
00931 
00932    return 0;
00933 }

const char* ast_fax_session_operation_str ( struct ast_fax_session s  ) 

get string representation of a FAX session's operation

Definition at line 4091 of file res_fax.c.

References AST_FAX_TECH_GATEWAY, AST_FAX_TECH_RECEIVE, AST_FAX_TECH_SEND, AST_FAX_TECH_V21_DETECT, ast_fax_session_details::caps, and ast_fax_session::details.

Referenced by cli_fax_show_sessions(), manager_fax_sessions_entry(), and spandsp_manager_fax_session().

04092 {
04093    if (s->details->caps & AST_FAX_TECH_GATEWAY) {
04094       return "gateway";
04095    }
04096    if (s->details->caps & AST_FAX_TECH_SEND) {
04097       return "send";
04098    }
04099    if (s->details->caps & AST_FAX_TECH_RECEIVE) {
04100       return "receive";
04101    }
04102    if (s->details->caps & AST_FAX_TECH_V21_DETECT) {
04103       return "V.21";
04104    }
04105 
04106    return "none";
04107 }

const char* ast_fax_state_to_str ( enum ast_fax_state  state  ) 

convert a ast_fax_state to a string

convert an ast_fax_state to a string

Definition at line 1020 of file res_fax.c.

References AST_FAX_STATE_ACTIVE, AST_FAX_STATE_COMPLETE, AST_FAX_STATE_INACTIVE, AST_FAX_STATE_INITIALIZED, AST_FAX_STATE_OPEN, AST_FAX_STATE_RESERVED, AST_FAX_STATE_UNINITIALIZED, ast_log, and LOG_WARNING.

Referenced by cli_fax_show_sessions(), manager_fax_sessions_entry(), spandsp_fax_cli_show_session(), spandsp_fax_write(), and spandsp_manager_fax_session().

01021 {
01022    switch (state) {
01023    case AST_FAX_STATE_UNINITIALIZED:
01024       return "Uninitialized";
01025    case AST_FAX_STATE_INITIALIZED:
01026       return "Initialized";
01027    case AST_FAX_STATE_OPEN:
01028       return "Open";
01029    case AST_FAX_STATE_ACTIVE:
01030       return "Active";
01031    case AST_FAX_STATE_COMPLETE:
01032       return "Complete";
01033    case AST_FAX_STATE_RESERVED:
01034       return "Reserved";
01035    case AST_FAX_STATE_INACTIVE:
01036       return "Inactive";
01037    default:
01038       ast_log(LOG_WARNING, "unhandled FAX state: %u\n", state);
01039       return "Unknown";
01040    }
01041 }

int ast_fax_tech_register ( struct ast_fax_tech tech  ) 

register a FAX technology module

register a fax technology

Definition at line 979 of file res_fax.c.

References ast_calloc, ast_module_ref, AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, ast_fax_tech::description, fax_module::tech, and ast_fax_tech::type.

Referenced by load_module().

00980 {
00981    struct fax_module *fax;
00982 
00983    if (!(fax = ast_calloc(1, sizeof(*fax)))) {
00984       return -1;
00985    }
00986    fax->tech = tech;
00987    AST_RWLIST_WRLOCK(&faxmodules);
00988    AST_RWLIST_INSERT_TAIL(&faxmodules, fax, list);
00989    AST_RWLIST_UNLOCK(&faxmodules);
00990    ast_module_ref(ast_module_info->self);
00991 
00992    ast_verb(3, "Registered handler for '%s' (%s)\n", fax->tech->type, fax->tech->description);
00993 
00994    return 0;
00995 }

void ast_fax_tech_unregister ( struct ast_fax_tech tech  ) 

unregister a FAX technology module

unregister a fax technology

Definition at line 998 of file res_fax.c.

References ast_free, ast_module_unref, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, fax_module::tech, and ast_fax_tech::type.

Referenced by unload_module().

00999 {
01000    struct fax_module *fax;
01001 
01002    ast_verb(3, "Unregistering FAX module type '%s'\n", tech->type);
01003 
01004    AST_RWLIST_WRLOCK(&faxmodules);
01005    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&faxmodules, fax, list) {
01006       if (fax->tech != tech) {
01007          continue;
01008       }
01009       AST_RWLIST_REMOVE_CURRENT(list);
01010       ast_module_unref(ast_module_info->self);
01011       ast_free(fax);
01012       ast_verb(4, "Unregistered FAX module type '%s'\n", tech->type);
01013       break;
01014    }
01015    AST_RWLIST_TRAVERSE_SAFE_END;
01016    AST_RWLIST_UNLOCK(&faxmodules);
01017 }

static int check_modem_rate ( enum ast_fax_modems  modems,
unsigned int  rate 
) [static]

Definition at line 935 of file res_fax.c.

References AST_FAX_MODEM_V17, AST_FAX_MODEM_V27, AST_FAX_MODEM_V29, and AST_FAX_MODEM_V34.

Referenced by receivefax_exec(), sendfax_exec(), and set_config().

00936 {
00937    switch (rate) {
00938    case 2400:
00939       if (!(modems & (AST_FAX_MODEM_V34))) {
00940          return 1;
00941       }
00942       break;
00943    case 4800:
00944       if (!(modems & (AST_FAX_MODEM_V27 | AST_FAX_MODEM_V34))) {
00945          return 1;
00946       }
00947       break;
00948    case 7200:
00949       if (!(modems & (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V29 | AST_FAX_MODEM_V34))) {
00950          return 1;
00951       }
00952       break;
00953    case 9600:
00954       if (!(modems & (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V27 | AST_FAX_MODEM_V29 | AST_FAX_MODEM_V34))) {
00955          return 1;
00956       }
00957       break;
00958    case 12000:
00959    case 14400:
00960       if (!(modems & (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V34))) {
00961          return 1;
00962       }
00963       break;
00964    case 28800:
00965    case 33600:
00966       if (!(modems & AST_FAX_MODEM_V34)) {
00967          return 1;
00968       }
00969       break;
00970    default:
00971       /* this should never happen */
00972       return 1;
00973    }
00974 
00975    return 0;
00976 }

static char* cli_fax_set_debug ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

enable FAX debugging

Definition at line 3841 of file res_fax.c.

References ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, global_fax_debug, NULL, and ast_cli_entry::usage.

03842 {
03843    int flag;
03844    const char *what;
03845 
03846    switch (cmd) {
03847    case CLI_INIT:
03848       e->command = "fax set debug {on|off}";
03849       e->usage =
03850          "Usage: fax set debug { on | off }\n"
03851          "       Enable/Disable FAX debugging on new FAX sessions.  The basic FAX debugging will result in\n"
03852          "       additional events sent to manager sessions with 'call' class permissions.  When\n"
03853          "       verbosity is greater than '5' events will be displayed to the console and audio versus\n"
03854          "       energy analysis will be performed and displayed to the console.\n";
03855       return NULL;
03856    case CLI_GENERATE:
03857       return NULL;
03858    }
03859 
03860    what = a->argv[e->args-1];      /* guaranteed to exist */
03861    if (!strcasecmp(what, "on")) {
03862       flag = 1;
03863    } else if (!strcasecmp(what, "off")) {
03864       flag = 0;
03865    } else {
03866       return CLI_SHOWUSAGE;
03867    }
03868 
03869    global_fax_debug = flag;
03870    ast_cli(a->fd, "\n\nFAX Debug %s\n\n", (flag) ? "Enabled" : "Disabled");
03871 
03872    return CLI_SUCCESS;
03873 }

static char* cli_fax_show_capabilities ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

display registered FAX capabilities

Definition at line 3876 of file res_fax.c.

References ast_cli(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, ast_fax_tech::cli_show_capabilities, CLI_SUCCESS, ast_cli_entry::command, ast_fax_tech::description, ast_cli_args::fd, NULL, fax_module::tech, ast_fax_tech::type, and ast_cli_entry::usage.

03877 {
03878    struct fax_module *fax;
03879    unsigned int num_modules = 0;
03880 
03881    switch (cmd) {
03882    case CLI_INIT:
03883       e->command = "fax show capabilities";
03884       e->usage =
03885          "Usage: fax show capabilities\n"
03886          "       Shows the capabilities of the registered FAX technology modules\n";
03887       return NULL;
03888    case CLI_GENERATE:
03889       return NULL;
03890    }
03891 
03892    ast_cli(a->fd, "\n\nRegistered FAX Technology Modules:\n\n");
03893    AST_RWLIST_RDLOCK(&faxmodules);
03894    AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
03895       ast_cli(a->fd, "%-15s : %s\n%-15s : %s\n%-15s : ", "Type", fax->tech->type, "Description", fax->tech->description, "Capabilities");
03896       fax->tech->cli_show_capabilities(a->fd);
03897       num_modules++;
03898    }
03899    AST_RWLIST_UNLOCK(&faxmodules);
03900    ast_cli(a->fd, "%u registered modules\n\n", num_modules);
03901 
03902    return CLI_SUCCESS;
03903 }

static char* cli_fax_show_session ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

display details of a specified fax session

Definition at line 3945 of file res_fax.c.

References ao2_find, ao2_ref, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_log, CLI_GENERATE, CLI_INIT, ast_fax_tech::cli_show_session, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, fax_session_tab_complete(), faxregistry, ast_cli_args::fd, ast_fax_session::id, LOG_ERROR, NULL, OBJ_POINTER, RESULT_SUCCESS, ast_fax_session::tech, tmp(), and ast_cli_entry::usage.

03946 {
03947    struct ast_fax_session *s, tmp;
03948 
03949    switch (cmd) {
03950    case CLI_INIT:
03951       e->command = "fax show session";
03952       e->usage =
03953          "Usage: fax show session <session number>\n"
03954          "       Shows status of the named FAX session\n";
03955       return NULL;
03956    case CLI_GENERATE:
03957       return fax_session_tab_complete(a);
03958    }
03959 
03960    if (a->argc != 4) {
03961       return CLI_SHOWUSAGE;
03962    }
03963 
03964    if (sscanf(a->argv[3], "%u", &tmp.id) != 1) {
03965       ast_log(LOG_ERROR, "invalid session id: '%s'\n", a->argv[3]);
03966       return RESULT_SUCCESS;
03967    }
03968 
03969    ast_cli(a->fd, "\nFAX Session Details:\n--------------------\n\n");
03970    s = ao2_find(faxregistry.container, &tmp, OBJ_POINTER);
03971    if (s) {
03972       s->tech->cli_show_session(s, a->fd);
03973       ao2_ref(s, -1);
03974    }
03975    ast_cli(a->fd, "\n\n");
03976 
03977    return CLI_SUCCESS;
03978 }

static char* cli_fax_show_sessions ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

display fax sessions

Definition at line 4110 of file res_fax.c.

References ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_cli(), ast_fax_session_operation_str(), ast_fax_state_to_str(), ast_free, ast_fax_session::channame, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_fax_session::details, fax_session_type(), faxregistry, ast_cli_args::fd, generate_filenames_string(), ast_fax_session::id, NULL, S_OR, session_count, ast_fax_session::state, ast_fax_session::tech, ast_fax_tech::type, and ast_cli_entry::usage.

04111 {
04112    struct ast_fax_session *s;
04113    struct ao2_iterator i;
04114    int session_count;
04115    char *filenames;
04116 
04117    switch (cmd) {
04118    case CLI_INIT:
04119       e->command = "fax show sessions";
04120       e->usage =
04121          "Usage: fax show sessions\n"
04122          "       Shows the current FAX sessions\n";
04123       return NULL;
04124    case CLI_GENERATE:
04125       return NULL;
04126    }
04127 
04128    ast_cli(a->fd, "\nCurrent FAX Sessions:\n\n");
04129    ast_cli(a->fd, "%-20.20s %-10.10s %-10.10s %-5.5s %-10.10s %-15.15s %-30.30s\n",
04130       "Channel", "Tech", "FAXID", "Type", "Operation", "State", "File(s)");
04131    i = ao2_iterator_init(faxregistry.container, 0);
04132    while ((s = ao2_iterator_next(&i))) {
04133       ao2_lock(s);
04134 
04135       filenames = generate_filenames_string(s->details, "", ", ");
04136 
04137       ast_cli(a->fd, "%-20.20s %-10.10s %-10u %-5.5s %-10.10s %-15.15s %-30s\n",
04138          s->channame, s->tech->type, s->id,
04139          fax_session_type(s),
04140          ast_fax_session_operation_str(s),
04141          ast_fax_state_to_str(s->state), S_OR(filenames, ""));
04142 
04143       ast_free(filenames);
04144       ao2_unlock(s);
04145       ao2_ref(s, -1);
04146    }
04147    ao2_iterator_destroy(&i);
04148    session_count = ao2_container_count(faxregistry.container);
04149    ast_cli(a->fd, "\n%d FAX sessions\n\n", session_count);
04150 
04151    return CLI_SUCCESS;
04152 }

static char* cli_fax_show_settings ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

display global defaults and settings

Definition at line 3906 of file res_fax.c.

References ast_cli(), ast_fax_modem_to_str(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, ast_fax_tech::cli_show_settings, CLI_SUCCESS, ast_cli_entry::command, ast_fax_tech::description, fax_options::ecm, ast_cli_args::fd, get_general_options(), fax_options::maxrate, fax_options::minrate, fax_options::modems, NULL, fax_options::statusevents, fax_options::t38timeout, fax_module::tech, ast_fax_tech::type, and ast_cli_entry::usage.

03907 {
03908    struct fax_module *fax;
03909    char modems[128] = "";
03910    struct fax_options options;
03911 
03912    switch (cmd) {
03913    case CLI_INIT:
03914       e->command = "fax show settings";
03915       e->usage =
03916          "Usage: fax show settings\n"
03917          "       Show the global settings and defaults of both the FAX core and technology modules\n";
03918       return NULL;
03919    case CLI_GENERATE:
03920       return NULL;
03921    }
03922 
03923    get_general_options(&options);
03924 
03925    ast_cli(a->fd, "FAX For Asterisk Settings:\n");
03926    ast_cli(a->fd, "\tECM: %s\n", options.ecm ? "Enabled" : "Disabled");
03927    ast_cli(a->fd, "\tStatus Events: %s\n",  options.statusevents ? "On" : "Off");
03928    ast_cli(a->fd, "\tMinimum Bit Rate: %u\n", options.minrate);
03929    ast_cli(a->fd, "\tMaximum Bit Rate: %u\n", options.maxrate);
03930    ast_fax_modem_to_str(options.modems, modems, sizeof(modems));
03931    ast_cli(a->fd, "\tModem Modulations Allowed: %s\n", modems);
03932    ast_cli(a->fd, "\tT.38 Negotiation Timeout: %u\n", options.t38timeout);
03933    ast_cli(a->fd, "\n\nFAX Technology Modules:\n\n");
03934    AST_RWLIST_RDLOCK(&faxmodules);
03935    AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
03936       ast_cli(a->fd, "%s (%s) Settings:\n", fax->tech->type, fax->tech->description);
03937       fax->tech->cli_show_settings(a->fd);
03938    }
03939    AST_RWLIST_UNLOCK(&faxmodules);
03940 
03941    return CLI_SUCCESS;
03942 }

static char* cli_fax_show_stats ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

display fax stats

Definition at line 4018 of file res_fax.c.

References ast_cli(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, ast_fax_tech::cli_show_stats, CLI_SUCCESS, ast_cli_entry::command, faxregistry, ast_cli_args::fd, NULL, fax_module::tech, and ast_cli_entry::usage.

04019 {
04020    struct fax_module *fax;
04021 
04022    switch (cmd) {
04023    case CLI_INIT:
04024       e->command = "fax show stats";
04025       e->usage =
04026          "Usage: fax show stats\n"
04027          "       Shows a statistical summary of FAX transmissions\n";
04028       return NULL;
04029    case CLI_GENERATE:
04030       return NULL;
04031    }
04032 
04033    ast_cli(a->fd, "\nFAX Statistics:\n---------------\n\n");
04034    ast_cli(a->fd, "%-20.20s : %d\n", "Current Sessions", faxregistry.active_sessions);
04035    ast_cli(a->fd, "%-20.20s : %d\n", "Reserved Sessions", faxregistry.reserved_sessions);
04036    ast_cli(a->fd, "%-20.20s : %d\n", "Transmit Attempts", faxregistry.fax_tx_attempts);
04037    ast_cli(a->fd, "%-20.20s : %d\n", "Receive Attempts", faxregistry.fax_rx_attempts);
04038    ast_cli(a->fd, "%-20.20s : %d\n", "Completed FAXes", faxregistry.fax_complete);
04039    ast_cli(a->fd, "%-20.20s : %d\n", "Failed FAXes", faxregistry.fax_failures);
04040    AST_RWLIST_RDLOCK(&faxmodules);
04041    AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
04042       fax->tech->cli_show_stats(a->fd);
04043    }
04044    AST_RWLIST_UNLOCK(&faxmodules);
04045    ast_cli(a->fd, "\n\n");
04046 
04047    return CLI_SUCCESS;
04048 }

static char* cli_fax_show_version ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 3809 of file res_fax.c.

References ast_cli_args::argc, ast_cli(), ast_get_version(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_fax_tech::description, ast_cli_args::fd, NULL, fax_module::tech, ast_cli_entry::usage, and ast_fax_tech::version.

03810 {
03811    struct fax_module *fax;
03812 
03813    switch(cmd) {
03814    case CLI_INIT:
03815       e->command = "fax show version";
03816       e->usage =
03817          "Usage: fax show version\n"
03818          "       Show versions of FAX For Asterisk components.\n";
03819       return NULL;
03820    case CLI_GENERATE:
03821       return NULL;
03822    }
03823 
03824    if (a->argc != 3) {
03825       return CLI_SHOWUSAGE;
03826    }
03827 
03828    ast_cli(a->fd, "FAX For Asterisk Components:\n");
03829    ast_cli(a->fd, "\tApplications: %s\n", ast_get_version());
03830    AST_RWLIST_RDLOCK(&faxmodules);
03831    AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
03832       ast_cli(a->fd, "\t%s: %s\n", fax->tech->description, fax->tech->version);
03833    }
03834    AST_RWLIST_UNLOCK(&faxmodules);
03835    ast_cli(a->fd, "\n");
03836 
03837    return CLI_SUCCESS;
03838 }

static void debug_check_frame_for_silence ( struct ast_fax_session s,
unsigned int  c2s,
struct ast_frame frame 
) [static]

Definition at line 578 of file res_fax.c.

References ast_dsp_reset(), ast_dsp_silence(), ast_tvnow(), ast_tvsub(), ast_verb, ast_fax_debug_info::base_tv, ast_fax_session::channame, debug_info_history::consec_frames, debug_info_history::consec_ms, ast_fax_session::debug_info, ast_fax_debug_info::dsp, ast_fax_session::id, ast_fax_debug_info::s2c, ast_frame::samples, and debug_info_history::silence.

Referenced by generic_fax_exec().

00579 {
00580    struct debug_info_history *history = c2s ? &s->debug_info->c2s : &s->debug_info->s2c;
00581    int dspsilence;
00582    unsigned int last_consec_frames, last_consec_ms;
00583    unsigned char wassil;
00584    struct timeval diff;
00585 
00586    diff = ast_tvsub(ast_tvnow(), s->debug_info->base_tv);
00587 
00588    ast_dsp_reset(s->debug_info->dsp);
00589    ast_dsp_silence(s->debug_info->dsp, frame, &dspsilence);
00590 
00591    wassil = history->silence;
00592    history->silence = (dspsilence != 0) ? 1 : 0;
00593    if (history->silence != wassil) {
00594       last_consec_frames = history->consec_frames;
00595       last_consec_ms = history->consec_ms;
00596       history->consec_frames = 0;
00597       history->consec_ms = 0;
00598 
00599       if ((last_consec_frames != 0)) {
00600          ast_verb(0, "Channel '%s' fax session '%u', [ %.3ld.%.6ld ], %s sent %u frames (%u ms) of %s.\n",
00601              s->channame, s->id, (long) diff.tv_sec, (long int) diff.tv_usec,
00602              (c2s) ? "channel" : "stack", last_consec_frames, last_consec_ms,
00603              (wassil) ? "silence" : "energy");
00604       }
00605    }
00606 
00607    history->consec_frames++;
00608    history->consec_ms += (frame->samples / 8);
00609 }

static void destroy_callback ( void *  data  )  [static]

Definition at line 611 of file res_fax.c.

References ao2_ref.

00612 {
00613    if (data) {
00614       ao2_ref(data, -1);
00615    }
00616 }

static void destroy_faxdetect ( void *  data  )  [static]

destroy a FAX detect structure

Definition at line 3521 of file res_fax.c.

References ao2_cleanup, ao2_ref, ast_dsp_free(), fax_detect::details, fax_detect::dsp, NULL, and fax_detect::orig_format.

Referenced by fax_detect_new().

03522 {
03523    struct fax_detect *faxdetect = data;
03524 
03525    if (faxdetect->dsp) {
03526       ast_dsp_free(faxdetect->dsp);
03527       faxdetect->dsp = NULL;
03528    }
03529    ao2_ref(faxdetect->details, -1);
03530    ao2_cleanup(faxdetect->orig_format);
03531 }

static void destroy_gateway ( void *  data  )  [static]

destroy a FAX gateway session structure

Definition at line 2816 of file res_fax.c.

References ao2_cleanup, ao2_ref, ao2_unlink, fax_gateway::chan_read_format, fax_gateway::chan_write_format, destroy_v21_sessions(), fax_session_release(), faxregistry, NULL, fax_gateway::peer_read_format, fax_gateway::peer_write_format, fax_gateway::s, and fax_gateway::token.

02817 {
02818    struct fax_gateway *gateway = data;
02819 
02820    destroy_v21_sessions(gateway);
02821 
02822    if (gateway->s) {
02823       fax_session_release(gateway->s, gateway->token);
02824       gateway->token = NULL;
02825 
02826       ao2_unlink(faxregistry.container, gateway->s);
02827 
02828       ao2_ref(gateway->s, -1);
02829       gateway->s = NULL;
02830    }
02831 
02832    ao2_cleanup(gateway->chan_read_format);
02833    ao2_cleanup(gateway->chan_write_format);
02834    ao2_cleanup(gateway->peer_read_format);
02835    ao2_cleanup(gateway->peer_write_format);
02836 }

static void destroy_session ( void *  session  )  [static]

static void destroy_session_details ( void *  details  )  [static]

destroy a FAX session details structure

Definition at line 682 of file res_fax.c.

References ast_free, AST_LIST_REMOVE_HEAD, ast_string_field_free_memory, d, ast_fax_session_details::documents, and fax_module::next.

Referenced by session_details_new().

00683 {
00684    struct ast_fax_session_details *d = details;
00685    struct ast_fax_document *doc;
00686 
00687    while ((doc = AST_LIST_REMOVE_HEAD(&d->documents, next))) {
00688       ast_free(doc);
00689    }
00690    ast_string_field_free_memory(d);
00691 }

static void destroy_v21_sessions ( struct fax_gateway gateway  )  [static]

destroy the v21 detection parts of a fax gateway session

Definition at line 2798 of file res_fax.c.

References ao2_ref, ao2_unlink, fax_gateway::chan_v21_session, faxregistry, NULL, and fax_gateway::peer_v21_session.

Referenced by destroy_gateway(), and fax_gateway_detect_v21().

02799 {
02800    if (gateway->chan_v21_session) {
02801       ao2_unlink(faxregistry.container, gateway->chan_v21_session);
02802 
02803       ao2_ref(gateway->chan_v21_session, -1);
02804       gateway->chan_v21_session = NULL;
02805    }
02806 
02807    if (gateway->peer_v21_session) {
02808       ao2_unlink(faxregistry.container, gateway->peer_v21_session);
02809 
02810       ao2_ref(gateway->peer_v21_session, -1);
02811       gateway->peer_v21_session = NULL;
02812    }
02813 }

static int disable_t38 ( struct ast_channel chan  )  [static]

Definition at line 1520 of file res_fax.c.

References ast_channel_name(), AST_CONTROL_T38_PARAMETERS, ast_debug, AST_FRAME_CONTROL, ast_frfree, ast_indicate_data(), ast_log, ast_read(), ast_remaining_ms(), AST_T38_REFUSED, AST_T38_REQUEST_TERMINATE, AST_T38_TERMINATED, ast_tvnow(), ast_waitfor(), ast_frame::data, ast_frame::datalen, ast_frame::frametype, ast_frame_subclass::integer, LOG_ERROR, LOG_WARNING, NULL, ast_frame::ptr, ast_control_t38_parameters::request_response, and ast_frame::subclass.

Referenced by receivefax_exec(), sendfax_exec(), and transmit_t38().

01521 {
01522    int timeout_ms;
01523    struct ast_frame *frame = NULL;
01524    struct ast_control_t38_parameters t38_parameters = { .request_response = AST_T38_REQUEST_TERMINATE, };
01525    struct timeval start;
01526    int ms;
01527 
01528    ast_debug(1, "Shutting down T.38 on %s\n", ast_channel_name(chan));
01529    if (ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0) {
01530       ast_debug(1, "error while disabling T.38 on channel '%s'\n", ast_channel_name(chan));
01531       return -1;
01532    }
01533 
01534    /* wait up to five seconds for negotiation to complete */
01535    timeout_ms = 5000;
01536    start = ast_tvnow();
01537    while ((ms = ast_remaining_ms(start, timeout_ms))) {
01538       ms = ast_waitfor(chan, ms);
01539 
01540       if (ms == 0) {
01541          break;
01542       }
01543       if (ms < 0) {
01544          ast_debug(1, "error while disabling T.38 on channel '%s'\n", ast_channel_name(chan));
01545          return -1;
01546       }
01547 
01548       if (!(frame = ast_read(chan))) {
01549          return -1;
01550       }
01551       if ((frame->frametype == AST_FRAME_CONTROL) &&
01552           (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
01553           (frame->datalen == sizeof(t38_parameters))) {
01554          struct ast_control_t38_parameters *parameters = frame->data.ptr;
01555 
01556          switch (parameters->request_response) {
01557          case AST_T38_TERMINATED:
01558             ast_debug(1, "Shut down T.38 on %s\n", ast_channel_name(chan));
01559             break;
01560          case AST_T38_REFUSED:
01561             ast_log(LOG_WARNING, "channel '%s' refused to disable T.38\n", ast_channel_name(chan));
01562             ast_frfree(frame);
01563             return -1;
01564          default:
01565             ast_log(LOG_ERROR, "channel '%s' failed to disable T.38\n", ast_channel_name(chan));
01566             ast_frfree(frame);
01567             return -1;
01568          }
01569          ast_frfree(frame);
01570          break;
01571       }
01572       ast_frfree(frame);
01573    }
01574 
01575    if (ms == 0) { /* all done, nothing happened */
01576       ast_debug(1, "channel '%s' timed-out during T.38 shutdown\n", ast_channel_name(chan));
01577    }
01578 
01579    return 0;
01580 }

static int fax_detect_attach ( struct ast_channel chan,
int  timeout,
int  flags 
) [static]

Attach a faxdetect framehook object to a channel.

Parameters:
chan the channel to attach to
timeout remove framehook in this time if set
Returns:
the faxdetect structure or NULL on error
Parameters:
flags required options
Return values:
-1 error

Definition at line 3727 of file res_fax.c.

References ao2_ref, ast_channel_lock, ast_channel_unlock, ast_framehook_attach(), AST_FRAMEHOOK_INTERFACE_VERSION, ast_log, ast_framehook_interface::data, fax_detect::details, fax_detect_framehook(), fax_detect_framehook_destroy(), fax_detect_new(), ast_fax_session_details::faxdetect_flags, ast_fax_session_details::faxdetect_id, ast_fax_session_details::faxdetect_timeout, find_or_create_details(), LOG_ERROR, and ast_framehook_interface::version.

Referenced by acf_faxopt_write(), and fixup_callback().

03728 {
03729    struct fax_detect *faxdetect;
03730    struct ast_fax_session_details *details;
03731    struct ast_framehook_interface fr_hook = {
03732       .version = AST_FRAMEHOOK_INTERFACE_VERSION,
03733       .event_cb = fax_detect_framehook,
03734       .destroy_cb = fax_detect_framehook_destroy,
03735    };
03736 
03737    if (!(details = find_or_create_details(chan))) {
03738       ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
03739       return -1;
03740    }
03741 
03742    /* set up the frame hook*/
03743    faxdetect = fax_detect_new(chan, timeout, flags);
03744    if (!faxdetect) {
03745       ao2_ref(details, -1);
03746       return -1;
03747    }
03748 
03749    fr_hook.data = faxdetect;
03750    faxdetect->details = details;
03751    ast_channel_lock(chan);
03752    details->faxdetect_id = ast_framehook_attach(chan, &fr_hook);
03753    details->faxdetect_timeout = timeout;
03754    details->faxdetect_flags = flags;
03755    ast_channel_unlock(chan);
03756 
03757    if (details->faxdetect_id < 0) {
03758       ao2_ref(faxdetect, -1);
03759    }
03760 
03761    return details->faxdetect_id;
03762 }

static struct ast_frame* fax_detect_framehook ( struct ast_channel chan,
struct ast_frame f,
enum ast_framehook_event  event,
void *  data 
) [static, read]

Fax Detect Framehook.

Listen for fax tones in audio path and enable jumping to a extension when detected.

Parameters:
chan channel
f frame to handle may be NULL
event framehook event
data framehook data (struct fax_detect *)
Returns:
processed frame or NULL when f is NULL or a null frame

Definition at line 3590 of file res_fax.c.

References ao2_cleanup, ao2_ref, ao2_replace, ast_async_goto(), ast_channel_bridge_peer(), ast_channel_caller(), ast_channel_context(), ast_channel_exten(), ast_channel_lock, ast_channel_macrocontext(), ast_channel_make_compatible(), ast_channel_name(), ast_channel_readformat(), ast_channel_unlock, AST_CONTROL_T38_PARAMETERS, ast_dsp_process(), ast_exists_extension(), ast_format_alaw, ast_format_cmp(), AST_FORMAT_CMP_EQUAL, ast_format_slin, ast_format_ulaw, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_framehook_detach(), AST_FRAMEHOOK_EVENT_ATTACHED, AST_FRAMEHOOK_EVENT_DETACHED, AST_FRAMEHOOK_EVENT_READ, ast_frfree, ast_log, ast_null_frame, ast_set_read_format(), AST_T38_NEGOTIATED, AST_T38_REQUEST_NEGOTIATE, ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), ast_verb, ast_frame::data, ast_frame::datalen, fax_detect::details, fax_detect::dsp, FAX_DETECT_MODE_T38, ast_fax_session_details::faxdetect_id, fax_detect::flags, ast_frame_subclass::format, ast_frame::frametype, ast_frame_subclass::integer, LOG_NOTICE, NULL, fax_detect::orig_format, pbx_builtin_setvar_helper(), ast_frame::ptr, RAII_VAR, ast_control_t38_parameters::request_response, result, S_COR, S_OR, ast_frame::subclass, fax_detect::timeout, and fax_detect::timeout_start.

Referenced by fax_detect_attach().

03591 {
03592    struct fax_detect *faxdetect = data;
03593    struct ast_fax_session_details *details;
03594    struct ast_control_t38_parameters *control_params;
03595    RAII_VAR(struct ast_channel *, peer, NULL, ao2_cleanup);
03596    RAII_VAR(struct ast_channel *, chan_ref, chan, ao2_cleanup);
03597    int result = 0;
03598 
03599    /* Ref bump the channel for when we have to unlock it */
03600    ao2_ref(chan, 1);
03601 
03602    details = faxdetect->details;
03603 
03604    switch (event) {
03605    case AST_FRAMEHOOK_EVENT_ATTACHED:
03606       /* Setup format for DSP on ATTACH*/
03607       ao2_replace(faxdetect->orig_format, ast_channel_readformat(chan));
03608 
03609       if ((ast_format_cmp(ast_channel_readformat(chan), ast_format_slin) != AST_FORMAT_CMP_EQUAL) &&
03610          (ast_format_cmp(ast_channel_readformat(chan), ast_format_alaw) != AST_FORMAT_CMP_EQUAL) &&
03611          (ast_format_cmp(ast_channel_readformat(chan), ast_format_ulaw) != AST_FORMAT_CMP_EQUAL)) {
03612          if (ast_set_read_format(chan, ast_format_slin)) {
03613             ast_framehook_detach(chan, details->faxdetect_id);
03614             details->faxdetect_id = -1;
03615             return f;
03616          }
03617       }
03618 
03619       return NULL;
03620    case AST_FRAMEHOOK_EVENT_DETACHED:
03621       /* restore audio formats when we are detached */
03622       ast_set_read_format(chan, faxdetect->orig_format);
03623       ast_channel_unlock(chan);
03624       peer = ast_channel_bridge_peer(chan);
03625       if (peer) {
03626          ast_channel_make_compatible(chan, peer);
03627       }
03628       ast_channel_lock(chan);
03629       return NULL;
03630    case AST_FRAMEHOOK_EVENT_READ:
03631       if (f) {
03632          break;
03633       }
03634    default:
03635       return f;
03636    };
03637 
03638    if (details->faxdetect_id < 0) {
03639       return f;
03640    }
03641 
03642    if ((!ast_tvzero(faxdetect->timeout_start) &&
03643        (ast_tvdiff_ms(ast_tvnow(), faxdetect->timeout_start) > faxdetect->timeout))) {
03644       ast_framehook_detach(chan, details->faxdetect_id);
03645       details->faxdetect_id = -1;
03646       return f;
03647    }
03648 
03649    /* only handle VOICE and CONTROL frames*/
03650    switch (f->frametype) {
03651    case AST_FRAME_VOICE:
03652       /* we have no DSP this means we not detecting CNG */
03653       if (!faxdetect->dsp) {
03654          return f;
03655       }
03656       /* We can only process some formats*/
03657       if ((ast_format_cmp(f->subclass.format, ast_format_slin) != AST_FORMAT_CMP_EQUAL) &&
03658          (ast_format_cmp(f->subclass.format, ast_format_alaw) != AST_FORMAT_CMP_EQUAL) &&
03659          (ast_format_cmp(f->subclass.format, ast_format_ulaw) != AST_FORMAT_CMP_EQUAL)) {
03660          return f;
03661       }
03662       break;
03663    case AST_FRAME_CONTROL:
03664       if ((f->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
03665           (faxdetect->flags & FAX_DETECT_MODE_T38)) {
03666          break;
03667       }
03668       return f;
03669    default:
03670       return f;
03671    }
03672 
03673    if (f->frametype == AST_FRAME_VOICE) {
03674       f = ast_dsp_process(chan, faxdetect->dsp, f);
03675       if (f->frametype == AST_FRAME_DTMF) {
03676          result = f->subclass.integer;
03677       }
03678    } else if ((f->frametype == AST_FRAME_CONTROL) && (f->datalen == sizeof(struct ast_control_t38_parameters))) {
03679       control_params = f->data.ptr;
03680       switch (control_params->request_response) {
03681       case AST_T38_NEGOTIATED:
03682       case AST_T38_REQUEST_NEGOTIATE:
03683          result = 't';
03684          break;
03685       default:
03686          break;
03687       }
03688    }
03689 
03690    if (result) {
03691       const char *target_context = S_OR(ast_channel_macrocontext(chan), ast_channel_context(chan));
03692       switch (result) {
03693       case 'f':
03694       case 't':
03695          ast_channel_unlock(chan);
03696          if (ast_exists_extension(chan, target_context, "fax", 1,
03697              S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
03698             ast_channel_lock(chan);
03699             ast_verb(2, "Redirecting '%s' to fax extension due to %s detection\n",
03700                ast_channel_name(chan), (result == 'f') ? "CNG" : "T38");
03701             pbx_builtin_setvar_helper(chan, "FAXEXTEN", ast_channel_exten(chan));
03702             if (ast_async_goto(chan, target_context, "fax", 1)) {
03703                ast_log(LOG_NOTICE, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(chan), target_context);
03704             }
03705             ast_frfree(f);
03706             f = &ast_null_frame;
03707          } else {
03708             ast_channel_lock(chan);
03709             ast_log(LOG_NOTICE, "FAX %s detected but no fax extension in context (%s)\n",
03710                (result == 'f') ? "CNG" : "T38", target_context);
03711          }
03712       }
03713       ast_framehook_detach(chan, details->faxdetect_id);
03714       details->faxdetect_id = -1;
03715    }
03716 
03717    return f;
03718 }

static void fax_detect_framehook_destroy ( void *  data  )  [static]

Deref the faxdetect data structure when the faxdetect framehook is detached.

Parameters:
data framehook data (faxdetect data)

Definition at line 3572 of file res_fax.c.

References ao2_ref.

Referenced by fax_detect_attach().

03573 {
03574    struct fax_detect *faxdetect = data;
03575 
03576    ao2_ref(faxdetect, -1);
03577 }

static struct fax_detect* fax_detect_new ( struct ast_channel chan,
int  timeout,
int  flags 
) [static, read]

Create a new fax detect object.

Parameters:
chan the channel attaching to
timeout remove framehook in this time if set
flags required options
Returns:
NULL or a fax gateway object

Definition at line 3539 of file res_fax.c.

References ao2_alloc, ao2_ref, ast_dsp_new(), ast_dsp_set_faxmode(), ast_dsp_set_features(), ast_tvnow(), destroy_faxdetect(), fax_detect::dsp, DSP_FAXMODE_DETECT_CNG, DSP_FAXMODE_DETECT_SQUELCH, DSP_FEATURE_FAX_DETECT, FAX_DETECT_MODE_CNG, fax_detect::flags, NULL, and fax_detect::timeout_start.

Referenced by fax_detect_attach().

03540 {
03541    struct fax_detect *faxdetect = ao2_alloc(sizeof(*faxdetect), destroy_faxdetect);
03542    if (!faxdetect) {
03543       return NULL;
03544    }
03545 
03546    faxdetect->flags = flags;
03547 
03548    if (timeout) {
03549       faxdetect->timeout_start = ast_tvnow();
03550    } else {
03551       faxdetect->timeout_start.tv_sec = 0;
03552       faxdetect->timeout_start.tv_usec = 0;
03553    }
03554 
03555    if (faxdetect->flags & FAX_DETECT_MODE_CNG) {
03556       faxdetect->dsp = ast_dsp_new();
03557       if (!faxdetect->dsp) {
03558          ao2_ref(faxdetect, -1);
03559          return NULL;
03560       }
03561       ast_dsp_set_features(faxdetect->dsp, DSP_FEATURE_FAX_DETECT);
03562       ast_dsp_set_faxmode(faxdetect->dsp, DSP_FAXMODE_DETECT_CNG | DSP_FAXMODE_DETECT_SQUELCH);
03563    } else {
03564       faxdetect->dsp = NULL;
03565    }
03566 
03567    return faxdetect;
03568 }

static int fax_gateway_attach ( struct ast_channel chan,
struct ast_fax_session_details details 
) [static]

Attach a gateway framehook object to a channel.

Parameters:
chan the channel to attach to
details fax session details
Returns:
the framehook id of the attached framehook or -1 on error
Return values:
-1 error

Definition at line 3477 of file res_fax.c.

References ao2_ref, ast_channel_lock, ast_channel_unlock, ast_framehook_attach(), AST_FRAMEHOOK_INTERFACE_VERSION, ast_string_field_set, ast_framehook_interface::data, error(), fax_gateway_framehook(), fax_gateway_framehook_destroy(), fax_gateway_new(), fax_gateway::framehook, report_fax_status(), result, set_channel_variables(), and ast_framehook_interface::version.

Referenced by acf_faxopt_write(), and fixup_callback().

03478 {
03479    struct fax_gateway *gateway;
03480    struct ast_framehook_interface fr_hook = {
03481       .version = AST_FRAMEHOOK_INTERFACE_VERSION,
03482       .event_cb = fax_gateway_framehook,
03483       .destroy_cb = fax_gateway_framehook_destroy,
03484       .disable_inheritance = 1, /* Masquerade inheritance is handled through the datastore fixup */
03485    };
03486 
03487    ast_string_field_set(details, result, "SUCCESS");
03488    ast_string_field_set(details, resultstr, "gateway operation started successfully");
03489    ast_string_field_set(details, error, "NO_ERROR");
03490    set_channel_variables(chan, details);
03491 
03492    /* set up the frame hook*/
03493    gateway = fax_gateway_new(chan, details);
03494    if (!gateway) {
03495       ast_string_field_set(details, result, "FAILED");
03496       ast_string_field_set(details, resultstr, "error initializing gateway session");
03497       ast_string_field_set(details, error, "INIT_ERROR");
03498       set_channel_variables(chan, details);
03499       report_fax_status(chan, details, "No Available Resource");
03500       return -1;
03501    }
03502 
03503    fr_hook.data = gateway;
03504    ast_channel_lock(chan);
03505    gateway->framehook = ast_framehook_attach(chan, &fr_hook);
03506    ast_channel_unlock(chan);
03507 
03508    if (gateway->framehook < 0) {
03509       ao2_ref(gateway, -1);
03510       ast_string_field_set(details, result, "FAILED");
03511       ast_string_field_set(details, resultstr, "error attaching gateway to channel");
03512       ast_string_field_set(details, error, "INIT_ERROR");
03513       set_channel_variables(chan, details);
03514       return -1;
03515    }
03516 
03517    return gateway->framehook;
03518 }

static struct ast_frame* fax_gateway_detect_t38 ( struct fax_gateway gateway,
struct ast_channel chan,
struct ast_channel peer,
struct ast_channel active,
struct ast_frame f 
) [static, read]

T38 Gateway Negotiate t38 parameters.

Parameters:
gateway gateway object
chan channel running the gateway
peer channel im bridged too
active channel the frame originated on
f the control frame to process
Returns:
processed control frame or null frame

Definition at line 3013 of file res_fax.c.

References ao2_ref, ast_channel_get_t38_state(), ast_channel_name(), ast_debug, ast_framehook_detach(), ast_log, ast_null_frame, ast_string_field_set, AST_T38_NEGOTIATED, AST_T38_REFUSED, AST_T38_REQUEST_NEGOTIATE, AST_T38_REQUEST_TERMINATE, AST_T38_TERMINATED, ast_tvnow(), ast_frame::data, ast_frame::datalen, error(), fax_gateway_indicate_t38(), fax_gateway_start(), FAX_GATEWAY_TIMEOUT, find_details(), fax_gateway::framehook, ast_fax_session_details::gateway_id, ast_fax_session_details::gateway_timeout, LOG_ERROR, LOG_WARNING, ast_fax_session_details::our_t38_parameters, ast_frame::ptr, report_fax_status(), ast_control_t38_parameters::request_response, result, ast_fax_session_details::resultstr, set_channel_variables(), t38_parameters_ast_to_fax(), t38_parameters_fax_to_ast(), fax_gateway::t38_state, T38_STATE_NEGOTIATED, T38_STATE_NEGOTIATING, T38_STATE_REJECTED, T38_STATE_UNAVAILABLE, T38_STATE_UNKNOWN, ast_fax_session_details::their_t38_parameters, and fax_gateway::timeout_start.

Referenced by fax_gateway_framehook().

03014 {
03015    struct ast_control_t38_parameters *control_params = f->data.ptr;
03016    struct ast_channel *other = (active == chan) ? peer : chan;
03017    struct ast_fax_session_details *details;
03018 
03019    if (f->datalen != sizeof(struct ast_control_t38_parameters)) {
03020       /* invalaid AST_CONTROL_T38_PARAMETERS frame, we can't
03021        * do anything with it, pass it on */
03022       return f;
03023    }
03024 
03025    /* ignore frames from ourselves */
03026    if ((gateway->t38_state == T38_STATE_NEGOTIATED && control_params->request_response == AST_T38_NEGOTIATED)
03027       || (gateway->t38_state == T38_STATE_REJECTED && control_params->request_response == AST_T38_REFUSED)
03028       || (gateway->t38_state == T38_STATE_NEGOTIATING && control_params->request_response == AST_T38_REQUEST_TERMINATE)) {
03029 
03030       return f;
03031    }
03032 
03033    if (!(details = find_details(chan))) {
03034       ast_log(LOG_ERROR, "no FAX session details found on chan %s for T.38 gateway session, odd\n", ast_channel_name(chan));
03035       ast_framehook_detach(chan, gateway->framehook);
03036       return f;
03037    }
03038 
03039    if (control_params->request_response == AST_T38_REQUEST_NEGOTIATE) {
03040       enum ast_t38_state state = ast_channel_get_t38_state(other);
03041 
03042       if (state == T38_STATE_UNKNOWN) {
03043          /* we detected a request to negotiate T.38 and the
03044           * other channel appears to support T.38, we'll pass
03045           * the request through and only step in if the other
03046           * channel rejects the request */
03047          ast_debug(1, "%s is attempting to negotiate T.38 with %s, we'll see what happens\n", ast_channel_name(active), ast_channel_name(other));
03048          t38_parameters_ast_to_fax(&details->their_t38_parameters, control_params);
03049          gateway->t38_state = T38_STATE_UNKNOWN;
03050          gateway->timeout_start = ast_tvnow();
03051          details->gateway_timeout = FAX_GATEWAY_TIMEOUT;
03052          ao2_ref(details, -1);
03053          return f;
03054       } else if (state == T38_STATE_UNAVAILABLE || state == T38_STATE_REJECTED) {
03055          /* the other channel does not support T.38, we need to
03056           * step in here */
03057          ast_debug(1, "%s is attempting to negotiate T.38 but %s does not support it\n", ast_channel_name(active), ast_channel_name(other));
03058          ast_debug(1, "starting T.38 gateway for T.38 channel %s and G.711 channel %s\n", ast_channel_name(active), ast_channel_name(other));
03059 
03060          t38_parameters_ast_to_fax(&details->their_t38_parameters, control_params);
03061          t38_parameters_fax_to_ast(control_params, &details->our_t38_parameters);
03062 
03063          if (fax_gateway_start(gateway, details, chan)) {
03064             ast_log(LOG_ERROR, "error starting T.38 gateway for T.38 channel %s and G.711 channel %s\n", ast_channel_name(active), ast_channel_name(other));
03065             gateway->t38_state = T38_STATE_REJECTED;
03066             control_params->request_response = AST_T38_REFUSED;
03067 
03068             ast_framehook_detach(chan, details->gateway_id);
03069             details->gateway_id = -1;
03070          } else {
03071             gateway->t38_state = T38_STATE_NEGOTIATED;
03072             control_params->request_response = AST_T38_NEGOTIATED;
03073             report_fax_status(chan, details, "T.38 Negotiated");
03074          }
03075 
03076          fax_gateway_indicate_t38(chan, active, control_params);
03077 
03078          ao2_ref(details, -1);
03079          return &ast_null_frame;
03080       } else if (gateway->t38_state == T38_STATE_NEGOTIATING) {
03081          /* we got a request to negotiate T.38 after we already
03082           * sent one to the other party based on v21 preamble
03083           * detection. We'll just pretend we passed this request
03084           * through in the first place. */
03085 
03086          t38_parameters_ast_to_fax(&details->their_t38_parameters, control_params);
03087          gateway->t38_state = T38_STATE_UNKNOWN;
03088          gateway->timeout_start = ast_tvnow();
03089          details->gateway_timeout = FAX_GATEWAY_TIMEOUT;
03090 
03091          ast_debug(1, "%s is attempting to negotiate T.38 after we already sent a negotiation request based on v21 preamble detection\n", ast_channel_name(active));
03092          ao2_ref(details, -1);
03093          return &ast_null_frame;
03094       } else if (gateway->t38_state == T38_STATE_NEGOTIATED) {
03095          /* we got a request to negotiate T.38 after we already
03096           * sent one to the other party based on v21 preamble
03097           * detection and received a response. We need to
03098           * respond to this and shut down the gateway. */
03099 
03100          t38_parameters_fax_to_ast(control_params, &details->their_t38_parameters);
03101          ast_framehook_detach(chan, details->gateway_id);
03102          details->gateway_id = -1;
03103 
03104          control_params->request_response = AST_T38_NEGOTIATED;
03105 
03106          fax_gateway_indicate_t38(chan, active, control_params);
03107 
03108          ast_string_field_set(details, result, "SUCCESS");
03109          ast_string_field_set(details, resultstr, "no gateway necessary");
03110          ast_string_field_set(details, error, "NATIVE_T38");
03111          set_channel_variables(chan, details);
03112 
03113          ast_debug(1, "%s is attempting to negotiate T.38 after we already negotiated T.38 with %s, disabling the gateway\n", ast_channel_name(active), ast_channel_name(other));
03114          ao2_ref(details, -1);
03115          return &ast_null_frame;
03116       } else {
03117          ast_log(LOG_WARNING, "%s is attempting to negotiate T.38 while %s is in an unsupported state\n", ast_channel_name(active), ast_channel_name(other));
03118          ao2_ref(details, -1);
03119          return f;
03120       }
03121    } else if (gateway->t38_state == T38_STATE_NEGOTIATING
03122       && control_params->request_response == AST_T38_REFUSED) {
03123 
03124       ast_debug(1, "unable to negotiate T.38 on %s for fax gateway\n", ast_channel_name(active));
03125 
03126       /* our request to negotiate T.38 was refused, if the other
03127        * channel supports T.38, they might still reinvite and save
03128        * the day.  Otherwise disable the gateway. */
03129       if (ast_channel_get_t38_state(other) == T38_STATE_UNKNOWN) {
03130          gateway->t38_state = T38_STATE_UNAVAILABLE;
03131       } else {
03132          ast_framehook_detach(chan, details->gateway_id);
03133          details->gateway_id = -1;
03134 
03135          ast_string_field_set(details, result, "FAILED");
03136          ast_string_field_set(details, resultstr, "unable to negotiate T.38");
03137          ast_string_field_set(details, error, "T38_NEG_ERROR");
03138          set_channel_variables(chan, details);
03139       }
03140 
03141       ao2_ref(details, -1);
03142       return &ast_null_frame;
03143    } else if (gateway->t38_state == T38_STATE_NEGOTIATING
03144       && control_params->request_response == AST_T38_NEGOTIATED) {
03145 
03146       ast_debug(1, "starting T.38 gateway for T.38 channel %s and G.711 channel %s\n", ast_channel_name(active), ast_channel_name(other));
03147 
03148       t38_parameters_ast_to_fax(&details->their_t38_parameters, control_params);
03149 
03150       if (fax_gateway_start(gateway, details, chan)) {
03151          ast_log(LOG_ERROR, "error starting T.38 gateway for T.38 channel %s and G.711 channel %s\n", ast_channel_name(active), ast_channel_name(other));
03152          gateway->t38_state = T38_STATE_NEGOTIATING;
03153          control_params->request_response = AST_T38_REQUEST_TERMINATE;
03154 
03155          fax_gateway_indicate_t38(chan, active, control_params);
03156       } else {
03157          gateway->t38_state = T38_STATE_NEGOTIATED;
03158          report_fax_status(chan, details, "T.38 Negotiated");
03159       }
03160 
03161       ao2_ref(details, -1);
03162       return &ast_null_frame;
03163    } else if (control_params->request_response == AST_T38_REFUSED) {
03164       /* the other channel refused the request to negotiate T.38,
03165        * we'll step in here and pretend the request was accepted */
03166 
03167       ast_debug(1, "%s attempted to negotiate T.38 but %s refused the request\n", ast_channel_name(other), ast_channel_name(active));
03168       ast_debug(1, "starting T.38 gateway for T.38 channel %s and G.711 channel %s\n", ast_channel_name(other), ast_channel_name(active));
03169 
03170       t38_parameters_fax_to_ast(control_params, &details->our_t38_parameters);
03171 
03172       if (fax_gateway_start(gateway, details, chan)) {
03173          ast_log(LOG_ERROR, "error starting T.38 gateway for T.38 channel %s and G.711 channel %s\n", ast_channel_name(active), ast_channel_name(other));
03174          gateway->t38_state = T38_STATE_REJECTED;
03175          control_params->request_response = AST_T38_REFUSED;
03176 
03177          ast_framehook_detach(chan, details->gateway_id);
03178          details->gateway_id = -1;
03179       } else {
03180          gateway->t38_state = T38_STATE_NEGOTIATED;
03181          control_params->request_response = AST_T38_NEGOTIATED;
03182       }
03183 
03184       ao2_ref(details, -1);
03185       return f;
03186    } else if (control_params->request_response == AST_T38_REQUEST_TERMINATE) {
03187       /* the channel wishes to end our short relationship, we shall
03188        * oblige */
03189 
03190       ast_debug(1, "T.38 channel %s is requesting a shutdown of T.38, disabling the gateway\n", ast_channel_name(active));
03191 
03192       ast_framehook_detach(chan, details->gateway_id);
03193       details->gateway_id = -1;
03194 
03195       gateway->t38_state = T38_STATE_REJECTED;
03196       control_params->request_response = AST_T38_TERMINATED;
03197 
03198       fax_gateway_indicate_t38(chan, active, control_params);
03199 
03200       ao2_ref(details, -1);
03201       return &ast_null_frame;
03202    } else if (control_params->request_response == AST_T38_NEGOTIATED) {
03203       ast_debug(1, "T.38 successfully negotiated between %s and %s, no gateway necessary\n", ast_channel_name(active), ast_channel_name(other));
03204 
03205       ast_framehook_detach(chan, details->gateway_id);
03206       details->gateway_id = -1;
03207 
03208       ast_string_field_set(details, result, "SUCCESS");
03209       ast_string_field_set(details, resultstr, "no gateway necessary");
03210       ast_string_field_set(details, error, "NATIVE_T38");
03211       set_channel_variables(chan, details);
03212 
03213       ao2_ref(details, -1);
03214       return f;
03215    } else if (control_params->request_response == AST_T38_TERMINATED) {
03216       ast_debug(1, "T.38 disabled on channel %s\n", ast_channel_name(active));
03217 
03218       ast_framehook_detach(chan, details->gateway_id);
03219       details->gateway_id = -1;
03220 
03221       ao2_ref(details, -1);
03222       return &ast_null_frame;
03223    }
03224 
03225    ao2_ref(details, -1);
03226    return f;
03227 }

static struct ast_frame* fax_gateway_detect_v21 ( struct fax_gateway gateway,
struct ast_channel chan,
struct ast_channel peer,
struct ast_channel active,
struct ast_frame f 
) [static, read]

Definition at line 2969 of file res_fax.c.

References ast_channel_get_t38_state(), ast_channel_name(), ast_debug, fax_gateway::chan_v21_session, destroy_v21_sessions(), ast_fax_session::details, fax_gateway::detected_v21, fax_gateway_request_t38(), ast_fax_session_details::option, fax_gateway::peer_v21_session, T38_STATE_UNKNOWN, ast_fax_session::tech, ast_fax_session_details::v21_detected, and ast_fax_tech::write.

Referenced by fax_gateway_framehook().

02970 {
02971    struct ast_channel *other = (active == chan) ? peer : chan;
02972    struct ast_fax_session *active_v21_session = (active == chan) ? gateway->chan_v21_session : gateway->peer_v21_session;
02973 
02974    if (!active_v21_session || gateway->detected_v21) {
02975       return f;
02976    }
02977 
02978    if (active_v21_session->tech->write(active_v21_session, f) == 0 &&
02979        active_v21_session->details->option.v21_detected) {
02980       gateway->detected_v21 = 1;
02981    }
02982 
02983    if (gateway->detected_v21) {
02984       destroy_v21_sessions(gateway);
02985       if (ast_channel_get_t38_state(other) == T38_STATE_UNKNOWN) {
02986          ast_debug(1, "detected v21 preamble from %s\n", ast_channel_name(active));
02987          return fax_gateway_request_t38(gateway, chan, f);
02988       } else {
02989          ast_debug(1, "detected v21 preamble on %s, but %s does not support T.38 for T.38 gateway session\n", ast_channel_name(active), ast_channel_name(other));
02990       }
02991    }
02992 
02993    return f;
02994 }

static struct ast_frame* fax_gateway_framehook ( struct ast_channel chan,
struct ast_frame f,
enum ast_framehook_event  event,
void *  data 
) [static, read]

T.30<->T.38 gateway framehook.

Intercept packets on bridged channels and determine if a T.38 gateway is required. If a gateway is required, start a gateway and handle T.38 negotiation if necessary.

Parameters:
chan channel running the gateway
f frame to handle may be NULL
event framehook event
data framehook data (struct fax_gateway *)
Returns:
processed frame or NULL when f is NULL or a null frame

Definition at line 3266 of file res_fax.c.

References ao2_cleanup, ao2_ref, ao2_replace, ast_channel_bridge_peer(), ast_channel_get_t38_state(), ast_channel_lock, ast_channel_make_compatible(), ast_channel_name(), ast_channel_readformat(), ast_channel_readtrans(), ast_channel_unlock, AST_CONTROL_T38_PARAMETERS, ast_debug, AST_FAX_FRFLAG_GATEWAY, ast_format_alaw, ast_format_cmp(), AST_FORMAT_CMP_EQUAL, ast_format_slin, ast_format_ulaw, AST_FRAME_CONTROL, AST_FRAME_MODEM, AST_FRAME_VOICE, ast_framehook_detach(), AST_FRAMEHOOK_EVENT_ATTACHED, AST_FRAMEHOOK_EVENT_DETACHED, AST_FRAMEHOOK_EVENT_READ, AST_FRAMEHOOK_EVENT_WRITE, ast_frfree, ast_frisolate(), ast_log, AST_MODEM_T38, ast_null_frame, ast_set_read_format(), ast_set_write_format(), ast_string_field_build, ast_string_field_set, ast_test_flag, ast_translate(), ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), fax_gateway::bridged, fax_gateway::chan_read_format, fax_gateway::chan_write_format, ast_fax_session::details, fax_gateway::detected_v21, error(), fax_gateway_detect_t38(), fax_gateway_detect_v21(), find_details(), ast_frame_subclass::format, fax_gateway::framehook, ast_frame::frametype, ast_frame_subclass::integer, LOG_ERROR, LOG_WARNING, NULL, fax_gateway::peer_read_format, fax_gateway::peer_write_format, RAII_VAR, result, fax_gateway::s, ast_frame::samples, set_channel_variables(), ast_frame::subclass, fax_gateway::t38_state, T38_STATE_NEGOTIATED, T38_STATE_REJECTED, T38_STATE_UNAVAILABLE, ast_fax_session::tech, fax_gateway::timeout_start, and ast_fax_tech::write.

Referenced by fax_gateway_attach().

03267 {
03268    struct fax_gateway *gateway = data;
03269    struct ast_channel *active;
03270    RAII_VAR(struct ast_fax_session_details *, details, NULL, ao2_cleanup);
03271    RAII_VAR(struct ast_channel *, peer, NULL, ao2_cleanup);
03272    RAII_VAR(struct ast_channel *, chan_ref, chan, ao2_cleanup);
03273 
03274    /* Ref bump channel for when we have to unlock it */
03275    ao2_ref(chan_ref, 1);
03276 
03277    if (gateway->s) {
03278       details = gateway->s->details;
03279       ao2_ref(details, 1);
03280    } else {
03281       if (!(details = find_details(chan))) {
03282          ast_log(LOG_ERROR, "no FAX session details found on chan %s for T.38 gateway session, odd\n", ast_channel_name(chan));
03283          ast_framehook_detach(chan, gateway->framehook);
03284          return f;
03285       }
03286    }
03287 
03288    /* restore audio formats when we are detached */
03289    if (event == AST_FRAMEHOOK_EVENT_DETACHED) {
03290       set_channel_variables(chan, details);
03291 
03292       if (gateway->bridged) {
03293          ast_set_read_format(chan, gateway->chan_read_format);
03294          ast_set_read_format(chan, gateway->chan_write_format);
03295 
03296          ast_channel_unlock(chan);
03297          peer = ast_channel_bridge_peer(chan);
03298          if (peer) {
03299             ast_set_read_format(peer, gateway->peer_read_format);
03300             ast_set_read_format(peer, gateway->peer_write_format);
03301             ast_channel_make_compatible(chan, peer);
03302          }
03303          ast_channel_lock(chan);
03304       }
03305       return NULL;
03306    }
03307 
03308    if (!f || (event == AST_FRAMEHOOK_EVENT_ATTACHED)) {
03309       return NULL;
03310    };
03311 
03312    /* this frame was generated by the fax gateway, pass it on */
03313    if (ast_test_flag(f, AST_FAX_FRFLAG_GATEWAY)) {
03314       return f;
03315    }
03316 
03317    /* If we aren't bridged or we don't have a peer, don't do anything */
03318    ast_channel_unlock(chan);
03319    peer = ast_channel_bridge_peer(chan);
03320    ast_channel_lock(chan);
03321    if (!peer) {
03322       return f;
03323    }
03324 
03325    if (!gateway->bridged) {
03326       /* don't start a gateway if neither channel can handle T.38 */
03327       if (ast_channel_get_t38_state(chan) == T38_STATE_UNAVAILABLE && ast_channel_get_t38_state(peer) == T38_STATE_UNAVAILABLE) {
03328          ast_debug(1, "not starting gateway for %s and %s; neither channel supports T.38\n", ast_channel_name(chan), ast_channel_name(peer));
03329          ast_framehook_detach(chan, gateway->framehook);
03330          details->gateway_id = -1;
03331 
03332          ast_string_field_set(details, result, "FAILED");
03333          ast_string_field_set(details, resultstr, "neither channel supports T.38");
03334          ast_string_field_set(details, error, "T38_NEG_ERROR");
03335          set_channel_variables(chan, details);
03336          return f;
03337       }
03338 
03339       if (details->gateway_timeout) {
03340          gateway->timeout_start = ast_tvnow();
03341       }
03342 
03343       /* we are bridged, change r/w formats to SLIN for v21 preamble
03344        * detection and T.30 */
03345       ao2_replace(gateway->chan_read_format, ast_channel_readformat(chan));
03346       ao2_replace(gateway->chan_write_format, ast_channel_readformat(chan));
03347 
03348       ao2_replace(gateway->peer_read_format, ast_channel_readformat(peer));
03349       ao2_replace(gateway->peer_write_format, ast_channel_readformat(peer));
03350 
03351       ast_set_read_format(chan, ast_format_slin);
03352       ast_set_write_format(chan, ast_format_slin);
03353 
03354       ast_channel_unlock(chan);
03355       ast_set_read_format(peer, ast_format_slin);
03356       ast_set_write_format(peer, ast_format_slin);
03357 
03358       ast_channel_make_compatible(chan, peer);
03359       ast_channel_lock(chan);
03360       gateway->bridged = 1;
03361    }
03362 
03363    if (gateway->bridged && !ast_tvzero(gateway->timeout_start)) {
03364       if (ast_tvdiff_ms(ast_tvnow(), gateway->timeout_start) > details->gateway_timeout) {
03365          ast_debug(1, "no fax activity between %s and %s after %d ms, disabling gateway\n", ast_channel_name(chan), ast_channel_name(peer), details->gateway_timeout);
03366          ast_framehook_detach(chan, gateway->framehook);
03367          details->gateway_id = -1;
03368 
03369          ast_string_field_set(details, result, "FAILED");
03370          ast_string_field_build(details, resultstr, "no fax activity after %d ms", details->gateway_timeout);
03371          ast_string_field_set(details, error, "TIMEOUT");
03372          set_channel_variables(chan, details);
03373          return f;
03374       }
03375    }
03376 
03377    /* only handle VOICE, MODEM, and CONTROL frames*/
03378    switch (f->frametype) {
03379    case AST_FRAME_VOICE:
03380       if ((ast_format_cmp(f->subclass.format, ast_format_slin) != AST_FORMAT_CMP_EQUAL) &&
03381          (ast_format_cmp(f->subclass.format, ast_format_alaw) != AST_FORMAT_CMP_EQUAL) &&
03382          (ast_format_cmp(f->subclass.format, ast_format_ulaw) != AST_FORMAT_CMP_EQUAL)) {
03383          return f;
03384       }
03385       break;
03386    case AST_FRAME_MODEM:
03387       if (f->subclass.integer == AST_MODEM_T38) {
03388          break;
03389       }
03390       return f;
03391    case AST_FRAME_CONTROL:
03392       if (f->subclass.integer == AST_CONTROL_T38_PARAMETERS) {
03393          break;
03394       }
03395       return f;
03396    default:
03397       return f;
03398    }
03399 
03400    /* detect the active channel */
03401    switch (event) {
03402    case AST_FRAMEHOOK_EVENT_WRITE:
03403       active = peer;
03404       break;
03405    case AST_FRAMEHOOK_EVENT_READ:
03406       active = chan;
03407       break;
03408    default:
03409       ast_log(LOG_WARNING, "unhandled framehook event %u\n", event);
03410       return f;
03411    }
03412 
03413    /* handle control frames */
03414    if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_T38_PARAMETERS) {
03415       return fax_gateway_detect_t38(gateway, chan, peer, active, f);
03416    }
03417 
03418    if (!gateway->detected_v21 && gateway->t38_state == T38_STATE_UNAVAILABLE && f->frametype == AST_FRAME_VOICE) {
03419       /* not in gateway mode and have not detected v21 yet, listen
03420        * for v21 */
03421       return fax_gateway_detect_v21(gateway, chan, peer, active, f);
03422    }
03423 
03424    /* in gateway mode, gateway some packets */
03425    if (gateway->t38_state == T38_STATE_NEGOTIATED) {
03426       struct ast_trans_pvt *readtrans;
03427       /* framehooks are called in __ast_read() before frame format
03428        * translation is done, so we need to translate here */
03429       if ((f->frametype == AST_FRAME_VOICE) && (ast_format_cmp(f->subclass.format, ast_format_slin) != AST_FORMAT_CMP_EQUAL)
03430          && (readtrans = ast_channel_readtrans(active))) {
03431          if ((f = ast_translate(readtrans, f, 1)) == NULL) {
03432             f = &ast_null_frame;
03433             return f;
03434          }
03435          /* XXX we ignore the return value here, perhaps we should
03436           * disable the gateway if a write fails. I am not sure how a
03437           * write would fail, or even if a failure would be fatal so for
03438           * now we'll just ignore the return value. */
03439          gateway->s->tech->write(gateway->s, f);
03440          ast_frfree(f);
03441       } else {
03442          gateway->s->tech->write(gateway->s, f);
03443       }
03444 
03445       f = &ast_null_frame;
03446       return f;
03447    }
03448 
03449    /* force silence on the line if T.38 negotiation might be taking place */
03450    if (gateway->t38_state != T38_STATE_UNAVAILABLE && gateway->t38_state != T38_STATE_REJECTED) {
03451       if (f->frametype == AST_FRAME_VOICE &&
03452          (ast_format_cmp(f->subclass.format, ast_format_slin) == AST_FORMAT_CMP_EQUAL)) {
03453          short silence_buf[f->samples];
03454          struct ast_frame silence_frame = {
03455             .frametype = AST_FRAME_VOICE,
03456             .subclass.format = ast_format_slin,
03457             .data.ptr = silence_buf,
03458             .samples = f->samples,
03459             .datalen = sizeof(silence_buf),
03460          };
03461          memset(silence_buf, 0, sizeof(silence_buf));
03462          return ast_frisolate(&silence_frame);
03463       } else {
03464          return &ast_null_frame;
03465       }
03466    }
03467 
03468    return f;
03469 }

static void fax_gateway_framehook_destroy ( void *  data  )  [static]

Destroy the gateway data structure when the framehook is detached.

Parameters:
data framehook data (gateway data)

Definition at line 3231 of file res_fax.c.

References ao2_ref, AST_FAX_STATE_ACTIVE, AST_FAX_STATE_COMPLETE, AST_FAX_STATE_INITIALIZED, AST_FAX_STATE_OPEN, ast_fax_tech::cancel_session, fax_gateway::s, ast_fax_session::state, and ast_fax_session::tech.

Referenced by fax_gateway_attach().

03232 {
03233    struct fax_gateway *gateway = data;
03234 
03235    if (gateway->s) {
03236       switch (gateway->s->state) {
03237       case AST_FAX_STATE_INITIALIZED:
03238       case AST_FAX_STATE_OPEN:
03239       case AST_FAX_STATE_ACTIVE:
03240       case AST_FAX_STATE_COMPLETE:
03241          if (gateway->s->tech->cancel_session) {
03242             gateway->s->tech->cancel_session(gateway->s);
03243          }
03244          /* fall through */
03245       default:
03246          break;
03247       }
03248    }
03249 
03250    ao2_ref(gateway, -1);
03251 }

static int fax_gateway_indicate_t38 ( struct ast_channel chan,
struct ast_channel active,
struct ast_control_t38_parameters control_params 
) [static]

Definition at line 2996 of file res_fax.c.

References AST_CONTROL_T38_PARAMETERS, ast_indicate_data(), and ast_queue_control_data().

Referenced by fax_gateway_detect_t38().

02997 {
02998    if (active == chan) {
02999       return ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, control_params, sizeof(*control_params));
03000    } else {
03001       return ast_queue_control_data(chan, AST_CONTROL_T38_PARAMETERS, control_params, sizeof(*control_params));
03002    }
03003 }

static struct fax_gateway* fax_gateway_new ( struct ast_channel chan,
struct ast_fax_session_details details 
) [static, read]

Create a new fax gateway object.

Parameters:
chan the channel the gateway object will be attached to
details the fax session details
Returns:
NULL or a fax gateway object

Definition at line 2843 of file res_fax.c.

References ao2_alloc, ao2_ref, AST_FAX_TECH_GATEWAY, AST_FAX_TECH_V21_DETECT, ast_log, ast_fax_session_details::caps, fax_gateway::chan_v21_session, destroy_gateway(), fax_session_new(), fax_session_reserve(), fax_gateway::framehook, ast_fax_session_details::gateway_timeout, LOG_ERROR, NULL, fax_gateway::peer_v21_session, fax_gateway::s, session_details_new(), and fax_gateway::token.

Referenced by fax_gateway_attach().

02844 {
02845    struct fax_gateway *gateway = ao2_alloc(sizeof(*gateway), destroy_gateway);
02846    struct ast_fax_session_details *v21_details;
02847    if (!gateway) {
02848       return NULL;
02849    }
02850 
02851    if (!(v21_details = session_details_new())) {
02852       ao2_ref(gateway, -1);
02853       return NULL;
02854    }
02855 
02856    v21_details->caps = AST_FAX_TECH_V21_DETECT;
02857    if (!(gateway->chan_v21_session = fax_session_new(v21_details, chan, NULL, NULL))) {
02858       ao2_ref(v21_details, -1);
02859       ao2_ref(gateway, -1);
02860       return NULL;
02861    }
02862 
02863    if (!(gateway->peer_v21_session = fax_session_new(v21_details, chan, NULL, NULL))) {
02864       ao2_ref(v21_details, -1);
02865       ao2_ref(gateway, -1);
02866       return NULL;
02867    }
02868    ao2_ref(v21_details, -1);
02869 
02870    gateway->framehook = -1;
02871 
02872    details->caps = AST_FAX_TECH_GATEWAY;
02873    if (details->gateway_timeout && !(gateway->s = fax_session_reserve(details, &gateway->token))) {
02874       details->caps &= ~AST_FAX_TECH_GATEWAY;
02875       ast_log(LOG_ERROR, "Can't reserve a FAX session, gateway attempt failed.\n");
02876       ao2_ref(gateway, -1);
02877       return NULL;
02878    }
02879 
02880    return gateway;
02881 }

static struct ast_frame* fax_gateway_request_t38 ( struct fax_gateway gateway,
struct ast_channel chan,
struct ast_frame f 
) [static, read]

Definition at line 2931 of file res_fax.c.

References ao2_ref, ast_channel_name(), AST_CONTROL_T38_PARAMETERS, ast_debug, AST_FRAME_CONTROL, ast_framehook_detach(), ast_frisolate(), ast_log, AST_T38_REQUEST_NEGOTIATE, ast_tvnow(), FAX_GATEWAY_TIMEOUT, find_details(), fax_gateway::framehook, ast_fax_session_details::gateway_timeout, ast_frame_subclass::integer, LOG_ERROR, ast_fax_session_details::our_t38_parameters, ast_control_t38_parameters::request_response, ast_frame::src, ast_frame::subclass, t38_parameters_fax_to_ast(), fax_gateway::t38_state, T38_STATE_NEGOTIATING, and fax_gateway::timeout_start.

Referenced by fax_gateway_detect_v21().

02932 {
02933    struct ast_frame *fp;
02934    struct ast_control_t38_parameters t38_parameters = {
02935       .request_response = AST_T38_REQUEST_NEGOTIATE,
02936    };
02937    struct ast_frame control_frame = {
02938       .src = "res_fax",
02939       .frametype = AST_FRAME_CONTROL,
02940       .datalen = sizeof(t38_parameters),
02941       .subclass.integer = AST_CONTROL_T38_PARAMETERS,
02942       .data.ptr = &t38_parameters,
02943    };
02944 
02945    struct ast_fax_session_details *details = find_details(chan);
02946 
02947    if (!details) {
02948       ast_log(LOG_ERROR, "no FAX session details found on chan %s for T.38 gateway session, odd\n", ast_channel_name(chan));
02949       ast_framehook_detach(chan, gateway->framehook);
02950       return f;
02951    }
02952 
02953    t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
02954    ao2_ref(details, -1);
02955 
02956    if (!(fp = ast_frisolate(&control_frame))) {
02957       ast_log(LOG_ERROR, "error generating T.38 request control frame on chan %s for T.38 gateway session\n", ast_channel_name(chan));
02958       return f;
02959    }
02960 
02961    gateway->t38_state = T38_STATE_NEGOTIATING;
02962    gateway->timeout_start = ast_tvnow();
02963    details->gateway_timeout = FAX_GATEWAY_TIMEOUT;
02964 
02965    ast_debug(1, "requesting T.38 for gateway session for %s\n", ast_channel_name(chan));
02966    return fp;
02967 }

static int fax_gateway_start ( struct fax_gateway gateway,
struct ast_fax_session_details details,
struct ast_channel chan 
) [static]

Create a fax session and start T.30<->T.38 gateway mode.

Parameters:
gateway a fax gateway object
details fax session details
chan active channel
Returns:
0 on error 1 on success

Definition at line 2888 of file res_fax.c.

References ao2_ref, ast_channel_lock, ast_channel_unlock, ast_log, ast_string_field_set, error(), fax_session_new(), LOG_ERROR, NULL, report_fax_status(), result, fax_gateway::s, set_channel_variables(), ast_fax_tech::start_session, ast_fax_session::tech, fax_gateway::timeout_start, and fax_gateway::token.

Referenced by fax_gateway_detect_t38().

02889 {
02890    struct ast_fax_session *s;
02891    int start_res;
02892 
02893    /* create the FAX session */
02894    if (!(s = fax_session_new(details, chan, gateway->s, gateway->token))) {
02895       gateway->token = NULL;
02896       ast_string_field_set(details, result, "FAILED");
02897       ast_string_field_set(details, resultstr, "error starting gateway session");
02898       ast_string_field_set(details, error, "INIT_ERROR");
02899       set_channel_variables(chan, details);
02900       report_fax_status(chan, details, "No Available Resource");
02901       ast_log(LOG_ERROR, "Can't create a FAX session, gateway attempt failed.\n");
02902       return -1;
02903    }
02904    /* release the reference for the reserved session and replace it with
02905     * the real session */
02906    if (gateway->s) {
02907       ao2_ref(gateway->s, -1);
02908    }
02909    gateway->s = s;
02910    gateway->token = NULL;
02911 
02912    ast_channel_unlock(chan);
02913    start_res = gateway->s->tech->start_session(gateway->s);
02914    ast_channel_lock(chan);
02915    if (start_res < 0) {
02916       ast_string_field_set(details, result, "FAILED");
02917       ast_string_field_set(details, resultstr, "error starting gateway session");
02918       ast_string_field_set(details, error, "INIT_ERROR");
02919       set_channel_variables(chan, details);
02920       return -1;
02921    }
02922 
02923    gateway->timeout_start.tv_sec = 0;
02924    gateway->timeout_start.tv_usec = 0;
02925 
02926    report_fax_status(chan, details, "FAX Transmission In Progress");
02927 
02928    return 0;
02929 }

static unsigned int fax_rate_str_to_int ( const char *  ratestr  )  [static]

convert a rate string to a rate

Definition at line 1053 of file res_fax.c.

References ast_log, LOG_ERROR, and LOG_WARNING.

Referenced by acf_faxopt_write(), and set_config().

01054 {
01055    int rate;
01056 
01057    if (sscanf(ratestr, "%d", &rate) != 1) {
01058       ast_log(LOG_ERROR, "failed to sscanf '%s' to rate\n", ratestr);
01059       return 0;
01060    }
01061    switch (rate) {
01062    case 2400:
01063    case 4800:
01064    case 7200:
01065    case 9600:
01066    case 12000:
01067    case 14400:
01068    case 28800:
01069    case 33600:
01070       return rate;
01071    default:
01072       ast_log(LOG_WARNING, "ignoring invalid rate '%s'.  Valid options are {2400 | 4800 | 7200 | 9600 | 12000 | 14400 | 28800 | 33600}\n", ratestr);
01073       return 0;
01074    }
01075 }

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 
) [static, read]

create a FAX session

Parameters:
details details for the session
chan the channel the session will run on
reserved a reserved session to base this session on (can be NULL)
token the token for a reserved session (can be NULL)
Create a new fax session based on the given details structure.

Note:
The given token is always consumed (by tech->new_session() or by fax_session_release() in the event of a failure). The given reference to a reserved session is never consumed and must be dereferenced separately from the reference returned by this function.
Returns:
NULL or a reference to a new fax session

Definition at line 1219 of file res_fax.c.

References ao2_alloc, ao2_link, ao2_ref, ao2_unlink, ast_atomic_fetchadd_int(), ast_calloc, ast_channel_name(), ast_channel_uniqueid(), ast_debug, ast_dsp_new(), ast_dsp_set_threshold(), ast_fax_caps_to_str(), AST_FAX_STATE_RESERVED, AST_FAX_STATE_UNINITIALIZED, AST_FAX_TECH_AUDIO, ast_free, ast_log, ast_module_ref, ast_module_unref, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdup, ast_fax_tech::caps, ast_fax_session_details::caps, ast_fax_session::chan, ast_fax_session::chan_uniqueid, ast_fax_session::channame, ast_fax_session_details::debug, ast_fax_session::debug_info, ast_fax_tech::description, destroy_session(), ast_fax_session::details, ast_fax_debug_info::dsp, fax_session_release(), faxregistry, ast_fax_session::id, ast_fax_session_details::id, LOG_ERROR, ast_fax_tech::module, ast_fax_tech::new_session, NULL, ast_fax_session_details::option, ast_fax_session::state, ast_fax_session::tech, fax_module::tech, and ast_fax_session::tech_pvt.

Referenced by fax_gateway_new(), fax_gateway_start(), and generic_fax_exec().

01220 {
01221    struct ast_fax_session *s = NULL;
01222    struct fax_module *faxmod;
01223 
01224    if (reserved) {
01225       s = reserved;
01226       ao2_ref(reserved, +1);
01227       ao2_unlink(faxregistry.container, reserved);
01228 
01229       /* NOTE: we don't consume the reference to the reserved
01230        * session. The session returned from fax_session_new() is a
01231        * new reference and must be derefed in addition to the
01232        * reserved session.
01233        */
01234 
01235       if (s->state == AST_FAX_STATE_RESERVED) {
01236          ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, -1);
01237          s->state = AST_FAX_STATE_UNINITIALIZED;
01238       }
01239    }
01240 
01241    if (!s && !(s = ao2_alloc(sizeof(*s), destroy_session))) {
01242       return NULL;
01243    }
01244 
01245    ast_atomic_fetchadd_int(&faxregistry.active_sessions, 1);
01246    s->state = AST_FAX_STATE_UNINITIALIZED;
01247 
01248    if (details->option.debug && (details->caps & AST_FAX_TECH_AUDIO)) {
01249       if (!(s->debug_info = ast_calloc(1, sizeof(*(s->debug_info))))) {
01250          fax_session_release(s, token);
01251          ao2_ref(s, -1);
01252          return NULL;
01253       }
01254       if (!(s->debug_info->dsp = ast_dsp_new())) {
01255          ast_free(s->debug_info);
01256          s->debug_info = NULL;
01257          fax_session_release(s, token);
01258          ao2_ref(s, -1);
01259          return NULL;
01260       }
01261       ast_dsp_set_threshold(s->debug_info->dsp, 128);
01262    }
01263 
01264    if (!(s->channame = ast_strdup(ast_channel_name(chan)))) {
01265       fax_session_release(s, token);
01266       ao2_ref(s, -1);
01267       return NULL;
01268    }
01269 
01270    if (!(s->chan_uniqueid = ast_strdup(ast_channel_uniqueid(chan)))) {
01271       fax_session_release(s, token);
01272       ao2_ref(s, -1);
01273       return NULL;
01274    }
01275 
01276    s->chan = chan;
01277    if (!s->details) {
01278       s->details = details;
01279       ao2_ref(s->details, 1);
01280    }
01281 
01282    details->id = s->id = ast_atomic_fetchadd_int(&faxregistry.nextsessionname, 1);
01283 
01284    if (!token) {
01285       /* locate a FAX technology module that can handle said requirements */
01286       AST_RWLIST_RDLOCK(&faxmodules);
01287       AST_RWLIST_TRAVERSE(&faxmodules, faxmod, list) {
01288          if ((faxmod->tech->caps & details->caps) != details->caps) {
01289             continue;
01290          }
01291          ast_debug(4, "Requesting a new FAX session from '%s'.\n", faxmod->tech->description);
01292          ast_module_ref(faxmod->tech->module);
01293          if (reserved) {
01294             /* Balance module ref from reserved session */
01295             ast_module_unref(reserved->tech->module);
01296          }
01297          s->tech = faxmod->tech;
01298          break;
01299       }
01300       AST_RWLIST_UNLOCK(&faxmodules);
01301 
01302       if (!faxmod) {
01303          char caps[128] = "";
01304          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)));
01305          ao2_ref(s, -1);
01306          return NULL;
01307       }
01308    }
01309 
01310    if (!(s->tech_pvt = s->tech->new_session(s, token))) {
01311       ast_log(LOG_ERROR, "FAX session failed to initialize.\n");
01312       ao2_ref(s, -1);
01313       return NULL;
01314    }
01315    /* link the session to the session container */
01316    if (!(ao2_link(faxregistry.container, s))) {
01317       ast_log(LOG_ERROR, "failed to add FAX session '%u' to container.\n", s->id);
01318       ao2_ref(s, -1);
01319       return NULL;
01320    }
01321    ast_debug(4, "channel '%s' using FAX session '%u'\n", s->channame, s->id);
01322 
01323    return s;
01324 }

static void fax_session_release ( struct ast_fax_session s,
struct ast_fax_tech_token *  token 
) [static]

Release a session token.

Parameters:
s a session returned from fax_session_reserve()
token a token generated from fax_session_reserve()
This function releases the given token and marks the given session as no longer reserved. It is safe to call on a session that is not actually reserved and with a NULL token. This is so that sessions returned by technologies that do not support reserved sessions don't require extra logic to handle.

Note:
This function DOES NOT release the given fax session, only the given token.

Definition at line 1090 of file res_fax.c.

References ast_atomic_fetchadd_int(), AST_FAX_STATE_INACTIVE, AST_FAX_STATE_RESERVED, faxregistry, ast_fax_tech::release_token, ast_fax_session::state, and ast_fax_session::tech.

Referenced by destroy_gateway(), destroy_session(), fax_session_new(), receivefax_exec(), and sendfax_exec().

01091 {
01092    if (token) {
01093       s->tech->release_token(token);
01094    }
01095 
01096    if (s->state == AST_FAX_STATE_RESERVED) {
01097       ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, -1);
01098       s->state = AST_FAX_STATE_INACTIVE;
01099    }
01100 }

static struct ast_fax_session* fax_session_reserve ( struct ast_fax_session_details details,
struct ast_fax_tech_token **  token 
) [static, read]

Reserve a fax session.

Parameters:
details the fax session details
token a pointer to a place to store a token to be passed to fax_session_new() later
This function reserves a fax session for use later. If the selected fax technology does not support reserving sessions a session will still be returned but token will not be set.

Note:
The reference returned by this function does not get consumed by fax_session_new() and must always be dereferenced separately.
Returns:
NULL or an uninitialized and possibly reserved session

Definition at line 1152 of file res_fax.c.

References ao2_alloc, ao2_ref, ast_atomic_fetchadd_int(), ast_debug, ast_fax_caps_to_str(), AST_FAX_STATE_INACTIVE, AST_FAX_STATE_RESERVED, ast_log, ast_module_ref, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_fax_session_details::caps, ast_fax_tech::caps, ast_fax_tech::description, destroy_session(), ast_fax_session::details, faxregistry, LOG_ERROR, ast_fax_tech::module, NULL, ast_fax_tech::reserve_session, ast_fax_session::state, ast_fax_session::tech, and fax_module::tech.

Referenced by fax_gateway_new(), receivefax_exec(), and sendfax_exec().

01153 {
01154    struct ast_fax_session *s;
01155    struct fax_module *faxmod;
01156 
01157    if (!(s = ao2_alloc(sizeof(*s), destroy_session))) {
01158       return NULL;
01159    }
01160 
01161    s->state = AST_FAX_STATE_INACTIVE;
01162    s->details = details;
01163    ao2_ref(s->details, 1);
01164 
01165    /* locate a FAX technology module that can handle said requirements
01166     * Note: the requirements have not yet been finalized as T.38
01167     * negotiation has not yet occured. */
01168    AST_RWLIST_RDLOCK(&faxmodules);
01169    AST_RWLIST_TRAVERSE(&faxmodules, faxmod, list) {
01170       if ((faxmod->tech->caps & details->caps) != details->caps) {
01171          continue;
01172       }
01173       ast_debug(4, "Reserving a FAX session from '%s'.\n", faxmod->tech->description);
01174       ast_module_ref(faxmod->tech->module);
01175       s->tech = faxmod->tech;
01176       break;
01177    }
01178    AST_RWLIST_UNLOCK(&faxmodules);
01179 
01180    if (!faxmod) {
01181       char caps[128] = "";
01182       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)));
01183       ao2_ref(s, -1);
01184       return NULL;
01185    }
01186 
01187    if (!s->tech->reserve_session) {
01188       ast_debug(1, "Selected FAX technology module (%s) does not support reserving sessions.\n", s->tech->description);
01189       return s;
01190    }
01191 
01192    if (!(*token = s->tech->reserve_session(s))) {
01193       ao2_ref(s, -1);
01194       return NULL;
01195    }
01196 
01197    s->state = AST_FAX_STATE_RESERVED;
01198    ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, 1);
01199 
01200    return s;
01201 }

static char* fax_session_tab_complete ( struct ast_cli_args a  )  [static]

fax session tab completion

Definition at line 3781 of file res_fax.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_strdup, faxregistry, ast_fax_session::id, ast_cli_args::n, name, NULL, ast_cli_args::pos, and ast_cli_args::word.

Referenced by cli_fax_show_session().

03782 {
03783    int tklen;
03784    int wordnum = 0;
03785    char *name = NULL;
03786    struct ao2_iterator i;
03787    struct ast_fax_session *s;
03788    char tbuf[5];
03789 
03790    if (a->pos != 3) {
03791       return NULL;
03792    }
03793 
03794    tklen = strlen(a->word);
03795    i = ao2_iterator_init(faxregistry.container, 0);
03796    while ((s = ao2_iterator_next(&i))) {
03797       snprintf(tbuf, sizeof(tbuf), "%u", s->id);
03798       if (!strncasecmp(a->word, tbuf, tklen) && ++wordnum > a->n) {
03799          name = ast_strdup(tbuf);
03800          ao2_ref(s, -1);
03801          break;
03802       }
03803       ao2_ref(s, -1);
03804    }
03805    ao2_iterator_destroy(&i);
03806    return name;
03807 }

static const char* fax_session_type ( struct ast_fax_session s  )  [static]

Definition at line 4079 of file res_fax.c.

References AST_FAX_TECH_AUDIO, AST_FAX_TECH_T38, ast_fax_session_details::caps, and ast_fax_session::details.

Referenced by cli_fax_show_sessions(), and manager_fax_sessions_entry().

04080 {
04081    if (s->details->caps & AST_FAX_TECH_AUDIO) {
04082       return "G.711";
04083    }
04084    if (s->details->caps & AST_FAX_TECH_T38) {
04085       return "T.38";
04086    }
04087 
04088    return "none";
04089 }

static struct ast_fax_session_details* find_details ( struct ast_channel chan  )  [static, read]

returns a reference counted pointer to a fax datastore, if it exists

Definition at line 660 of file res_fax.c.

References ao2_ref, ast_channel_datastore_find(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_log, ast_datastore::data, LOG_WARNING, and NULL.

Referenced by acf_faxopt_read(), fax_gateway_detect_t38(), fax_gateway_framehook(), fax_gateway_request_t38(), and find_or_create_details().

00661 {
00662    struct ast_fax_session_details *details;
00663    struct ast_datastore *datastore;
00664 
00665    ast_channel_lock(chan);
00666    if (!(datastore = ast_channel_datastore_find(chan, &fax_datastore, NULL))) {
00667       ast_channel_unlock(chan);
00668       return NULL;
00669    }
00670    if (!(details = datastore->data)) {
00671       ast_log(LOG_WARNING, "Huh?  channel '%s' has a FAX datastore without data!\n", ast_channel_name(chan));
00672       ast_channel_unlock(chan);
00673       return NULL;
00674    }
00675    ao2_ref(details, 1);
00676    ast_channel_unlock(chan);
00677 
00678    return details;
00679 }

static struct ast_fax_session_details * find_or_create_details ( struct ast_channel chan  )  [static, read]

returns a reference counted details structure from the channel's fax datastore. If the datastore does not exist it will be created

Definition at line 761 of file res_fax.c.

References ao2_ref, ast_channel_datastore_add(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_datastore_alloc, ast_log, ast_datastore::data, find_details(), LOG_WARNING, NULL, ast_fax_session_details::our_t38_parameters, session_details_new(), t38_parameters_ast_to_fax(), and ast_fax_session_details::their_t38_parameters.

Referenced by acf_faxopt_write(), fax_detect_attach(), fixup_callback(), receivefax_exec(), and sendfax_exec().

00762 {
00763    struct ast_fax_session_details *details;
00764    struct ast_datastore *datastore;
00765 
00766    if ((details = find_details(chan))) {
00767       return details;
00768    }
00769    /* channel does not have one so we must create one */
00770    if (!(details = session_details_new())) {
00771       ast_log(LOG_WARNING, "channel '%s' can't get a FAX details structure for the datastore!\n", ast_channel_name(chan));
00772       return NULL;
00773    }
00774    if (!(datastore = ast_datastore_alloc(&fax_datastore, NULL))) {
00775       ao2_ref(details, -1);
00776       ast_log(LOG_WARNING, "channel '%s' can't get a datastore!\n", ast_channel_name(chan));
00777       return NULL;
00778    }
00779    /* add the datastore to the channel and increment the refcount */
00780    datastore->data = details;
00781 
00782    /* initialize default T.38 parameters */
00783    t38_parameters_ast_to_fax(&details->our_t38_parameters, &our_t38_parameters);
00784    t38_parameters_ast_to_fax(&details->their_t38_parameters, &our_t38_parameters);
00785 
00786    ao2_ref(details, 1);
00787    ast_channel_lock(chan);
00788    ast_channel_datastore_add(chan, datastore);
00789    ast_channel_unlock(chan);
00790    return details;
00791 }

static void fixup_callback ( void *  data,
struct ast_channel old_chan,
struct ast_channel new_chan 
) [static]

Copies fax detection and gateway framehooks during masquerades.

Note:
must be called with both old_chan and new_chan locked. Since this is only called by do_masquerade, that shouldn't be an issue.

Definition at line 635 of file res_fax.c.

References ao2_cleanup, ast_channel_datastore_find(), ast_channel_datastore_remove(), ast_datastore_free(), ast_framehook_detach(), fax_detect_attach(), fax_gateway_attach(), ast_fax_session_details::faxdetect_flags, ast_fax_session_details::faxdetect_id, ast_fax_session_details::faxdetect_timeout, find_or_create_details(), ast_fax_session_details::gateway_id, and NULL.

00636 {
00637    struct ast_fax_session_details *old_details = data;
00638    struct ast_datastore *datastore = ast_channel_datastore_find(old_chan, &fax_datastore, NULL);
00639 
00640    if (old_details->gateway_id >= 0) {
00641       struct ast_fax_session_details *new_details = find_or_create_details(new_chan);
00642 
00643       ast_framehook_detach(old_chan, old_details->gateway_id);
00644       fax_gateway_attach(new_chan, new_details);
00645       ao2_cleanup(new_details);
00646    }
00647 
00648    if (old_details->faxdetect_id >= 0) {
00649       ast_framehook_detach(old_chan, old_details->faxdetect_id);
00650       fax_detect_attach(new_chan, old_details->faxdetect_timeout, old_details->faxdetect_flags);
00651    }
00652 
00653    if (datastore) {
00654       ast_channel_datastore_remove(old_chan, datastore);
00655       ast_datastore_free(datastore);
00656    }
00657 }

static struct ast_json* generate_filenames_json ( struct ast_fax_session_details details  )  [static, read]

Definition at line 1332 of file res_fax.c.

References ast_json_array_append(), ast_json_array_create(), ast_json_ref(), ast_json_string_create(), ast_json_unref(), AST_LIST_EMPTY, AST_LIST_TRAVERSE, ast_fax_session_details::documents, ast_fax_document::filename, fax_module::next, NULL, and RAII_VAR.

Referenced by report_fax_status(), and report_send_fax_status().

01333 {
01334    RAII_VAR(struct ast_json *, json_array, ast_json_array_create(), ast_json_unref);
01335    struct ast_fax_document *doc;
01336 
01337    if (!details || !json_array) {
01338       return NULL;
01339    }
01340 
01341    /* don't process empty lists */
01342    if (AST_LIST_EMPTY(&details->documents)) {
01343       return NULL;
01344    }
01345 
01346    AST_LIST_TRAVERSE(&details->documents, doc, next) {
01347       struct ast_json *entry = ast_json_string_create(doc->filename);
01348       if (!entry) {
01349          return NULL;
01350       }
01351       if (ast_json_array_append(json_array, entry)) {
01352          return NULL;
01353       }
01354    }
01355 
01356    ast_json_ref(json_array);
01357    return json_array;
01358 }

static char* generate_filenames_string ( struct ast_fax_session_details details,
char *  prefix,
char *  separator 
) [static]

Generate a string of filenames using the given prefix and separator.

Parameters:
details the fax session details
prefix the prefix to each filename
separator the separator between filenames
This function generates a string of filenames from the given details structure and using the given prefix and separator.

Return values:
NULL there was an error generating the string
Returns:
the string generated string

Definition at line 1372 of file res_fax.c.

References ast_build_string(), AST_LIST_EMPTY, AST_LIST_FIRST, AST_LIST_TRAVERSE, ast_malloc, ast_strdup, c, ast_fax_session_details::documents, ast_fax_document::filename, first, fax_module::next, and NULL.

Referenced by acf_faxopt_read(), cli_fax_show_sessions(), manager_fax_sessions_entry(), and sendfax_exec().

01373 {
01374    char *filenames, *c;
01375    size_t size = 0;
01376    int first = 1;
01377    struct ast_fax_document *doc;
01378 
01379    /* don't process empty lists */
01380    if (AST_LIST_EMPTY(&details->documents)) {
01381       return ast_strdup("");
01382    }
01383 
01384    /* Calculate the total length of all of the file names */
01385    AST_LIST_TRAVERSE(&details->documents, doc, next) {
01386       size += strlen(separator) + strlen(prefix) + strlen(doc->filename);
01387    }
01388    size += 1; /* add space for the terminating null */
01389 
01390    if (!(filenames = ast_malloc(size))) {
01391       return NULL;
01392    }
01393    c = filenames;
01394 
01395    ast_build_string(&c, &size, "%s%s", prefix, AST_LIST_FIRST(&details->documents)->filename);
01396    AST_LIST_TRAVERSE(&details->documents, doc, next) {
01397       if (first) {
01398          first = 0;
01399          continue;
01400       }
01401 
01402       ast_build_string(&c, &size, "%s%s%s", separator, prefix, doc->filename);
01403    }
01404 
01405    return filenames;
01406 }

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 
) [static]

this is the generic FAX session handling function

Definition at line 1583 of file res_fax.c.

References ao2_bump, ao2_cleanup, ao2_ref, ao2_unlink, ast_atomic_fetchadd_int(), ast_channel_get_t38_state(), ast_channel_lock, ast_channel_name(), ast_channel_readformat(), ast_channel_unlock, ast_channel_writeformat(), AST_CONTROL_T38_PARAMETERS, ast_debug, AST_FAX_TECH_AUDIO, AST_FAX_TECH_T38, ast_format_cmp(), AST_FORMAT_CMP_NOT_EQUAL, ast_format_slin, AST_FRAME_CONTROL, AST_FRAME_MODEM, AST_FRAME_VOICE, ast_frfree, ast_indicate_data(), ast_log, AST_MODEM_T38, ast_read(), ast_remaining_ms(), ast_set_read_format(), ast_set_write_format(), ast_smoother_feed, ast_smoother_free(), ast_smoother_new(), ast_smoother_read(), ast_string_field_set, ast_strlen_zero, AST_T38_NEGOTIATED, AST_T38_REFUSED, AST_T38_REQUEST_NEGOTIATE, ast_tvnow(), ast_verb, ast_waitfor_nandfds(), ast_write(), ast_fax_debug_info::base_tv, c, ast_fax_tech::cancel_session, ast_fax_session_details::caps, chancount, ast_frame::data, ast_frame::datalen, debug_check_frame_for_silence(), ast_fax_session::debug_info, errno, error(), f, fax_session_new(), faxregistry, ast_fax_session::fd, ast_frame_subclass::format, ast_fax_session::frames_received, ast_fax_session::frames_sent, ast_frame::frametype, ast_fax_tech::generate_silence, GENERIC_FAX_EXEC_ERROR, GENERIC_FAX_EXEC_SET_VARS, ast_fax_session_details::headerinfo, ast_fax_session::id, ast_frame_subclass::integer, ast_fax_session_details::localstationid, LOG_ERROR, LOG_WARNING, NULL, ast_fax_session_details::our_t38_parameters, pbx_builtin_getvar_helper(), ast_frame::ptr, RAII_VAR, ast_fax_tech::read, report_fax_status(), ast_control_t38_parameters::request_response, RES_FAX_TIMEOUT, ast_fax_session_details::result, result, set_channel_variables(), ast_fax_session::smoother, ast_fax_tech::start_session, ast_frame::subclass, ast_fax_tech::switch_to_t38, t38_parameters_ast_to_fax(), t38_parameters_fax_to_ast(), T38_STATE_NEGOTIATED, ast_fax_session::tech, ast_fax_session_details::their_t38_parameters, timeout, and ast_fax_tech::write.

Referenced by receivefax_exec(), and sendfax_exec().

01584 {
01585    int ms;
01586    int timeout = RES_FAX_TIMEOUT;
01587    int chancount;
01588    unsigned int expected_frametype = -1;
01589    struct ast_frame_subclass expected_framesubclass = { .integer = 0, };
01590    unsigned int t38negotiated = (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED);
01591    struct ast_control_t38_parameters t38_parameters;
01592    const char *tempvar;
01593    struct ast_fax_session *fax = NULL;
01594    struct ast_frame *frame = NULL;
01595    struct ast_channel *c = chan;
01596    RAII_VAR(struct ast_format *, orig_write_format, NULL, ao2_cleanup);
01597    RAII_VAR(struct ast_format *, orig_read_format, NULL, ao2_cleanup);
01598    int remaining_time;
01599    struct timeval start;
01600 
01601    chancount = 1;
01602 
01603    /* create the FAX session */
01604    if (!(fax = fax_session_new(details, chan, reserved, token))) {
01605       ast_log(LOG_ERROR, "Can't create a FAX session, FAX attempt failed.\n");
01606       report_fax_status(chan, details, "No Available Resource");
01607       return -1;
01608    }
01609 
01610    ast_channel_lock(chan);
01611    /* update session details */
01612    if (ast_strlen_zero(details->headerinfo) && (tempvar = pbx_builtin_getvar_helper(chan, "LOCALHEADERINFO"))) {
01613       ast_string_field_set(details, headerinfo, tempvar);
01614    }
01615    if (ast_strlen_zero(details->localstationid)) {
01616       tempvar = pbx_builtin_getvar_helper(chan, "LOCALSTATIONID");
01617       ast_string_field_set(details, localstationid, tempvar ? tempvar : "unknown");
01618    }
01619    ast_channel_unlock(chan);
01620 
01621    report_fax_status(chan, details, "Allocating Resources");
01622 
01623    if (details->caps & AST_FAX_TECH_AUDIO) {
01624       expected_frametype = AST_FRAME_VOICE;
01625       expected_framesubclass.format = ast_format_slin;
01626       orig_write_format = ao2_bump(ast_channel_writeformat(chan));
01627       if (ast_set_write_format(chan, ast_format_slin) < 0) {
01628          ast_log(LOG_ERROR, "channel '%s' failed to set write format to signed linear'.\n", ast_channel_name(chan));
01629          ao2_unlink(faxregistry.container, fax);
01630          ao2_ref(fax, -1);
01631          return -1;
01632       }
01633       orig_read_format = ao2_bump(ast_channel_readformat(chan));
01634       if (ast_set_read_format(chan, ast_format_slin) < 0) {
01635          ast_log(LOG_ERROR, "channel '%s' failed to set read format to signed linear.\n", ast_channel_name(chan));
01636          ao2_unlink(faxregistry.container, fax);
01637          ao2_ref(fax, -1);
01638          return -1;
01639       }
01640       if (fax->smoother) {
01641          ast_smoother_free(fax->smoother);
01642          fax->smoother = NULL;
01643       }
01644       if (!(fax->smoother = ast_smoother_new(320))) {
01645          ast_log(LOG_WARNING, "Channel '%s' FAX session '%u' failed to obtain a smoother.\n", ast_channel_name(chan), fax->id);
01646       }
01647    } else {
01648       expected_frametype = AST_FRAME_MODEM;
01649       expected_framesubclass.integer = AST_MODEM_T38;
01650    }
01651 
01652    if (fax->debug_info) {
01653       fax->debug_info->base_tv = ast_tvnow();
01654    }
01655 
01656    /* reset our result fields just in case the fax tech driver wants to
01657     * set custom error messages */
01658    ast_string_field_set(details, result, "");
01659    ast_string_field_set(details, resultstr, "");
01660    ast_string_field_set(details, error, "");
01661    set_channel_variables(chan, details);
01662 
01663    if (fax->tech->start_session(fax) < 0) {
01664       GENERIC_FAX_EXEC_ERROR(fax, chan, "INIT_ERROR", "failed to start FAX session");
01665    }
01666 
01667    report_fax_status(chan, details, "FAX Transmission In Progress");
01668 
01669    ast_debug(5, "channel %s will wait on FAX fd %d\n", ast_channel_name(chan), fax->fd);
01670 
01671    /* handle frames for the session */
01672    remaining_time = timeout;
01673    start = ast_tvnow();
01674    while (remaining_time > 0) {
01675       struct ast_channel *ready_chan;
01676       int ofd, exception;
01677 
01678       ms = 1000;
01679       errno = 0;
01680       ready_chan = ast_waitfor_nandfds(&c, chancount, &fax->fd, 1, &exception, &ofd, &ms);
01681       if (ready_chan) {
01682          if (!(frame = ast_read(chan))) {
01683             /* the channel is probably gone, so lets stop polling on it and let the
01684              * FAX session complete before we exit the application.  if needed,
01685              * send the FAX stack silence so the modems can finish their session without
01686              * any problems */
01687             ast_debug(1, "Channel '%s' did not return a frame; probably hung up.\n", ast_channel_name(chan));
01688             GENERIC_FAX_EXEC_SET_VARS(fax, chan, "HANGUP", "remote channel hungup");
01689             c = NULL;
01690             chancount = 0;
01691             remaining_time = ast_remaining_ms(start, timeout);
01692             fax->tech->cancel_session(fax);
01693             if (fax->tech->generate_silence) {
01694                fax->tech->generate_silence(fax);
01695             }
01696             continue;
01697          }
01698 
01699          if ((frame->frametype == AST_FRAME_CONTROL) &&
01700              (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
01701              (frame->datalen == sizeof(t38_parameters))) {
01702             unsigned int was_t38 = t38negotiated;
01703             struct ast_control_t38_parameters *parameters = frame->data.ptr;
01704 
01705             switch (parameters->request_response) {
01706             case AST_T38_REQUEST_NEGOTIATE:
01707                /* the other end has requested a switch to T.38, so reply that we are willing, if we can
01708                 * do T.38 as well
01709                 */
01710                t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
01711                t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
01712                ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
01713                break;
01714             case AST_T38_NEGOTIATED:
01715                t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
01716                t38negotiated = 1;
01717                break;
01718             default:
01719                break;
01720             }
01721             if (t38negotiated && !was_t38) {
01722                if (fax->tech->switch_to_t38(fax)) {
01723                   GENERIC_FAX_EXEC_ERROR(fax, chan, "UNKNOWN", "T.38 switch failed");
01724                   break;
01725                }
01726                details->caps &= ~AST_FAX_TECH_AUDIO;
01727                expected_frametype = AST_FRAME_MODEM;
01728                expected_framesubclass.integer = AST_MODEM_T38;
01729                if (fax->smoother) {
01730                   ast_smoother_free(fax->smoother);
01731                   fax->smoother = NULL;
01732                }
01733 
01734                report_fax_status(chan, details, "T.38 Negotiated");
01735 
01736                ast_verb(3, "Channel '%s' switched to T.38 FAX session '%u'.\n", ast_channel_name(chan), fax->id);
01737             }
01738          } else if ((frame->frametype == expected_frametype) && (expected_framesubclass.integer == frame->subclass.integer) &&
01739             ((!frame->subclass.format && !expected_framesubclass.format) ||
01740             (frame->subclass.format && expected_framesubclass.format &&
01741                (ast_format_cmp(frame->subclass.format, expected_framesubclass.format) != AST_FORMAT_CMP_NOT_EQUAL)))) {
01742             struct ast_frame *f;
01743 
01744             if (fax->smoother) {
01745                /* push the frame into a smoother */
01746                if (ast_smoother_feed(fax->smoother, frame) < 0) {
01747                   GENERIC_FAX_EXEC_ERROR(fax, chan, "UNKNOWN", "Failed to feed the smoother");
01748                }
01749                while ((f = ast_smoother_read(fax->smoother)) && (f->data.ptr)) {
01750                   if (fax->debug_info) {
01751                      debug_check_frame_for_silence(fax, 1, f);
01752                   }
01753                   /* write the frame to the FAX stack */
01754                   fax->tech->write(fax, f);
01755                   fax->frames_received++;
01756                   if (f != frame) {
01757                      ast_frfree(f);
01758                   }
01759                }
01760             } else {
01761                /* write the frame to the FAX stack */
01762                fax->tech->write(fax, frame);
01763                fax->frames_received++;
01764             }
01765             start = ast_tvnow();
01766          }
01767          ast_frfree(frame);
01768       } else if (ofd == fax->fd) {
01769          /* read a frame from the FAX stack and send it out the channel.
01770           * the FAX stack will return a NULL if the FAX session has already completed */
01771          if (!(frame = fax->tech->read(fax))) {
01772             break;
01773          }
01774 
01775          if (fax->debug_info && (frame->frametype == AST_FRAME_VOICE)) {
01776             debug_check_frame_for_silence(fax, 0, frame);
01777          }
01778 
01779          ast_write(chan, frame);
01780          fax->frames_sent++;
01781          ast_frfree(frame);
01782          start = ast_tvnow();
01783       } else {
01784          if (ms && (ofd < 0)) {
01785             if ((errno == 0) || (errno == EINTR)) {
01786                remaining_time = ast_remaining_ms(start, timeout);
01787                if (remaining_time <= 0)
01788                   GENERIC_FAX_EXEC_ERROR(fax, chan, "TIMEOUT", "fax session timed-out");
01789                continue;
01790             } else {
01791                ast_log(LOG_WARNING, "something bad happened while channel '%s' was polling.\n", ast_channel_name(chan));
01792                GENERIC_FAX_EXEC_ERROR(fax, chan, "UNKNOWN", "error polling data");
01793                break;
01794             }
01795          } else {
01796             /* nothing happened */
01797             remaining_time = ast_remaining_ms(start, timeout);
01798             if (remaining_time <= 0) {
01799                GENERIC_FAX_EXEC_ERROR(fax, chan, "TIMEOUT", "fax session timed-out");
01800                break;
01801             }
01802          }
01803       }
01804    }
01805    ast_debug(3, "channel '%s' - event loop stopped { timeout: %d, remaining_time: %d }\n", ast_channel_name(chan), timeout, remaining_time);
01806 
01807    set_channel_variables(chan, details);
01808 
01809    ast_atomic_fetchadd_int(&faxregistry.fax_complete, 1);
01810    if (!strcasecmp(details->result, "FAILED")) {
01811       ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
01812    }
01813 
01814    if (fax) {
01815       ao2_unlink(faxregistry.container, fax);
01816       ao2_ref(fax, -1);
01817    }
01818 
01819    /* if the channel is still alive, and we changed its read/write formats,
01820     * restore them now
01821     */
01822    if (chancount) {
01823       if (orig_read_format) {
01824          ast_set_read_format(chan, orig_read_format);
01825       }
01826       if (orig_write_format) {
01827          ast_set_write_format(chan, orig_write_format);
01828       }
01829    }
01830 
01831    /* return the chancount so the calling function can determine if the channel hungup during this FAX session or not */
01832    return chancount;
01833 }

static void get_general_options ( struct fax_options options  )  [static]

static int load_module ( void   )  [static]

Load the module.

Module loading including tests for configuration or dependencies. This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE, or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails tests return AST_MODULE_LOAD_FAILURE. If the module can not load the configuration file or other non-critical problem return AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.

Definition at line 4615 of file res_fax.c.

References ao2_container_alloc, ao2_ref, ARRAY_LEN, ast_cli_register_multiple(), ast_custom_function_register, ast_log, ast_logger_register_level(), ast_manager_register_xml, ast_manager_unregister(), AST_MODULE_LOAD_DECLINE, ast_register_application_xml, ast_unregister_application(), config, EVENT_FLAG_CALL, EVENT_FLAG_REPORTING, FAX_MAXBUCKETS, faxregistry, LOG_ERROR, LOG_WARNING, manager_fax_session(), manager_fax_sessions(), manager_fax_stats(), receivefax_exec(), sendfax_exec(), session_cmp_cb(), session_hash_cb(), and set_config().

04616 {
04617    int res;
04618 
04619    /* initialize the registry */
04620    faxregistry.active_sessions = 0;
04621    faxregistry.reserved_sessions = 0;
04622    if (!(faxregistry.container = ao2_container_alloc(FAX_MAXBUCKETS, session_hash_cb, session_cmp_cb))) {
04623       return AST_MODULE_LOAD_DECLINE;
04624    }
04625 
04626    if (set_config(0) < 0) {
04627       ast_log(LOG_ERROR, "failed to load configuration file '%s'\n", config);
04628       ao2_ref(faxregistry.container, -1);
04629       return AST_MODULE_LOAD_DECLINE;
04630    }
04631 
04632    /* register CLI operations and applications */
04633    if (ast_register_application_xml(app_sendfax, sendfax_exec) < 0) {
04634       ast_log(LOG_WARNING, "failed to register '%s'.\n", app_sendfax);
04635       ao2_ref(faxregistry.container, -1);
04636       return AST_MODULE_LOAD_DECLINE;
04637    }
04638    if (ast_register_application_xml(app_receivefax, receivefax_exec) < 0) {
04639       ast_log(LOG_WARNING, "failed to register '%s'.\n", app_receivefax);
04640       ast_unregister_application(app_sendfax);
04641       ao2_ref(faxregistry.container, -1);
04642       return AST_MODULE_LOAD_DECLINE;
04643    }
04644 
04645    if (ast_manager_register_xml("FAXSessions", EVENT_FLAG_CALL, manager_fax_sessions)) {
04646       ast_log(LOG_WARNING, "failed to register 'FAXSessions' AMI command.\n");
04647       ast_unregister_application(app_receivefax);
04648       ast_unregister_application(app_sendfax);
04649       ao2_ref(faxregistry.container, -1);
04650       return AST_MODULE_LOAD_DECLINE;
04651    }
04652 
04653    if (ast_manager_register_xml("FAXSession", EVENT_FLAG_CALL, manager_fax_session)) {
04654       ast_log(LOG_WARNING, "failed to register 'FAXSession' AMI command.\n");
04655       ast_manager_unregister("FAXSession");
04656       ast_unregister_application(app_receivefax);
04657       ast_unregister_application(app_sendfax);
04658       ao2_ref(faxregistry.container, -1);
04659       return AST_MODULE_LOAD_DECLINE;
04660    }
04661 
04662    if (ast_manager_register_xml("FAXStats", EVENT_FLAG_REPORTING, manager_fax_stats)) {
04663       ast_log(LOG_WARNING, "failed to register 'FAXStats' AMI command.\n");
04664       ast_manager_unregister("FAXSession");
04665       ast_manager_unregister("FAXSessions");
04666       ast_unregister_application(app_receivefax);
04667       ast_unregister_application(app_sendfax);
04668       ao2_ref(faxregistry.container, -1);
04669       return AST_MODULE_LOAD_DECLINE;
04670    }
04671 
04672    ast_cli_register_multiple(fax_cli, ARRAY_LEN(fax_cli));
04673    res = ast_custom_function_register(&acf_faxopt);
04674    fax_logger_level = ast_logger_register_level("FAX");
04675 
04676    return res;
04677 }

static int manager_fax_session ( struct mansession s,
const struct message m 
) [static]

Definition at line 3980 of file res_fax.c.

References ao2_find, ao2_ref, ast_strlen_zero, astman_get_header(), astman_send_ack(), astman_send_error(), faxregistry, ast_fax_session::id, ast_fax_tech::manager_fax_session, OBJ_POINTER, session, and ast_fax_session::tech.

Referenced by load_module().

03981 {
03982    const char *action_id = astman_get_header(m, "ActionID");
03983    const char *session_number = astman_get_header(m, "SessionNumber");
03984    char id_text[256] = "";
03985    struct ast_fax_session *session;
03986    struct ast_fax_session find_session;
03987 
03988    if (sscanf(session_number, "%30u", &find_session.id) != 1) {
03989       astman_send_error(s, m, "Invalid session ID");
03990       return 0;
03991    }
03992 
03993    session = ao2_find(faxregistry.container, &find_session, OBJ_POINTER);
03994    if (!session) {
03995       astman_send_error(s, m, "Session not found");
03996       return 0;
03997    }
03998 
03999    if (!session->tech->manager_fax_session) {
04000       astman_send_error(s, m, "Fax technology doesn't provide a handler for FAXSession");
04001       ao2_ref(session, -1);
04002       return 0;
04003    }
04004 
04005    if (!ast_strlen_zero(action_id)) {
04006       snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", action_id);
04007    }
04008 
04009    astman_send_ack(s, m, "FAXSession event will follow");
04010 
04011    session->tech->manager_fax_session(s, id_text, session);
04012    ao2_ref(session, -1);
04013 
04014    return 0;
04015 }

static int manager_fax_sessions ( struct mansession s,
const struct message m 
) [static]

Definition at line 4186 of file res_fax.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_strlen_zero, astman_append(), astman_get_header(), astman_send_list_complete_end(), astman_send_list_complete_start(), astman_send_listack(), faxregistry, manager_fax_sessions_entry(), session, and session_count.

Referenced by load_module().

04187 {
04188    const char *action_id = astman_get_header(m, "ActionID");
04189    char id_text[256];
04190    struct ast_fax_session *session;
04191    struct ao2_iterator iter;
04192    int session_count = 0;
04193 
04194    id_text[0] = '\0';
04195    if (!ast_strlen_zero(action_id)) {
04196       snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", action_id);
04197    }
04198 
04199    astman_send_listack(s, m, "FAXSessionsEntry event list will follow", "Start");
04200 
04201    iter = ao2_iterator_init(faxregistry.container, 0);
04202    while ((session = ao2_iterator_next(&iter))) {
04203       if (!manager_fax_sessions_entry(s, session, id_text)) {
04204          session_count++;
04205       }
04206       ao2_ref(session, -1);
04207    }
04208    ao2_iterator_destroy(&iter);
04209 
04210    astman_send_list_complete_start(s, m, "FAXSessionsComplete", session_count);
04211    astman_append(s, "Total: %d\r\n", session_count);
04212    astman_send_list_complete_end(s);
04213 
04214    return 0;
04215 }

static int manager_fax_sessions_entry ( struct mansession s,
struct ast_fax_session session,
const char *  id_text 
) [static]

Definition at line 4154 of file res_fax.c.

References ao2_lock, ao2_unlock, ast_fax_session_operation_str(), ast_fax_state_to_str(), ast_free, ast_log, astman_append(), ast_fax_session::channame, ast_fax_session::details, fax_session_type(), generate_filenames_string(), ast_fax_session::id, LOG_ERROR, S_OR, ast_fax_session::state, ast_fax_session::tech, and ast_fax_tech::type.

Referenced by manager_fax_sessions().

04156 {
04157    char *filenames;
04158 
04159    ao2_lock(session);
04160    filenames = generate_filenames_string(session->details, "", ",");
04161 
04162    if (!filenames) {
04163       ast_log(LOG_ERROR, "Error generating Files string");
04164       ao2_unlock(session);
04165       return -1;
04166    }
04167 
04168    astman_append(s, "Event: FAXSessionsEntry\r\n"
04169       "%s" /* ActionID if present */
04170       "Channel: %s\r\n" /* Channel name */
04171       "Technology: %s\r\n" /* Fax session technology */
04172       "SessionNumber: %u\r\n" /* Session ID */
04173       "SessionType: %s\r\n" /* G711 or T38 */
04174       "Operation: %s\r\n"
04175       "State: %s\r\n"
04176       "Files: %s\r\n"
04177       "\r\n",
04178       id_text, session->channame, session->tech->type, session->id,
04179       fax_session_type(session), ast_fax_session_operation_str(session),
04180       ast_fax_state_to_str(session->state), S_OR(filenames, ""));
04181    ast_free(filenames);
04182    ao2_unlock(session);
04183    return 0;
04184 }

static int manager_fax_stats ( struct mansession s,
const struct message m 
) [static]

Definition at line 4050 of file res_fax.c.

References ast_strlen_zero, astman_append(), astman_get_header(), astman_send_ack(), and faxregistry.

Referenced by load_module().

04051 {
04052    const char *action_id = astman_get_header(m, "ActionID");
04053 
04054    char id_text[256] = "";
04055 
04056    astman_send_ack(s, m, "FAXStats event will follow");
04057 
04058    if (!ast_strlen_zero(action_id)) {
04059       snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", action_id);
04060    }
04061 
04062    astman_append(s, "Event: FAXStats\r\n"
04063       "%s"
04064       "CurrentSessions: %d\r\n"
04065       "ReservedSessions: %d\r\n"
04066       "TransmitAttempts: %d\r\n"
04067       "ReceiveAttempts: %d\r\n"
04068       "CompletedFAXes: %d\r\n"
04069       "FailedFAXes: %d\r\n"
04070       "\r\n",
04071       id_text,
04072       faxregistry.active_sessions, faxregistry.reserved_sessions,
04073       faxregistry.fax_tx_attempts, faxregistry.fax_rx_attempts,
04074       faxregistry.fax_complete, faxregistry.fax_failures);
04075 
04076    return 0;
04077 }

static int receivefax_exec ( struct ast_channel chan,
const char *  data 
) [static]

initiate a receive FAX session

Definition at line 2061 of file res_fax.c.

References ao2_cleanup, args, ast_answer(), AST_APP_ARG, ast_app_parse_options(), ast_atomic_fetchadd_int(), ast_calloc, ast_channel_get_t38_state(), ast_channel_name(), ast_debug, AST_DECLARE_APP_ARGS, ast_fax_modem_to_str(), AST_FAX_OPTFLAG_TRUE, AST_FAX_TECH_AUDIO, AST_FAX_TECH_RECEIVE, AST_FAX_TECH_T38, AST_LIST_INSERT_TAIL, ast_log, AST_LOG_ERROR, AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strdupa, ast_string_field_set, ast_strlen_zero, ast_test_flag, ast_verb, check_modem_rate(), disable_t38(), error(), fax_exec_options, fax_session_release(), fax_session_reserve(), faxregistry, ast_fax_document::filename, find_or_create_details(), generic_fax_exec(), global_fax_debug, LOG_ERROR, LOG_WARNING, fax_module::next, NULL, OPT_ALLOWAUDIO, OPT_CALLEDMODE, OPT_CALLERMODE, OPT_DEBUG, OPT_FORCE_AUDIO, OPT_STATUS, parse(), pbx_builtin_setvar_helper(), RAII_VAR, receivefax_t38_init(), report_receive_fax_status(), result, set_channel_variables(), set_fax_t38_caps(), T38_STATE_NEGOTIATED, T38_STATE_REJECTED, and T38_STATE_UNAVAILABLE.

Referenced by load_module().

02062 {
02063    char *parse, modems[128] = "";
02064    int channel_alive;
02065    RAII_VAR(struct ast_fax_session *, s, NULL, ao2_cleanup);
02066    RAII_VAR(struct ast_fax_session_details *, details, NULL, ao2_cleanup);
02067    struct ast_fax_tech_token *token = NULL;
02068    struct ast_fax_document *doc;
02069    AST_DECLARE_APP_ARGS(args,
02070       AST_APP_ARG(filename);
02071       AST_APP_ARG(options);
02072    );
02073    struct ast_flags opts = { 0, };
02074    enum ast_t38_state t38state;
02075 
02076    /* initialize output channel variables */
02077    pbx_builtin_setvar_helper(chan, "FAXSTATUS", "FAILED");
02078    pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", NULL);
02079    pbx_builtin_setvar_helper(chan, "FAXPAGES", "0");
02080    pbx_builtin_setvar_helper(chan, "FAXBITRATE", NULL);
02081    pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", NULL);
02082 
02083    /* Get a FAX session details structure from the channel's FAX datastore and create one if
02084     * it does not already exist. */
02085    if (!(details = find_or_create_details(chan))) {
02086       pbx_builtin_setvar_helper(chan, "FAXERROR", "MEMORY_ERROR");
02087       pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "error allocating memory");
02088       ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
02089       return -1;
02090    }
02091 
02092    ast_string_field_set(details, result, "FAILED");
02093    ast_string_field_set(details, resultstr, "error starting fax session");
02094    ast_string_field_set(details, error, "INIT_ERROR");
02095    set_channel_variables(chan, details);
02096 
02097    if (details->gateway_id > 0) {
02098       ast_string_field_set(details, resultstr, "can't receive a fax on a channel with a T.38 gateway");
02099       set_channel_variables(chan, details);
02100       ast_log(LOG_ERROR, "executing ReceiveFAX on a channel with a T.38 Gateway is not supported\n");
02101       return -1;
02102    }
02103 
02104    if (details->maxrate < details->minrate) {
02105       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
02106       ast_string_field_set(details, resultstr, "maxrate is less than minrate");
02107       set_channel_variables(chan, details);
02108       ast_log(LOG_ERROR, "maxrate %u is less than minrate %u\n", details->maxrate, details->minrate);
02109       return -1;
02110    }
02111 
02112    if (check_modem_rate(details->modems, details->minrate)) {
02113       ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
02114       ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %u\n", modems, details->minrate);
02115       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
02116       ast_string_field_set(details, resultstr, "incompatible 'modems' and 'minrate' settings");
02117       set_channel_variables(chan, details);
02118       return -1;
02119    }
02120 
02121    if (check_modem_rate(details->modems, details->maxrate)) {
02122       ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
02123       ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %u\n", modems, details->maxrate);
02124       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
02125       ast_string_field_set(details, resultstr, "incompatible 'modems' and 'maxrate' settings");
02126       set_channel_variables(chan, details);
02127       return -1;
02128    }
02129 
02130    if (ast_strlen_zero(data)) {
02131       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
02132       ast_string_field_set(details, resultstr, "invalid arguments");
02133       set_channel_variables(chan, details);
02134       ast_log(LOG_WARNING, "%s requires an argument (filename[,options])\n", app_receivefax);
02135       return -1;
02136    }
02137    parse = ast_strdupa(data);
02138    AST_STANDARD_APP_ARGS(args, parse);
02139 
02140    if (!ast_strlen_zero(args.options) &&
02141        ast_app_parse_options(fax_exec_options, &opts, NULL, args.options)) {
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       return -1;
02146    }
02147    if (ast_strlen_zero(args.filename)) {
02148       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
02149       ast_string_field_set(details, resultstr, "invalid arguments");
02150       set_channel_variables(chan, details);
02151       ast_log(LOG_WARNING, "%s requires an argument (filename[,options])\n", app_receivefax);
02152       return -1;
02153    }
02154 
02155    /* check for unsupported FAX application options */
02156    if (ast_test_flag(&opts, OPT_CALLERMODE) || ast_test_flag(&opts, OPT_CALLEDMODE)) {
02157       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
02158       ast_string_field_set(details, resultstr, "invalid arguments");
02159       set_channel_variables(chan, details);
02160       ast_log(LOG_WARNING, "%s does not support polling\n", app_receivefax);
02161       return -1;
02162    }
02163 
02164    ast_atomic_fetchadd_int(&faxregistry.fax_rx_attempts, 1);
02165 
02166    pbx_builtin_setvar_helper(chan, "FAXERROR", "Channel Problems");
02167    pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "Error before FAX transmission started.");
02168 
02169    if (!(doc = ast_calloc(1, sizeof(*doc) + strlen(args.filename) + 1))) {
02170       ast_string_field_set(details, error, "MEMORY_ERROR");
02171       ast_string_field_set(details, resultstr, "error allocating memory");
02172       set_channel_variables(chan, details);
02173       ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
02174       return -1;
02175    }
02176 
02177    strcpy(doc->filename, args.filename);
02178    AST_LIST_INSERT_TAIL(&details->documents, doc, next);
02179 
02180    ast_verb(3, "Channel '%s' receiving FAX '%s'\n", ast_channel_name(chan), args.filename);
02181 
02182    details->caps = AST_FAX_TECH_RECEIVE;
02183    details->option.send_ced = AST_FAX_OPTFLAG_TRUE;
02184 
02185    /* check for debug */
02186    if (ast_test_flag(&opts, OPT_DEBUG) || global_fax_debug) {
02187       details->option.debug = AST_FAX_OPTFLAG_TRUE;
02188    }
02189 
02190    /* check for request for status events */
02191    if (ast_test_flag(&opts, OPT_STATUS)) {
02192       details->option.statusevents = AST_FAX_OPTFLAG_TRUE;
02193    }
02194 
02195    t38state = ast_channel_get_t38_state(chan);
02196    if ((t38state == T38_STATE_UNAVAILABLE) || (t38state == T38_STATE_REJECTED) ||
02197        ast_test_flag(&opts, OPT_ALLOWAUDIO) ||
02198        ast_test_flag(&opts, OPT_FORCE_AUDIO)) {
02199       details->option.allow_audio = AST_FAX_OPTFLAG_TRUE;
02200    }
02201 
02202    if (!(s = fax_session_reserve(details, &token))) {
02203       ast_string_field_set(details, resultstr, "error reserving fax session");
02204       set_channel_variables(chan, details);
02205       ast_log(LOG_ERROR, "Unable to reserve FAX session.\n");
02206       return -1;
02207    }
02208 
02209    /* make sure the channel is up */
02210    if (ast_channel_state(chan) != AST_STATE_UP) {
02211       if (ast_answer(chan)) {
02212          ast_string_field_set(details, resultstr, "error answering channel");
02213          set_channel_variables(chan, details);
02214          ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", ast_channel_name(chan));
02215          fax_session_release(s, token);
02216          return -1;
02217       }
02218    }
02219 
02220    if (!ast_test_flag(&opts, OPT_FORCE_AUDIO)) {
02221       if (set_fax_t38_caps(chan, details)) {
02222          ast_string_field_set(details, error, "T38_NEG_ERROR");
02223          ast_string_field_set(details, resultstr, "error negotiating T.38");
02224          set_channel_variables(chan, details);
02225          fax_session_release(s, token);
02226          return -1;
02227       }
02228    } else {
02229       details->caps |= AST_FAX_TECH_AUDIO;
02230    }
02231 
02232    if (!ast_test_flag(&opts, OPT_FORCE_AUDIO) && (details->caps & AST_FAX_TECH_T38)) {
02233       if (receivefax_t38_init(chan, details)) {
02234          ast_string_field_set(details, error, "T38_NEG_ERROR");
02235          ast_string_field_set(details, resultstr, "error negotiating T.38");
02236          set_channel_variables(chan, details);
02237          fax_session_release(s, token);
02238          ast_log(LOG_ERROR, "error initializing channel '%s' in T.38 mode\n", ast_channel_name(chan));
02239          return -1;
02240       }
02241    }
02242 
02243    if ((channel_alive = generic_fax_exec(chan, details, s, token)) < 0) {
02244       ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
02245    }
02246 
02247    if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) {
02248       if (disable_t38(chan)) {
02249          ast_debug(1, "error disabling T.38 mode on %s\n", ast_channel_name(chan));
02250       }
02251    }
02252 
02253    if (report_receive_fax_status(chan, args.filename)) {
02254       ast_log(AST_LOG_ERROR, "Error publishing ReceiveFax status message\n");
02255    }
02256 
02257    /* If the channel hungup return -1; otherwise, return 0 to continue in the dialplan */
02258    return (!channel_alive) ? -1 : 0;
02259 }

static int receivefax_t38_init ( struct ast_channel chan,
struct ast_fax_session_details details 
) [static]

Definition at line 1835 of file res_fax.c.

References ast_fax_session_details::allow_audio, ast_channel_get_t38_state(), ast_channel_name(), AST_CONTROL_T38_PARAMETERS, ast_debug, AST_FAX_OPTFLAG_TRUE, AST_FAX_TECH_AUDIO, AST_FAX_TECH_T38, AST_FRAME_CONTROL, ast_frfree, ast_indicate_data(), ast_log, ast_playtones_start(), ast_playtones_stop(), ast_read(), ast_remaining_ms(), AST_T38_NEGOTIATED, AST_T38_REFUSED, AST_T38_REQUEST_NEGOTIATE, ast_tvnow(), ast_waitfor(), ast_fax_session_details::caps, ast_frame::data, ast_frame::datalen, ast_frame::frametype, ast_frame_subclass::integer, LOG_ERROR, LOG_WARNING, NULL, ast_fax_session_details::option, ast_fax_session_details::our_t38_parameters, ast_frame::ptr, report_fax_status(), ast_control_t38_parameters::request_response, ast_frame::subclass, t38_parameters_ast_to_fax(), t38_parameters_fax_to_ast(), T38_STATE_NEGOTIATED, T38_STATE_NEGOTIATING, ast_fax_session_details::t38timeout, and ast_fax_session_details::their_t38_parameters.

Referenced by receivefax_exec().

01836 {
01837    int timeout_ms;
01838    struct ast_frame *frame = NULL;
01839    struct ast_control_t38_parameters t38_parameters;
01840    struct timeval start;
01841    int ms;
01842 
01843    /* don't send any audio if we've already received a T.38 reinvite */
01844    if (ast_channel_get_t38_state(chan) != T38_STATE_NEGOTIATING) {
01845       /* generate 3 seconds of CED */
01846       if (ast_playtones_start(chan, 1024, "!2100/3000", 1)) {
01847          ast_log(LOG_ERROR, "error generating CED tone on %s\n", ast_channel_name(chan));
01848          return -1;
01849       }
01850 
01851       timeout_ms = 3000;
01852       start = ast_tvnow();
01853       while ((ms = ast_remaining_ms(start, timeout_ms))) {
01854          ms = ast_waitfor(chan, ms);
01855 
01856          if (ms < 0) {
01857             ast_log(LOG_ERROR, "error while generating CED tone on %s\n", ast_channel_name(chan));
01858             ast_playtones_stop(chan);
01859             return -1;
01860          }
01861 
01862          if (ms == 0) { /* all done, nothing happened */
01863             break;
01864          }
01865 
01866          if (!(frame = ast_read(chan))) {
01867             ast_log(LOG_ERROR, "error reading frame while generating CED tone on %s\n", ast_channel_name(chan));
01868             ast_playtones_stop(chan);
01869             return -1;
01870          }
01871 
01872          if ((frame->frametype == AST_FRAME_CONTROL) &&
01873              (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
01874              (frame->datalen == sizeof(t38_parameters))) {
01875             struct ast_control_t38_parameters *parameters = frame->data.ptr;
01876 
01877             switch (parameters->request_response) {
01878             case AST_T38_REQUEST_NEGOTIATE:
01879                /* the other end has requested a switch to T.38, so reply that we are willing, if we can
01880                 * do T.38 as well
01881                 */
01882                t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
01883                t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
01884                ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
01885                ast_playtones_stop(chan);
01886                break;
01887             case AST_T38_NEGOTIATED:
01888                ast_debug(1, "Negotiated T.38 for receive on %s\n", ast_channel_name(chan));
01889                t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
01890                details->caps &= ~AST_FAX_TECH_AUDIO;
01891                report_fax_status(chan, details, "T.38 Negotiated");
01892                break;
01893             default:
01894                break;
01895             }
01896          }
01897          ast_frfree(frame);
01898       }
01899 
01900       ast_playtones_stop(chan);
01901    }
01902 
01903    /* if T.38 was negotiated, we are done initializing */
01904    if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) {
01905       return 0;
01906    }
01907 
01908    /* request T.38 */
01909    ast_debug(1, "Negotiating T.38 for receive on %s\n", ast_channel_name(chan));
01910 
01911    /* wait for negotiation to complete */
01912    timeout_ms = details->t38timeout;
01913 
01914    /* set parameters based on the session's parameters */
01915    t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
01916    t38_parameters.request_response = AST_T38_REQUEST_NEGOTIATE;
01917    if ((ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0)) {
01918       return -1;
01919    }
01920 
01921    start = ast_tvnow();
01922    while ((ms = ast_remaining_ms(start, timeout_ms))) {
01923       int break_loop = 0;
01924 
01925       ms = ast_waitfor(chan, ms);
01926       if (ms < 0) {
01927          ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", ast_channel_name(chan));
01928          return -1;
01929       }
01930       if (ms == 0) { /* all done, nothing happened */
01931          ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 negotiation.\n", ast_channel_name(chan));
01932          details->caps &= ~AST_FAX_TECH_T38;
01933          break;
01934       }
01935 
01936       if (!(frame = ast_read(chan))) {
01937          ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", ast_channel_name(chan));
01938          return -1;
01939       }
01940 
01941       if ((frame->frametype == AST_FRAME_CONTROL) &&
01942             (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
01943             (frame->datalen == sizeof(t38_parameters))) {
01944          struct ast_control_t38_parameters *parameters = frame->data.ptr;
01945 
01946          switch (parameters->request_response) {
01947          case AST_T38_REQUEST_NEGOTIATE:
01948             t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
01949             t38_parameters.request_response = AST_T38_NEGOTIATED;
01950             ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
01951             break;
01952          case AST_T38_NEGOTIATED:
01953             ast_debug(1, "Negotiated T.38 for receive on %s\n", ast_channel_name(chan));
01954             t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
01955             details->caps &= ~AST_FAX_TECH_AUDIO;
01956             report_fax_status(chan, details, "T.38 Negotiated");
01957             break_loop = 1;
01958             break;
01959          case AST_T38_REFUSED:
01960             ast_log(LOG_WARNING, "channel '%s' refused to negotiate T.38\n", ast_channel_name(chan));
01961             details->caps &= ~AST_FAX_TECH_T38;
01962             break_loop = 1;
01963             break;
01964          default:
01965             ast_log(LOG_ERROR, "channel '%s' failed to negotiate T.38\n", ast_channel_name(chan));
01966             details->caps &= ~AST_FAX_TECH_T38;
01967             break_loop = 1;
01968             break;
01969          }
01970       }
01971       ast_frfree(frame);
01972       if (break_loop) {
01973          break;
01974       }
01975    }
01976 
01977    /* if T.38 was negotiated, we are done initializing */
01978    if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) {
01979       return 0;
01980    }
01981 
01982    /* if we made it here, then T.38 failed, check the 'f' flag */
01983    if (details->option.allow_audio != AST_FAX_OPTFLAG_TRUE) {
01984       ast_log(LOG_WARNING, "Audio FAX not allowed on channel '%s' and T.38 negotiation failed; aborting.\n", ast_channel_name(chan));
01985       return -1;
01986    }
01987 
01988    /* ok, audio fallback is allowed */
01989    details->caps |= AST_FAX_TECH_AUDIO;
01990 
01991    return 0;
01992 }

static int reload_module ( void   )  [static]

Definition at line 4679 of file res_fax.c.

References set_config().

04680 {
04681    set_config(1);
04682    return 0;
04683 }

static int report_fax_status ( struct ast_channel chan,
struct ast_fax_session_details details,
const char *  status 
) [static]

send a FAX status manager event

Definition at line 1409 of file res_fax.c.

References ao2_cleanup, ast_channel_blob_create_from_cache(), ast_channel_fax_type(), ast_channel_topic(), ast_channel_uniqueid(), AST_FAX_TECH_GATEWAY, AST_FAX_TECH_RECEIVE, ast_json_pack(), ast_json_unref(), ast_fax_session_details::caps, generate_filenames_json(), ast_fax_session_details::localstationid, lock, NULL, ast_fax_session_details::option, RAII_VAR, SCOPED_CHANNELLOCK, stasis_publish(), and ast_fax_session_details::statusevents.

Referenced by fax_gateway_attach(), fax_gateway_detect_t38(), fax_gateway_start(), generic_fax_exec(), receivefax_t38_init(), and sendfax_t38_init().

01410 {
01411    RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
01412    RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
01413    struct ast_json *json_filenames = NULL;
01414 
01415    if (!details->option.statusevents) {
01416       return 0;
01417    }
01418 
01419    json_filenames = generate_filenames_json(details);
01420    if (!json_filenames) {
01421       return -1;
01422    }
01423 
01424    json_object = ast_json_pack("{s: s, s: s, s: s, s: s, s: o}",
01425          "type", "status",
01426          "operation", (details->caps & AST_FAX_TECH_GATEWAY) ? "gateway" : (details->caps & AST_FAX_TECH_RECEIVE) ? "receive" : "send",
01427          "status", status,
01428          "local_station_id", details->localstationid,
01429          "filenames", json_filenames);
01430    if (!json_object) {
01431       return -1;
01432    }
01433 
01434    {
01435       SCOPED_CHANNELLOCK(lock, chan);
01436 
01437       message = ast_channel_blob_create_from_cache(ast_channel_uniqueid(chan), ast_channel_fax_type(), json_object);
01438       if (!message) {
01439          return -1;
01440       }
01441       stasis_publish(ast_channel_topic(chan), message);
01442    }
01443    return 0;
01444 }

static int report_receive_fax_status ( struct ast_channel chan,
const char *  filename 
) [static]

Report on the final state of a receive fax operation.

Note:
This will lock the ast_channel

Definition at line 1997 of file res_fax.c.

References ao2_cleanup, ast_channel_blob_create_from_cache(), ast_channel_fax_type(), ast_channel_topic(), ast_channel_uniqueid(), ast_json_array_append(), ast_json_array_create(), ast_json_pack(), ast_json_string_create(), ast_json_unref(), ast_strdupa, ast_strlen_zero, lock, NULL, pbx_builtin_getvar_helper(), RAII_VAR, S_OR, SCOPED_CHANNELLOCK, and stasis_publish().

Referenced by receivefax_exec().

01998 {
01999    RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
02000    RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
02001    RAII_VAR(struct ast_json *, json_array, ast_json_array_create(), ast_json_unref);
02002    struct ast_json *json_filename = ast_json_string_create(filename);
02003 
02004    if (!json_array || !json_filename) {
02005       ast_json_unref(json_filename);
02006       return -1;
02007    }
02008    ast_json_array_append(json_array, json_filename);
02009 
02010    {
02011       const char *remote_station_id;
02012       const char *local_station_id;
02013       const char *fax_pages;
02014       const char *fax_resolution;
02015       const char *fax_bitrate;
02016       SCOPED_CHANNELLOCK(lock, chan);
02017 
02018       remote_station_id = S_OR(pbx_builtin_getvar_helper(chan, "REMOTESTATIONID"), "");
02019       if (!ast_strlen_zero(remote_station_id)) {
02020          remote_station_id = ast_strdupa(remote_station_id);
02021       }
02022       local_station_id = S_OR(pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"), "");
02023       if (!ast_strlen_zero(local_station_id)) {
02024          local_station_id = ast_strdupa(local_station_id);
02025       }
02026       fax_pages = S_OR(pbx_builtin_getvar_helper(chan, "FAXPAGES"), "");
02027       if (!ast_strlen_zero(fax_pages)) {
02028          fax_pages = ast_strdupa(fax_pages);
02029       }
02030       fax_resolution = S_OR(pbx_builtin_getvar_helper(chan, "FAXRESOLUTION"), "");
02031       if (!ast_strlen_zero(fax_resolution)) {
02032          fax_resolution = ast_strdupa(fax_resolution);
02033       }
02034       fax_bitrate = S_OR(pbx_builtin_getvar_helper(chan, "FAXBITRATE"), "");
02035       if (!ast_strlen_zero(fax_bitrate)) {
02036          fax_bitrate = ast_strdupa(fax_bitrate);
02037       }
02038 
02039       json_object = ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: s, s: O}",
02040             "type", "receive",
02041             "remote_station_id", S_OR(remote_station_id, ""),
02042             "local_station_id", S_OR(local_station_id, ""),
02043             "fax_pages", S_OR(fax_pages, ""),
02044             "fax_resolution", S_OR(fax_resolution, ""),
02045             "fax_bitrate", S_OR(fax_bitrate, ""),
02046             "filenames", json_array);
02047       if (!json_object) {
02048          return -1;
02049       }
02050 
02051       message = ast_channel_blob_create_from_cache(ast_channel_uniqueid(chan), ast_channel_fax_type(), json_object);
02052       if (!message) {
02053          return -1;
02054       }
02055       stasis_publish(ast_channel_topic(chan), message);
02056    }
02057    return 0;
02058 }

static int report_send_fax_status ( struct ast_channel chan,
struct ast_fax_session_details details 
) [static]

Report on the status of a completed fax send attempt.

Note:
This will lock the ast_channel

Definition at line 2505 of file res_fax.c.

References ao2_cleanup, ast_channel_blob_create_from_cache(), ast_channel_fax_type(), ast_channel_topic(), ast_channel_uniqueid(), ast_json_pack(), ast_json_unref(), ast_strdupa, ast_strlen_zero, generate_filenames_json(), lock, NULL, pbx_builtin_getvar_helper(), RAII_VAR, S_OR, SCOPED_CHANNELLOCK, and stasis_publish().

Referenced by sendfax_exec().

02506 {
02507    RAII_VAR(struct ast_json *, json_obj, NULL, ast_json_unref);
02508    RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
02509    struct ast_json *json_filenames;
02510 
02511    json_filenames = generate_filenames_json(details);
02512    if (!json_filenames) {
02513       return -1;
02514    }
02515 
02516    {
02517       const char *remote_station_id;
02518       const char *local_station_id;
02519       const char *fax_pages;
02520       const char *fax_resolution;
02521       const char *fax_bitrate;
02522       SCOPED_CHANNELLOCK(lock, chan);
02523 
02524       remote_station_id = S_OR(pbx_builtin_getvar_helper(chan, "REMOTESTATIONID"), "");
02525       if (!ast_strlen_zero(remote_station_id)) {
02526          remote_station_id = ast_strdupa(remote_station_id);
02527       }
02528       local_station_id = S_OR(pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"), "");
02529       if (!ast_strlen_zero(local_station_id)) {
02530          local_station_id = ast_strdupa(local_station_id);
02531       }
02532       fax_pages = S_OR(pbx_builtin_getvar_helper(chan, "FAXPAGES"), "");
02533       if (!ast_strlen_zero(fax_pages)) {
02534          fax_pages = ast_strdupa(fax_pages);
02535       }
02536       fax_resolution = S_OR(pbx_builtin_getvar_helper(chan, "FAXRESOLUTION"), "");
02537       if (!ast_strlen_zero(fax_resolution)) {
02538          fax_resolution = ast_strdupa(fax_resolution);
02539       }
02540       fax_bitrate = S_OR(pbx_builtin_getvar_helper(chan, "FAXBITRATE"), "");
02541       if (!ast_strlen_zero(fax_bitrate)) {
02542          fax_bitrate = ast_strdupa(fax_bitrate);
02543       }
02544       json_obj = ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: s, s: o}",
02545             "type", "send",
02546             "remote_station_id", S_OR(remote_station_id, ""),
02547             "local_station_id", S_OR(local_station_id, ""),
02548             "fax_pages", S_OR(fax_pages, ""),
02549             "fax_resolution", S_OR(fax_resolution, ""),
02550             "fax_bitrate", S_OR(fax_bitrate, ""),
02551             "filenames", json_filenames);
02552       if (!json_obj) {
02553          return -1;
02554       }
02555 
02556       message = ast_channel_blob_create_from_cache(ast_channel_uniqueid(chan), ast_channel_fax_type(), json_obj);
02557       if (!message) {
02558          return -1;
02559       }
02560       stasis_publish(ast_channel_topic(chan), message);
02561    }
02562    return 0;
02563 }

static int sendfax_exec ( struct ast_channel chan,
const char *  data 
) [static]

initiate a send FAX session

Definition at line 2568 of file res_fax.c.

References ao2_cleanup, args, ast_answer(), AST_APP_ARG, ast_app_parse_options(), ast_atomic_fetchadd_int(), ast_calloc, ast_channel_get_t38_state(), ast_channel_name(), ast_debug, AST_DECLARE_APP_ARGS, ast_fax_modem_to_str(), AST_FAX_OPTFLAG_TRUE, AST_FAX_TECH_AUDIO, AST_FAX_TECH_MULTI_DOC, AST_FAX_TECH_SEND, AST_FAX_TECH_T38, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_log, AST_LOG_ERROR, AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strdupa, ast_string_field_set, ast_strlen_zero, ast_test_flag, ast_verb, c, check_modem_rate(), disable_t38(), error(), fax_exec_options, fax_session_release(), fax_session_reserve(), faxregistry, ast_fax_document::filename, find_or_create_details(), generate_filenames_string(), generic_fax_exec(), global_fax_debug, LOG_ERROR, LOG_WARNING, fax_module::next, NULL, OPT_ALLOWAUDIO, OPT_CALLEDMODE, OPT_CALLERMODE, OPT_DEBUG, OPT_FORCE_AUDIO, OPT_REQUEST_T38, OPT_STATUS, parse(), pbx_builtin_setvar_helper(), RAII_VAR, report_send_fax_status(), result, sendfax_t38_init(), set_channel_variables(), set_fax_t38_caps(), strsep(), T38_STATE_NEGOTIATED, T38_STATE_REJECTED, and T38_STATE_UNAVAILABLE.

Referenced by load_module().

02569 {
02570    char *parse, *filenames, *c, modems[128] = "";
02571    int channel_alive, file_count;
02572    RAII_VAR(struct ast_fax_session_details *, details, NULL, ao2_cleanup);
02573    RAII_VAR(struct ast_fax_session *, s, NULL, ao2_cleanup);
02574    struct ast_fax_tech_token *token = NULL;
02575    struct ast_fax_document *doc;
02576    AST_DECLARE_APP_ARGS(args,
02577       AST_APP_ARG(filenames);
02578       AST_APP_ARG(options);
02579    );
02580    struct ast_flags opts = { 0, };
02581    enum ast_t38_state t38state;
02582 
02583    /* initialize output channel variables */
02584    pbx_builtin_setvar_helper(chan, "FAXSTATUS", "FAILED");
02585    pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", NULL);
02586    pbx_builtin_setvar_helper(chan, "FAXPAGES", "0");
02587    pbx_builtin_setvar_helper(chan, "FAXBITRATE", NULL);
02588    pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", NULL);
02589 
02590    /* Get a requirement structure and set it.  This structure is used
02591     * to tell the FAX technology module about the higher level FAX session */
02592    if (!(details = find_or_create_details(chan))) {
02593       pbx_builtin_setvar_helper(chan, "FAXERROR", "MEMORY_ERROR");
02594       pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "error allocating memory");
02595       ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
02596       return -1;
02597    }
02598 
02599    ast_string_field_set(details, result, "FAILED");
02600    ast_string_field_set(details, resultstr, "error starting fax session");
02601    ast_string_field_set(details, error, "INIT_ERROR");
02602    set_channel_variables(chan, details);
02603 
02604    if (details->gateway_id > 0) {
02605       ast_string_field_set(details, resultstr, "can't send a fax on a channel with a T.38 gateway");
02606       set_channel_variables(chan, details);
02607       ast_log(LOG_ERROR, "executing SendFAX on a channel with a T.38 Gateway is not supported\n");
02608       return -1;
02609    }
02610 
02611    if (details->maxrate < details->minrate) {
02612       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
02613       ast_string_field_set(details, resultstr, "maxrate is less than minrate");
02614       set_channel_variables(chan, details);
02615       ast_log(LOG_ERROR, "maxrate %u is less than minrate %u\n", details->maxrate, details->minrate);
02616       return -1;
02617    }
02618 
02619    if (check_modem_rate(details->modems, details->minrate)) {
02620       ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
02621       ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %u\n", modems, details->minrate);
02622       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
02623       ast_string_field_set(details, resultstr, "incompatible 'modems' and 'minrate' settings");
02624       set_channel_variables(chan, details);
02625       return -1;
02626    }
02627 
02628    if (check_modem_rate(details->modems, details->maxrate)) {
02629       ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
02630       ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %u\n", modems, details->maxrate);
02631       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
02632       ast_string_field_set(details, resultstr, "incompatible 'modems' and 'maxrate' settings");
02633       set_channel_variables(chan, details);
02634       return -1;
02635    }
02636 
02637    if (ast_strlen_zero(data)) {
02638       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
02639       ast_string_field_set(details, resultstr, "invalid arguments");
02640       set_channel_variables(chan, details);
02641       ast_log(LOG_WARNING, "%s requires an argument (filename[&filename[&filename]][,options])\n", app_sendfax);
02642       return -1;
02643    }
02644    parse = ast_strdupa(data);
02645    AST_STANDARD_APP_ARGS(args, parse);
02646 
02647 
02648    if (!ast_strlen_zero(args.options) &&
02649       ast_app_parse_options(fax_exec_options, &opts, NULL, args.options)) {
02650       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
02651       ast_string_field_set(details, resultstr, "invalid arguments");
02652       set_channel_variables(chan, details);
02653       return -1;
02654    }
02655    if (ast_strlen_zero(args.filenames)) {
02656       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
02657       ast_string_field_set(details, resultstr, "invalid arguments");
02658       set_channel_variables(chan, details);
02659       ast_log(LOG_WARNING, "%s requires an argument (filename[&filename[&filename]],options])\n", app_sendfax);
02660       return -1;
02661    }
02662 
02663    /* check for unsupported FAX application options */
02664    if (ast_test_flag(&opts, OPT_CALLERMODE) || ast_test_flag(&opts, OPT_CALLEDMODE)) {
02665       ast_string_field_set(details, error, "INVALID_ARGUMENTS");
02666       ast_string_field_set(details, resultstr, "invalid arguments");
02667       set_channel_variables(chan, details);
02668       ast_log(LOG_WARNING, "%s does not support polling\n", app_sendfax);
02669       return -1;
02670    }
02671 
02672    ast_atomic_fetchadd_int(&faxregistry.fax_tx_attempts, 1);
02673 
02674    file_count = 0;
02675    filenames = args.filenames;
02676    while ((c = strsep(&filenames, "&"))) {
02677       if (access(c, (F_OK | R_OK)) < 0) {
02678          ast_string_field_set(details, error, "FILE_ERROR");
02679          ast_string_field_set(details, resultstr, "error reading file");
02680          set_channel_variables(chan, details);
02681          ast_log(LOG_ERROR, "access failure.  Verify '%s' exists and check permissions.\n", args.filenames);
02682          return -1;
02683       }
02684 
02685       if (!(doc = ast_calloc(1, sizeof(*doc) + strlen(c) + 1))) {
02686          ast_string_field_set(details, error, "MEMORY_ERROR");
02687          ast_string_field_set(details, resultstr, "error allocating memory");
02688          set_channel_variables(chan, details);
02689          ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
02690          return -1;
02691       }
02692 
02693       strcpy(doc->filename, c);
02694       AST_LIST_INSERT_TAIL(&details->documents, doc, next);
02695       file_count++;
02696    }
02697 
02698    ast_verb(3, "Channel '%s' sending FAX:\n", ast_channel_name(chan));
02699    AST_LIST_TRAVERSE(&details->documents, doc, next) {
02700       ast_verb(3, "   %s\n", doc->filename);
02701    }
02702 
02703    details->caps = AST_FAX_TECH_SEND;
02704 
02705    if (file_count > 1) {
02706       details->caps |= AST_FAX_TECH_MULTI_DOC;
02707    }
02708 
02709    /* check for debug */
02710    if (ast_test_flag(&opts, OPT_DEBUG) || global_fax_debug) {
02711       details->option.debug = AST_FAX_OPTFLAG_TRUE;
02712    }
02713 
02714    /* check for request for status events */
02715    if (ast_test_flag(&opts, OPT_STATUS)) {
02716       details->option.statusevents = AST_FAX_OPTFLAG_TRUE;
02717    }
02718 
02719    t38state = ast_channel_get_t38_state(chan);
02720    if ((t38state == T38_STATE_UNAVAILABLE) || (t38state == T38_STATE_REJECTED) ||
02721        ast_test_flag(&opts, OPT_ALLOWAUDIO) ||
02722        ast_test_flag(&opts, OPT_FORCE_AUDIO)) {
02723       details->option.allow_audio = AST_FAX_OPTFLAG_TRUE;
02724    }
02725 
02726    if (ast_test_flag(&opts, OPT_REQUEST_T38)) {
02727       details->option.request_t38 = AST_FAX_OPTFLAG_TRUE;
02728    }
02729 
02730    if (!(s = fax_session_reserve(details, &token))) {
02731       ast_string_field_set(details, resultstr, "error reserving fax session");
02732       set_channel_variables(chan, details);
02733       ast_log(LOG_ERROR, "Unable to reserve FAX session.\n");
02734       return -1;
02735    }
02736 
02737    /* make sure the channel is up */
02738    if (ast_channel_state(chan) != AST_STATE_UP) {
02739       if (ast_answer(chan)) {
02740          ast_string_field_set(details, resultstr, "error answering channel");
02741          set_channel_variables(chan, details);
02742          ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", ast_channel_name(chan));
02743          fax_session_release(s, token);
02744          return -1;
02745       }
02746    }
02747 
02748    if (!ast_test_flag(&opts, OPT_FORCE_AUDIO)) {
02749       if (set_fax_t38_caps(chan, details)) {
02750          ast_string_field_set(details, error, "T38_NEG_ERROR");
02751          ast_string_field_set(details, resultstr, "error negotiating T.38");
02752          set_channel_variables(chan, details);
02753          fax_session_release(s, token);
02754          return -1;
02755       }
02756    } else {
02757       details->caps |= AST_FAX_TECH_AUDIO;
02758    }
02759 
02760    if (!ast_test_flag(&opts, OPT_FORCE_AUDIO) && (details->caps & AST_FAX_TECH_T38)) {
02761       if (sendfax_t38_init(chan, details)) {
02762          ast_string_field_set(details, error, "T38_NEG_ERROR");
02763          ast_string_field_set(details, resultstr, "error negotiating T.38");
02764          set_channel_variables(chan, details);
02765          fax_session_release(s, token);
02766          ast_log(LOG_ERROR, "error initializing channel '%s' in T.38 mode\n", ast_channel_name(chan));
02767          return -1;
02768       }
02769    } else {
02770       details->option.send_cng = 1;
02771    }
02772 
02773    if ((channel_alive = generic_fax_exec(chan, details, s, token)) < 0) {
02774       ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
02775    }
02776 
02777    if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) {
02778       if (disable_t38(chan)) {
02779          ast_debug(1, "error disabling T.38 mode on %s\n", ast_channel_name(chan));
02780       }
02781    }
02782 
02783    if (!(filenames = generate_filenames_string(details, "FileName: ", "\r\n"))) {
02784       ast_log(LOG_ERROR, "Error generating SendFAX manager event\n");
02785       return (!channel_alive) ? -1 : 0;
02786    }
02787 
02788    /* send out the AMI completion event */
02789    if (report_send_fax_status(chan, details)) {
02790       ast_log(AST_LOG_ERROR, "Error publishing SendFAX status message\n");
02791    }
02792 
02793    /* If the channel hungup return -1; otherwise, return 0 to continue in the dialplan */
02794    return (!channel_alive) ? -1 : 0;
02795 }

static int sendfax_t38_init ( struct ast_channel chan,
struct ast_fax_session_details details 
) [static]

Definition at line 2261 of file res_fax.c.

References ast_fax_session_details::allow_audio, ast_channel_get_t38_state(), ast_channel_name(), AST_CONTROL_T38_PARAMETERS, ast_debug, AST_FAX_OPTFLAG_FALSE, AST_FAX_OPTFLAG_TRUE, AST_FAX_TECH_AUDIO, AST_FAX_TECH_T38, AST_FRAME_CONTROL, ast_frfree, ast_indicate_data(), ast_log, ast_playtones_start(), ast_playtones_stop(), ast_read(), ast_remaining_ms(), AST_T38_NEGOTIATED, AST_T38_REFUSED, AST_T38_REQUEST_NEGOTIATE, ast_tvnow(), ast_waitfor(), ast_fax_session_details::caps, ast_frame::data, ast_frame::datalen, ast_frame::frametype, ast_frame_subclass::integer, LOG_ERROR, LOG_WARNING, NULL, ast_fax_session_details::option, ast_fax_session_details::our_t38_parameters, ast_frame::ptr, report_fax_status(), ast_control_t38_parameters::request_response, ast_fax_session_details::request_t38, ast_frame::subclass, t38_parameters_ast_to_fax(), t38_parameters_fax_to_ast(), T38_STATE_NEGOTIATED, T38_STATE_NEGOTIATING, and ast_fax_session_details::their_t38_parameters.

Referenced by sendfax_exec().

02262 {
02263    int timeout_ms;
02264    struct ast_frame *frame = NULL;
02265    struct ast_control_t38_parameters t38_parameters;
02266    struct timeval start;
02267    int ms;
02268 
02269    /* send CNG tone while listening for the receiver to initiate a switch
02270     * to T.38 mode; if they do, stop sending the CNG tone and proceed with
02271     * the switch.
02272     *
02273     * 10500 is enough time for 3 CNG tones
02274     */
02275    timeout_ms = 10500;
02276 
02277    /* don't send any audio if we've already received a T.38 reinvite */
02278    if (ast_channel_get_t38_state(chan) != T38_STATE_NEGOTIATING) {
02279       if (ast_playtones_start(chan, 1024, "!1100/500,!0/3000,!1100/500,!0/3000,!1100/500,!0/3000", 1)) {
02280          ast_log(LOG_ERROR, "error generating CNG tone on %s\n", ast_channel_name(chan));
02281          return -1;
02282       }
02283    }
02284 
02285    start = ast_tvnow();
02286    while ((ms = ast_remaining_ms(start, timeout_ms))) {
02287       int break_loop = 0;
02288       ms = ast_waitfor(chan, ms);
02289 
02290       if (ms < 0) {
02291          ast_log(LOG_ERROR, "error while generating CNG tone on %s\n", ast_channel_name(chan));
02292          ast_playtones_stop(chan);
02293          return -1;
02294       }
02295 
02296       if (ms == 0) { /* all done, nothing happened */
02297          break;
02298       }
02299 
02300       if (!(frame = ast_read(chan))) {
02301          ast_log(LOG_ERROR, "error reading frame while generating CNG tone on %s\n", ast_channel_name(chan));
02302          ast_playtones_stop(chan);
02303          return -1;
02304       }
02305 
02306       if ((frame->frametype == AST_FRAME_CONTROL) &&
02307             (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
02308             (frame->datalen == sizeof(t38_parameters))) {
02309          struct ast_control_t38_parameters *parameters = frame->data.ptr;
02310 
02311          switch (parameters->request_response) {
02312          case AST_T38_REQUEST_NEGOTIATE:
02313             /* the other end has requested a switch to T.38, so reply that we are willing, if we can
02314              * do T.38 as well
02315              */
02316             t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
02317             t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
02318             ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
02319             ast_playtones_stop(chan);
02320             break;
02321          case AST_T38_NEGOTIATED:
02322             ast_debug(1, "Negotiated T.38 for send on %s\n", ast_channel_name(chan));
02323             t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
02324             details->caps &= ~AST_FAX_TECH_AUDIO;
02325             report_fax_status(chan, details, "T.38 Negotiated");
02326             break_loop = 1;
02327             break;
02328          default:
02329             break;
02330          }
02331       }
02332       ast_frfree(frame);
02333       if (break_loop) {
02334          break;
02335       }
02336    }
02337 
02338    ast_playtones_stop(chan);
02339 
02340    if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) {
02341       return 0;
02342    }
02343 
02344    /* T.38 negotiation did not happen, initiate a switch if requested */
02345    if (details->option.request_t38 == AST_FAX_OPTFLAG_TRUE) {
02346       ast_debug(1, "Negotiating T.38 for send on %s\n", ast_channel_name(chan));
02347 
02348       /* wait up to five seconds for negotiation to complete */
02349       timeout_ms = 5000;
02350 
02351       /* set parameters based on the session's parameters */
02352       t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
02353       t38_parameters.request_response = AST_T38_REQUEST_NEGOTIATE;
02354       if ((ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0)) {
02355          return -1;
02356       }
02357 
02358       start = ast_tvnow();
02359       while ((ms = ast_remaining_ms(start, timeout_ms))) {
02360          int break_loop = 0;
02361 
02362          ms = ast_waitfor(chan, ms);
02363          if (ms < 0) {
02364             ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", ast_channel_name(chan));
02365             return -1;
02366          }
02367          if (ms == 0) { /* all done, nothing happened */
02368             ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 negotiation.\n", ast_channel_name(chan));
02369             details->caps &= ~AST_FAX_TECH_T38;
02370             break;
02371          }
02372 
02373          if (!(frame = ast_read(chan))) {
02374             ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", ast_channel_name(chan));
02375             return -1;
02376          }
02377 
02378          if ((frame->frametype == AST_FRAME_CONTROL) &&
02379                (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
02380                (frame->datalen == sizeof(t38_parameters))) {
02381             struct ast_control_t38_parameters *parameters = frame->data.ptr;
02382 
02383             switch (parameters->request_response) {
02384             case AST_T38_REQUEST_NEGOTIATE:
02385                t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
02386                t38_parameters.request_response = AST_T38_NEGOTIATED;
02387                ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
02388                break;
02389             case AST_T38_NEGOTIATED:
02390                ast_debug(1, "Negotiated T.38 for receive on %s\n", ast_channel_name(chan));
02391                t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
02392                details->caps &= ~AST_FAX_TECH_AUDIO;
02393                report_fax_status(chan, details, "T.38 Negotiated");
02394                break_loop = 1;
02395                break;
02396             case AST_T38_REFUSED:
02397                ast_log(LOG_WARNING, "channel '%s' refused to negotiate T.38\n", ast_channel_name(chan));
02398                details->caps &= ~AST_FAX_TECH_T38;
02399                break_loop = 1;
02400                break;
02401             default:
02402                ast_log(LOG_ERROR, "channel '%s' failed to negotiate T.38\n", ast_channel_name(chan));
02403                details->caps &= ~AST_FAX_TECH_T38;
02404                break_loop = 1;
02405                break;
02406             }
02407          }
02408          ast_frfree(frame);
02409          if (break_loop) {
02410             break;
02411          }
02412       }
02413 
02414       /* if T.38 was negotiated, we are done initializing */
02415       if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) {
02416          return 0;
02417       }
02418 
02419       /* send one more CNG tone to get audio going again for some
02420        * carriers if we are going to fall back to audio mode */
02421       if (details->option.allow_audio == AST_FAX_OPTFLAG_TRUE) {
02422          if (ast_playtones_start(chan, 1024, "!1100/500,!0/3000", 1)) {
02423             ast_log(LOG_ERROR, "error generating second CNG tone on %s\n", ast_channel_name(chan));
02424             return -1;
02425          }
02426 
02427          timeout_ms = 3500;
02428          start = ast_tvnow();
02429          while ((ms = ast_remaining_ms(start, timeout_ms))) {
02430             int break_loop = 0;
02431 
02432             ms = ast_waitfor(chan, ms);
02433             if (ms < 0) {
02434                ast_log(LOG_ERROR, "error while generating second CNG tone on %s\n", ast_channel_name(chan));
02435                ast_playtones_stop(chan);
02436                return -1;
02437             }
02438             if (ms == 0) { /* all done, nothing happened */
02439                break;
02440             }
02441 
02442             if (!(frame = ast_read(chan))) {
02443                ast_log(LOG_ERROR, "error reading frame while generating second CNG tone on %s\n", ast_channel_name(chan));
02444                ast_playtones_stop(chan);
02445                return -1;
02446             }
02447 
02448             if ((frame->frametype == AST_FRAME_CONTROL) &&
02449                   (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
02450                   (frame->datalen == sizeof(t38_parameters))) {
02451                struct ast_control_t38_parameters *parameters = frame->data.ptr;
02452 
02453                switch (parameters->request_response) {
02454                case AST_T38_REQUEST_NEGOTIATE:
02455                   /* the other end has requested a switch to T.38, so reply that we are willing, if we can
02456                    * do T.38 as well
02457                    */
02458                   t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
02459                   t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
02460                   ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
02461                   ast_playtones_stop(chan);
02462                   break;
02463                case AST_T38_NEGOTIATED:
02464                   ast_debug(1, "Negotiated T.38 for send on %s\n", ast_channel_name(chan));
02465                   t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
02466                   details->caps &= ~AST_FAX_TECH_AUDIO;
02467                   report_fax_status(chan, details, "T.38 Negotiated");
02468                   break_loop = 1;
02469                   break;
02470                default:
02471                   break;
02472                }
02473             }
02474             ast_frfree(frame);
02475             if (break_loop) {
02476                break;
02477             }
02478          }
02479 
02480          ast_playtones_stop(chan);
02481 
02482          /* if T.38 was negotiated, we are done initializing */
02483          if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) {
02484             return 0;
02485          }
02486       }
02487    }
02488 
02489    /* if we made it here, then T.38 failed, check the 'f' flag */
02490    if (details->option.allow_audio == AST_FAX_OPTFLAG_FALSE) {
02491       ast_log(LOG_WARNING, "Audio FAX not allowed on channel '%s' and T.38 negotiation failed; aborting.\n", ast_channel_name(chan));
02492       return -1;
02493    }
02494 
02495    /* ok, audio fallback is allowed */
02496    details->caps |= AST_FAX_TECH_AUDIO;
02497 
02498    return 0;
02499 }

static int session_cmp_cb ( void *  obj,
void *  arg,
int  flags 
) [static]

compare callback for ao2

Definition at line 3773 of file res_fax.c.

References CMP_MATCH, CMP_STOP, and ast_fax_session::id.

Referenced by load_module().

03774 {
03775    struct ast_fax_session *lhs = obj, *rhs = arg;
03776 
03777    return (lhs->id == rhs->id) ? CMP_MATCH | CMP_STOP : 0;
03778 }

static struct ast_fax_session_details* session_details_new ( void   )  [static, read]

create a FAX session details structure

Definition at line 694 of file res_fax.c.

References ao2_alloc, ao2_ref, AST_FAX_OPTFLAG_FALSE, AST_LIST_HEAD_INIT_NOLOCK, ast_string_field_init, d, destroy_session_details(), ast_fax_session_details::documents, fax_options::ecm, ast_fax_session_details::ecm, ast_fax_session_details::faxdetect_id, ast_fax_session_details::gateway_id, ast_fax_session_details::gateway_timeout, get_general_options(), fax_options::maxrate, ast_fax_session_details::maxrate, fax_options::minrate, ast_fax_session_details::minrate, fax_options::modems, ast_fax_session_details::modems, NULL, ast_fax_session_details::option, ast_fax_session_details::request_t38, ast_fax_session_details::send_ced, ast_fax_session_details::send_cng, fax_options::statusevents, ast_fax_session_details::statusevents, fax_options::t38timeout, and ast_fax_session_details::t38timeout.

Referenced by fax_gateway_new(), and find_or_create_details().

00695 {
00696    struct ast_fax_session_details *d;
00697    struct fax_options options;
00698 
00699    if (!(d = ao2_alloc(sizeof(*d), destroy_session_details))) {
00700       return NULL;
00701    }
00702 
00703    if (ast_string_field_init(d, 512)) {
00704       ao2_ref(d, -1);
00705       return NULL;
00706    }
00707 
00708    get_general_options(&options);
00709 
00710    AST_LIST_HEAD_INIT_NOLOCK(&d->documents);
00711 
00712    /* These options need to be set to the configured default and may be overridden by
00713     * SendFAX, ReceiveFAX, or FAXOPT */
00714    d->option.request_t38 = AST_FAX_OPTFLAG_FALSE;
00715    d->option.send_cng = AST_FAX_OPTFLAG_FALSE;
00716    d->option.send_ced = AST_FAX_OPTFLAG_FALSE;
00717    d->option.ecm = options.ecm;
00718    d->option.statusevents = options.statusevents;
00719    d->modems = options.modems;
00720    d->minrate = options.minrate;
00721    d->maxrate = options.maxrate;
00722    d->t38timeout = options.t38timeout;
00723    d->gateway_id = -1;
00724    d->faxdetect_id = -1;
00725    d->gateway_timeout = 0;
00726 
00727    return d;
00728 }

static int session_hash_cb ( const void *  obj,
const int  flags 
) [static]

hash callback for ao2

Definition at line 3765 of file res_fax.c.

References ast_fax_session::id.

Referenced by load_module().

03766 {
03767    const struct ast_fax_session *s = obj;
03768 
03769    return s->id;
03770 }

static void set_channel_variables ( struct ast_channel chan,
struct ast_fax_session_details details 
) [static]

Set fax related channel variables.

Definition at line 1447 of file res_fax.c.

References buf, ast_fax_session_details::error, ast_fax_session_details::localstationid, NULL, ast_fax_session_details::pages_transferred, pbx_builtin_setvar_helper(), ast_fax_session_details::remotestationid, ast_fax_session_details::resolution, ast_fax_session_details::result, ast_fax_session_details::resultstr, S_OR, and ast_fax_session_details::transfer_rate.

Referenced by fax_gateway_attach(), fax_gateway_detect_t38(), fax_gateway_framehook(), fax_gateway_start(), generic_fax_exec(), receivefax_exec(), and sendfax_exec().

01448 {
01449    char buf[10];
01450    pbx_builtin_setvar_helper(chan, "FAXSTATUS", S_OR(details->result, NULL));
01451    pbx_builtin_setvar_helper(chan, "FAXERROR", S_OR(details->error, NULL));
01452    pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", S_OR(details->resultstr, NULL));
01453    pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", S_OR(details->remotestationid, NULL));
01454    pbx_builtin_setvar_helper(chan, "LOCALSTATIONID", S_OR(details->localstationid, NULL));
01455    pbx_builtin_setvar_helper(chan, "FAXBITRATE", S_OR(details->transfer_rate, NULL));
01456    pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", S_OR(details->resolution, NULL));
01457 
01458    snprintf(buf, sizeof(buf), "%u", details->pages_transferred);
01459    pbx_builtin_setvar_helper(chan, "FAXPAGES", buf);
01460 }

static int set_config ( int  reload  )  [static]

configure res_fax

Definition at line 4259 of file res_fax.c.

References ast_config_destroy(), ast_config_load2(), ast_debug, ast_fax_modem_to_str(), ast_log, ast_true(), ast_variable_browse(), check_modem_rate(), config, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, default_options, fax_options::ecm, end, fax_rate_str_to_int(), LOG_ERROR, LOG_NOTICE, fax_options::maxrate, fax_options::minrate, fax_options::modems, ast_variable::name, ast_variable::next, set_general_options(), set_t38timeout(), fax_options::statusevents, fax_options::t38timeout, update_modem_bits(), and ast_variable::value.

04260 {
04261    struct ast_config *cfg;
04262    struct ast_variable *v;
04263    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
04264    char modems[128] = "";
04265    struct fax_options options;
04266    int res = 0;
04267 
04268    options = default_options;
04269 
04270    /* When we're not reloading, we have to be certain to set the general options
04271     * to the defaults in case config loading goes wrong at some point. On a reload,
04272     * the general options need to stay the same as what they were prior to the
04273     * reload rather than being reset to the defaults.
04274     */
04275    if (!reload) {
04276       set_general_options(&options);
04277    }
04278 
04279    /* read configuration */
04280    if (!(cfg = ast_config_load2(config, "res_fax", config_flags))) {
04281       ast_log(LOG_NOTICE, "Configuration file '%s' not found, %s options.\n",
04282             config, reload ? "not changing" : "using default");
04283       return 0;
04284    }
04285 
04286    if (cfg == CONFIG_STATUS_FILEINVALID) {
04287       ast_log(LOG_NOTICE, "Configuration file '%s' is invalid, %s options.\n",
04288             config, reload ? "not changing" : "using default");
04289       return 0;
04290    }
04291 
04292    if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
04293       return 0;
04294    }
04295 
04296    if (reload) {
04297       options = default_options;
04298    }
04299 
04300    /* create configuration */
04301    for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
04302       int rate;
04303 
04304       if (!strcasecmp(v->name, "minrate")) {
04305          ast_debug(3, "reading minrate '%s' from configuration file\n", v->value);
04306          if ((rate = fax_rate_str_to_int(v->value)) == 0) {
04307             res = -1;
04308             goto end;
04309          }
04310          options.minrate = rate;
04311       } else if (!strcasecmp(v->name, "maxrate")) {
04312          ast_debug(3, "reading maxrate '%s' from configuration file\n", v->value);
04313          if ((rate = fax_rate_str_to_int(v->value)) == 0) {
04314             res = -1;
04315             goto end;
04316          }
04317          options.maxrate = rate;
04318       } else if (!strcasecmp(v->name, "statusevents")) {
04319          ast_debug(3, "reading statusevents '%s' from configuration file\n", v->value);
04320          options.statusevents = ast_true(v->value);
04321       } else if (!strcasecmp(v->name, "ecm")) {
04322          ast_debug(3, "reading ecm '%s' from configuration file\n", v->value);
04323          options.ecm = ast_true(v->value);
04324       } else if ((!strcasecmp(v->name, "modem")) || (!strcasecmp(v->name, "modems"))) {
04325          options.modems = 0;
04326          update_modem_bits(&options.modems, v->value);
04327       } else if (!strcasecmp(v->name, "t38timeout")) {
04328          if (set_t38timeout(v->value, &options.t38timeout)) {
04329             res = -1;
04330             goto end;
04331          }
04332       }
04333    }
04334 
04335    if (options.maxrate < options.minrate) {
04336       ast_log(LOG_ERROR, "maxrate %u is less than minrate %u\n", options.maxrate, options.minrate);
04337       res = -1;
04338       goto end;
04339    }
04340 
04341    if (check_modem_rate(options.modems, options.minrate)) {
04342       ast_fax_modem_to_str(options.modems, modems, sizeof(modems));
04343       ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %u\n", modems, options.minrate);
04344       res = -1;
04345       goto end;
04346    }
04347 
04348    if (check_modem_rate(options.modems, options.maxrate)) {
04349       ast_fax_modem_to_str(options.modems, modems, sizeof(modems));
04350       ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %u\n", modems, options.maxrate);
04351       res = -1;
04352       goto end;
04353    }
04354 
04355    set_general_options(&options);
04356 
04357 end:
04358    ast_config_destroy(cfg);
04359    return res;
04360 }

static int set_fax_t38_caps ( struct ast_channel chan,
struct ast_fax_session_details details 
) [static]

Definition at line 1484 of file res_fax.c.

References ast_channel_get_t38_state(), ast_channel_name(), AST_CONTROL_T38_PARAMETERS, AST_FAX_TECH_AUDIO, AST_FAX_TECH_T38, ast_indicate_data(), ast_log, AST_T38_REQUEST_PARMS, ast_fax_session_details::caps, LOG_ERROR, ast_control_t38_parameters::request_response, T38_STATE_NEGOTIATED, T38_STATE_NEGOTIATING, T38_STATE_REJECTED, T38_STATE_UNAVAILABLE, and T38_STATE_UNKNOWN.

Referenced by receivefax_exec(), and sendfax_exec().

01485 {
01486    switch (ast_channel_get_t38_state(chan)) {
01487    case T38_STATE_UNKNOWN:
01488       details->caps |= AST_FAX_TECH_T38;
01489       break;
01490    case T38_STATE_REJECTED:
01491    case T38_STATE_UNAVAILABLE:
01492       details->caps |= AST_FAX_TECH_AUDIO;
01493       break;
01494    case T38_STATE_NEGOTIATED:
01495       /* already in T.38 mode? This should not happen. */
01496    case T38_STATE_NEGOTIATING: {
01497       /* the other end already sent us a T.38 reinvite, so we need to prod the channel
01498        * driver into resending their parameters to us if it supports doing so... if
01499        * not, we can't proceed, because we can't create a proper reply without them.
01500        * if it does work, the channel driver will send an AST_CONTROL_T38_PARAMETERS
01501        * with a request of AST_T38_REQUEST_NEGOTIATE, which will be read by the function
01502        * that gets called after this one completes
01503        */
01504       struct ast_control_t38_parameters parameters = { .request_response = AST_T38_REQUEST_PARMS, };
01505       if (ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &parameters, sizeof(parameters)) != AST_T38_REQUEST_PARMS) {
01506          ast_log(LOG_ERROR, "channel '%s' is in an unsupported T.38 negotiation state, cannot continue.\n", ast_channel_name(chan));
01507          return -1;
01508       }
01509       details->caps |= AST_FAX_TECH_T38;
01510       break;
01511    }
01512    default:
01513       ast_log(LOG_ERROR, "channel '%s' is in an unsupported T.38 negotiation state, cannot continue.\n", ast_channel_name(chan));
01514       return -1;
01515    }
01516 
01517    return 0;
01518 }

static void set_general_options ( const struct fax_options options  )  [static]

Definition at line 4227 of file res_fax.c.

References ast_rwlock_unlock, ast_rwlock_wrlock, general_options, and options_lock.

Referenced by set_config().

04228 {
04229    ast_rwlock_wrlock(&options_lock);
04230    general_options = *options;
04231    ast_rwlock_unlock(&options_lock);
04232 }

static int set_t38timeout ( const char *  value,
unsigned int *  t38timeout 
) [static]

Definition at line 4241 of file res_fax.c.

References ast_log, LOG_ERROR, and timeout.

Referenced by acf_faxopt_write(), and set_config().

04242 {
04243    unsigned int timeout;
04244 
04245    if (sscanf(value, "%u", &timeout) != 1) {
04246       ast_log(LOG_ERROR, "Unable to get timeout from '%s'\n", value);
04247       return -1;
04248    } else if (timeout) {
04249       *t38timeout = timeout;
04250    } else {
04251       ast_log(LOG_ERROR, "T.38 negotiation timeout must be non-zero\n");
04252       return -1;
04253    }
04254 
04255    return 0;
04256 }

static void t38_parameters_ast_to_fax ( struct ast_fax_t38_parameters dst,
const struct ast_control_t38_parameters src 
) [static]

static void t38_parameters_fax_to_ast ( struct ast_control_t38_parameters dst,
const struct ast_fax_t38_parameters src 
) [static]

static int unload_module ( void   )  [static]

unload res_fax

Definition at line 4576 of file res_fax.c.

References ao2_ref, ARRAY_LEN, ast_cli_unregister_multiple(), ast_custom_function_unregister(), ast_log, ast_logger_unregister_level(), ast_manager_unregister(), ast_unregister_application(), faxregistry, LOG_WARNING, and ast_custom_function::name.

04577 {
04578    ast_cli_unregister_multiple(fax_cli, ARRAY_LEN(fax_cli));
04579 
04580    if (ast_custom_function_unregister(&acf_faxopt) < 0) {
04581       ast_log(LOG_WARNING, "failed to unregister function '%s'\n", acf_faxopt.name);
04582    }
04583 
04584    if (ast_unregister_application(app_sendfax) < 0) {
04585       ast_log(LOG_WARNING, "failed to unregister '%s'\n", app_sendfax);
04586    }
04587 
04588    if (ast_unregister_application(app_receivefax) < 0) {
04589       ast_log(LOG_WARNING, "failed to unregister '%s'\n", app_receivefax);
04590    }
04591 
04592    ast_manager_unregister("FAXSessions");
04593    ast_manager_unregister("FAXSession");
04594    ast_manager_unregister("FAXStats");
04595 
04596    if (fax_logger_level != -1) {
04597       ast_logger_unregister_level("FAX");
04598    }
04599 
04600    ao2_ref(faxregistry.container, -1);
04601 
04602    return 0;
04603 }

static int update_modem_bits ( enum ast_fax_modems bits,
const char *  value 
) [static]

Definition at line 809 of file res_fax.c.

References ARRAY_LEN, AST_FAX_MODEM_V17, AST_FAX_MODEM_V27, AST_FAX_MODEM_V29, AST_FAX_MODEM_V34, ast_log, LOG_WARNING, and NULL.

Referenced by acf_faxopt_write(), and set_config().

00810 {
00811    char *m[5], *tok, *v = (char *)value;
00812    int i = 0, j;
00813 
00814    if (!strchr(v, ',')) {
00815       m[i++] = v;
00816       m[i] = NULL;
00817    } else {
00818       tok = strtok(v, ", ");
00819       while (tok && i < ARRAY_LEN(m) - 1) {
00820          m[i++] = tok;
00821          tok = strtok(NULL, ", ");
00822       }
00823       m[i] = NULL;
00824    }
00825 
00826    *bits = 0;
00827    for (j = 0; j < i; j++) {
00828       if (!strcasecmp(m[j], "v17")) {
00829          *bits |= AST_FAX_MODEM_V17;
00830       } else if (!strcasecmp(m[j], "v27")) {
00831          *bits |= AST_FAX_MODEM_V27;
00832       } else if (!strcasecmp(m[j], "v29")) {
00833          *bits |= AST_FAX_MODEM_V29;
00834       } else if (!strcasecmp(m[j], "v34")) {
00835          *bits |= AST_FAX_MODEM_V34;
00836       } else {
00837          ast_log(LOG_WARNING, "ignoring invalid modem setting: '%s', valid options {v17 | v27 | v29 | v34}\n", m[j]);
00838       }
00839    }
00840    return 0;
00841 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "Generic FAX Applications" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_APP_DEPEND, } [static]

Definition at line 4692 of file res_fax.c.

Initial value:

 {
   .name = "FAXOPT",
   .read = acf_faxopt_read,
   .write = acf_faxopt_write,
}
FAXOPT dialplan function.

Definition at line 4569 of file res_fax.c.

The number of active FAX sessions

Definition at line 499 of file res_fax.c.

const char app_receivefax[] = "ReceiveFAX" [static]

Definition at line 427 of file res_fax.c.

const char app_sendfax[] = "SendFAX" [static]

Definition at line 428 of file res_fax.c.

Definition at line 4692 of file res_fax.c.

const char* config = "res_fax.conf" [static]

Definition at line 554 of file res_fax.c.

active sessions are astobj2 objects

Definition at line 503 of file res_fax.c.

struct fax_options default_options [static]

Definition at line 540 of file res_fax.c.

Referenced by set_config().

struct ast_cli_entry fax_cli[] [static]

Definition at line 4217 of file res_fax.c.

Number of successful FAX transmissions

Definition at line 509 of file res_fax.c.

Initial value:

 {
   .type = "res_fax",
   .destroy = destroy_callback,
   .chan_fixup = fixup_callback,
}

Definition at line 620 of file res_fax.c.

struct ast_app_option fax_exec_options[128] = { [ 'a' ] = { .flag = OPT_CALLEDMODE }, [ 'c' ] = { .flag = OPT_CALLERMODE }, [ 'd' ] = { .flag = OPT_DEBUG }, [ 'f' ] = { .flag = OPT_ALLOWAUDIO }, [ 'F' ] = { .flag = OPT_FORCE_AUDIO }, [ 's' ] = { .flag = OPT_STATUS }, [ 'z' ] = { .flag = OPT_REQUEST_T38 }, } [static]

Definition at line 576 of file res_fax.c.

Referenced by receivefax_exec(), and sendfax_exec().

Number of failed FAX transmissions

Definition at line 511 of file res_fax.c.

int fax_logger_level = -1 [static]

Definition at line 488 of file res_fax.c.

Total number of Rx FAX attempts

Definition at line 507 of file res_fax.c.

Total number of Tx FAX attempts

Definition at line 505 of file res_fax.c.

struct { ... } faxregistry [static]

struct fax_options general_options [static]

Definition at line 538 of file res_fax.c.

int global_fax_debug = 0 [static]

Definition at line 556 of file res_fax.c.

Referenced by cli_fax_set_debug(), receivefax_exec(), and sendfax_exec().

the next unique session name

Definition at line 513 of file res_fax.c.

ast_rwlock_t options_lock = { {0} , NULL, 1 } [static]

Definition at line 549 of file res_fax.c.

Referenced by get_general_options(), and set_general_options().

Definition at line 730 of file res_fax.c.

The number of reserved FAX sessions

Definition at line 501 of file res_fax.c.


Generated on Thu Apr 16 06:32:49 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6