Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Macros | Enumerations | Functions | Variables
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
 

Macros

#define FAX_DETECT_MODE_BOTH   (FAX_DETECT_MODE_CNG | FAX_DETECT_MODE_T38)
 
#define FAX_DETECT_MODE_CNG   (1 << 0)
 FAX Detect flags. More...
 
#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 More...
 
#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_V27TER | 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 __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. More...
 
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. More...
 
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. More...
 
unsigned int ast_fax_maxrate (void)
 get the maxiumum supported fax rate More...
 
unsigned int ast_fax_minrate (void)
 get the minimum supported fax rate More...
 
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 More...
 
const char * ast_fax_state_to_str (enum ast_fax_state state)
 convert a ast_fax_state to a string More...
 
int ast_fax_tech_register (struct ast_fax_tech *tech)
 register a FAX technology module More...
 
void ast_fax_tech_unregister (struct ast_fax_tech *tech)
 unregister a FAX technology module More...
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
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 More...
 
static char * cli_fax_show_capabilities (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 display registered FAX capabilities More...
 
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 More...
 
static char * cli_fax_show_sessions (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 display fax sessions More...
 
static char * cli_fax_show_settings (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 display global defaults and settings More...
 
static char * cli_fax_show_stats (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 display fax stats More...
 
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 More...
 
static void destroy_gateway (void *data)
 destroy a FAX gateway session structure More...
 
static void destroy_session (void *session)
 destroy a FAX session structure More...
 
static void destroy_session_details (void *details)
 destroy a FAX session details structure More...
 
static void destroy_v21_sessions (struct fax_gateway *gateway)
 destroy the v21 detection parts of a fax gateway session More...
 
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. More...
 
static struct ast_framefax_detect_framehook (struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data)
 Fax Detect Framehook. More...
 
static void fax_detect_framehook_destroy (void *data)
 Deref the faxdetect data structure when the faxdetect framehook is detached. More...
 
static struct fax_detectfax_detect_new (struct ast_channel *chan, int timeout, int flags)
 Create a new fax detect object. More...
 
static int fax_gateway_attach (struct ast_channel *chan, struct ast_fax_session_details *details)
 Attach a gateway framehook object to a channel. More...
 
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. More...
 
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. More...
 
static void fax_gateway_framehook_destroy (void *data)
 Destroy the gateway data structure when the framehook is detached. More...
 
static void 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. More...
 
static struct ast_framefax_gateway_request_t38 (struct fax_gateway *gateway, struct ast_channel *chan)
 
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. More...
 
static unsigned int fax_rate_str_to_int (const char *ratestr)
 convert a rate string to a rate More...
 
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 More...
 
static void fax_session_release (struct ast_fax_session *s, struct ast_fax_tech_token *token)
 Release a session token. More...
 
static struct ast_fax_sessionfax_session_reserve (struct ast_fax_session_details *details, struct ast_fax_tech_token **token)
 Reserve a fax session. More...
 
static char * fax_session_tab_complete (struct ast_cli_args *a)
 fax session tab completion More...
 
static const char * fax_session_type (struct ast_fax_session *s)
 
static struct ast_fax_sessionfax_v21_session_new (struct ast_channel *chan)
 
static struct ast_fax_session_detailsfind_details (struct ast_channel *chan)
 returns a reference counted pointer to a fax datastore, if it exists More...
 
static struct ast_fax_session_detailsfind_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 More...
 
static void fixup_callback (void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
 Copies fax detection and gateway framehooks during masquerades. More...
 
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. More...
 
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 More...
 
static void get_general_options (struct fax_options *options)
 
static int load_module (void)
 Load the module. More...
 
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 More...
 
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 More...
 
static int report_receive_fax_status (struct ast_channel *chan, const char *filename)
 Report on the final state of a receive fax operation. More...
 
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. More...
 
static int sendfax_exec (struct ast_channel *chan, const char *data)
 initiate a send FAX session More...
 
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 More...
 
static struct ast_fax_session_detailssession_details_new (void)
 create a FAX session details structure More...
 
static int session_hash_cb (const void *obj, const int flags)
 hash callback for ao2 More...
 
static void set_channel_variables (struct ast_channel *chan, struct ast_fax_session_details *details)
 Set fax related channel variables. More...
 
static int set_config (int reload)
 configure res_fax More...
 
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 More...
 
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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .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. More...
 
static const char app_receivefax [] = "ReceiveFAX"
 
static const char app_sendfax [] = "SendFAX"
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static const char * config = "res_fax.conf"
 
static const struct fax_options default_options
 
static struct ast_cli_entry fax_cli []
 
static const struct ast_datastore_info fax_datastore
 
static const 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
 
static struct faxmodules faxmodules = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
 
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. More...
 
static struct fax_options general_options
 
static int global_fax_debug = 0
 
static ast_rwlock_t options_lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} }
 
static struct ast_control_t38_parameters our_t38_parameters
 

Detailed Description

Generic FAX Resource for FAX technology resource modules.

Author
Dwayne M. Hubbard dhubb.nosp@m.ard@.nosp@m.digiu.nosp@m.m.co.nosp@m.m
Kevin P. Fleming kpfle.nosp@m.ming.nosp@m.@digi.nosp@m.um.c.nosp@m.om
Matthew Nicholson mnich.nosp@m.olso.nosp@m.n@dig.nosp@m.ium..nosp@m.com
Gregory H. Nietsky grego.nosp@m.ry@d.nosp@m.istro.nosp@m.tech.nosp@m..co.z.nosp@m.a

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.

Macro Definition Documentation

◆ FAX_DETECT_MODE_BOTH

#define FAX_DETECT_MODE_BOTH   (FAX_DETECT_MODE_CNG | FAX_DETECT_MODE_T38)

Definition at line 485 of file res_fax.c.

Referenced by acf_faxopt_write().

◆ FAX_DETECT_MODE_CNG

#define FAX_DETECT_MODE_CNG   (1 << 0)

FAX Detect flags.

Definition at line 483 of file res_fax.c.

Referenced by acf_faxopt_write(), and fax_detect_new().

◆ FAX_DETECT_MODE_T38

#define FAX_DETECT_MODE_T38   (1 << 1)

Definition at line 484 of file res_fax.c.

Referenced by acf_faxopt_write(), and fax_detect_framehook().

◆ FAX_GATEWAY_TIMEOUT

#define FAX_GATEWAY_TIMEOUT   RES_FAX_TIMEOUT

Definition at line 493 of file res_fax.c.

Referenced by fax_gateway_detect_t38(), and fax_gateway_request_t38().

◆ FAX_MAXBUCKETS

#define FAX_MAXBUCKETS   10

maximum buckets for res_fax ao2 containers

Definition at line 490 of file res_fax.c.

Referenced by load_module().

◆ GENERIC_FAX_EXEC_ERROR

#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)
#define LOG_ERROR
Definition: logger.h:285
const char * ast_channel_name(const struct ast_channel *chan)

Definition at line 1485 of file res_fax.c.

Referenced by generic_fax_exec().

◆ GENERIC_FAX_EXEC_ERROR_QUIET

#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 1480 of file res_fax.c.

◆ GENERIC_FAX_EXEC_SET_VARS

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

Definition at line 1469 of file res_fax.c.

Referenced by generic_fax_exec().

◆ RES_FAX_MAXRATE

#define RES_FAX_MAXRATE   14400

Definition at line 523 of file res_fax.c.

◆ RES_FAX_MINRATE

#define RES_FAX_MINRATE   4800

Definition at line 522 of file res_fax.c.

◆ RES_FAX_MODEM

#define RES_FAX_MODEM   (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V27TER | AST_FAX_MODEM_V29)

Definition at line 525 of file res_fax.c.

◆ RES_FAX_STATUSEVENTS

#define RES_FAX_STATUSEVENTS   0

Definition at line 524 of file res_fax.c.

◆ RES_FAX_T38TIMEOUT

#define RES_FAX_T38TIMEOUT   5000

Definition at line 526 of file res_fax.c.

◆ RES_FAX_TIMEOUT

#define RES_FAX_TIMEOUT   10000

Definition at line 492 of file res_fax.c.

Referenced by generic_fax_exec().

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
OPT_CALLEDMODE 
OPT_CALLERMODE 
OPT_DEBUG 
OPT_STATUS 
OPT_ALLOWAUDIO 
OPT_REQUEST_T38 
OPT_FORCE_AUDIO 

Definition at line 557 of file res_fax.c.

557  {
558  OPT_CALLEDMODE = (1 << 0),
559  OPT_CALLERMODE = (1 << 1),
560  OPT_DEBUG = (1 << 2),
561  OPT_STATUS = (1 << 3),
562  OPT_ALLOWAUDIO = (1 << 5),
563  OPT_REQUEST_T38 = (1 << 6),
564  OPT_FORCE_AUDIO = (1 << 7),
565 };

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 4867 of file res_fax.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 4867 of file res_fax.c.

◆ acf_faxopt_read()

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 4526 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::negotiate_both, 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.

4527 {
4528  struct ast_fax_session_details *details = find_details(chan);
4529  int res = 0;
4530  char *filenames;
4531 
4532  if (!details) {
4533  ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s) because it has never been written.\n", ast_channel_name(chan), data);
4534  return -1;
4535  }
4536  if (!strcasecmp(data, "ecm")) {
4537  ast_copy_string(buf, details->option.ecm ? "yes" : "no", len);
4538  } else if (!strcasecmp(data, "t38gateway") || !strcasecmp(data, "gateway") ||
4539  !strcasecmp(data, "t38_gateway") || !strcasecmp(data, "faxgateway")) {
4540  ast_copy_string(buf, details->gateway_id != -1 ? "yes" : "no", len);
4541  } else if (!strcasecmp(data, "faxdetect")) {
4542  ast_copy_string(buf, details->faxdetect_id != -1 ? "yes" : "no", len);
4543  } else if (!strcasecmp(data, "error")) {
4544  ast_copy_string(buf, details->error, len);
4545  } else if (!strcasecmp(data, "filename")) {
4546  if (AST_LIST_EMPTY(&details->documents)) {
4547  ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s) because it has never been written.\n", ast_channel_name(chan), data);
4548  res = -1;
4549  } else {
4550  ast_copy_string(buf, AST_LIST_FIRST(&details->documents)->filename, len);
4551  }
4552  } else if (!strcasecmp(data, "filenames")) {
4553  if (AST_LIST_EMPTY(&details->documents)) {
4554  ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s) because it has never been written.\n", ast_channel_name(chan), data);
4555  res = -1;
4556  } else if ((filenames = generate_filenames_string(details, "", ","))) {
4557  ast_copy_string(buf, filenames, len);
4558  ast_free(filenames);
4559  } else {
4560  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);
4561  res = -1;
4562  }
4563  } else if (!strcasecmp(data, "headerinfo")) {
4564  ast_copy_string(buf, details->headerinfo, len);
4565  } else if (!strcasecmp(data, "localstationid")) {
4566  ast_copy_string(buf, details->localstationid, len);
4567  } else if (!strcasecmp(data, "maxrate")) {
4568  snprintf(buf, len, "%u", details->maxrate);
4569  } else if (!strcasecmp(data, "minrate")) {
4570  snprintf(buf, len, "%u", details->minrate);
4571  } else if (!strcasecmp(data, "pages")) {
4572  snprintf(buf, len, "%u", details->pages_transferred);
4573  } else if (!strcasecmp(data, "rate")) {
4574  ast_copy_string(buf, details->transfer_rate, len);
4575  } else if (!strcasecmp(data, "remotestationid")) {
4576  ast_copy_string(buf, details->remotestationid, len);
4577  } else if (!strcasecmp(data, "resolution")) {
4578  ast_copy_string(buf, details->resolution, len);
4579  } else if (!strcasecmp(data, "sessionid")) {
4580  snprintf(buf, len, "%u", details->id);
4581  } else if (!strcasecmp(data, "status")) {
4582  ast_copy_string(buf, details->result, len);
4583  } else if (!strcasecmp(data, "statusstr")) {
4584  ast_copy_string(buf, details->resultstr, len);
4585  } else if ((!strcasecmp(data, "modem")) || (!strcasecmp(data, "modems"))) {
4586  ast_fax_modem_to_str(details->modems, buf, len);
4587  } else if (!strcasecmp(data, "t38timeout")) {
4588  snprintf(buf, len, "%u", details->t38timeout);
4589  } else if (!strcasecmp(data, "negotiate_both")) {
4590  ast_copy_string(buf, details->negotiate_both != -1 ? "yes" : "no", len);
4591  } else {
4592  ast_log(LOG_WARNING, "channel '%s' can't read FAXOPT(%s) because it is unhandled!\n", ast_channel_name(chan), data);
4593  res = -1;
4594  }
4595  ao2_ref(details, -1);
4596 
4597  return res;
4598 }
const ast_string_field result
Definition: res_fax.h:142
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
unsigned int t38timeout
Definition: res_fax.h:179
const ast_string_field headerinfo
Definition: res_fax.h:142
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define LOG_WARNING
Definition: logger.h:274
const ast_string_field transfer_rate
Definition: res_fax.h:142
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
unsigned int id
Definition: res_fax.h:117
union ast_fax_session_details::@290 option
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Definition: astobj2.h:464
The data communicated between the high level applications and the generic fax function.
Definition: res_fax.h:110
const ast_string_field remotestationid
Definition: res_fax.h:142
#define LOG_ERROR
Definition: logger.h:285
unsigned int pages_transferred
Definition: res_fax.h:144
struct ast_fax_documents documents
Definition: res_fax.h:119
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
unsigned int minrate
Definition: res_fax.h:171
#define ast_free(a)
Definition: astmm.h:182
enum ast_fax_modems modems
Definition: res_fax.h:115
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static struct ast_fax_session_details * find_details(struct ast_channel *chan)
returns a reference counted pointer to a fax datastore, if it exists
Definition: res_fax.c:662
const char * ast_channel_name(const struct ast_channel *chan)
static int ast_fax_modem_to_str(enum ast_fax_modems bits, char *tbuf, size_t bufsize)
Definition: res_fax.c:905
const ast_string_field resultstr
Definition: res_fax.h:142
const ast_string_field localstationid
Definition: res_fax.h:142
unsigned int maxrate
Definition: res_fax.h:173
const ast_string_field error
Definition: res_fax.h:142
const ast_string_field resolution
Definition: res_fax.h:142
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.
Definition: res_fax.c:1370

◆ acf_faxopt_write()

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 4601 of file res_fax.c.

References ao2_ref, ast_channel_lock, ast_channel_name(), ast_channel_unlock, 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::negotiate_both, ast_fax_session_details::option, set_t38timeout(), ast_fax_session_details::t38timeout, and update_modem_bits().

4602 {
4603  int res = 0;
4604  struct ast_fax_session_details *details;
4605 
4606  if (!(details = find_or_create_details(chan))) {
4607  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);
4608  return -1;
4609  }
4610  ast_debug(3, "channel '%s' setting FAXOPT(%s) to '%s'\n", ast_channel_name(chan), data, value);
4611 
4612  if (!strcasecmp(data, "ecm")) {
4613  const char *val = ast_skip_blanks(value);
4614  if (ast_true(val)) {
4615  details->option.ecm = AST_FAX_OPTFLAG_TRUE;
4616  } else if (ast_false(val)) {
4617  details->option.ecm = AST_FAX_OPTFLAG_FALSE;
4618  } else {
4619  ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(ecm).\n", value);
4620  }
4621  } else if (!strcasecmp(data, "t38gateway") || !strcasecmp(data, "gateway") ||
4622  !strcasecmp(data, "t38_gateway") || !strcasecmp(data, "faxgateway")) {
4623  const char *val = ast_skip_blanks(value);
4624  char *timeout = strchr(val, ',');
4625 
4626  if (timeout) {
4627  *timeout++ = '\0';
4628  }
4629 
4630  if (ast_true(val)) {
4631  if (details->gateway_id < 0) {
4632  details->gateway_timeout = 0;
4633  if (timeout) {
4634  unsigned int gwtimeout;
4635 
4636  if (sscanf(timeout, "%30u", &gwtimeout) == 1) {
4637  details->gateway_timeout = gwtimeout * 1000;
4638  } else {
4639  ast_log(LOG_WARNING, "Unsupported timeout '%s' passed to FAXOPT(%s).\n", timeout, data);
4640  }
4641  }
4642 
4643  details->gateway_id = fax_gateway_attach(chan, details);
4644  if (details->gateway_id < 0) {
4645  ast_log(LOG_ERROR, "Error attaching T.38 gateway to channel %s.\n", ast_channel_name(chan));
4646  res = -1;
4647  } else {
4648  ast_debug(1, "Attached T.38 gateway to channel %s.\n", ast_channel_name(chan));
4649  }
4650  } else {
4651  ast_log(LOG_WARNING, "Attempt to attach a T.38 gateway on channel (%s) with gateway already running.\n", ast_channel_name(chan));
4652  }
4653  } else if (ast_false(val)) {
4654  ast_channel_lock(chan);
4655  ast_framehook_detach(chan, details->gateway_id);
4656  ast_channel_unlock(chan);
4657  details->gateway_id = -1;
4658  } else {
4659  ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(%s).\n", value, data);
4660  }
4661  } else if (!strcasecmp(data, "faxdetect")) {
4662  const char *val = ast_skip_blanks(value);
4663  char *timeout = strchr(val, ',');
4664  unsigned int fdtimeout = 0;
4665  int flags;
4666  int faxdetect;
4667 
4668  if (timeout) {
4669  *timeout++ = '\0';
4670  }
4671 
4672  if (ast_true(val) || !strcasecmp(val, "t38") || !strcasecmp(val, "cng")) {
4673  if (details->faxdetect_id < 0) {
4674  if (timeout) {
4675  if (sscanf(timeout, "%30u", &fdtimeout) == 1) {
4676  fdtimeout *= 1000;
4677  } else {
4678  ast_log(LOG_WARNING, "Unsupported timeout '%s' passed to FAXOPT(%s).\n",
4679  timeout, data);
4680  }
4681  }
4682 
4683  if (!strcasecmp(val, "t38")) {
4684  flags = FAX_DETECT_MODE_T38;
4685  } else if (!strcasecmp(val, "cng")) {
4686  flags = FAX_DETECT_MODE_CNG;
4687  } else {
4688  flags = FAX_DETECT_MODE_BOTH;
4689  }
4690 
4691  faxdetect = fax_detect_attach(chan, fdtimeout, flags);
4692  if (faxdetect < 0) {
4693  ast_log(LOG_ERROR, "Error attaching FAX detect to channel %s.\n", ast_channel_name(chan));
4694  res = -1;
4695  } else {
4696  ast_debug(1, "Attached FAX detect to channel %s.\n", ast_channel_name(chan));
4697  }
4698  } else {
4699  ast_log(LOG_WARNING, "Attempt to attach a FAX detect on channel (%s) with FAX detect already running.\n", ast_channel_name(chan));
4700  }
4701  } else if (ast_false(val)) {
4702  ast_channel_lock(chan);
4703  ast_framehook_detach(chan, details->faxdetect_id);
4704  ast_channel_unlock(chan);
4705  details->faxdetect_id = -1;
4706  } else {
4707  ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(%s).\n", value, data);
4708  }
4709  } else if (!strcasecmp(data, "headerinfo")) {
4711  } else if (!strcasecmp(data, "localstationid")) {
4713  } else if (!strcasecmp(data, "maxrate")) {
4714  details->maxrate = fax_rate_str_to_int(value);
4715  if (!details->maxrate) {
4716  details->maxrate = ast_fax_maxrate();
4717  }
4718  } else if (!strcasecmp(data, "minrate")) {
4719  details->minrate = fax_rate_str_to_int(value);
4720  if (!details->minrate) {
4721  details->minrate = ast_fax_minrate();
4722  }
4723  } else if (!strcasecmp(data, "t38timeout")) {
4724  if (set_t38timeout(value, &details->t38timeout)) {
4725  res = -1;
4726  }
4727  } else if ((!strcasecmp(data, "modem")) || (!strcasecmp(data, "modems"))) {
4728  update_modem_bits(&details->modems, value);
4729  } else if (!strcasecmp(data, "negotiate_both")) {
4731  } else {
4732  ast_log(LOG_WARNING, "channel '%s' set FAXOPT(%s) to '%s' is unhandled!\n", ast_channel_name(chan), data, value);
4733  res = -1;
4734  }
4735 
4736  ao2_ref(details, -1);
4737 
4738  return res;
4739 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
unsigned int t38timeout
Definition: res_fax.h:179
const ast_string_field headerinfo
Definition: res_fax.h:142
Definition: ast_expr2.c:325
static unsigned int fax_rate_str_to_int(const char *ratestr)
convert a rate string to a rate
Definition: res_fax.c:1046
static int fdtimeout
#define LOG_WARNING
Definition: logger.h:274
static int timeout
Definition: cdr_mysql.c:86
int ast_framehook_detach(struct ast_channel *chan, int framehook_id)
Detach an framehook from a channel.
Definition: framehook.c:177
int value
Definition: syslog.c:37
static int fax_gateway_attach(struct ast_channel *chan, struct ast_fax_session_details *details)
Attach a gateway framehook object to a channel.
Definition: res_fax.c:3626
union ast_fax_session_details::@290 option
static int update_modem_bits(enum ast_fax_modems *bits, const char *value)
Definition: res_fax.c:812
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Definition: astobj2.h:464
unsigned int ast_fax_minrate(void)
get the minimum supported fax rate
Definition: res_fax.c:804
The data communicated between the high level applications and the generic fax function.
Definition: res_fax.h:110
static struct ast_fax_session_details * find_or_create_details(struct ast_channel *chan)
returns a reference counted details structure from the channel&#39;s fax datastore. If the datastore does...
Definition: res_fax.c:764
#define LOG_ERROR
Definition: logger.h:285
#define FAX_DETECT_MODE_CNG
FAX Detect flags.
Definition: res_fax.c:483
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: main/utils.c:1951
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition: strings.h:157
unsigned int minrate
Definition: res_fax.h:171
#define ast_channel_unlock(chan)
Definition: channel.h:2946
static int set_t38timeout(const char *value, unsigned int *t38timeout)
Definition: res_fax.c:4404
enum ast_fax_modems modems
Definition: res_fax.h:115
unsigned int ast_fax_maxrate(void)
get the maxiumum supported fax rate
Definition: res_fax.c:796
const char * ast_channel_name(const struct ast_channel *chan)
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"...
Definition: main/utils.c:1968
static int fax_detect_attach(struct ast_channel *chan, int timeout, int flags)
Attach a faxdetect framehook object to a channel.
Definition: res_fax.c:3889
const ast_string_field localstationid
Definition: res_fax.h:142
unsigned int maxrate
Definition: res_fax.h:173
#define FAX_DETECT_MODE_T38
Definition: res_fax.c:484
#define FAX_DETECT_MODE_BOTH
Definition: res_fax.c:485
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ ast_fax_caps_to_str()

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

Definition at line 846 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, buf, first, and out.

Referenced by fax_session_new(), and fax_session_reserve().

847 {
848  char *out = buf;
849  size_t size = bufsize;
850  int first = 1;
851 
852  if (caps & AST_FAX_TECH_SEND) {
853  if (!first) {
854  ast_build_string(&buf, &size, ",");
855  }
856  ast_build_string(&buf, &size, "SEND");
857  first = 0;
858  }
859  if (caps & AST_FAX_TECH_RECEIVE) {
860  if (!first) {
861  ast_build_string(&buf, &size, ",");
862  }
863  ast_build_string(&buf, &size, "RECEIVE");
864  first = 0;
865  }
866  if (caps & AST_FAX_TECH_AUDIO) {
867  if (!first) {
868  ast_build_string(&buf, &size, ",");
869  }
870  ast_build_string(&buf, &size, "AUDIO");
871  first = 0;
872  }
873  if (caps & AST_FAX_TECH_T38) {
874  if (!first) {
875  ast_build_string(&buf, &size, ",");
876  }
877  ast_build_string(&buf, &size, "T38");
878  first = 0;
879  }
881  if (!first) {
882  ast_build_string(&buf, &size, ",");
883  }
884  ast_build_string(&buf, &size, "MULTI_DOC");
885  first = 0;
886  }
887  if (caps & AST_FAX_TECH_GATEWAY) {
888  if (!first) {
889  ast_build_string(&buf, &size, ",");
890  }
891  ast_build_string(&buf, &size, "GATEWAY");
892  first = 0;
893  }
895  if (!first) {
896  ast_build_string(&buf, &size, ",");
897  }
898  ast_build_string(&buf, &size, "V21");
899  first = 0;
900  }
901 
902  return out;
903 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
int ast_build_string(char **buffer, size_t *space, const char *fmt,...)
Build a string in a buffer, designed to be called repeatedly.
Definition: main/utils.c:1919
struct sla_ringing_trunk * first
Definition: app_meetme.c:1092
FILE * out
Definition: utils/frame.c:33
enum ast_fax_capabilities caps
Definition: res_fax.h:113

◆ ast_fax_log()

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 1036 of file res_fax.c.

References ast_log, ast_log_dynamic_level, and fax_logger_level.

Referenced by spandsp_log().

1037 {
1038  if (fax_logger_level != -1) {
1040  } else {
1041  ast_log(level, file, line, function, "%s", msg);
1042  }
1043 }
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:439
#define ast_log
Definition: astobj2.c:42
static int fax_logger_level
Definition: res_fax.c:487

◆ ast_fax_maxrate()

unsigned int ast_fax_maxrate ( void  )

get the maxiumum supported fax rate

Definition at line 796 of file res_fax.c.

References get_general_options(), and fax_options::maxrate.

Referenced by acf_faxopt_write().

797 {
798  struct fax_options options;
800 
801  return options.maxrate;
802 }
static struct test_options options
static void get_general_options(struct fax_options *options)
Definition: res_fax.c:4397

◆ ast_fax_minrate()

unsigned int ast_fax_minrate ( void  )

get the minimum supported fax rate

Definition at line 804 of file res_fax.c.

References get_general_options(), and fax_options::minrate.

Referenced by acf_faxopt_write().

805 {
806  struct fax_options options;
808 
809  return options.minrate;
810 }
static struct test_options options
static void get_general_options(struct fax_options *options)
Definition: res_fax.c:4397

◆ ast_fax_modem_to_str()

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

Definition at line 905 of file res_fax.c.

References AST_FAX_MODEM_V17, AST_FAX_MODEM_V27TER, 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().

906 {
907  int count = 0;
908 
909  if (bits & AST_FAX_MODEM_V17) {
910  strcat(tbuf, "V17");
911  count++;
912  }
913  if (bits & AST_FAX_MODEM_V27TER) {
914  if (count) {
915  strcat(tbuf, ",");
916  }
917  strcat(tbuf, "V27");
918  count++;
919  }
920  if (bits & AST_FAX_MODEM_V29) {
921  if (count) {
922  strcat(tbuf, ",");
923  }
924  strcat(tbuf, "V29");
925  count++;
926  }
927  if (bits & AST_FAX_MODEM_V34) {
928  if (count) {
929  strcat(tbuf, ",");
930  }
931  strcat(tbuf, "V34");
932  count++;
933  }
934 
935  return 0;
936 }

◆ ast_fax_session_operation_str()

const char* ast_fax_session_operation_str ( struct ast_fax_session s)

get string representation of a FAX session's operation

Definition at line 4254 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().

4255 {
4256  if (s->details->caps & AST_FAX_TECH_GATEWAY) {
4257  return "gateway";
4258  }
4259  if (s->details->caps & AST_FAX_TECH_SEND) {
4260  return "send";
4261  }
4262  if (s->details->caps & AST_FAX_TECH_RECEIVE) {
4263  return "receive";
4264  }
4265  if (s->details->caps & AST_FAX_TECH_V21_DETECT) {
4266  return "V.21";
4267  }
4268 
4269  return "none";
4270 }
struct ast_fax_session_details * details
Definition: res_fax.h:208
enum ast_fax_capabilities caps
Definition: res_fax.h:113

◆ ast_fax_state_to_str()

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 1013 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().

1014 {
1015  switch (state) {
1017  return "Uninitialized";
1019  return "Initialized";
1020  case AST_FAX_STATE_OPEN:
1021  return "Open";
1022  case AST_FAX_STATE_ACTIVE:
1023  return "Active";
1025  return "Complete";
1027  return "Reserved";
1029  return "Inactive";
1030  default:
1031  ast_log(LOG_WARNING, "unhandled FAX state: %u\n", state);
1032  return "Unknown";
1033  }
1034 }
#define LOG_WARNING
Definition: logger.h:274
#define ast_log
Definition: astobj2.c:42

◆ ast_fax_tech_register()

int ast_fax_tech_register ( struct ast_fax_tech tech)

register a FAX technology module

register a fax technology

Definition at line 974 of file res_fax.c.

References ast_calloc, 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().

975 {
976  struct fax_module *fax;
977 
978  if (!(fax = ast_calloc(1, sizeof(*fax)))) {
979  return -1;
980  }
981  fax->tech = tech;
983  AST_RWLIST_INSERT_TAIL(&faxmodules, fax, list);
985 
986  ast_verb(3, "Registered handler for '%s' (%s)\n", fax->tech->type, fax->tech->description);
987 
988  return 0;
989 }
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
const char *const type
Definition: res_fax.h:237
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
const struct ast_fax_tech * tech
Definition: res_fax.c:517
const char *const description
Definition: res_fax.h:239
#define ast_verb(level,...)
Definition: logger.h:463
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
registered FAX technology modules are put into this list
Definition: res_fax.c:516
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:740

◆ ast_fax_tech_unregister()

void ast_fax_tech_unregister ( struct ast_fax_tech tech)

unregister a FAX technology module

unregister a fax technology

Definition at line 992 of file res_fax.c.

References ast_free, 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().

993 {
994  struct fax_module *fax;
995 
996  ast_verb(3, "Unregistering FAX module type '%s'\n", tech->type);
997 
1000  if (fax->tech != tech) {
1001  continue;
1002  }
1004  ast_free(fax);
1005  ast_verb(4, "Unregistered FAX module type '%s'\n", tech->type);
1006  break;
1007  }
1010 }
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
const char *const type
Definition: res_fax.h:237
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
const struct ast_fax_tech * tech
Definition: res_fax.c:517
#define ast_verb(level,...)
Definition: logger.h:463
#define AST_RWLIST_REMOVE_CURRENT
Definition: linkedlists.h:569
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:544
#define ast_free(a)
Definition: astmm.h:182
registered FAX technology modules are put into this list
Definition: res_fax.c:516
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:616

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 4867 of file res_fax.c.

◆ check_modem_rate()

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

Definition at line 938 of file res_fax.c.

References AST_FAX_MODEM_V17, AST_FAX_MODEM_V27TER, AST_FAX_MODEM_V29, and AST_FAX_MODEM_V34.

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

939 {
940  switch (rate) {
941  case 2400:
942  case 4800:
943  if (!(modems & (AST_FAX_MODEM_V27TER | AST_FAX_MODEM_V34))) {
944  return 1;
945  }
946  break;
947  case 7200:
948  case 9600:
949  if (!(modems & (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V29 | AST_FAX_MODEM_V34))) {
950  return 1;
951  }
952  break;
953  case 12000:
954  case 14400:
955  if (!(modems & (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V34))) {
956  return 1;
957  }
958  break;
959  case 28800:
960  case 33600:
961  if (!(modems & AST_FAX_MODEM_V34)) {
962  return 1;
963  }
964  break;
965  default:
966  /* this should never happen */
967  return 1;
968  }
969 
970  return 0;
971 }

◆ cli_fax_set_debug()

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 4003 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.

4004 {
4005  int flag;
4006  const char *what;
4007 
4008  switch (cmd) {
4009  case CLI_INIT:
4010  e->command = "fax set debug {on|off}";
4011  e->usage =
4012  "Usage: fax set debug { on | off }\n"
4013  " Enable/Disable FAX debugging on new FAX sessions. The basic FAX debugging will result in\n"
4014  " additional events sent to manager sessions with 'call' class permissions. When\n"
4015  " verbosity is greater than '5' events will be displayed to the console and audio versus\n"
4016  " energy analysis will be performed and displayed to the console.\n";
4017  return NULL;
4018  case CLI_GENERATE:
4019  return NULL;
4020  }
4021 
4022  what = a->argv[e->args-1]; /* guaranteed to exist */
4023  if (!strcasecmp(what, "on")) {
4024  flag = 1;
4025  } else if (!strcasecmp(what, "off")) {
4026  flag = 0;
4027  } else {
4028  return CLI_SHOWUSAGE;
4029  }
4030 
4032  ast_cli(a->fd, "\n\nFAX Debug %s\n\n", (flag) ? "Enabled" : "Disabled");
4033 
4034  return CLI_SUCCESS;
4035 }
Definition: cli.h:152
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
int args
This gets set in ast_cli_register()
Definition: cli.h:185
const int fd
Definition: cli.h:159
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
long int flag
Definition: f2c.h:83
char * command
Definition: cli.h:186
static int global_fax_debug
Definition: res_fax.c:555
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44

◆ cli_fax_show_capabilities()

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 4038 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.

4039 {
4040  struct fax_module *fax;
4041  unsigned int num_modules = 0;
4042 
4043  switch (cmd) {
4044  case CLI_INIT:
4045  e->command = "fax show capabilities";
4046  e->usage =
4047  "Usage: fax show capabilities\n"
4048  " Shows the capabilities of the registered FAX technology modules\n";
4049  return NULL;
4050  case CLI_GENERATE:
4051  return NULL;
4052  }
4053 
4054  ast_cli(a->fd, "\n\nRegistered FAX Technology Modules:\n\n");
4056  AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
4057  ast_cli(a->fd, "%-15s : %s\n%-15s : %s\n%-15s : ", "Type", fax->tech->type, "Description", fax->tech->description, "Capabilities");
4058  fax->tech->cli_show_capabilities(a->fd);
4059  num_modules++;
4060  }
4062  ast_cli(a->fd, "%u registered modules\n\n", num_modules);
4063 
4064  return CLI_SUCCESS;
4065 }
const char *const type
Definition: res_fax.h:237
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
Definition: cli.h:152
const struct ast_fax_tech * tech
Definition: res_fax.c:517
const char *const description
Definition: res_fax.h:239
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
const int fd
Definition: cli.h:159
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
registered FAX technology modules are put into this list
Definition: res_fax.c:516
char *(*const cli_show_capabilities)(int)
Definition: res_fax.h:267

◆ cli_fax_show_session()

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 4107 of file res_fax.c.

References ao2_find, ao2_ref, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_log, ast_fax_session::channame, 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.

4108 {
4109  struct ast_fax_session *s, tmp;
4110 
4111  switch (cmd) {
4112  case CLI_INIT:
4113  e->command = "fax show session";
4114  e->usage =
4115  "Usage: fax show session <session number>\n"
4116  " Shows status of the named FAX session\n";
4117  return NULL;
4118  case CLI_GENERATE:
4119  return fax_session_tab_complete(a);
4120  }
4121 
4122  if (a->argc != 4) {
4123  return CLI_SHOWUSAGE;
4124  }
4125 
4126  if (sscanf(a->argv[3], "%u", &tmp.id) != 1) {
4127  ast_log(LOG_ERROR, "invalid session id: '%s'\n", a->argv[3]);
4128  return RESULT_SUCCESS;
4129  }
4130 
4131  ast_cli(a->fd, "\nFAX Session Details:\n--------------------\n\n");
4132  s = ao2_find(faxregistry.container, &tmp, OBJ_POINTER);
4133  if (s) {
4134  ast_cli(a->fd, "%-22s : %s\n", "channel", s->channame);
4135  s->tech->cli_show_session(s, a->fd);
4136  ao2_ref(s, -1);
4137  }
4138  ast_cli(a->fd, "\n\n");
4139 
4140  return CLI_SUCCESS;
4141 }
const struct ast_fax_tech * tech
Definition: res_fax.h:214
unsigned int id
Definition: res_fax.h:204
#define OBJ_POINTER
Definition: astobj2.h:1154
const int argc
Definition: cli.h:160
static int tmp()
Definition: bt_open.c:389
Definition: cli.h:152
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
#define ast_log
Definition: astobj2.c:42
const int fd
Definition: cli.h:159
#define ao2_ref(o, delta)
Definition: astobj2.h:464
char * channame
Definition: res_fax.h:220
const char *const * argv
Definition: cli.h:161
#define LOG_ERROR
Definition: logger.h:285
#define CLI_SHOWUSAGE
Definition: cli.h:45
char * command
Definition: cli.h:186
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
char *(*const cli_show_session)(struct ast_fax_session *, int)
Definition: res_fax.h:269
static struct @460 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.
The data required to handle a fax session.
Definition: res_fax.h:202
static char * fax_session_tab_complete(struct ast_cli_args *a)
fax session tab completion
Definition: res_fax.c:3943
#define RESULT_SUCCESS
Definition: cli.h:40

◆ cli_fax_show_sessions()

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 4273 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.

4274 {
4275  struct ast_fax_session *s;
4276  struct ao2_iterator i;
4277  int session_count;
4278  char *filenames;
4279 
4280  switch (cmd) {
4281  case CLI_INIT:
4282  e->command = "fax show sessions";
4283  e->usage =
4284  "Usage: fax show sessions\n"
4285  " Shows the current FAX sessions\n";
4286  return NULL;
4287  case CLI_GENERATE:
4288  return NULL;
4289  }
4290 
4291  ast_cli(a->fd, "\nCurrent FAX Sessions:\n\n");
4292  ast_cli(a->fd, "%-30.30s %-10.10s %-10.10s %-5.5s %-10.10s %-15.15s %-30.30s\n",
4293  "Channel", "Tech", "FAXID", "Type", "Operation", "State", "File(s)");
4294  i = ao2_iterator_init(faxregistry.container, 0);
4295  while ((s = ao2_iterator_next(&i))) {
4296  ao2_lock(s);
4297 
4298  filenames = generate_filenames_string(s->details, "", ", ");
4299 
4300  ast_cli(a->fd, "%-30.30s %-10.10s %-10u %-5.5s %-10.10s %-15.15s %-30s\n",
4301  s->channame, s->tech->type, s->id,
4302  fax_session_type(s),
4304  ast_fax_state_to_str(s->state), S_OR(filenames, ""));
4305 
4306  ast_free(filenames);
4307  ao2_unlock(s);
4308  ao2_ref(s, -1);
4309  }
4311  session_count = ao2_container_count(faxregistry.container);
4312  ast_cli(a->fd, "\n%d FAX sessions\n\n", session_count);
4313 
4314  return CLI_SUCCESS;
4315 }
const struct ast_fax_tech * tech
Definition: res_fax.h:214
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
unsigned int id
Definition: res_fax.h:204
const char *const type
Definition: res_fax.h:237
Definition: cli.h:152
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
const int fd
Definition: cli.h:159
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct ast_fax_session_details * details
Definition: res_fax.h:208
#define ao2_lock(a)
Definition: astobj2.h:718
char * channame
Definition: res_fax.h:220
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
#define ast_free(a)
Definition: astmm.h:182
char * command
Definition: cli.h:186
enum ast_fax_state state
Definition: res_fax.h:218
static int session_count
Definition: http.c:109
static const char * fax_session_type(struct ast_fax_session *s)
Definition: res_fax.c:4242
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
static struct @460 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.
const char * ast_fax_session_operation_str(struct ast_fax_session *s)
get string representation of a FAX session&#39;s operation
Definition: res_fax.c:4254
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
The data required to handle a fax session.
Definition: res_fax.h:202
const char * ast_fax_state_to_str(enum ast_fax_state state)
convert a ast_fax_state to a string
Definition: res_fax.c:1013
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
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.
Definition: res_fax.c:1370

◆ cli_fax_show_settings()

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 4068 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.

4069 {
4070  struct fax_module *fax;
4071  char modems[128] = "";
4072  struct fax_options options;
4073 
4074  switch (cmd) {
4075  case CLI_INIT:
4076  e->command = "fax show settings";
4077  e->usage =
4078  "Usage: fax show settings\n"
4079  " Show the global settings and defaults of both the FAX core and technology modules\n";
4080  return NULL;
4081  case CLI_GENERATE:
4082  return NULL;
4083  }
4084 
4086 
4087  ast_cli(a->fd, "FAX For Asterisk Settings:\n");
4088  ast_cli(a->fd, "\tECM: %s\n", options.ecm ? "Enabled" : "Disabled");
4089  ast_cli(a->fd, "\tStatus Events: %s\n", options.statusevents ? "On" : "Off");
4090  ast_cli(a->fd, "\tMinimum Bit Rate: %u\n", options.minrate);
4091  ast_cli(a->fd, "\tMaximum Bit Rate: %u\n", options.maxrate);
4092  ast_fax_modem_to_str(options.modems, modems, sizeof(modems));
4093  ast_cli(a->fd, "\tModem Modulations Allowed: %s\n", modems);
4094  ast_cli(a->fd, "\tT.38 Negotiation Timeout: %u\n", options.t38timeout);
4095  ast_cli(a->fd, "\n\nFAX Technology Modules:\n\n");
4097  AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
4098  ast_cli(a->fd, "%s (%s) Settings:\n", fax->tech->type, fax->tech->description);
4099  fax->tech->cli_show_settings(a->fd);
4100  }
4102 
4103  return CLI_SUCCESS;
4104 }
const char *const type
Definition: res_fax.h:237
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
Definition: cli.h:152
const struct ast_fax_tech * tech
Definition: res_fax.c:517
const char *const description
Definition: res_fax.h:239
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
const int fd
Definition: cli.h:159
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
registered FAX technology modules are put into this list
Definition: res_fax.c:516
static int ast_fax_modem_to_str(enum ast_fax_modems bits, char *tbuf, size_t bufsize)
Definition: res_fax.c:905
static struct test_options options
char *(*const cli_show_settings)(int)
Definition: res_fax.h:276
static void get_general_options(struct fax_options *options)
Definition: res_fax.c:4397

◆ cli_fax_show_stats()

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 4181 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.

4182 {
4183  struct fax_module *fax;
4184 
4185  switch (cmd) {
4186  case CLI_INIT:
4187  e->command = "fax show stats";
4188  e->usage =
4189  "Usage: fax show stats\n"
4190  " Shows a statistical summary of FAX transmissions\n";
4191  return NULL;
4192  case CLI_GENERATE:
4193  return NULL;
4194  }
4195 
4196  ast_cli(a->fd, "\nFAX Statistics:\n---------------\n\n");
4197  ast_cli(a->fd, "%-20.20s : %d\n", "Current Sessions", faxregistry.active_sessions);
4198  ast_cli(a->fd, "%-20.20s : %d\n", "Reserved Sessions", faxregistry.reserved_sessions);
4199  ast_cli(a->fd, "%-20.20s : %d\n", "Transmit Attempts", faxregistry.fax_tx_attempts);
4200  ast_cli(a->fd, "%-20.20s : %d\n", "Receive Attempts", faxregistry.fax_rx_attempts);
4201  ast_cli(a->fd, "%-20.20s : %d\n", "Completed FAXes", faxregistry.fax_complete);
4202  ast_cli(a->fd, "%-20.20s : %d\n", "Failed FAXes", faxregistry.fax_failures);
4204  AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
4205  fax->tech->cli_show_stats(a->fd);
4206  }
4208  ast_cli(a->fd, "\n\n");
4209 
4210  return CLI_SUCCESS;
4211 }
char *(*const cli_show_stats)(int)
Definition: res_fax.h:274
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
Definition: cli.h:152
const struct ast_fax_tech * tech
Definition: res_fax.c:517
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
const int fd
Definition: cli.h:159
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
registered FAX technology modules are put into this list
Definition: res_fax.c:516
static struct @460 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.

◆ cli_fax_show_version()

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

Definition at line 3971 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.

3972 {
3973  struct fax_module *fax;
3974 
3975  switch(cmd) {
3976  case CLI_INIT:
3977  e->command = "fax show version";
3978  e->usage =
3979  "Usage: fax show version\n"
3980  " Show versions of FAX For Asterisk components.\n";
3981  return NULL;
3982  case CLI_GENERATE:
3983  return NULL;
3984  }
3985 
3986  if (a->argc != 3) {
3987  return CLI_SHOWUSAGE;
3988  }
3989 
3990  ast_cli(a->fd, "FAX For Asterisk Components:\n");
3991  ast_cli(a->fd, "\tApplications: %s\n", ast_get_version());
3993  AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
3994  ast_cli(a->fd, "\t%s: %s\n", fax->tech->description, fax->tech->version);
3995  }
3997  ast_cli(a->fd, "\n");
3998 
3999  return CLI_SUCCESS;
4000 }
const char * ast_get_version(void)
Retrieve the Asterisk version string.
Definition: version.c:16
const int argc
Definition: cli.h:160
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
Definition: cli.h:152
const struct ast_fax_tech * tech
Definition: res_fax.c:517
const char *const description
Definition: res_fax.h:239
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
const int fd
Definition: cli.h:159
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
#define CLI_SHOWUSAGE
Definition: cli.h:45
char * command
Definition: cli.h:186
const char *const version
Definition: res_fax.h:241
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
registered FAX technology modules are put into this list
Definition: res_fax.c:516

◆ debug_check_frame_for_silence()

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

Definition at line 577 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().

578 {
579  struct debug_info_history *history = c2s ? &s->debug_info->c2s : &s->debug_info->s2c;
580  int dspsilence;
581  unsigned int last_consec_frames, last_consec_ms;
582  unsigned char wassil;
583  struct timeval diff;
584 
585  diff = ast_tvsub(ast_tvnow(), s->debug_info->base_tv);
586 
588  ast_dsp_silence(s->debug_info->dsp, frame, &dspsilence);
589 
590  wassil = history->silence;
591  history->silence = (dspsilence != 0) ? 1 : 0;
592  if (history->silence != wassil) {
593  last_consec_frames = history->consec_frames;
594  last_consec_ms = history->consec_ms;
595  history->consec_frames = 0;
596  history->consec_ms = 0;
597 
598  if ((last_consec_frames != 0)) {
599  ast_verb(0, "Channel '%s' fax session '%u', [ %.3ld.%.6ld ], %s sent %u frames (%u ms) of %s.\n",
600  s->channame, s->id, (long) diff.tv_sec, (long int) diff.tv_usec,
601  (c2s) ? "channel" : "stack", last_consec_frames, last_consec_ms,
602  (wassil) ? "silence" : "energy");
603  }
604  }
605 
606  history->consec_frames++;
607  history->consec_ms += (frame->samples / 8);
608 }
unsigned int consec_frames
Definition: res_fax.c:432
unsigned int id
Definition: res_fax.h:204
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define ast_verb(level,...)
Definition: logger.h:463
struct ast_fax_debug_info * debug_info
Definition: res_fax.h:226
char * channame
Definition: res_fax.h:220
void ast_dsp_reset(struct ast_dsp *dsp)
Reset total silence count.
Definition: dsp.c:1830
unsigned int consec_ms
Definition: res_fax.c:433
struct ast_dsp * dsp
Definition: res_fax.c:440
int ast_dsp_silence(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
Process the audio frame for silence.
Definition: dsp.c:1483
struct timeval base_tv
Definition: res_fax.c:438
struct timeval ast_tvsub(struct timeval a, struct timeval b)
Returns the difference of two timevals a - b.
Definition: extconf.c:2298
unsigned char silence
Definition: res_fax.c:434
struct debug_info_history c2s s2c
Definition: res_fax.c:439

◆ destroy_callback()

static void destroy_callback ( void *  data)
static

Definition at line 610 of file res_fax.c.

References ao2_ref, and fixup_callback().

611 {
612  if (data) {
613  ao2_ref(data, -1);
614  }
615 }
#define ao2_ref(o, delta)
Definition: astobj2.h:464

◆ destroy_faxdetect()

static void destroy_faxdetect ( void *  data)
static

destroy a FAX detect structure

Definition at line 3676 of file res_fax.c.

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

Referenced by fax_detect_new().

3677 {
3678  struct fax_detect *faxdetect = data;
3679 
3680  if (faxdetect->dsp) {
3681  ast_dsp_free(faxdetect->dsp);
3682  faxdetect->dsp = NULL;
3683  }
3684  ao2_cleanup(faxdetect->details);
3685  ao2_cleanup(faxdetect->orig_format);
3686 }
void ast_dsp_free(struct ast_dsp *dsp)
Definition: dsp.c:1770
used for fax detect framehook
Definition: res_fax.c:469
#define NULL
Definition: resample.c:96
struct ast_fax_session_details * details
fax session details
Definition: res_fax.c:477
struct ast_format * orig_format
original audio formats
Definition: res_fax.c:475
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct ast_dsp * dsp
DSP Processor.
Definition: res_fax.c:473

◆ destroy_gateway()

static void destroy_gateway ( void *  data)
static

destroy a FAX gateway session structure

Definition at line 2839 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.

Referenced by fax_gateway_new().

2840 {
2841  struct fax_gateway *gateway = data;
2842 
2843  destroy_v21_sessions(gateway);
2844 
2845  if (gateway->s) {
2846  fax_session_release(gateway->s, gateway->token);
2847  gateway->token = NULL;
2848 
2849  ao2_unlink(faxregistry.container, gateway->s);
2850 
2851  ao2_ref(gateway->s, -1);
2852  gateway->s = NULL;
2853  }
2854 
2855  ao2_cleanup(gateway->chan_read_format);
2856  ao2_cleanup(gateway->chan_write_format);
2857  ao2_cleanup(gateway->peer_read_format);
2858  ao2_cleanup(gateway->peer_write_format);
2859 }
used for gateway framehook
Definition: res_fax.c:444
#define NULL
Definition: resample.c:96
struct ast_fax_session * s
FAX Session.
Definition: res_fax.c:446
struct ast_format * peer_read_format
Definition: res_fax.c:464
struct ast_format * peer_write_format
Definition: res_fax.c:465
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static void destroy_v21_sessions(struct fax_gateway *gateway)
destroy the v21 detection parts of a fax gateway session
Definition: res_fax.c:2821
struct ast_format * chan_read_format
original audio formats
Definition: res_fax.c:462
static void fax_session_release(struct ast_fax_session *s, struct ast_fax_tech_token *token)
Release a session token.
Definition: res_fax.c:1083
#define ao2_unlink(container, obj)
Definition: astobj2.h:1598
struct ast_format * chan_write_format
Definition: res_fax.c:463
static struct @460 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct ast_fax_tech_token * token
reserved fax session token
Definition: res_fax.c:450

◆ destroy_session()

static void destroy_session ( void *  session)
static

destroy a FAX session structure

Definition at line 1096 of file res_fax.c.

References ao2_ref, ast_atomic_fetchadd_int(), ast_dsp_free(), AST_FAX_STATE_INACTIVE, AST_FAX_TECH_GATEWAY, ast_free, ast_module_unref, ast_smoother_free(), ast_fax_session_details::caps, ast_fax_session::chan_uniqueid, ast_fax_session::channame, ast_fax_session::debug_info, ast_fax_tech::destroy_session, ast_fax_session::details, ast_fax_debug_info::dsp, fax_session_release(), faxregistry, ast_fax_tech::module, NULL, session, ast_fax_session::smoother, ast_fax_session::state, ast_fax_session::tech, and ast_fax_session::tech_pvt.

Referenced by fax_session_new(), and fax_session_reserve().

1097 {
1098  struct ast_fax_session *s = session;
1099 
1100  if (s->tech) {
1102  if (s->tech_pvt) {
1103  s->tech->destroy_session(s);
1104  }
1106  }
1107 
1108  if (s->details) {
1109  if (s->details->caps & AST_FAX_TECH_GATEWAY) {
1111  }
1112  ao2_ref(s->details, -1);
1113  s->details = NULL;
1114  }
1115 
1116  if (s->debug_info) {
1118  ast_free(s->debug_info);
1119  }
1120 
1121  if (s->smoother) {
1123  }
1124 
1125  if (s->state != AST_FAX_STATE_INACTIVE) {
1126  ast_atomic_fetchadd_int(&faxregistry.active_sessions, -1);
1127  }
1128 
1129  ast_free(s->channame);
1130  ast_free(s->chan_uniqueid);
1131 }
const struct ast_fax_tech * tech
Definition: res_fax.h:214
void ast_dsp_free(struct ast_dsp *dsp)
Definition: dsp.c:1770
struct ast_smoother * smoother
Definition: res_fax.h:228
#define NULL
Definition: resample.c:96
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:755
#define ast_module_unref(mod)
Release a reference to the module.
Definition: module.h:469
void ast_smoother_free(struct ast_smoother *s)
Definition: smoother.c:220
struct ast_fax_debug_info * debug_info
Definition: res_fax.h:226
static struct ast_mansession session
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct ast_fax_session_details * details
Definition: res_fax.h:208
char * channame
Definition: res_fax.h:220
struct ast_module * module
Definition: res_fax.h:245
void(*const destroy_session)(struct ast_fax_session *)
Definition: res_fax.h:253
static void fax_session_release(struct ast_fax_session *s, struct ast_fax_tech_token *token)
Release a session token.
Definition: res_fax.c:1083
#define ast_free(a)
Definition: astmm.h:182
enum ast_fax_state state
Definition: res_fax.h:218
struct ast_dsp * dsp
Definition: res_fax.c:440
static struct @460 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.
The data required to handle a fax session.
Definition: res_fax.h:202
enum ast_fax_capabilities caps
Definition: res_fax.h:113
char * chan_uniqueid
Definition: res_fax.h:222
void * tech_pvt
Definition: res_fax.h:216

◆ destroy_session_details()

static void destroy_session_details ( void *  details)
static

destroy a FAX session details structure

Definition at line 684 of file res_fax.c.

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

Referenced by session_details_new().

685 {
686  struct ast_fax_session_details *d = details;
687  struct ast_fax_document *doc;
688 
689  while ((doc = AST_LIST_REMOVE_HEAD(&d->documents, next))) {
690  ast_free(doc);
691  }
693 }
static struct test_val d
The data communicated between the high level applications and the generic fax function.
Definition: res_fax.h:110
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
struct ast_fax_documents documents
Definition: res_fax.h:119
#define ast_free(a)
Definition: astmm.h:182
struct ast_fax_document * next
Definition: res_fax.h:103
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:368

◆ destroy_v21_sessions()

static void destroy_v21_sessions ( struct fax_gateway gateway)
static

destroy the v21 detection parts of a fax gateway session

Definition at line 2821 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(), fax_gateway_detect_v21(), and fax_gateway_start().

2822 {
2823  if (gateway->chan_v21_session) {
2824  ao2_unlink(faxregistry.container, gateway->chan_v21_session);
2825 
2826  ao2_ref(gateway->chan_v21_session, -1);
2827  gateway->chan_v21_session = NULL;
2828  }
2829 
2830  if (gateway->peer_v21_session) {
2831  ao2_unlink(faxregistry.container, gateway->peer_v21_session);
2832 
2833  ao2_ref(gateway->peer_v21_session, -1);
2834  gateway->peer_v21_session = NULL;
2835  }
2836 }
struct ast_fax_session * chan_v21_session
Definition: res_fax.c:448
#define NULL
Definition: resample.c:96
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_unlink(container, obj)
Definition: astobj2.h:1598
static struct @460 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.
struct ast_fax_session * peer_v21_session
Definition: res_fax.c:447

◆ disable_t38()

static int disable_t38 ( struct ast_channel chan)
static

Definition at line 1527 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().

1528 {
1529  int timeout_ms;
1530  struct ast_frame *frame = NULL;
1532  struct timeval start;
1533  int ms;
1534 
1535  ast_debug(1, "Shutting down T.38 on %s\n", ast_channel_name(chan));
1536  if (ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0) {
1537  ast_debug(1, "error while disabling T.38 on channel '%s'\n", ast_channel_name(chan));
1538  return -1;
1539  }
1540 
1541  /* wait up to five seconds for negotiation to complete */
1542  timeout_ms = 5000;
1543  start = ast_tvnow();
1544  while ((ms = ast_remaining_ms(start, timeout_ms))) {
1545  ms = ast_waitfor(chan, ms);
1546 
1547  if (ms == 0) {
1548  break;
1549  }
1550  if (ms < 0) {
1551  ast_debug(1, "error while disabling T.38 on channel '%s'\n", ast_channel_name(chan));
1552  return -1;
1553  }
1554 
1555  if (!(frame = ast_read(chan))) {
1556  return -1;
1557  }
1558  if ((frame->frametype == AST_FRAME_CONTROL) &&
1560  (frame->datalen == sizeof(t38_parameters))) {
1561  struct ast_control_t38_parameters *parameters = frame->data.ptr;
1562 
1563  switch (parameters->request_response) {
1564  case AST_T38_TERMINATED:
1565  ast_debug(1, "Shut down T.38 on %s\n", ast_channel_name(chan));
1566  break;
1567  case AST_T38_REFUSED:
1568  ast_log(LOG_WARNING, "channel '%s' refused to disable T.38\n", ast_channel_name(chan));
1569  ast_frfree(frame);
1570  return -1;
1571  default:
1572  ast_log(LOG_ERROR, "channel '%s' failed to disable T.38\n", ast_channel_name(chan));
1573  ast_frfree(frame);
1574  return -1;
1575  }
1576  ast_frfree(frame);
1577  break;
1578  }
1579  ast_frfree(frame);
1580  }
1581 
1582  if (ms == 0) { /* all done, nothing happened */
1583  ast_debug(1, "channel '%s' timed-out during T.38 shutdown\n", ast_channel_name(chan));
1584  }
1585 
1586  return 0;
1587 }
#define LOG_WARNING
Definition: logger.h:274
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4302
enum ast_control_t38 request_response
int ast_indicate_data(struct ast_channel *chan, int condition, const void *data, size_t datalen)
Indicates condition of channel, with payload.
Definition: channel.c:4698
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define NULL
Definition: resample.c:96
struct ast_frame_subclass subclass
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
Definition: main/utils.c:2033
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3171
const char * ast_channel_name(const struct ast_channel *chan)
#define ast_frfree(fr)
Data structure associated with a single frame of data.
union ast_frame::@263 data
enum ast_frame_type frametype

◆ fax_detect_attach()

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

Attach a faxdetect framehook object to a channel.

Parameters
chanthe channel to attach to
timeoutin ms to remove framehook in this time if not zero
Returns
the faxdetect structure or NULL on error
Parameters
flagsrequired options
Return values
-1error

Definition at line 3889 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, timeout, and ast_framehook_interface::version.

Referenced by acf_faxopt_write(), and fixup_callback().

3890 {
3891  struct fax_detect *faxdetect;
3892  struct ast_fax_session_details *details;
3893  struct ast_framehook_interface fr_hook = {
3895  .event_cb = fax_detect_framehook,
3896  .destroy_cb = fax_detect_framehook_destroy,
3897  };
3898 
3899  if (!(details = find_or_create_details(chan))) {
3900  ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
3901  return -1;
3902  }
3903 
3904  /* set up the frame hook*/
3905  faxdetect = fax_detect_new(chan, timeout, flags);
3906  if (!faxdetect) {
3907  ao2_ref(details, -1);
3908  return -1;
3909  }
3910 
3911  fr_hook.data = faxdetect;
3912  faxdetect->details = details;
3913  ast_channel_lock(chan);
3914  details->faxdetect_id = ast_framehook_attach(chan, &fr_hook);
3915  details->faxdetect_timeout = timeout;
3916  details->faxdetect_flags = flags;
3917  ast_channel_unlock(chan);
3918 
3919  if (details->faxdetect_id < 0) {
3920  ao2_ref(faxdetect, -1);
3921  }
3922 
3923  return details->faxdetect_id;
3924 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
static int timeout
Definition: cdr_mysql.c:86
static struct fax_detect * fax_detect_new(struct ast_channel *chan, int timeout, int flags)
Create a new fax detect object.
Definition: res_fax.c:3694
used for fax detect framehook
Definition: res_fax.c:469
static struct ast_frame * fax_detect_framehook(struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data)
Fax Detect Framehook.
Definition: res_fax.c:3745
int ast_framehook_attach(struct ast_channel *chan, struct ast_framehook_interface *i)
Attach an framehook onto a channel for frame interception.
Definition: framehook.c:132
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct ast_fax_session_details * details
fax session details
Definition: res_fax.c:477
The data communicated between the high level applications and the generic fax function.
Definition: res_fax.h:110
static struct ast_fax_session_details * find_or_create_details(struct ast_channel *chan)
returns a reference counted details structure from the channel&#39;s fax datastore. If the datastore does...
Definition: res_fax.c:764
#define LOG_ERROR
Definition: logger.h:285
#define AST_FRAMEHOOK_INTERFACE_VERSION
Definition: framehook.h:227
#define ast_channel_unlock(chan)
Definition: channel.h:2946
static void fax_detect_framehook_destroy(void *data)
Deref the faxdetect data structure when the faxdetect framehook is detached.
Definition: res_fax.c:3727

◆ fax_detect_framehook()

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

Fax Detect Framehook.

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

Parameters
chanchannel
fframe to handle may be NULL
eventframehook event
dataframehook data (struct fax_detect *)
Returns
processed frame or NULL when f is NULL or a null frame

Definition at line 3745 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_debug, 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, ast_fax_session_details::faxdetect_timeout, 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, and fax_detect::timeout_start.

Referenced by fax_detect_attach().

3746 {
3747  struct fax_detect *faxdetect = data;
3748  struct ast_fax_session_details *details;
3749  struct ast_control_t38_parameters *control_params;
3750  RAII_VAR(struct ast_channel *, peer, NULL, ao2_cleanup);
3751  RAII_VAR(struct ast_channel *, chan_ref, chan, ao2_cleanup);
3752  int result = 0;
3753 
3754  /* Ref bump the channel for when we have to unlock it */
3755  ao2_ref(chan, 1);
3756 
3757  details = faxdetect->details;
3758 
3759  switch (event) {
3761  /* Setup format for DSP on ATTACH*/
3762  ao2_replace(faxdetect->orig_format, ast_channel_readformat(chan));
3763 
3767  if (ast_set_read_format(chan, ast_format_slin)) {
3768  ast_framehook_detach(chan, details->faxdetect_id);
3769  details->faxdetect_id = -1;
3770  return f;
3771  }
3772  }
3773 
3774  return NULL;
3776  /* restore audio formats when we are detached */
3777  ast_set_read_format(chan, faxdetect->orig_format);
3778  ast_channel_unlock(chan);
3779  peer = ast_channel_bridge_peer(chan);
3780  if (peer) {
3781  ast_channel_make_compatible(chan, peer);
3782  }
3783  ast_channel_lock(chan);
3784  return NULL;
3786  if (f) {
3787  break;
3788  }
3789  default:
3790  return f;
3791  };
3792 
3793  if (details->faxdetect_id < 0) {
3794  return f;
3795  }
3796 
3797  if (!ast_tvzero(faxdetect->timeout_start)
3798  && ast_tvdiff_ms(ast_tvnow(), faxdetect->timeout_start) > details->faxdetect_timeout) {
3799  ast_debug(1, "FAXOPT(faxdetect) timeout on %s\n", ast_channel_name(chan));
3800  ast_framehook_detach(chan, details->faxdetect_id);
3801  details->faxdetect_id = -1;
3802  return f;
3803  }
3804 
3805  /* only handle VOICE and CONTROL frames*/
3806  switch (f->frametype) {
3807  case AST_FRAME_VOICE:
3808  /* we have no DSP this means we not detecting CNG */
3809  if (!faxdetect->dsp) {
3810  return f;
3811  }
3812  /* We can only process some formats*/
3816  return f;
3817  }
3818  break;
3819  case AST_FRAME_CONTROL:
3821  (faxdetect->flags & FAX_DETECT_MODE_T38)) {
3822  break;
3823  }
3824  return f;
3825  default:
3826  return f;
3827  }
3828 
3829  if (f->frametype == AST_FRAME_VOICE) {
3830  f = ast_dsp_process(chan, faxdetect->dsp, f);
3831  if (f->frametype == AST_FRAME_DTMF) {
3832  result = f->subclass.integer;
3833  }
3834  } else if ((f->frametype == AST_FRAME_CONTROL) && (f->datalen == sizeof(struct ast_control_t38_parameters))) {
3835  control_params = f->data.ptr;
3836  switch (control_params->request_response) {
3837  case AST_T38_NEGOTIATED:
3839  result = 't';
3840  break;
3841  default:
3842  break;
3843  }
3844  }
3845 
3846  if (result) {
3847  const char *target_context;
3848 
3849  switch (result) {
3850  case 'f':
3851  case 't':
3852  target_context = S_OR(ast_channel_macrocontext(chan), ast_channel_context(chan));
3853 
3854  ast_channel_unlock(chan);
3855  ast_frfree(f);
3856  f = &ast_null_frame;
3857  if (ast_exists_extension(chan, target_context, "fax", 1,
3858  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
3859  ast_verb(2, "Redirecting '%s' to fax extension due to %s detection\n",
3860  ast_channel_name(chan), (result == 'f') ? "CNG" : "T38");
3861  pbx_builtin_setvar_helper(chan, "FAXEXTEN", ast_channel_exten(chan));
3862  if (ast_async_goto(chan, target_context, "fax", 1)) {
3863  ast_log(LOG_NOTICE, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(chan), target_context);
3864  }
3865  } else {
3866  ast_log(LOG_NOTICE, "FAX %s detected but no fax extension in context (%s)\n",
3867  (result == 'f') ? "CNG" : "T38", target_context);
3868  }
3869  ast_channel_lock(chan);
3870 
3871  ast_framehook_detach(chan, details->faxdetect_id);
3872  details->faxdetect_id = -1;
3873  break;
3874  default:
3875  break;
3876  }
3877  }
3878 
3879  return f;
3880 }
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
#define ast_channel_lock(chan)
Definition: channel.h:2945
struct ast_frame * ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *inf)
Return AST_FRAME_NULL frames when there is silence, AST_FRAME_BUSY on busies, and call progress...
Definition: dsp.c:1494
Main Channel structure associated with a channel.
struct ast_format * ast_format_ulaw
Built-in cached ulaw format.
Definition: format_cache.c:86
int ast_framehook_detach(struct ast_channel *chan, int framehook_id)
Detach an framehook from a channel.
Definition: framehook.c:177
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:108
enum ast_control_t38 request_response
used for fax detect framehook
Definition: res_fax.c:469
Definition: astman.c:222
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:98
#define NULL
Definition: resample.c:96
#define AST_FRAME_DTMF
#define ast_verb(level,...)
Definition: logger.h:463
struct ast_frame_subclass subclass
struct ast_format * ast_channel_readformat(struct ast_channel *chan)
Number structure.
Definition: app_followme.c:154
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
int ast_channel_make_compatible(struct ast_channel *chan, struct ast_channel *peer)
Make the frame formats of two channels compatible.
Definition: channel.c:6817
enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
Compare two formats.
Definition: format.c:201
int ast_set_read_format(struct ast_channel *chan, struct ast_format *format)
Sets read format on channel chan.
Definition: channel.c:5849
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:85
struct ast_fax_session_details * details
fax session details
Definition: res_fax.c:477
The data communicated between the high level applications and the generic fax function.
Definition: res_fax.h:110
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition: pbx.c:4179
const char * ast_channel_exten(const struct ast_channel *chan)
struct timeval timeout_start
the start of our timeout counter
Definition: res_fax.c:471
#define LOG_NOTICE
Definition: logger.h:263
#define ast_channel_unlock(chan)
Definition: channel.h:2946
struct ast_format * orig_format
original audio formats
Definition: res_fax.c:475
int flags
mode
Definition: res_fax.c:479
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
struct ast_frame ast_null_frame
Definition: main/frame.c:79
#define ao2_replace(dst, src)
Definition: astobj2.h:517
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
struct ast_format * ast_format_alaw
Built-in cached alaw format.
Definition: format_cache.c:91
struct ast_channel * ast_channel_bridge_peer(struct ast_channel *chan)
Get the channel&#39;s bridge peer only if the bridge is two-party.
Definition: channel.c:10765
const char * ast_channel_name(const struct ast_channel *chan)
int ast_async_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Set the channel to next execute the specified dialplan location.
Definition: pbx.c:7011
#define ast_frfree(fr)
static PGresult * result
Definition: cel_pgsql.c:88
struct ast_dsp * dsp
DSP Processor.
Definition: res_fax.c:473
const char * ast_channel_context(const struct ast_channel *chan)
union ast_frame::@263 data
enum ast_frame_type frametype
struct ast_format * format
const char * ast_channel_macrocontext(const struct ast_channel *chan)
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
#define FAX_DETECT_MODE_T38
Definition: res_fax.c:484

◆ fax_detect_framehook_destroy()

static void fax_detect_framehook_destroy ( void *  data)
static

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

Parameters
dataframehook data (faxdetect data)

Definition at line 3727 of file res_fax.c.

References ao2_ref.

Referenced by fax_detect_attach().

3728 {
3729  struct fax_detect *faxdetect = data;
3730 
3731  ao2_ref(faxdetect, -1);
3732 }
used for fax detect framehook
Definition: res_fax.c:469
#define ao2_ref(o, delta)
Definition: astobj2.h:464

◆ fax_detect_new()

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

Create a new fax detect object.

Parameters
chanthe channel attaching to
timeoutin ms to remove framehook in this time if not zero
flagsrequired options
Returns
NULL or a fax gateway object

Definition at line 3694 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().

3695 {
3696  struct fax_detect *faxdetect = ao2_alloc(sizeof(*faxdetect), destroy_faxdetect);
3697  if (!faxdetect) {
3698  return NULL;
3699  }
3700 
3701  faxdetect->flags = flags;
3702 
3703  if (timeout) {
3704  faxdetect->timeout_start = ast_tvnow();
3705  } else {
3706  faxdetect->timeout_start.tv_sec = 0;
3707  faxdetect->timeout_start.tv_usec = 0;
3708  }
3709 
3710  if (faxdetect->flags & FAX_DETECT_MODE_CNG) {
3711  faxdetect->dsp = ast_dsp_new();
3712  if (!faxdetect->dsp) {
3713  ao2_ref(faxdetect, -1);
3714  return NULL;
3715  }
3718  } else {
3719  faxdetect->dsp = NULL;
3720  }
3721 
3722  return faxdetect;
3723 }
static void destroy_faxdetect(void *data)
destroy a FAX detect structure
Definition: res_fax.c:3676
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
Definition: dsp.c:1745
static int timeout
Definition: cdr_mysql.c:86
used for fax detect framehook
Definition: res_fax.c:469
#define DSP_FAXMODE_DETECT_SQUELCH
Definition: dsp.h:49
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define NULL
Definition: resample.c:96
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define DSP_FEATURE_FAX_DETECT
Definition: dsp.h:29
int ast_dsp_set_faxmode(struct ast_dsp *dsp, int faxmode)
Set fax mode.
Definition: dsp.c:1870
#define FAX_DETECT_MODE_CNG
FAX Detect flags.
Definition: res_fax.c:483
struct timeval timeout_start
the start of our timeout counter
Definition: res_fax.c:471
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
Definition: dsp.c:1755
int flags
mode
Definition: res_fax.c:479
struct ast_dsp * dsp
DSP Processor.
Definition: res_fax.c:473
#define DSP_FAXMODE_DETECT_CNG
Definition: dsp.h:47

◆ fax_gateway_attach()

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
chanthe channel to attach to
detailsfax session details
Returns
the framehook id of the attached framehook or -1 on error
Return values
-1error

Definition at line 3626 of file res_fax.c.

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

Referenced by acf_faxopt_write(), and fixup_callback().

3627 {
3628  struct fax_gateway *gateway;
3629  struct ast_framehook_interface fr_hook = {
3631  .event_cb = fax_gateway_framehook,
3632  .destroy_cb = fax_gateway_framehook_destroy,
3633  .disable_inheritance = 1, /* Masquerade inheritance is handled through the datastore fixup */
3634  };
3635 
3636  if (global_fax_debug) {
3637  details->option.debug = AST_FAX_OPTFLAG_TRUE;
3638  }
3639 
3640  ast_string_field_set(details, result, "SUCCESS");
3641  ast_string_field_set(details, resultstr, "gateway operation started successfully");
3642  ast_string_field_set(details, error, "NO_ERROR");
3643  set_channel_variables(chan, details);
3644 
3645  /* set up the frame hook*/
3646  gateway = fax_gateway_new(chan, details);
3647  if (!gateway) {
3648  ast_string_field_set(details, result, "FAILED");
3649  ast_string_field_set(details, resultstr, "error initializing gateway session");
3650  ast_string_field_set(details, error, "INIT_ERROR");
3651  details->is_t38_negotiated = 0;
3652  set_channel_variables(chan, details);
3653  report_fax_status(chan, details, "No Available Resource");
3654  return -1;
3655  }
3656 
3657  fr_hook.data = gateway;
3658  ast_channel_lock(chan);
3659  gateway->framehook = ast_framehook_attach(chan, &fr_hook);
3660  ast_channel_unlock(chan);
3661 
3662  if (gateway->framehook < 0) {
3663  ao2_ref(gateway, -1);
3664  ast_string_field_set(details, result, "FAILED");
3665  ast_string_field_set(details, resultstr, "error attaching gateway to channel");
3666  ast_string_field_set(details, error, "INIT_ERROR");
3667  details->is_t38_negotiated = 0;
3668  set_channel_variables(chan, details);
3669  return -1;
3670  }
3671 
3672  return gateway->framehook;
3673 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
used for gateway framehook
Definition: res_fax.c:444
int framehook
framehook used in gateway mode
Definition: res_fax.c:454
static struct ast_frame * fax_gateway_framehook(struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data)
T.30<->T.38 gateway framehook.
Definition: res_fax.c:3383
int ast_framehook_attach(struct ast_channel *chan, struct ast_framehook_interface *i)
Attach an framehook onto a channel for frame interception.
Definition: framehook.c:132
union ast_fax_session_details::@290 option
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static void fax_gateway_framehook_destroy(void *data)
Destroy the gateway data structure when the framehook is detached.
Definition: res_fax.c:3345
#define AST_FRAMEHOOK_INTERFACE_VERSION
Definition: framehook.h:227
static void set_channel_variables(struct ast_channel *chan, struct ast_fax_session_details *details)
Set fax related channel variables.
Definition: res_fax.c:1447
#define ast_channel_unlock(chan)
Definition: channel.h:2946
static int global_fax_debug
Definition: res_fax.c:555
static int report_fax_status(struct ast_channel *chan, struct ast_fax_session_details *details, const char *status)
send a FAX status manager event
Definition: res_fax.c:1407
static struct fax_gateway * fax_gateway_new(struct ast_channel *chan, struct ast_fax_session_details *details)
Create a new fax gateway object.
Definition: res_fax.c:2880
static PGresult * result
Definition: cel_pgsql.c:88
int error(const char *format,...)
Definition: utils/frame.c:999
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ fax_gateway_detect_t38()

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

T38 Gateway Negotiate t38 parameters.

Parameters
gatewaygateway object
chanchannel running the gateway
peerchannel im bridged too
activechannel the frame originated on
fthe control frame to process
Precondition
chan is locked on entry
Returns
processed control frame or null frame

Definition at line 3109 of file res_fax.c.

References ao2_ref, ast_channel_get_t38_state(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, 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, ast_fax_session_details::is_t38_negotiated, 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().

3110 {
3111  struct ast_control_t38_parameters *control_params = f->data.ptr;
3112  struct ast_channel *other = (active == chan) ? peer : chan;
3113  struct ast_fax_session_details *details;
3114  enum ast_t38_state state_other;
3115 
3116  if (f->datalen != sizeof(struct ast_control_t38_parameters)) {
3117  /* invalaid AST_CONTROL_T38_PARAMETERS frame, we can't
3118  * do anything with it, pass it on */
3119  return f;
3120  }
3121 
3122  /* ignore frames from ourselves */
3123  if ((gateway->t38_state == T38_STATE_NEGOTIATED && control_params->request_response == AST_T38_NEGOTIATED)
3124  || (gateway->t38_state == T38_STATE_REJECTED && control_params->request_response == AST_T38_REFUSED)
3125  || (gateway->t38_state == T38_STATE_NEGOTIATING && control_params->request_response == AST_T38_REQUEST_TERMINATE)) {
3126 
3127  return f;
3128  }
3129 
3130  if (!(details = find_details(chan))) {
3131  ast_log(LOG_ERROR, "no FAX session details found on chan %s for T.38 gateway session, odd\n", ast_channel_name(chan));
3132  ast_framehook_detach(chan, gateway->framehook);
3133  return f;
3134  }
3135 
3136  if (control_params->request_response == AST_T38_REQUEST_NEGOTIATE) {
3137  ast_channel_unlock(chan);
3138  state_other = ast_channel_get_t38_state(other);
3139  ast_channel_lock(chan);
3140 
3141  if (state_other == T38_STATE_UNKNOWN) {
3142  /* we detected a request to negotiate T.38 and the
3143  * other channel appears to support T.38, we'll pass
3144  * the request through and only step in if the other
3145  * channel rejects the request */
3146  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));
3147  t38_parameters_ast_to_fax(&details->their_t38_parameters, control_params);
3148  gateway->t38_state = T38_STATE_UNKNOWN;
3149  gateway->timeout_start = ast_tvnow();
3150  details->is_t38_negotiated = 0;
3152  ao2_ref(details, -1);
3153  return f;
3154  } else if (state_other == T38_STATE_UNAVAILABLE || state_other == T38_STATE_REJECTED) {
3155  /* the other channel does not support T.38, we need to
3156  * step in here */
3157  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));
3158  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));
3159 
3160  t38_parameters_ast_to_fax(&details->their_t38_parameters, control_params);
3161  t38_parameters_fax_to_ast(control_params, &details->our_t38_parameters);
3162 
3163  if (fax_gateway_start(gateway, details, chan)) {
3164  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));
3165  gateway->t38_state = T38_STATE_REJECTED;
3166  details->is_t38_negotiated = 0;
3167  control_params->request_response = AST_T38_REFUSED;
3168 
3169  ast_framehook_detach(chan, details->gateway_id);
3170  details->gateway_id = -1;
3171  } else {
3172  gateway->t38_state = T38_STATE_NEGOTIATED;
3173  details->is_t38_negotiated = chan == active;
3174  control_params->request_response = AST_T38_NEGOTIATED;
3175  report_fax_status(chan, details, "T.38 Negotiated");
3176  }
3177 
3178  fax_gateway_indicate_t38(chan, active, control_params);
3179 
3180  ao2_ref(details, -1);
3181  return &ast_null_frame;
3182  } else if (gateway->t38_state == T38_STATE_NEGOTIATING) {
3183  /* we got a request to negotiate T.38 after we already
3184  * sent one to the other party based on v21 preamble
3185  * detection. We'll just pretend we passed this request
3186  * through in the first place. */
3187 
3188  t38_parameters_ast_to_fax(&details->their_t38_parameters, control_params);
3189  gateway->t38_state = T38_STATE_UNKNOWN;
3190  gateway->timeout_start = ast_tvnow();
3191  details->is_t38_negotiated = 0;
3193 
3194  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));
3195  ao2_ref(details, -1);
3196  return &ast_null_frame;
3197  } else if (gateway->t38_state == T38_STATE_NEGOTIATED) {
3198  /* we got a request to negotiate T.38 after we already
3199  * sent one to the other party based on v21 preamble
3200  * detection and received a response. We need to
3201  * respond to this and shut down the gateway. */
3202 
3203  t38_parameters_fax_to_ast(control_params, &details->their_t38_parameters);
3204  ast_framehook_detach(chan, details->gateway_id);
3205  details->gateway_id = -1;
3206 
3207  control_params->request_response = AST_T38_NEGOTIATED;
3208 
3209  fax_gateway_indicate_t38(chan, active, control_params);
3210 
3211  ast_string_field_set(details, result, "SUCCESS");
3212  ast_string_field_set(details, resultstr, "no gateway necessary");
3213  ast_string_field_set(details, error, "NATIVE_T38");
3214  details->is_t38_negotiated = 1;
3215  set_channel_variables(chan, details);
3216 
3217  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));
3218  ao2_ref(details, -1);
3219  return &ast_null_frame;
3220  } else {
3221  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));
3222  ao2_ref(details, -1);
3223  return f;
3224  }
3225  } else if (gateway->t38_state == T38_STATE_NEGOTIATING
3226  && control_params->request_response == AST_T38_REFUSED) {
3227 
3228  ast_debug(1, "unable to negotiate T.38 on %s for fax gateway\n", ast_channel_name(active));
3229  details->is_t38_negotiated = 0;
3230 
3231  /* our request to negotiate T.38 was refused, if the other
3232  * channel supports T.38, they might still reinvite and save
3233  * the day. Otherwise disable the gateway. */
3234  ast_channel_unlock(chan);
3235  state_other = ast_channel_get_t38_state(other);
3236  ast_channel_lock(chan);
3237  if (state_other == T38_STATE_UNKNOWN) {
3238  gateway->t38_state = T38_STATE_UNAVAILABLE;
3239  } else if (state_other != T38_STATE_NEGOTIATING) {
3240  ast_framehook_detach(chan, details->gateway_id);
3241  details->gateway_id = -1;
3242 
3243  ast_string_field_set(details, result, "FAILED");
3244  ast_string_field_set(details, resultstr, "unable to negotiate T.38");
3245  ast_string_field_set(details, error, "T38_NEG_ERROR");
3246  set_channel_variables(chan, details);
3247  }
3248 
3249  ao2_ref(details, -1);
3250  return &ast_null_frame;
3251  } else if (gateway->t38_state == T38_STATE_NEGOTIATING
3252  && control_params->request_response == AST_T38_NEGOTIATED) {
3253 
3254  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));
3255 
3256  t38_parameters_ast_to_fax(&details->their_t38_parameters, control_params);
3257 
3258  if (fax_gateway_start(gateway, details, chan)) {
3259  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));
3260  gateway->t38_state = T38_STATE_NEGOTIATING;
3261  details->is_t38_negotiated = 0;
3262  control_params->request_response = AST_T38_REQUEST_TERMINATE;
3263 
3264  fax_gateway_indicate_t38(chan, active, control_params);
3265  } else {
3266  gateway->t38_state = T38_STATE_NEGOTIATED;
3267  details->is_t38_negotiated = chan == active;
3268  report_fax_status(chan, details, "T.38 Negotiated");
3269  }
3270 
3271  ao2_ref(details, -1);
3272  return &ast_null_frame;
3273  } else if (control_params->request_response == AST_T38_REFUSED) {
3274  /* the other channel refused the request to negotiate T.38,
3275  * we'll step in here and pretend the request was accepted */
3276 
3277  ast_debug(1, "%s attempted to negotiate T.38 but %s refused the request\n", ast_channel_name(other), ast_channel_name(active));
3278  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));
3279 
3280  t38_parameters_fax_to_ast(control_params, &details->our_t38_parameters);
3281 
3282  if (fax_gateway_start(gateway, details, chan)) {
3283  ast_log(LOG_ERROR, "error starting T.38 gateway for T.38 channel %s and G.711 channel %s\n", ast_channel_name(other), ast_channel_name(active));
3284  gateway->t38_state = T38_STATE_REJECTED;
3285  details->is_t38_negotiated = 0;
3286  control_params->request_response = AST_T38_REFUSED;
3287 
3288  ast_framehook_detach(chan, details->gateway_id);
3289  details->gateway_id = -1;
3290  } else {
3291  gateway->t38_state = T38_STATE_NEGOTIATED;
3292  details->is_t38_negotiated = chan == other;
3293  control_params->request_response = AST_T38_NEGOTIATED;
3294  }
3295 
3296  ao2_ref(details, -1);
3297  return f;
3298  } else if (control_params->request_response == AST_T38_REQUEST_TERMINATE) {
3299  /* the channel wishes to end our short relationship, we shall
3300  * oblige */
3301 
3302  ast_debug(1, "T.38 channel %s is requesting a shutdown of T.38, disabling the gateway\n", ast_channel_name(active));
3303 
3304  ast_framehook_detach(chan, details->gateway_id);
3305  details->gateway_id = -1;
3306 
3307  gateway->t38_state = T38_STATE_REJECTED;
3308  details->is_t38_negotiated = 0;
3309  control_params->request_response = AST_T38_TERMINATED;
3310 
3311  fax_gateway_indicate_t38(chan, active, control_params);
3312 
3313  ao2_ref(details, -1);
3314  return &ast_null_frame;
3315  } else if (control_params->request_response == AST_T38_NEGOTIATED) {
3316  ast_debug(1, "T.38 successfully negotiated between %s and %s, no gateway necessary\n", ast_channel_name(active), ast_channel_name(other));
3317 
3318  ast_framehook_detach(chan, details->gateway_id);
3319  details->gateway_id = -1;
3320 
3321  ast_string_field_set(details, result, "SUCCESS");
3322  ast_string_field_set(details, resultstr, "no gateway necessary");
3323  ast_string_field_set(details, error, "NATIVE_T38");
3324  details->is_t38_negotiated = 1;
3325  set_channel_variables(chan, details);
3326 
3327  ao2_ref(details, -1);
3328  return f;
3329  } else if (control_params->request_response == AST_T38_TERMINATED) {
3330  ast_debug(1, "T.38 disabled on channel %s\n", ast_channel_name(active));
3331 
3332  ast_framehook_detach(chan, details->gateway_id);
3333  details->gateway_id = -1;
3334 
3335  ao2_ref(details, -1);
3336  return &ast_null_frame;
3337  }
3338 
3339  ao2_ref(details, -1);
3340  return f;
3341 }
static enum ast_t38_state ast_channel_get_t38_state(struct ast_channel *chan)
Retrieves the current T38 state of a channel.
Definition: channel.h:2873
#define ast_channel_lock(chan)
Definition: channel.h:2945
Main Channel structure associated with a channel.
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.
Definition: res_fax.c:2917
#define LOG_WARNING
Definition: logger.h:274
int framehook
framehook used in gateway mode
Definition: res_fax.c:454
static void t38_parameters_ast_to_fax(struct ast_fax_t38_parameters *dst, const struct ast_control_t38_parameters *src)
Definition: res_fax.c:740
int ast_framehook_detach(struct ast_channel *chan, int framehook_id)
Detach an framehook from a channel.
Definition: framehook.c:177
static void t38_parameters_fax_to_ast(struct ast_control_t38_parameters *dst, const struct ast_fax_t38_parameters *src)
Definition: res_fax.c:751
enum ast_control_t38 request_response
ast_t38_state
Possible T38 states on channels.
Definition: channel.h:879
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
static void fax_gateway_indicate_t38(struct ast_channel *chan, struct ast_channel *active, struct ast_control_t38_parameters *control_params)
Definition: res_fax.c:3085
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
struct ast_fax_t38_parameters our_t38_parameters
Definition: res_fax.h:175
#define ao2_ref(o, delta)
Definition: astobj2.h:464
The data communicated between the high level applications and the generic fax function.
Definition: res_fax.h:110
#define LOG_ERROR
Definition: logger.h:285
static void set_channel_variables(struct ast_channel *chan, struct ast_fax_session_details *details)
Set fax related channel variables.
Definition: res_fax.c:1447
#define FAX_GATEWAY_TIMEOUT
Definition: res_fax.c:493
#define ast_channel_unlock(chan)
Definition: channel.h:2946
enum ast_t38_state t38_state
a flag to track the state of our negotiation
Definition: res_fax.c:460
struct ast_frame ast_null_frame
Definition: main/frame.c:79
static struct ast_fax_session_details * find_details(struct ast_channel *chan)
returns a reference counted pointer to a fax datastore, if it exists
Definition: res_fax.c:662
const char * ast_channel_name(const struct ast_channel *chan)
static int report_fax_status(struct ast_channel *chan, struct ast_fax_session_details *details, const char *status)
send a FAX status manager event
Definition: res_fax.c:1407
static PGresult * result
Definition: cel_pgsql.c:88
int error(const char *format,...)
Definition: utils/frame.c:999
const ast_string_field resultstr
Definition: res_fax.h:142
union ast_frame::@263 data
struct timeval timeout_start
the start of our timeout counter
Definition: res_fax.c:452
struct ast_fax_t38_parameters their_t38_parameters
Definition: res_fax.h:177
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ fax_gateway_detect_v21()

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
Precondition
chan is locked on entry

Definition at line 3012 of file res_fax.c.

References ao2_ref, ast_channel_get_t38_state(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_debug, ast_log, ast_write(), ast_fax_session::chan, fax_gateway::chan_v21_session, destroy_v21_sessions(), ast_fax_session::details, fax_gateway::detected_v21, fax_gateway_request_t38(), find_or_create_details(), if(), LOG_WARNING, ast_fax_session_details::negotiate_both, 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().

3013 {
3014  struct ast_channel *other = (active == chan) ? peer : chan;
3015  struct ast_fax_session *active_v21_session = (active == chan) ? gateway->chan_v21_session : gateway->peer_v21_session;
3016 
3017  if (!active_v21_session || gateway->detected_v21) {
3018  return f;
3019  }
3020 
3021  if (active_v21_session->tech->write(active_v21_session, f) == 0 &&
3022  active_v21_session->details->option.v21_detected) {
3023  gateway->detected_v21 = 1;
3024  }
3025 
3026  if (gateway->detected_v21) {
3027  enum ast_t38_state state_other;
3028  enum ast_t38_state state_active;
3029  struct ast_frame *fp;
3030  struct ast_fax_session_details *details;
3031  int negotiate_both = 0;
3032 
3033  /*
3034  * The default behavior is to wait for the active endpoint to initiate negotiation.
3035  * Find out if this has been overridden. If so, instead of waiting have Asterisk
3036  * initiate the negotiation requests out to both endpoints.
3037  */
3038  details = find_or_create_details(active);
3039  if (details) {
3040  negotiate_both = details->negotiate_both;
3041  ao2_ref(details, -1);
3042  } else {
3043  ast_log(LOG_WARNING, "Detect v21 - no session details for channel '%s'\n",
3044  ast_channel_name(chan));
3045  }
3046 
3047  destroy_v21_sessions(gateway);
3048 
3049  ast_channel_unlock(chan);
3050  state_active = ast_channel_get_t38_state(active);
3051  state_other = ast_channel_get_t38_state(other);
3052  ast_channel_lock(chan);
3053 
3054  ast_debug(1, "detected v21 preamble from %s\n", ast_channel_name(active));
3055 
3056  if (state_active == T38_STATE_UNKNOWN || state_other == T38_STATE_UNKNOWN) {
3057  if (!(fp = fax_gateway_request_t38(gateway, chan))) {
3058  return f;
3059  }
3060  /* May be called endpoint is improperly configured to rely on the calling endpoint
3061  * to initiate T.38 re-INVITEs, send T.38 negotiation request to called endpoint */
3062  if (negotiate_both && state_active == T38_STATE_UNKNOWN) {
3063  ast_debug(1, "sending T.38 negotiation request to %s\n", ast_channel_name(active));
3064  if (active == chan) {
3065  ast_channel_unlock(chan);
3066  }
3067  ast_write(active, fp);
3068  if (active == chan) {
3069  ast_channel_lock(chan);
3070  }
3071  }
3072  if (state_other == T38_STATE_UNKNOWN) {
3073  ast_debug(1, "sending T.38 negotiation request to %s\n", ast_channel_name(other));
3074  return fp;
3075  }
3076  } else {
3077  ast_debug(1, "neither %s nor %s support T.38 for T.38 gateway session\n", ast_channel_name(active), ast_channel_name(other));
3078  }
3079  }
3080 
3081  return f;
3082 }
static enum ast_t38_state ast_channel_get_t38_state(struct ast_channel *chan)
Retrieves the current T38 state of a channel.
Definition: channel.h:2873
#define ast_channel_lock(chan)
Definition: channel.h:2945
Main Channel structure associated with a channel.
const struct ast_fax_tech * tech
Definition: res_fax.h:214
#define LOG_WARNING
Definition: logger.h:274
if(!yyg->yy_init)
Definition: ast_expr2f.c:868
ast_t38_state
Possible T38 states on channels.
Definition: channel.h:879
struct ast_fax_session * chan_v21_session
Definition: res_fax.c:448
static struct ast_frame * fax_gateway_request_t38(struct fax_gateway *gateway, struct ast_channel *chan)
Definition: res_fax.c:2972
struct ast_channel * chan
Definition: res_fax.h:224
union ast_fax_session_details::@290 option
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct ast_fax_session_details * details
Definition: res_fax.h:208
int detected_v21
1 if a v21 preamble has been detected
Definition: res_fax.c:458
static void destroy_v21_sessions(struct fax_gateway *gateway)
destroy the v21 detection parts of a fax gateway session
Definition: res_fax.c:2821
The data communicated between the high level applications and the generic fax function.
Definition: res_fax.h:110
static struct ast_fax_session_details * find_or_create_details(struct ast_channel *chan)
returns a reference counted details structure from the channel&#39;s fax datastore. If the datastore does...
Definition: res_fax.c:764
#define ast_channel_unlock(chan)
Definition: channel.h:2946
int ast_write(struct ast_channel *chan, struct ast_frame *frame)
Write a frame to a channel This function writes the given frame to the indicated channel.
Definition: channel.c:5189
const char * ast_channel_name(const struct ast_channel *chan)
The data required to handle a fax session.
Definition: res_fax.h:202
Data structure associated with a single frame of data.
int(*const write)(struct ast_fax_session *, const struct ast_frame *)
Definition: res_fax.h:257
struct ast_fax_session * peer_v21_session
Definition: res_fax.c:447

◆ fax_gateway_framehook()

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

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
chanchannel running the gateway
fframe to handle may be NULL
eventframehook event
dataframehook data (struct fax_gateway *)
Precondition
chan is locked on entry
Returns
processed frame or NULL when f is NULL or a null frame

Definition at line 3383 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_lock_both, ast_channel_make_compatible(), ast_channel_name(), ast_channel_readformat(), ast_channel_readtrans(), ast_channel_unlock, ast_channel_writeformat(), ast_check_hangup(), 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(), ast_trans_pvt::f, fax_gateway_detect_t38(), fax_gateway_detect_v21(), find_details(), ast_frame_subclass::format, fax_gateway::framehook, ast_frame::frametype, ast_fax_session_details::gateway_id, ast_fax_session_details::gateway_timeout, ast_frame_subclass::integer, ast_fax_session_details::is_t38_negotiated, LOG_ERROR, LOG_WARNING, NULL, fax_gateway::peer_read_format, fax_gateway::peer_v21_session, 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, ast_fax_session::tech_pvt, fax_gateway::timeout_start, and ast_fax_tech::write.

Referenced by fax_gateway_attach().

3384 {
3385  struct fax_gateway *gateway = data;
3386  struct ast_channel *active;
3387  RAII_VAR(struct ast_fax_session_details *, details, NULL, ao2_cleanup);
3388  RAII_VAR(struct ast_channel *, peer, NULL, ao2_cleanup);
3389  RAII_VAR(struct ast_channel *, chan_ref, chan, ao2_cleanup);
3390 
3391  /* Ref bump channel for when we have to unlock it */
3392  ao2_ref(chan_ref, 1);
3393 
3394  if (gateway->s) {
3395  details = gateway->s->details;
3396  ao2_ref(details, 1);
3397  } else {
3398  if (!(details = find_details(chan))) {
3399  ast_log(LOG_ERROR, "no FAX session details found on chan %s for T.38 gateway session, odd\n", ast_channel_name(chan));
3400  ast_framehook_detach(chan, gateway->framehook);
3401  return f;
3402  }
3403  }
3404 
3405  /* restore audio formats when we are detached */
3407  set_channel_variables(chan, details);
3408 
3409  if (gateway->bridged) {
3410  ast_set_read_format(chan, gateway->chan_read_format);
3411  ast_set_write_format(chan, gateway->chan_write_format);
3412 
3413  ast_channel_unlock(chan);
3414  peer = ast_channel_bridge_peer(chan);
3415  if (peer) {
3416  ast_set_read_format(peer, gateway->peer_read_format);
3417  ast_set_write_format(peer, gateway->peer_write_format);
3418  ast_channel_make_compatible(chan, peer);
3419  }
3420  ast_channel_lock(chan);
3421  }
3422  return NULL;
3423  }
3424 
3425  if (!f || (event == AST_FRAMEHOOK_EVENT_ATTACHED)) {
3426  return NULL;
3427  };
3428 
3429  /* this frame was generated by the fax gateway, pass it on */
3431  return f;
3432  }
3433 
3434  /* If we aren't bridged or we don't have a peer, don't do anything */
3435  ast_channel_unlock(chan);
3436  peer = ast_channel_bridge_peer(chan);
3437  ast_channel_lock(chan);
3438  if (!peer) {
3439  return f;
3440  }
3441 
3442  if (!gateway->bridged) {
3443  enum ast_t38_state state_chan;
3444  enum ast_t38_state state_peer;
3445  int chan_is_hungup;
3446  int peer_is_hungup;
3447 
3448  chan_is_hungup = ast_check_hangup(chan);
3449  peer_is_hungup = ast_check_hangup(peer);
3450  /* Don't start a gateway if either channel is hung up */
3451  if (chan_is_hungup || peer_is_hungup) {
3452  return f;
3453  }
3454 
3455  ast_channel_unlock(chan);
3456  state_chan = ast_channel_get_t38_state(chan);
3457  state_peer = ast_channel_get_t38_state(peer);
3458  ast_channel_lock(chan);
3459 
3460  /* don't start a gateway if neither channel can handle T.38 */
3461  if (state_chan == T38_STATE_UNAVAILABLE && state_peer == T38_STATE_UNAVAILABLE) {
3462  ast_debug(1, "not starting gateway for %s and %s; neither channel supports T.38\n", ast_channel_name(chan), ast_channel_name(peer));
3463  ast_framehook_detach(chan, gateway->framehook);
3464  details->gateway_id = -1;
3465 
3466  ast_string_field_set(details, result, "FAILED");
3467  ast_string_field_set(details, resultstr, "neither channel supports T.38");
3468  ast_string_field_set(details, error, "T38_NEG_ERROR");
3469  details->is_t38_negotiated = 0;
3470  set_channel_variables(chan, details);
3471  return f;
3472  }
3473 
3474  if (details->gateway_timeout) {
3475  gateway->timeout_start = ast_tvnow();
3476  }
3477 
3478  ast_channel_unlock(chan);
3479  ast_channel_lock_both(chan, peer);
3480 
3481  /* we are bridged, change r/w formats to SLIN for v21 preamble
3482  * detection and T.30 */
3485 
3488 
3491 
3494 
3495  ast_channel_unlock(peer);
3496 
3497  gateway->bridged = 1;
3498  if (!(gateway->peer_v21_session = fax_v21_session_new(peer))) {
3499  ast_log(LOG_ERROR, "Can't create V21 session on chan %s for T.38 gateway session\n", ast_channel_name(peer));
3500  ast_framehook_detach(chan, gateway->framehook);
3501  return f;
3502  }
3503  }
3504 
3505  if (gateway->bridged && !ast_tvzero(gateway->timeout_start)) {
3506  if (ast_tvdiff_ms(ast_tvnow(), gateway->timeout_start) > details->gateway_timeout) {
3507  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);
3508  ast_framehook_detach(chan, gateway->framehook);
3509  details->gateway_id = -1;
3510 
3511  ast_string_field_set(details, result, "FAILED");
3512  ast_string_field_build(details, resultstr, "no fax activity after %d ms", details->gateway_timeout);
3513  ast_string_field_set(details, error, "TIMEOUT");
3514  details->is_t38_negotiated = 0;
3515  set_channel_variables(chan, details);
3516  return f;
3517  }
3518  }
3519 
3520  /* only handle VOICE, MODEM, and CONTROL frames*/
3521  switch (f->frametype) {
3522  case AST_FRAME_VOICE:
3526  return f;
3527  }
3528  break;
3529  case AST_FRAME_MODEM:
3530  if (f->subclass.integer == AST_MODEM_T38) {
3531  break;
3532  }
3533  return f;
3534  case AST_FRAME_CONTROL:
3536  break;
3537  }
3538  return f;
3539  default:
3540  return f;
3541  }
3542 
3543  /* detect the active channel */
3544  switch (event) {
3546  active = peer;
3547  break;
3549  active = chan;
3550  break;
3551  default:
3552  ast_log(LOG_WARNING, "unhandled framehook event %u\n", event);
3553  return f;
3554  }
3555 
3556  /* handle control frames */
3558  return fax_gateway_detect_t38(gateway, chan, peer, active, f);
3559  }
3560 
3561  if (!gateway->detected_v21 && gateway->t38_state == T38_STATE_UNAVAILABLE && f->frametype == AST_FRAME_VOICE) {
3562  /* not in gateway mode and have not detected v21 yet, listen
3563  * for v21 */
3564  return fax_gateway_detect_v21(gateway, chan, peer, active, f);
3565  }
3566 
3567  /* in gateway mode, gateway some packets */
3568  if (gateway->t38_state == T38_STATE_NEGOTIATED) {
3569  struct ast_trans_pvt *readtrans;
3570 
3571  if (!gateway->s || !gateway->s->tech_pvt) {
3572  ast_log(LOG_ERROR, "no FAX session on chan %s for T.38 gateway session, odd", ast_channel_name(chan));
3573  return f;
3574  }
3575 
3576  /* framehooks are called in __ast_read() before frame format
3577  * translation is done, so we need to translate here */
3579  && (readtrans = ast_channel_readtrans(active))) {
3580  if ((f = ast_translate(readtrans, f, event == AST_FRAMEHOOK_EVENT_WRITE ? 0 : 1)) == NULL) {
3581  f = &ast_null_frame;
3582  return f;
3583  }
3584  /* XXX we ignore the return value here, perhaps we should
3585  * disable the gateway if a write fails. I am not sure how a
3586  * write would fail, or even if a failure would be fatal so for
3587  * now we'll just ignore the return value. */
3588  gateway->s->tech->write(gateway->s, f);
3589  ast_frfree(f);
3590  } else {
3591  gateway->s->tech->write(gateway->s, f);
3592  }
3593 
3594  f = &ast_null_frame;
3595  return f;
3596  }
3597 
3598  /* force silence on the line if T.38 negotiation might be taking place */
3599  if (gateway->t38_state != T38_STATE_UNAVAILABLE && gateway->t38_state != T38_STATE_REJECTED) {
3600  if (f->frametype == AST_FRAME_VOICE &&
3602  short silence_buf[f->samples];
3603  struct ast_frame silence_frame = {
3605  .subclass.format = ast_format_slin,
3606  .data.ptr = silence_buf,
3607  .samples = f->samples,
3608  .datalen = sizeof(silence_buf),
3609  };
3610  memset(silence_buf, 0, sizeof(silence_buf));
3611  return ast_frisolate(&silence_frame);
3612  } else {
3613  return &ast_null_frame;
3614  }
3615  }
3616 
3617  return f;
3618 }
static enum ast_t38_state ast_channel_get_t38_state(struct ast_channel *chan)
Retrieves the current T38 state of a channel.
Definition: channel.h:2873
#define ast_channel_lock(chan)
Definition: channel.h:2945
Main Channel structure associated with a channel.
#define AST_FAX_FRFLAG_GATEWAY
Definition: res_fax.h:232
const struct ast_fax_tech * tech
Definition: res_fax.h:214
int bridged
bridged
Definition: res_fax.c:456
#define ast_test_flag(p, flag)
Definition: utils.h:63
used for gateway framehook
Definition: res_fax.c:444
struct ast_frame f
Definition: translate.h:215
struct ast_format * ast_format_ulaw
Built-in cached ulaw format.
Definition: format_cache.c:86
#define LOG_WARNING
Definition: logger.h:274
int framehook
framehook used in gateway mode
Definition: res_fax.c:454
int ast_framehook_detach(struct ast_channel *chan, int framehook_id)
Detach an framehook from a channel.
Definition: framehook.c:177
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:108
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)
Definition: res_fax.c:3012
Definition: astman.c:222
ast_t38_state
Possible T38 states on channels.
Definition: channel.h:879
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
struct ast_frame * ast_translate(struct ast_trans_pvt *tr, struct ast_frame *f, int consume)
translates one or more frames Apply an input frame into the translator and receive zero or one output...
Definition: translate.c:565
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:98
#define NULL
Definition: resample.c:96
struct ast_fax_session * s
FAX Session.
Definition: res_fax.c:446
struct ast_format * peer_read_format
Definition: res_fax.c:464
static struct ast_fax_session * fax_v21_session_new(struct ast_channel *chan)
Definition: res_fax.c:2861
struct ast_trans_pvt * ast_channel_readtrans(const struct ast_channel *chan)
struct ast_frame_subclass subclass
struct ast_format * ast_channel_readformat(struct ast_channel *chan)
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
int ast_channel_make_compatible(struct ast_channel *chan, struct ast_channel *peer)
Make the frame formats of two channels compatible.
Definition: channel.c:6817
enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
Compare two formats.
Definition: format.c:201
int ast_set_read_format(struct ast_channel *chan, struct ast_format *format)
Sets read format on channel chan.
Definition: channel.c:5849
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
struct ast_format * peer_write_format
Definition: res_fax.c:465
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct ast_fax_session_details * details
Definition: res_fax.h:208
int detected_v21
1 if a v21 preamble has been detected
Definition: res_fax.c:458
The data communicated between the high level applications and the generic fax function.
Definition: res_fax.h:110
int ast_set_write_format(struct ast_channel *chan, struct ast_format *format)
Sets write format on channel chan.
Definition: channel.c:5890
struct ast_format * chan_read_format
original audio formats
Definition: res_fax.c:462
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:445
#define LOG_ERROR
Definition: logger.h:285
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)
T38 Gateway Negotiate t38 parameters.
Definition: res_fax.c:3109
Default structure for translators, with the basic fields and buffers, all allocated as part of the sa...
Definition: translate.h:213
struct ast_format * chan_write_format
Definition: res_fax.c:463
static void set_channel_variables(struct ast_channel *chan, struct ast_fax_session_details *details)
Set fax related channel variables.
Definition: res_fax.c:1447
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#define ast_frisolate(fr)
Makes a frame independent of any static storage.
enum ast_t38_state t38_state
a flag to track the state of our negotiation
Definition: res_fax.c:460
#define ast_string_field_build(x, field, fmt, args...)
Set a field to a complex (built) value.
Definition: stringfields.h:550
struct ast_frame ast_null_frame
Definition: main/frame.c:79
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
Definition: channel.h:2952
#define ao2_replace(dst, src)
Definition: astobj2.h:517
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static struct ast_fax_session_details * find_details(struct ast_channel *chan)
returns a reference counted pointer to a fax datastore, if it exists
Definition: res_fax.c:662
struct ast_format * ast_format_alaw
Built-in cached alaw format.
Definition: format_cache.c:91
struct ast_channel * ast_channel_bridge_peer(struct ast_channel *chan)
Get the channel&#39;s bridge peer only if the bridge is two-party.
Definition: channel.c:10765
const char * ast_channel_name(const struct ast_channel *chan)
#define ast_frfree(fr)
static PGresult * result
Definition: cel_pgsql.c:88
#define AST_MODEM_T38
Data structure associated with a single frame of data.
void * tech_pvt
Definition: res_fax.h:216
int(*const write)(struct ast_fax_session *, const struct ast_frame *)
Definition: res_fax.h:257
int error(const char *format,...)
Definition: utils/frame.c:999
enum ast_frame_type frametype
struct ast_format * format
struct timeval timeout_start
the start of our timeout counter
Definition: res_fax.c:452
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
struct ast_format * ast_channel_writeformat(struct ast_channel *chan)
struct ast_fax_session * peer_v21_session
Definition: res_fax.c:447
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ fax_gateway_framehook_destroy()

static void fax_gateway_framehook_destroy ( void *  data)
static

Destroy the gateway data structure when the framehook is detached.

Parameters
dataframehook data (gateway data)

Definition at line 3345 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().

3346 {
3347  struct fax_gateway *gateway = data;
3348 
3349  if (gateway->s) {
3350  switch (gateway->s->state) {
3352  case AST_FAX_STATE_OPEN:
3353  case AST_FAX_STATE_ACTIVE:
3355  if (gateway->s->tech->cancel_session) {
3356  gateway->s->tech->cancel_session(gateway->s);
3357  }
3358  /* fall through */
3359  default:
3360  break;
3361  }
3362  }
3363 
3364  ao2_ref(gateway, -1);
3365 }
const struct ast_fax_tech * tech
Definition: res_fax.h:214
used for gateway framehook
Definition: res_fax.c:444
int(*const cancel_session)(struct ast_fax_session *)
Definition: res_fax.h:261
struct ast_fax_session * s
FAX Session.
Definition: res_fax.c:446
#define ao2_ref(o, delta)
Definition: astobj2.h:464
enum ast_fax_state state
Definition: res_fax.h:218

◆ fax_gateway_indicate_t38()

static void fax_gateway_indicate_t38 ( struct ast_channel chan,
struct ast_channel active,
struct ast_control_t38_parameters control_params 
)
static
Precondition
chan is locked on entry

Definition at line 3085 of file res_fax.c.

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

Referenced by fax_gateway_detect_t38().

3086 {
3087  if (active == chan) {
3088  ast_channel_unlock(chan);
3089  ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, control_params, sizeof(*control_params));
3090  ast_channel_lock(chan);
3091  } else {
3092  ast_queue_control_data(chan, AST_CONTROL_T38_PARAMETERS, control_params, sizeof(*control_params));
3093  }
3094 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
int ast_indicate_data(struct ast_channel *chan, int condition, const void *data, size_t datalen)
Indicates condition of channel, with payload.
Definition: channel.c:4698
#define ast_channel_unlock(chan)
Definition: channel.h:2946
int ast_queue_control_data(struct ast_channel *chan, enum ast_control_frame_type control, const void *data, size_t datalen)
Queue a control frame with payload.
Definition: channel.c:1238

◆ fax_gateway_new()

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

Create a new fax gateway object.

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

Definition at line 2880 of file res_fax.c.

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

Referenced by fax_gateway_attach().

2881 {
2882  struct fax_gateway *gateway = ao2_alloc(sizeof(*gateway), destroy_gateway);
2883  if (!gateway) {
2884  return NULL;
2885  }
2886 
2887  if (!(gateway->chan_v21_session = fax_v21_session_new(chan))) {
2888  ast_log(LOG_ERROR, "Can't create V21 session on chan %s for T.38 gateway session\n", ast_channel_name(chan));
2889  ao2_ref(gateway, -1);
2890  return NULL;
2891  }
2892 
2893  gateway->framehook = -1;
2894 
2895  details->caps = AST_FAX_TECH_GATEWAY;
2896  if (details->gateway_timeout && !(gateway->s = fax_session_reserve(details, &gateway->token))) {
2897  details->caps &= ~AST_FAX_TECH_GATEWAY;
2898  ast_log(LOG_ERROR, "Can't reserve a FAX session, gateway attempt failed.\n");
2899  ao2_ref(gateway, -1);
2900  return NULL;
2901  }
2902 
2903  return gateway;
2904 }
used for gateway framehook
Definition: res_fax.c:444
int framehook
framehook used in gateway mode
Definition: res_fax.c:454
struct ast_fax_session * chan_v21_session
Definition: res_fax.c:448
#define NULL
Definition: resample.c:96
struct ast_fax_session * s
FAX Session.
Definition: res_fax.c:446
static struct ast_fax_session * fax_v21_session_new(struct ast_channel *chan)
Definition: res_fax.c:2861
#define ast_log
Definition: astobj2.c:42
static void destroy_gateway(void *data)
destroy a FAX gateway session structure
Definition: res_fax.c:2839
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define LOG_ERROR
Definition: logger.h:285
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
static struct ast_fax_session * fax_session_reserve(struct ast_fax_session_details *details, struct ast_fax_tech_token **token)
Reserve a fax session.
Definition: res_fax.c:1146
struct ast_fax_tech_token * token
reserved fax session token
Definition: res_fax.c:450
const char * ast_channel_name(const struct ast_channel *chan)
enum ast_fax_capabilities caps
Definition: res_fax.h:113

◆ fax_gateway_request_t38()

static struct ast_frame* fax_gateway_request_t38 ( struct fax_gateway gateway,
struct ast_channel chan 
)
static
Precondition
chan is locked on entry

Definition at line 2972 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, ast_fax_session_details::is_t38_negotiated, LOG_ERROR, NULL, 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().

2973 {
2974  struct ast_frame *fp;
2975  struct ast_control_t38_parameters t38_parameters = {
2977  };
2978  struct ast_frame control_frame = {
2979  .src = "res_fax",
2980  .frametype = AST_FRAME_CONTROL,
2981  .datalen = sizeof(t38_parameters),
2983  .data.ptr = &t38_parameters,
2984  };
2985 
2986  struct ast_fax_session_details *details = find_details(chan);
2987 
2988  if (!details) {
2989  ast_log(LOG_ERROR, "no FAX session details found on chan %s for T.38 gateway session, odd\n", ast_channel_name(chan));
2990  ast_framehook_detach(chan, gateway->framehook);
2991  return NULL;
2992  }
2993 
2994  t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
2995  ao2_ref(details, -1);
2996 
2997  if (!(fp = ast_frisolate(&control_frame))) {
2998  ast_log(LOG_ERROR, "error generating T.38 request control frame on chan %s for T.38 gateway session\n", ast_channel_name(chan));
2999  return NULL;
3000  }
3001 
3002  gateway->t38_state = T38_STATE_NEGOTIATING;
3003  gateway->timeout_start = ast_tvnow();
3004  details->is_t38_negotiated = 0;
3006 
3007  ast_debug(1, "requesting T.38 for gateway session for %s\n", ast_channel_name(chan));
3008  return fp;
3009 }
int framehook
framehook used in gateway mode
Definition: res_fax.c:454
int ast_framehook_detach(struct ast_channel *chan, int framehook_id)
Detach an framehook from a channel.
Definition: framehook.c:177
static void t38_parameters_fax_to_ast(struct ast_control_t38_parameters *dst, const struct ast_fax_t38_parameters *src)
Definition: res_fax.c:751
enum ast_control_t38 request_response
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define NULL
Definition: resample.c:96
struct ast_frame_subclass subclass
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
struct ast_fax_t38_parameters our_t38_parameters
Definition: res_fax.h:175
const char * src
#define ao2_ref(o, delta)
Definition: astobj2.h:464
The data communicated between the high level applications and the generic fax function.
Definition: res_fax.h:110
#define LOG_ERROR
Definition: logger.h:285
#define FAX_GATEWAY_TIMEOUT
Definition: res_fax.c:493
#define ast_frisolate(fr)
Makes a frame independent of any static storage.
enum ast_t38_state t38_state
a flag to track the state of our negotiation
Definition: res_fax.c:460
static struct ast_fax_session_details * find_details(struct ast_channel *chan)
returns a reference counted pointer to a fax datastore, if it exists
Definition: res_fax.c:662
const char * ast_channel_name(const struct ast_channel *chan)
Data structure associated with a single frame of data.
struct timeval timeout_start
the start of our timeout counter
Definition: res_fax.c:452

◆ fax_gateway_start()

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
gatewaya fax gateway object
detailsfax session details
chanactive channel
Precondition
chan is locked on entry
Returns
0 on error 1 on success

Definition at line 2917 of file res_fax.c.

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

Referenced by fax_gateway_detect_t38().

2918 {
2919  struct ast_fax_session *s;
2920  int start_res;
2921 
2922  /* if the fax gateway is already started then do nothing */
2923  if (gateway->s &&
2924  gateway->s->state != AST_FAX_STATE_RESERVED && gateway->s->state != AST_FAX_STATE_INACTIVE) {
2925  return 0;
2926  }
2927 
2928  /* if we start gateway we don't need v21 detection sessions any more */
2929  destroy_v21_sessions(gateway);
2930 
2931  /* create the FAX session */
2932  if (!(s = fax_session_new(details, chan, gateway->s, gateway->token))) {
2933  gateway->token = NULL;
2934  ast_string_field_set(details, result, "FAILED");
2935  ast_string_field_set(details, resultstr, "error starting gateway session");
2936  ast_string_field_set(details, error, "INIT_ERROR");
2937  details->is_t38_negotiated = 0;
2938  set_channel_variables(chan, details);
2939  report_fax_status(chan, details, "No Available Resource");
2940  ast_log(LOG_ERROR, "Can't create a FAX session, gateway attempt failed.\n");
2941  return -1;
2942  }
2943  /* release the reference for the reserved session and replace it with
2944  * the real session */
2945  if (gateway->s) {
2946  ao2_ref(gateway->s, -1);
2947  }
2948  gateway->s = s;
2949  gateway->token = NULL;
2950 
2951  ast_channel_unlock(chan);
2952  start_res = gateway->s->tech->start_session(gateway->s);
2953  ast_channel_lock(chan);
2954  if (start_res < 0) {
2955  ast_string_field_set(details, result, "FAILED");
2956  ast_string_field_set(details, resultstr, "error starting gateway session");
2957  ast_string_field_set(details, error, "INIT_ERROR");
2958  details->is_t38_negotiated = 0;
2959  set_channel_variables(chan, details);
2960  return -1;
2961  }
2962 
2963  gateway->timeout_start.tv_sec = 0;
2964  gateway->timeout_start.tv_usec = 0;
2965 
2966  report_fax_status(chan, details, "FAX Transmission In Progress");
2967 
2968  return 0;
2969 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
const struct ast_fax_tech * tech
Definition: res_fax.h:214
#define NULL
Definition: resample.c:96
struct ast_fax_session * s
FAX Session.
Definition: res_fax.c:446
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Definition: astobj2.h:464
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)
create a FAX session
Definition: res_fax.c:1215
static void destroy_v21_sessions(struct fax_gateway *gateway)
destroy the v21 detection parts of a fax gateway session
Definition: res_fax.c:2821
#define LOG_ERROR
Definition: logger.h:285
static void set_channel_variables(struct ast_channel *chan, struct ast_fax_session_details *details)
Set fax related channel variables.
Definition: res_fax.c:1447
#define ast_channel_unlock(chan)
Definition: channel.h:2946
enum ast_fax_state state
Definition: res_fax.h:218
struct ast_fax_tech_token * token
reserved fax session token
Definition: res_fax.c:450
static int report_fax_status(struct ast_channel *chan, struct ast_fax_session_details *details, const char *status)
send a FAX status manager event
Definition: res_fax.c:1407
static PGresult * result
Definition: cel_pgsql.c:88
The data required to handle a fax session.
Definition: res_fax.h:202
int error(const char *format,...)
Definition: utils/frame.c:999
struct timeval timeout_start
the start of our timeout counter
Definition: res_fax.c:452
int(*const start_session)(struct ast_fax_session *)
Definition: res_fax.h:259
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ fax_rate_str_to_int()

static unsigned int fax_rate_str_to_int ( const char *  ratestr)
static

convert a rate string to a rate

Definition at line 1046 of file res_fax.c.

References ast_log, LOG_ERROR, and LOG_WARNING.

Referenced by acf_faxopt_write(), and set_config().

1047 {
1048  int rate;
1049 
1050  if (sscanf(ratestr, "%d", &rate) != 1) {
1051  ast_log(LOG_ERROR, "failed to sscanf '%s' to rate\n", ratestr);
1052  return 0;
1053  }
1054  switch (rate) {
1055  case 2400:
1056  case 4800:
1057  case 7200:
1058  case 9600:
1059  case 12000:
1060  case 14400:
1061  case 28800:
1062  case 33600:
1063  return rate;
1064  default:
1065  ast_log(LOG_WARNING, "ignoring invalid rate '%s'. Valid options are {2400 | 4800 | 7200 | 9600 | 12000 | 14400 | 28800 | 33600}\n", ratestr);
1066  return 0;
1067  }
1068 }
#define LOG_WARNING
Definition: logger.h:274
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285

◆ fax_session_new()

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

create a FAX session

Parameters
detailsdetails for the session
chanthe channel the session will run on
reserveda reserved session to base this session on (can be NULL)
tokenthe 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 1215 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_running_ref, ast_module_unref, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdup, ast_fax_session_details::caps, ast_fax_tech::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_details::id, ast_fax_session::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_start(), fax_v21_session_new(), and generic_fax_exec().

1216 {
1217  struct ast_fax_session *s = NULL;
1218  struct fax_module *faxmod;
1219 
1220  if (reserved) {
1221  s = reserved;
1222  ao2_ref(reserved, +1);
1223  ao2_unlink(faxregistry.container, reserved);
1224 
1225  /* NOTE: we don't consume the reference to the reserved
1226  * session. The session returned from fax_session_new() is a
1227  * new reference and must be derefed in addition to the
1228  * reserved session.
1229  */
1230 
1231  if (s->state == AST_FAX_STATE_RESERVED) {
1232  ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, -1);
1234  }
1235  }
1236 
1237  if (!s && !(s = ao2_alloc(sizeof(*s), destroy_session))) {
1238  return NULL;
1239  }
1240 
1241  ast_atomic_fetchadd_int(&faxregistry.active_sessions, 1);
1243 
1244  if (details->option.debug && (details->caps & AST_FAX_TECH_AUDIO)) {
1245  if (!(s->debug_info = ast_calloc(1, sizeof(*(s->debug_info))))) {
1246  fax_session_release(s, token);
1247  ao2_ref(s, -1);
1248  return NULL;
1249  }
1250  if (!(s->debug_info->dsp = ast_dsp_new())) {
1251  ast_free(s->debug_info);
1252  s->debug_info = NULL;
1253  fax_session_release(s, token);
1254  ao2_ref(s, -1);
1255  return NULL;
1256  }
1258  }
1259 
1260  if (!(s->channame = ast_strdup(ast_channel_name(chan)))) {
1261  fax_session_release(s, token);
1262  ao2_ref(s, -1);
1263  return NULL;
1264  }
1265 
1266  if (!(s->chan_uniqueid = ast_strdup(ast_channel_uniqueid(chan)))) {
1267  fax_session_release(s, token);
1268  ao2_ref(s, -1);
1269  return NULL;
1270  }
1271 
1272  s->chan = chan;
1273  if (!s->details) {
1274  s->details = details;
1275  ao2_ref(s->details, 1);
1276  }
1277 
1278  details->id = s->id = ast_atomic_fetchadd_int(&faxregistry.nextsessionname, 1);
1279 
1280  if (!token) {
1281  /* locate a FAX technology module that can handle said requirements */
1283  AST_RWLIST_TRAVERSE(&faxmodules, faxmod, list) {
1284  if ((faxmod->tech->caps & details->caps) != details->caps) {
1285  continue;
1286  }
1287  if (!ast_module_running_ref(faxmod->tech->module)) {
1288  continue;
1289  }
1290  ast_debug(4, "Requesting a new FAX session from '%s'.\n", faxmod->tech->description);
1291  if (reserved) {
1292  /* Balance module ref from reserved session */
1293  ast_module_unref(reserved->tech->module);
1294  }
1295  s->tech = faxmod->tech;
1296  break;
1297  }
1299 
1300  if (!faxmod) {
1301  char caps[128] = "";
1302  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)));
1303  ao2_ref(s, -1);
1304  return NULL;
1305  }
1306  }
1307 
1308  if (!(s->tech_pvt = s->tech->new_session(s, token))) {
1309  ast_log(LOG_ERROR, "FAX session failed to initialize.\n");
1310  ao2_ref(s, -1);
1311  return NULL;
1312  }
1313  /* link the session to the session container */
1314  if (!(ao2_link(faxregistry.container, s))) {
1315  ast_log(LOG_ERROR, "failed to add FAX session '%u' to container.\n", s->id);
1316  ao2_ref(s, -1);
1317  return NULL;
1318  }
1319  ast_debug(4, "channel '%s' using FAX session '%u'\n", s->channame, s->id);
1320 
1321  return s;
1322 }
const struct ast_fax_tech * tech
Definition: res_fax.h:214
unsigned int id
Definition: res_fax.h:204
static char * ast_fax_caps_to_str(enum ast_fax_capabilities caps, char *buf, size_t bufsize)
Definition: res_fax.c:846
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
Definition: dsp.c:1745
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
static void destroy_session(void *session)
destroy a FAX session structure
Definition: res_fax.c:1096
const struct ast_fax_tech * tech
Definition: res_fax.c:517
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
const char *const description
Definition: res_fax.h:239
#define NULL
Definition: resample.c:96
struct ast_channel * chan
Definition: res_fax.h:224
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:755
#define ast_module_unref(mod)
Release a reference to the module.
Definition: module.h:469
unsigned int id
Definition: res_fax.h:117
union ast_fax_session_details::@290 option
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
struct ast_fax_debug_info * debug_info
Definition: res_fax.h:226
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
enum ast_fax_capabilities caps
Definition: res_fax.h:243
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct ast_fax_session_details * details
Definition: res_fax.h:208
char * channame
Definition: res_fax.h:220
struct ast_module * module
Definition: res_fax.h:245
void ast_dsp_set_threshold(struct ast_dsp *dsp, int threshold)
Set the minimum average magnitude threshold to determine talking by the DSP.
Definition: dsp.c:1775
const char * ast_channel_uniqueid(const struct ast_channel *chan)
#define LOG_ERROR
Definition: logger.h:285
static void fax_session_release(struct ast_fax_session *s, struct ast_fax_tech_token *token)
Release a session token.
Definition: res_fax.c:1083
#define ao2_unlink(container, obj)
Definition: astobj2.h:1598
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
void *(*const new_session)(struct ast_fax_session *, struct ast_fax_tech_token *)
Definition: res_fax.h:251
enum ast_fax_state state
Definition: res_fax.h:218
struct ast_dsp * dsp
Definition: res_fax.c:440
#define ast_module_running_ref(mod)
Hold a reference to the module if it is running.
Definition: module.h:455
registered FAX technology modules are put into this list
Definition: res_fax.c:516
static struct @460 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.
const char * ast_channel_name(const struct ast_channel *chan)
The data required to handle a fax session.
Definition: res_fax.h:202
enum ast_fax_capabilities caps
Definition: res_fax.h:113
char * chan_uniqueid
Definition: res_fax.h:222
void * tech_pvt
Definition: res_fax.h:216
#define ao2_link(container, obj)
Definition: astobj2.h:1549

◆ fax_session_release()

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

Release a session token.

Parameters
sa session returned from fax_session_reserve()
tokena 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 1083 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().

1084 {
1085  if (token) {
1086  s->tech->release_token(token);
1087  }
1088 
1089  if (s->state == AST_FAX_STATE_RESERVED) {
1090  ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, -1);
1092  }
1093 }
const struct ast_fax_tech * tech
Definition: res_fax.h:214
void(*const release_token)(struct ast_fax_tech_token *)
Definition: res_fax.h:249
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:755
enum ast_fax_state state
Definition: res_fax.h:218
static struct @460 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.

◆ fax_session_reserve()

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

Reserve a fax session.

Parameters
detailsthe fax session details
tokena 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 1146 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_running_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().

1147 {
1148  struct ast_fax_session *s;
1149  struct fax_module *faxmod;
1150 
1151  if (!(s = ao2_alloc(sizeof(*s), destroy_session))) {
1152  return NULL;
1153  }
1154 
1156  s->details = details;
1157  ao2_ref(s->details, 1);
1158 
1159  /* locate a FAX technology module that can handle said requirements
1160  * Note: the requirements have not yet been finalized as T.38
1161  * negotiation has not yet occured. */
1163  AST_RWLIST_TRAVERSE(&faxmodules, faxmod, list) {
1164  if ((faxmod->tech->caps & details->caps) != details->caps) {
1165  continue;
1166  }
1167  if (!ast_module_running_ref(faxmod->tech->module)) {
1168  continue;
1169  }
1170  ast_debug(4, "Reserving a FAX session from '%s'.\n", faxmod->tech->description);
1171  s->tech = faxmod->tech;
1172  break;
1173  }
1175 
1176  if (!faxmod) {
1177  char caps[128] = "";
1178  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)));
1179  ao2_ref(s, -1);
1180  return NULL;
1181  }
1182 
1183  if (!s->tech->reserve_session) {
1184  ast_debug(1, "Selected FAX technology module (%s) does not support reserving sessions.\n", s->tech->description);
1185  return s;
1186  }
1187 
1188  if (!(*token = s->tech->reserve_session(s))) {
1189  ao2_ref(s, -1);
1190  return NULL;
1191  }
1192 
1194  ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, 1);
1195 
1196  return s;
1197 }
const struct ast_fax_tech * tech
Definition: res_fax.h:214
static char * ast_fax_caps_to_str(enum ast_fax_capabilities caps, char *buf, size_t bufsize)
Definition: res_fax.c:846
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
static void destroy_session(void *session)
destroy a FAX session structure
Definition: res_fax.c:1096
const struct ast_fax_tech * tech
Definition: res_fax.c:517
const char *const description
Definition: res_fax.h:239
#define NULL
Definition: resample.c:96
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:755
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
enum ast_fax_capabilities caps
Definition: res_fax.h:243
struct ast_fax_tech_token *(*const reserve_session)(struct ast_fax_session *)
Definition: res_fax.h:247
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct ast_fax_session_details * details
Definition: res_fax.h:208
struct ast_module * module
Definition: res_fax.h:245
#define LOG_ERROR
Definition: logger.h:285
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
enum ast_fax_state state
Definition: res_fax.h:218
#define ast_module_running_ref(mod)
Hold a reference to the module if it is running.
Definition: module.h:455
registered FAX technology modules are put into this list
Definition: res_fax.c:516
static struct @460 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.
The data required to handle a fax session.
Definition: res_fax.h:202
enum ast_fax_capabilities caps
Definition: res_fax.h:113

◆ fax_session_tab_complete()

static char* fax_session_tab_complete ( struct ast_cli_args a)
static

fax session tab completion

Definition at line 3943 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().

3944 {
3945  int tklen;
3946  int wordnum = 0;
3947  char *name = NULL;
3948  struct ao2_iterator i;
3949  struct ast_fax_session *s;
3950  char tbuf[5];
3951 
3952  if (a->pos != 3) {
3953  return NULL;
3954  }
3955 
3956  tklen = strlen(a->word);
3957  i = ao2_iterator_init(faxregistry.container, 0);
3958  while ((s = ao2_iterator_next(&i))) {
3959  snprintf(tbuf, sizeof(tbuf), "%u", s->id);
3960  if (!strncasecmp(a->word, tbuf, tklen) && ++wordnum > a->n) {
3961  name = ast_strdup(tbuf);
3962  ao2_ref(s, -1);
3963  break;
3964  }
3965  ao2_ref(s, -1);
3966  }
3968  return name;
3969 }
unsigned int id
Definition: res_fax.h:204
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
const int n
Definition: cli.h:165
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
static const char name[]
Definition: cdr_mysql.c:74
const char * word
Definition: cli.h:163
static struct @460 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
const int pos
Definition: cli.h:164
The data required to handle a fax session.
Definition: res_fax.h:202
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.

◆ fax_session_type()

static const char* fax_session_type ( struct ast_fax_session s)
static

Definition at line 4242 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().

4243 {
4244  if (s->details->caps & AST_FAX_TECH_AUDIO) {
4245  return "G.711";
4246  }
4247  if (s->details->caps & AST_FAX_TECH_T38) {
4248  return "T.38";
4249  }
4250 
4251  return "none";
4252 }
struct ast_fax_session_details * details
Definition: res_fax.h:208
enum ast_fax_capabilities caps
Definition: res_fax.h:113

◆ fax_v21_session_new()

static struct ast_fax_session * fax_v21_session_new ( struct ast_channel chan)
static

Definition at line 2861 of file res_fax.c.

References ao2_ref, AST_FAX_TECH_V21_DETECT, ast_fax_session_details::caps, fax_session_new(), NULL, and session_details_new().

2861  {
2862  struct ast_fax_session_details *v21_details;
2863  struct ast_fax_session *v21_session;
2864 
2865  if (!chan || !(v21_details = session_details_new())) {
2866  return NULL;
2867  }
2868 
2869  v21_details->caps = AST_FAX_TECH_V21_DETECT;
2870  v21_session = fax_session_new(v21_details, chan, NULL, NULL);
2871  ao2_ref(v21_details, -1);
2872  return v21_session;
2873 }
#define NULL
Definition: resample.c:96
static struct ast_fax_session_details * session_details_new(void)
create a FAX session details structure
Definition: res_fax.c:696
#define ao2_ref(o, delta)
Definition: astobj2.h:464
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)
create a FAX session
Definition: res_fax.c:1215
The data communicated between the high level applications and the generic fax function.
Definition: res_fax.h:110
The data required to handle a fax session.
Definition: res_fax.h:202
enum ast_fax_capabilities caps
Definition: res_fax.h:113

◆ find_details()

static struct ast_fax_session_details* find_details ( struct ast_channel chan)
static

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

Definition at line 662 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().

663 {
664  struct ast_fax_session_details *details;
665  struct ast_datastore *datastore;
666 
667  ast_channel_lock(chan);
668  if (!(datastore = ast_channel_datastore_find(chan, &fax_datastore, NULL))) {
669  ast_channel_unlock(chan);
670  return NULL;
671  }
672  if (!(details = datastore->data)) {
673  ast_log(LOG_WARNING, "Huh? channel '%s' has a FAX datastore without data!\n", ast_channel_name(chan));
674  ast_channel_unlock(chan);
675  return NULL;
676  }
677  ao2_ref(details, 1);
678  ast_channel_unlock(chan);
679 
680  return details;
681 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
#define LOG_WARNING
Definition: logger.h:274
Structure for a data store object.
Definition: datastore.h:68
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2404
static const struct ast_datastore_info fax_datastore
Definition: res_fax.c:619
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Definition: astobj2.h:464
The data communicated between the high level applications and the generic fax function.
Definition: res_fax.h:110
#define ast_channel_unlock(chan)
Definition: channel.h:2946
void * data
Definition: datastore.h:70
const char * ast_channel_name(const struct ast_channel *chan)

◆ find_or_create_details()

static struct ast_fax_session_details * find_or_create_details ( struct ast_channel chan)
static

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 764 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(), fax_gateway_detect_v21(), fixup_callback(), receivefax_exec(), and sendfax_exec().

765 {
766  struct ast_fax_session_details *details;
767  struct ast_datastore *datastore;
768 
769  if ((details = find_details(chan))) {
770  return details;
771  }
772  /* channel does not have one so we must create one */
773  if (!(details = session_details_new())) {
774  ast_log(LOG_WARNING, "channel '%s' can't get a FAX details structure for the datastore!\n", ast_channel_name(chan));
775  return NULL;
776  }
777  if (!(datastore = ast_datastore_alloc(&fax_datastore, NULL))) {
778  ao2_ref(details, -1);
779  ast_log(LOG_WARNING, "channel '%s' can't get a datastore!\n", ast_channel_name(chan));
780  return NULL;
781  }
782  /* add the datastore to the channel and increment the refcount */
783  datastore->data = details;
784 
785  /* initialize default T.38 parameters */
788 
789  ao2_ref(details, 1);
790  ast_channel_lock(chan);
791  ast_channel_datastore_add(chan, datastore);
792  ast_channel_unlock(chan);
793  return details;
794 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
static struct ast_control_t38_parameters our_t38_parameters
Definition: res_fax.c:733
#define LOG_WARNING
Definition: logger.h:274
static void t38_parameters_ast_to_fax(struct ast_fax_t38_parameters *dst, const struct ast_control_t38_parameters *src)
Definition: res_fax.c:740
Structure for a data store object.
Definition: datastore.h:68
static const struct ast_datastore_info fax_datastore
Definition: res_fax.c:619
#define NULL
Definition: resample.c:96
static struct ast_fax_session_details * session_details_new(void)
create a FAX session details structure
Definition: res_fax.c:696
#define ast_log
Definition: astobj2.c:42
struct ast_fax_t38_parameters our_t38_parameters
Definition: res_fax.h:175
#define ao2_ref(o, delta)
Definition: astobj2.h:464
The data communicated between the high level applications and the generic fax function.
Definition: res_fax.h:110
#define ast_channel_unlock(chan)
Definition: channel.h:2946
void * data
Definition: datastore.h:70
static struct ast_fax_session_details * find_details(struct ast_channel *chan)
returns a reference counted pointer to a fax datastore, if it exists
Definition: res_fax.c:662
const char * ast_channel_name(const struct ast_channel *chan)
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:89
struct ast_fax_t38_parameters their_t38_parameters
Definition: res_fax.h:177
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2390

◆ fixup_callback()

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 636 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, ast_fax_session_details::is_t38_negotiated, and NULL.

Referenced by destroy_callback().

637 {
638  struct ast_fax_session_details *old_details = data;
639  struct ast_datastore *datastore = ast_channel_datastore_find(old_chan, &fax_datastore, NULL);
640 
641  if (old_details->gateway_id >= 0) {
642  struct ast_fax_session_details *new_details = find_or_create_details(new_chan);
643 
644  ast_framehook_detach(old_chan, old_details->gateway_id);
645  new_details->is_t38_negotiated = old_details->is_t38_negotiated;
646  fax_gateway_attach(new_chan, new_details);
647  ao2_cleanup(new_details);
648  }
649 
650  if (old_details->faxdetect_id >= 0) {
651  ast_framehook_detach(old_chan, old_details->faxdetect_id);
652  fax_detect_attach(new_chan, old_details->faxdetect_timeout, old_details->faxdetect_flags);
653  }
654 
655  if (datastore) {
656  ast_channel_datastore_remove(old_chan, datastore);
657  ast_datastore_free(datastore);
658  }
659 }
int ast_framehook_detach(struct ast_channel *chan, int framehook_id)
Detach an framehook from a channel.
Definition: framehook.c:177
Structure for a data store object.
Definition: datastore.h:68
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2404
static const struct ast_datastore_info fax_datastore
Definition: res_fax.c:619
#define NULL
Definition: resample.c:96
static int fax_gateway_attach(struct ast_channel *chan, struct ast_fax_session_details *details)
Attach a gateway framehook object to a channel.
Definition: res_fax.c:3626
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
The data communicated between the high level applications and the generic fax function.
Definition: res_fax.h:110
static struct ast_fax_session_details * find_or_create_details(struct ast_channel *chan)
returns a reference counted details structure from the channel&#39;s fax datastore. If the datastore does...
Definition: res_fax.c:764
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static int fax_detect_attach(struct ast_channel *chan, int timeout, int flags)
Attach a faxdetect framehook object to a channel.
Definition: res_fax.c:3889
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition: channel.c:2399

◆ generate_filenames_json()

static struct ast_json* generate_filenames_json ( struct ast_fax_session_details details)
static

Definition at line 1330 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, ast_fax_document::next, NULL, and RAII_VAR.

Referenced by report_fax_status(), and report_send_fax_status().

1331 {
1332  RAII_VAR(struct ast_json *, json_array, ast_json_array_create(), ast_json_unref);
1333  struct ast_fax_document *doc;
1334 
1335  if (!details || !json_array) {
1336  return NULL;
1337  }
1338 
1339  /* don't process empty lists */
1340  if (AST_LIST_EMPTY(&details->documents)) {
1341  return NULL;
1342  }
1343 
1344  AST_LIST_TRAVERSE(&details->documents, doc, next) {
1346  if (!entry) {
1347  return NULL;
1348  }
1349  if (ast_json_array_append(json_array, entry)) {
1350  return NULL;
1351  }
1352  }
1353 
1354  ast_json_ref(json_array);
1355  return json_array;
1356 }
struct ast_json * ast_json_ref(struct ast_json *value)
Increase refcount on value.
Definition: json.c:67
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
#define NULL
Definition: resample.c:96
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
struct ast_json * ast_json_string_create(const char *value)
Construct a JSON string from value.
Definition: json.c:268
char filename[0]
Definition: res_fax.h:104
struct ast_json * ast_json_array_create(void)
Create a empty JSON array.
Definition: json.c:352
int ast_json_array_append(struct ast_json *array, struct ast_json *value)
Append to an array.
Definition: json.c:368
struct ast_fax_documents documents
Definition: res_fax.h:119
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct ast_fax_document * next
Definition: res_fax.h:103
Abstract JSON element (object, array, string, int, ...).
Definition: search.h:40

◆ generate_filenames_string()

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
detailsthe fax session details
prefixthe prefix to each filename
separatorthe separator between filenames

This function generates a string of filenames from the given details structure and using the given prefix and separator.

Return values
NULLthere was an error generating the string
Returns
the string generated string

Definition at line 1370 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, ast_fax_document::next, and NULL.

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

1371 {
1372  char *filenames, *c;
1373  size_t size = 0;
1374  int first = 1;
1375  struct ast_fax_document *doc;
1376 
1377  /* don't process empty lists */
1378  if (AST_LIST_EMPTY(&details->documents)) {
1379  return ast_strdup("");
1380  }
1381 
1382  /* Calculate the total length of all of the file names */
1383  AST_LIST_TRAVERSE(&details->documents, doc, next) {
1384  size += strlen(separator) + strlen(prefix) + strlen(doc->filename);
1385  }
1386  size += 1; /* add space for the terminating null */
1387 
1388  if (!(filenames = ast_malloc(size))) {
1389  return NULL;
1390  }
1391  c = filenames;
1392 
1393  ast_build_string(&c, &size, "%s%s", prefix, AST_LIST_FIRST(&details->documents)->filename);
1394  AST_LIST_TRAVERSE(&details->documents, doc, next) {
1395  if (first) {
1396  first = 0;
1397  continue;
1398  }
1399 
1400  ast_build_string(&c, &size, "%s%s%s", separator, prefix, doc->filename);
1401  }
1402 
1403  return filenames;
1404 }
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
static struct test_val c
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
int ast_build_string(char **buffer, size_t *space, const char *fmt,...)
Build a string in a buffer, designed to be called repeatedly.
Definition: main/utils.c:1919
char filename[0]
Definition: res_fax.h:104
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
struct ast_fax_documents documents
Definition: res_fax.h:119
struct sla_ringing_trunk * first
Definition: app_meetme.c:1092
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct ast_fax_document * next
Definition: res_fax.h:103
static char prefix[MAX_PREFIX]
Definition: http.c:141

◆ generic_fax_exec()

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 1590 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(), 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::is_t38_negotiated, 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, result, ast_fax_session_details::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().

1591 {
1592  int ms;
1593  int timeout = RES_FAX_TIMEOUT;
1594  int chancount;
1595  unsigned int expected_frametype = -1;
1596  struct ast_frame_subclass expected_framesubclass = { .integer = 0, };
1597  unsigned int t38negotiated = (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED);
1598  struct ast_control_t38_parameters t38_parameters;
1599  const char *tempvar;
1600  struct ast_fax_session *fax = NULL;
1601  struct ast_frame *frame = NULL;
1602  struct ast_channel *c = chan;
1603  RAII_VAR(struct ast_format *, orig_write_format, NULL, ao2_cleanup);
1604  RAII_VAR(struct ast_format *, orig_read_format, NULL, ao2_cleanup);
1605  int remaining_time;
1606  struct timeval start;
1607 
1608  chancount = 1;
1609 
1610  /* Make sure one or the other is set to avoid race condition */
1611  if (t38negotiated) {
1612  details->caps |= AST_FAX_TECH_T38;
1613  } else {
1614  details->caps |= AST_FAX_TECH_AUDIO;
1615  }
1616 
1617  /* create the FAX session */
1618  if (!(fax = fax_session_new(details, chan, reserved, token))) {
1619  ast_log(LOG_ERROR, "Can't create a FAX session, FAX attempt failed.\n");
1620  report_fax_status(chan, details, "No Available Resource");
1621  return -1;
1622  }
1623 
1624  ast_channel_lock(chan);
1625  /* update session details */
1626  if (ast_strlen_zero(details->headerinfo) && (tempvar = pbx_builtin_getvar_helper(chan, "LOCALHEADERINFO"))) {
1627  ast_string_field_set(details, headerinfo, tempvar);
1628  }
1629  if (ast_strlen_zero(details->localstationid)) {
1630  tempvar = pbx_builtin_getvar_helper(chan, "LOCALSTATIONID");
1631  ast_string_field_set(details, localstationid, tempvar ? tempvar : "unknown");
1632  }
1633  ast_channel_unlock(chan);
1634 
1635  report_fax_status(chan, details, "Allocating Resources");
1636 
1637  if (details->caps & AST_FAX_TECH_AUDIO) {
1638  expected_frametype = AST_FRAME_VOICE;
1639  expected_framesubclass.format = ast_format_slin;
1640  orig_write_format = ao2_bump(ast_channel_writeformat(chan));
1641  if (ast_set_write_format(chan, ast_format_slin) < 0) {
1642  ast_log(LOG_ERROR, "channel '%s' failed to set write format to signed linear'.\n", ast_channel_name(chan));
1643  ao2_unlink(faxregistry.container, fax);
1644  ao2_ref(fax, -1);
1645  return -1;
1646  }
1647  orig_read_format = ao2_bump(ast_channel_readformat(chan));
1648  if (ast_set_read_format(chan, ast_format_slin) < 0) {
1649  ast_log(LOG_ERROR, "channel '%s' failed to set read format to signed linear.\n", ast_channel_name(chan));
1650  ao2_unlink(faxregistry.container, fax);
1651  ao2_ref(fax, -1);
1652  return -1;
1653  }
1654  if (fax->smoother) {
1656  fax->smoother = NULL;
1657  }
1658  if (!(fax->smoother = ast_smoother_new(320))) {
1659  ast_log(LOG_WARNING, "Channel '%s' FAX session '%u' failed to obtain a smoother.\n", ast_channel_name(chan), fax->id);
1660  }
1661  } else {
1662  expected_frametype = AST_FRAME_MODEM;
1663  expected_framesubclass.integer = AST_MODEM_T38;
1664  }
1665 
1666  if (fax->debug_info) {
1667  fax->debug_info->base_tv = ast_tvnow();
1668  }
1669 
1670  /* reset our result fields just in case the fax tech driver wants to
1671  * set custom error messages */
1672  ast_string_field_set(details, result, "");
1673  ast_string_field_set(details, resultstr, "");
1674  ast_string_field_set(details, error, "");
1675  details->is_t38_negotiated = t38negotiated;
1676  set_channel_variables(chan, details);
1677 
1678  if (fax->tech->start_session(fax) < 0) {
1679  GENERIC_FAX_EXEC_ERROR(fax, chan, "INIT_ERROR", "failed to start FAX session");
1680  }
1681 
1682  report_fax_status(chan, details, "FAX Transmission In Progress");
1683 
1684  ast_debug(5, "channel %s will wait on FAX fd %d\n", ast_channel_name(chan), fax->fd);
1685 
1686  /* handle frames for the session */
1687  remaining_time = timeout;
1688  start = ast_tvnow();
1689  while (remaining_time > 0) {
1690  struct ast_channel *ready_chan;
1691  int ofd, exception;
1692 
1693  ms = 1000;
1694  errno = 0;
1695  ready_chan = ast_waitfor_nandfds(&c, chancount, &fax->fd, 1, &exception, &ofd, &ms);
1696  if (ready_chan) {
1697  if (!(frame = ast_read(chan))) {
1698  /* the channel is probably gone, so lets stop polling on it and let the
1699  * FAX session complete before we exit the application. if needed,
1700  * send the FAX stack silence so the modems can finish their session without
1701  * any problems */
1702  ast_debug(1, "Channel '%s' did not return a frame; probably hung up.\n", ast_channel_name(chan));
1703  GENERIC_FAX_EXEC_SET_VARS(fax, chan, "HANGUP", "remote channel hungup");
1704  c = NULL;
1705  chancount = 0;
1706  remaining_time = ast_remaining_ms(start, timeout);
1707  fax->tech->cancel_session(fax);
1708  if (fax->tech->generate_silence) {
1709  fax->tech->generate_silence(fax);
1710  }
1711  continue;
1712  }
1713 
1714  if ((frame->frametype == AST_FRAME_CONTROL) &&
1716  (frame->datalen == sizeof(t38_parameters))) {
1717  unsigned int was_t38 = t38negotiated;
1718  struct ast_control_t38_parameters *parameters = frame->data.ptr;
1719 
1720  switch (parameters->request_response) {
1722  /* the other end has requested a switch to T.38, so reply that we are willing, if we can
1723  * do T.38 as well
1724  */
1725  t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
1726  if (details->caps & AST_FAX_TECH_T38) {
1727  details->is_t38_negotiated = 1;
1728  t38_parameters.request_response = AST_T38_NEGOTIATED;
1729  } else {
1730  t38_parameters.request_response = AST_T38_REFUSED;
1731  }
1732  ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
1733  break;
1734  case AST_T38_NEGOTIATED:
1735  t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
1736  t38negotiated = 1;
1737  details->is_t38_negotiated = 1;
1738  break;
1739  default:
1740  break;
1741  }
1742  if (t38negotiated && !was_t38) {
1743  if (fax->tech->switch_to_t38(fax)) {
1744  GENERIC_FAX_EXEC_ERROR(fax, chan, "UNKNOWN", "T.38 switch failed");
1745  break;
1746  }
1747  details->caps &= ~AST_FAX_TECH_AUDIO;
1748  expected_frametype = AST_FRAME_MODEM;
1749  expected_framesubclass.integer = AST_MODEM_T38;
1750  if (fax->smoother) {
1752  fax->smoother = NULL;
1753  }
1754 
1755  report_fax_status(chan, details, "T.38 Negotiated");
1756 
1757  ast_verb(3, "Channel '%s' switched to T.38 FAX session '%u'.\n", ast_channel_name(chan), fax->id);
1758  }
1759  } else if ((frame->frametype == expected_frametype) && (expected_framesubclass.integer == frame->subclass.integer) &&
1760  ((!frame->subclass.format && !expected_framesubclass.format) ||
1761  (frame->subclass.format && expected_framesubclass.format &&
1762  (ast_format_cmp(frame->subclass.format, expected_framesubclass.format) != AST_FORMAT_CMP_NOT_EQUAL)))) {
1763  struct ast_frame *f;
1764 
1765  if (fax->smoother) {
1766  /* push the frame into a smoother */
1767  if (ast_smoother_feed(fax->smoother, frame) < 0) {
1768  GENERIC_FAX_EXEC_ERROR(fax, chan, "UNKNOWN", "Failed to feed the smoother");
1769  }
1770  while ((f = ast_smoother_read(fax->smoother)) && (f->data.ptr)) {
1771  if (fax->debug_info) {
1772  debug_check_frame_for_silence(fax, 1, f);
1773  }
1774  /* write the frame to the FAX stack */
1775  fax->tech->write(fax, f);
1776  fax->frames_received++;
1777  if (f != frame) {
1778  ast_frfree(f);
1779  }
1780  }
1781  } else {
1782  /* write the frame to the FAX stack */
1783  fax->tech->write(fax, frame);
1784  fax->frames_received++;
1785  }
1786  start = ast_tvnow();
1787  }
1788  ast_frfree(frame);
1789  } else if (ofd == fax->fd) {
1790  /* read a frame from the FAX stack and send it out the channel.
1791  * the FAX stack will return a NULL if the FAX session has already completed */
1792  if (!(frame = fax->tech->read(fax))) {
1793  break;
1794  }
1795 
1796  if (fax->debug_info && (frame->frametype == AST_FRAME_VOICE)) {
1797  debug_check_frame_for_silence(fax, 0, frame);
1798  }
1799 
1800  ast_write(chan, frame);
1801  fax->frames_sent++;
1802  ast_frfree(frame);
1803  start = ast_tvnow();
1804  } else {
1805  if (ms && (ofd < 0)) {
1806  if ((errno == 0) || (errno == EINTR)) {
1807  remaining_time = ast_remaining_ms(start, timeout);
1808  if (remaining_time <= 0)
1809  GENERIC_FAX_EXEC_ERROR(fax, chan, "TIMEOUT", "fax session timed-out");
1810  continue;
1811  } else {
1812  ast_log(LOG_WARNING, "something bad happened while channel '%s' was polling.\n", ast_channel_name(chan));
1813  GENERIC_FAX_EXEC_ERROR(fax, chan, "UNKNOWN", "error polling data");
1814  break;
1815  }
1816  } else {
1817  /* nothing happened */
1818  remaining_time = ast_remaining_ms(start, timeout);
1819  if (remaining_time <= 0) {
1820  GENERIC_FAX_EXEC_ERROR(fax, chan, "TIMEOUT", "fax session timed-out");
1821  break;
1822  }
1823  }
1824  }
1825  }
1826  ast_debug(3, "channel '%s' - event loop stopped { timeout: %d, remaining_time: %d }\n", ast_channel_name(chan), timeout, remaining_time);
1827 
1828  set_channel_variables(chan, details);
1829 
1830  ast_atomic_fetchadd_int(&faxregistry.fax_complete, 1);
1831  if (!strcasecmp(details->result, "FAILED")) {
1832  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1833  }
1834 
1835  if (fax) {
1836  ao2_unlink(faxregistry.container, fax);
1837  ao2_ref(fax, -1);
1838  }
1839 
1840  /* if the channel is still alive, and we changed its read/write formats,
1841  * restore them now
1842  */
1843  if (chancount) {
1844  if (orig_read_format) {
1845  ast_set_read_format(chan, orig_read_format);
1846  }
1847  if (orig_write_format) {
1848  ast_set_write_format(chan, orig_write_format);
1849  }
1850  }
1851 
1852  /* return the chancount so the calling function can determine if the channel hungup during this FAX session or not */
1853  return chancount;
1854 }
static enum ast_t38_state ast_channel_get_t38_state(struct ast_channel *chan)
Retrieves the current T38 state of a channel.
Definition: channel.h:2873
const ast_string_field result
Definition: res_fax.h:142
int(*const switch_to_t38)(struct ast_fax_session *)
Definition: res_fax.h:265
#define GENERIC_FAX_EXEC_ERROR(fax, chan, errorstr, reason)
Definition: res_fax.c:1485
#define ast_channel_lock(chan)
Definition: channel.h:2945
Main Channel structure associated with a channel.
const struct ast_fax_tech * tech
Definition: res_fax.h:214
int(*const generate_silence)(struct ast_fax_session *)
Definition: res_fax.h:263
#define ast_smoother_feed(s, f)
Definition: smoother.h:76
struct ast_smoother * ast_smoother_new(int bytes)
Definition: smoother.c:108
unsigned long frames_sent
Definition: res_fax.h:212
const ast_string_field headerinfo
Definition: res_fax.h:142
unsigned long frames_received
Definition: res_fax.h:210
unsigned int id
Definition: res_fax.h:204
#define LOG_WARNING
Definition: logger.h:274
static int timeout
Definition: cdr_mysql.c:86
static void t38_parameters_ast_to_fax(struct ast_fax_t38_parameters *dst, const struct ast_control_t38_parameters *src)
Definition: res_fax.c:740
static void t38_parameters_fax_to_ast(struct ast_control_t38_parameters *dst, const struct ast_fax_t38_parameters *src)
Definition: res_fax.c:751
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4302
struct ast_smoother * smoother
Definition: res_fax.h:228
enum ast_control_t38 request_response
int ast_indicate_data(struct ast_channel *chan, int condition, const void *data, size_t datalen)
Indicates condition of channel, with payload.
Definition: channel.c:4698
Definition of a media format.
Definition: format.c:43
int(*const cancel_session)(struct ast_fax_session *)
Definition: res_fax.h:261
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
static struct test_val c
#define NULL
Definition: resample.c:96
struct ast_channel * ast_waitfor_nandfds(struct ast_channel **chan, int n, int *fds, int nfds, int *exception, int *outfd, int *ms)
Waits for activity on a group of channels.
Definition: channel.c:2997
#define ast_verb(level,...)
Definition: logger.h:463
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:755
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
struct ast_frame_subclass subclass
#define ast_strlen_zero(foo)
Definition: strings.h:52
struct ast_format * ast_channel_readformat(struct ast_channel *chan)
#define ao2_bump(obj)
Definition: astobj2.h:491
void ast_smoother_free(struct ast_smoother *s)
Definition: smoother.c:220
struct ast_fax_debug_info * debug_info
Definition: res_fax.h:226
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define GENERIC_FAX_EXEC_SET_VARS(fax, chan, errorstr, reason)
Definition: res_fax.c:1469
struct ast_fax_t38_parameters our_t38_parameters
Definition: res_fax.h:175
enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
Compare two formats.
Definition: format.c:201
int ast_set_read_format(struct ast_channel *chan, struct ast_format *format)
Sets read format on channel chan.
Definition: channel.c:5849
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
#define ao2_ref(o, delta)
Definition: astobj2.h:464
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)
create a FAX session
Definition: res_fax.c:1215
int ast_set_write_format(struct ast_channel *chan, struct ast_format *format)
Sets write format on channel chan.
Definition: channel.c:5890
#define LOG_ERROR
Definition: logger.h:285
#define ao2_unlink(container, obj)
Definition: astobj2.h:1598
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
Definition: main/utils.c:2033
static void set_channel_variables(struct ast_channel *chan, struct ast_fax_session_details *details)
Set fax related channel variables.
Definition: res_fax.c:1447
int errno
#define ast_channel_unlock(chan)
Definition: channel.h:2946
int ast_write(struct ast_channel *chan, struct ast_frame *frame)
Write a frame to a channel This function writes the given frame to the indicated channel.
Definition: channel.c:5189
static struct @460 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.
static int chancount
Definition: channel.c:93
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
struct ast_frame * ast_smoother_read(struct ast_smoother *s)
Definition: smoother.c:169
struct ast_frame *(*const read)(struct ast_fax_session *)
Definition: res_fax.h:255
const char * ast_channel_name(const struct ast_channel *chan)
static int report_fax_status(struct ast_channel *chan, struct ast_fax_session_details *details, const char *status)
send a FAX status manager event
Definition: res_fax.c:1407
#define ast_frfree(fr)
static PGresult * result
Definition: cel_pgsql.c:88
The data required to handle a fax session.
Definition: res_fax.h:202
#define AST_MODEM_T38
struct timeval base_tv
Definition: res_fax.c:438
static void debug_check_frame_for_silence(struct ast_fax_session *s, unsigned int c2s, struct ast_frame *frame)
Definition: res_fax.c:577
Data structure associated with a single frame of data.
enum ast_fax_capabilities caps
Definition: res_fax.h:113
int(*const write)(struct ast_fax_session *, const struct ast_frame *)
Definition: res_fax.h:257
#define RES_FAX_TIMEOUT
Definition: res_fax.c:492
int error(const char *format,...)
Definition: utils/frame.c:999
union ast_frame::@263 data
enum ast_frame_type frametype
const ast_string_field localstationid
Definition: res_fax.h:142
struct ast_format * format
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
int(*const start_session)(struct ast_fax_session *)
Definition: res_fax.h:259
struct ast_format * ast_channel_writeformat(struct ast_channel *chan)
struct ast_fax_t38_parameters their_t38_parameters
Definition: res_fax.h:177
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ get_general_options()

static void get_general_options ( struct fax_options options)
static

Definition at line 4397 of file res_fax.c.

References ast_rwlock_rdlock, ast_rwlock_unlock, general_options, and options_lock.

Referenced by ast_fax_maxrate(), ast_fax_minrate(), cli_fax_show_settings(), and session_details_new().

4398 {
4400  *options = general_options;
4402 }
#define ast_rwlock_rdlock(a)
Definition: lock.h:233
static ast_rwlock_t options_lock
Definition: res_fax.c:548
#define ast_rwlock_unlock(a)
Definition: lock.h:232
static struct fax_options general_options
Definition: res_fax.c:537

◆ load_module()

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 4788 of file res_fax.c.

References AO2_ALLOC_OPT_LOCK_MUTEX, ao2_container_alloc_hash, ao2_ref, app_receivefax, app_sendfax, 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_logger_level, FAX_MAXBUCKETS, faxregistry, LOG_ERROR, LOG_WARNING, manager_fax_session(), manager_fax_sessions(), manager_fax_stats(), NULL, receivefax_exec(), sendfax_exec(), session_cmp_cb(), session_hash_cb(), and set_config().

Referenced by reload_module().

4789 {
4790  int res;
4791 
4792  /* initialize the registry */
4793  faxregistry.active_sessions = 0;
4794  faxregistry.reserved_sessions = 0;
4797  if (!faxregistry.container) {
4798  return AST_MODULE_LOAD_DECLINE;
4799  }
4800 
4801  if (set_config(0) < 0) {
4802  ast_log(LOG_ERROR, "failed to load configuration file '%s'\n", config);
4803  ao2_ref(faxregistry.container, -1);
4804  return AST_MODULE_LOAD_DECLINE;
4805  }
4806 
4807  /* register CLI operations and applications */
4809  ast_log(LOG_WARNING, "failed to register '%s'.\n", app_sendfax);
4810  ao2_ref(faxregistry.container, -1);
4811  return AST_MODULE_LOAD_DECLINE;
4812  }
4814  ast_log(LOG_WARNING, "failed to register '%s'.\n", app_receivefax);
4816  ao2_ref(faxregistry.container, -1);
4817  return AST_MODULE_LOAD_DECLINE;
4818  }
4819 
4821  ast_log(LOG_WARNING, "failed to register 'FAXSessions' AMI command.\n");
4824  ao2_ref(faxregistry.container, -1);
4825  return AST_MODULE_LOAD_DECLINE;
4826  }
4827 
4829  ast_log(LOG_WARNING, "failed to register 'FAXSession' AMI command.\n");
4830  ast_manager_unregister("FAXSession");
4833  ao2_ref(faxregistry.container, -1);
4834  return AST_MODULE_LOAD_DECLINE;
4835  }
4836 
4838  ast_log(LOG_WARNING, "failed to register 'FAXStats' AMI command.\n");
4839  ast_manager_unregister("FAXSession");
4840  ast_manager_unregister("FAXSessions");
4843  ao2_ref(faxregistry.container, -1);
4844  return AST_MODULE_LOAD_DECLINE;
4845  }
4846 
4850 
4851  return res;
4852 }
static int receivefax_exec(struct ast_channel *chan, const char *data)
initiate a receive FAX session
Definition: res_fax.c:2082
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static const char app_sendfax[]
Definition: res_fax.c:429
#define LOG_WARNING
Definition: logger.h:274
static int manager_fax_session(struct mansession *s, const struct message *m)
Definition: res_fax.c:4143
#define EVENT_FLAG_CALL
Definition: manager.h:72
static int session_hash_cb(const void *obj, const int flags)
hash callback for ao2
Definition: res_fax.c:3927
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
static int session_cmp_cb(void *obj, void *arg, int flags)
compare callback for ao2
Definition: res_fax.c:3935
#define NULL
Definition: resample.c:96
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
#define ast_log
Definition: astobj2.c:42
static const char app_receivefax[]
Definition: res_fax.c:428
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static int sendfax_exec(struct ast_channel *chan, const char *data)
initiate a send FAX session
Definition: res_fax.c:2590
int ast_logger_register_level(const char *name)
Register a new logger level.
Definition: logger.c:2503
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7258
#define LOG_ERROR
Definition: logger.h:285
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Definition: astobj2.h:1310
#define FAX_MAXBUCKETS
maximum buckets for res_fax ao2 containers
Definition: res_fax.c:490
static int manager_fax_stats(struct mansession *s, const struct message *m)
Definition: res_fax.c:4213
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static int fax_logger_level
Definition: res_fax.c:487
static const char * config
Definition: res_fax.c:553
#define EVENT_FLAG_REPORTING
Definition: manager.h:80
static struct @460 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.
static int set_config(int reload)
configure res_fax
Definition: res_fax.c:4422
static int manager_fax_sessions(struct mansession *s, const struct message *m)
Definition: res_fax.c:4349
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:186
static struct ast_cli_entry fax_cli[]
Definition: res_fax.c:4380
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1508
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:626
struct ast_custom_function acf_faxopt
FAXOPT dialplan function.
Definition: res_fax.c:4742

◆ manager_fax_session()

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

Definition at line 4143 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().

4144 {
4145  const char *action_id = astman_get_header(m, "ActionID");
4146  const char *session_number = astman_get_header(m, "SessionNumber");
4147  char id_text[256] = "";
4148  struct ast_fax_session *session;
4150 
4151  if (sscanf(session_number, "%30u", &find_session.id) != 1) {
4152  astman_send_error(s, m, "Invalid session ID");
4153  return 0;
4154  }
4155 
4156  session = ao2_find(faxregistry.container, &find_session, OBJ_POINTER);
4157  if (!session) {
4158  astman_send_error(s, m, "Session not found");
4159  return 0;
4160  }
4161 
4162  if (!session->tech->manager_fax_session) {
4163  astman_send_error(s, m, "Fax technology doesn't provide a handler for FAXSession");
4164  ao2_ref(session, -1);
4165  return 0;
4166  }
4167 
4168  if (!ast_strlen_zero(action_id)) {
4169  snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", action_id);
4170  }
4171 
4172  astman_send_ack(s, m, "FAXSession event will follow");
4173 
4174  session->tech->manager_fax_session(s, id_text, session);
4175  ao2_ref(session, -1);
4176 
4177  return 0;
4178 }
const struct ast_fax_tech * tech
Definition: res_fax.h:214
#define OBJ_POINTER
Definition: astobj2.h:1154
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3191
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
static struct mansession_session * find_session(uint32_t ident, int incinuse)
Definition: manager.c:7479
#define ast_strlen_zero(foo)
Definition: strings.h:52
static struct ast_mansession session
#define ao2_ref(o, delta)
Definition: astobj2.h:464
void(*const manager_fax_session)(struct mansession *, const char *, struct ast_fax_session *)
Definition: res_fax.h:271
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
static struct @460 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.
The data required to handle a fax session.
Definition: res_fax.h:202
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3159

◆ manager_fax_sessions()

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

Definition at line 4349 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().

4350 {
4351  const char *action_id = astman_get_header(m, "ActionID");
4352  char id_text[256];
4353  struct ast_fax_session *session;
4354  struct ao2_iterator iter;
4355  int session_count = 0;
4356 
4357  id_text[0] = '\0';
4358  if (!ast_strlen_zero(action_id)) {
4359  snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", action_id);
4360  }
4361 
4362  astman_send_listack(s, m, "FAXSessionsEntry event list will follow", "Start");
4363 
4364  iter = ao2_iterator_init(faxregistry.container, 0);
4365  while ((session = ao2_iterator_next(&iter))) {
4366  if (!manager_fax_sessions_entry(s, session, id_text)) {
4367  session_count++;
4368  }
4369  ao2_ref(session, -1);
4370  }
4371  ao2_iterator_destroy(&iter);
4372 
4373  astman_send_list_complete_start(s, m, "FAXSessionsComplete", session_count);
4374  astman_append(s, "Total: %d\r\n", session_count);
4376 
4377  return 0;
4378 }
static int manager_fax_sessions_entry(struct mansession *s, struct ast_fax_session *session, const char *id_text)
Definition: res_fax.c:4317
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3080
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
Definition: manager.c:3237
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
#define ast_strlen_zero(foo)
Definition: strings.h:52
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:3245
static struct ast_mansession session
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
static int session_count
Definition: http.c:109
static struct @460 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
The data required to handle a fax session.
Definition: res_fax.h:202
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
Definition: manager.c:3201

◆ manager_fax_sessions_entry()

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

Definition at line 4317 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().

4319 {
4320  char *filenames;
4321 
4322  ao2_lock(session);
4323  filenames = generate_filenames_string(session->details, "", ",");
4324 
4325  if (!filenames) {
4326  ast_log(LOG_ERROR, "Error generating Files string");
4327  ao2_unlock(session);
4328  return -1;
4329  }
4330 
4331  astman_append(s, "Event: FAXSessionsEntry\r\n"
4332  "%s" /* ActionID if present */
4333  "Channel: %s\r\n" /* Channel name */
4334  "Technology: %s\r\n" /* Fax session technology */
4335  "SessionNumber: %u\r\n" /* Session ID */
4336  "SessionType: %s\r\n" /* G711 or T38 */
4337  "Operation: %s\r\n"
4338  "State: %s\r\n"
4339  "Files: %s\r\n"
4340  "\r\n",
4341  id_text, session->channame, session->tech->type, session->id,
4343  ast_fax_state_to_str(session->state), S_OR(filenames, ""));
4344  ast_free(filenames);
4345  ao2_unlock(session);
4346  return 0;
4347 }
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3080
const struct ast_fax_tech * tech
Definition: res_fax.h:214
unsigned int id
Definition: res_fax.h:204
const char *const type
Definition: res_fax.h:237
#define ao2_unlock(a)
Definition: astobj2.h:730
#define ast_log
Definition: astobj2.c:42
struct ast_fax_session_details * details
Definition: res_fax.h:208
#define ao2_lock(a)
Definition: astobj2.h:718
char * channame
Definition: res_fax.h:220
#define LOG_ERROR
Definition: logger.h:285
#define ast_free(a)
Definition: astmm.h:182
enum ast_fax_state state
Definition: res_fax.h:218
static const char * fax_session_type(struct ast_fax_session *s)
Definition: res_fax.c:4242
const char * ast_fax_session_operation_str(struct ast_fax_session *s)
get string representation of a FAX session&#39;s operation
Definition: res_fax.c:4254
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
const char * ast_fax_state_to_str(enum ast_fax_state state)
convert a ast_fax_state to a string
Definition: res_fax.c:1013
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.
Definition: res_fax.c:1370

◆ manager_fax_stats()

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

Definition at line 4213 of file res_fax.c.

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

Referenced by load_module().

4214 {
4215  const char *action_id = astman_get_header(m, "ActionID");
4216 
4217  char id_text[256] = "";
4218 
4219  astman_send_ack(s, m, "FAXStats event will follow");
4220 
4221  if (!ast_strlen_zero(action_id)) {
4222  snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", action_id);
4223  }
4224 
4225  astman_append(s, "Event: FAXStats\r\n"
4226  "%s"
4227  "CurrentSessions: %d\r\n"
4228  "ReservedSessions: %d\r\n"
4229  "TransmitAttempts: %d\r\n"
4230  "ReceiveAttempts: %d\r\n"
4231  "CompletedFAXes: %d\r\n"
4232  "FailedFAXes: %d\r\n"
4233  "\r\n",
4234  id_text,
4235  faxregistry.active_sessions, faxregistry.reserved_sessions,
4236  faxregistry.fax_tx_attempts, faxregistry.fax_rx_attempts,
4237  faxregistry.fax_complete, faxregistry.fax_failures);
4238 
4239  return 0;
4240 }
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3080
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3191
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
#define ast_strlen_zero(foo)
Definition: strings.h:52
static struct @460 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.

◆ receivefax_exec()

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

initiate a receive FAX session

Definition at line 2082 of file res_fax.c.

References ast_fax_session_details::allow_audio, ao2_cleanup, app_receivefax, 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, ast_fax_session_details::caps, check_modem_rate(), ast_fax_session_details::debug, disable_t38(), ast_fax_session_details::documents, error(), fax_exec_options, fax_session_release(), fax_session_reserve(), faxregistry, ast_fax_document::filename, find_or_create_details(), ast_fax_session_details::gateway_id, generic_fax_exec(), global_fax_debug, LOG_ERROR, LOG_WARNING, ast_fax_session_details::maxrate, ast_fax_session_details::minrate, ast_fax_session_details::modems, NULL, OPT_ALLOWAUDIO, OPT_CALLEDMODE, OPT_CALLERMODE, OPT_DEBUG, OPT_FORCE_AUDIO, OPT_STATUS, ast_fax_session_details::option, options, parse(), pbx_builtin_setvar_helper(), RAII_VAR, receivefax_t38_init(), report_receive_fax_status(), result, ast_fax_session_details::send_ced, set_channel_variables(), set_fax_t38_caps(), ast_fax_session_details::statusevents, T38_STATE_NEGOTIATED, T38_STATE_REJECTED, and T38_STATE_UNAVAILABLE.

Referenced by load_module().

2083 {
2084  char *parse, modems[128] = "";
2085  int channel_alive;
2086  RAII_VAR(struct ast_fax_session *, s, NULL, ao2_cleanup);
2087  RAII_VAR(struct ast_fax_session_details *, details, NULL, ao2_cleanup);
2088  struct ast_fax_tech_token *token = NULL;
2089  struct ast_fax_document *doc;
2093  );
2094  struct ast_flags opts = { 0, };
2095  enum ast_t38_state t38state;
2096 
2097  /* initialize output channel variables */
2098  pbx_builtin_setvar_helper(chan, "FAXSTATUS", "FAILED");
2099  pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", NULL);
2100  pbx_builtin_setvar_helper(chan, "FAXPAGES", "0");
2101  pbx_builtin_setvar_helper(chan, "FAXBITRATE", NULL);
2102  pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", NULL);
2103  pbx_builtin_setvar_helper(chan, "FAXMODE", NULL);
2104 
2105  /* Get a FAX session details structure from the channel's FAX datastore and create one if
2106  * it does not already exist. */
2107  if (!(details = find_or_create_details(chan))) {
2108  pbx_builtin_setvar_helper(chan, "FAXERROR", "MEMORY_ERROR");
2109  pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "error allocating memory");
2110  ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
2111  return -1;
2112  }
2113 
2114  ast_string_field_set(details, result, "FAILED");
2115  ast_string_field_set(details, resultstr, "error starting fax session");
2116  ast_string_field_set(details, error, "INIT_ERROR");
2117  set_channel_variables(chan, details);
2118 
2119  if (details->gateway_id > 0) {
2120  ast_string_field_set(details, resultstr, "can't receive a fax on a channel with a T.38 gateway");
2121  set_channel_variables(chan, details);
2122  ast_log(LOG_ERROR, "executing ReceiveFAX on a channel with a T.38 Gateway is not supported\n");
2123  return -1;
2124  }
2125 
2126  if (details->maxrate < details->minrate) {
2127  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2128  ast_string_field_set(details, resultstr, "maxrate is less than minrate");
2129  set_channel_variables(chan, details);
2130  ast_log(LOG_ERROR, "maxrate %u is less than minrate %u\n", details->maxrate, details->minrate);
2131  return -1;
2132  }
2133 
2134  if (check_modem_rate(details->modems, details->minrate)) {
2135  ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
2136  ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %u\n", modems, details->minrate);
2137  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2138  ast_string_field_set(details, resultstr, "incompatible 'modems' and 'minrate' settings");
2139  set_channel_variables(chan, details);
2140  return -1;
2141  }
2142 
2143  if (check_modem_rate(details->modems, details->maxrate)) {
2144  ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
2145  ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %u\n", modems, details->maxrate);
2146  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2147  ast_string_field_set(details, resultstr, "incompatible 'modems' and 'maxrate' settings");
2148  set_channel_variables(chan, details);
2149  return -1;
2150  }
2151 
2152  if (ast_strlen_zero(data)) {
2153  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2154  ast_string_field_set(details, resultstr, "invalid arguments");
2155  set_channel_variables(chan, details);
2156  ast_log(LOG_WARNING, "%s requires an argument (filename[,options])\n", app_receivefax);
2157  return -1;
2158  }
2159  parse = ast_strdupa(data);
2160  AST_STANDARD_APP_ARGS(args, parse);
2161 
2162  if (!ast_strlen_zero(args.options) &&
2163  ast_app_parse_options(fax_exec_options, &opts, NULL, args.options)) {
2164  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2165  ast_string_field_set(details, resultstr, "invalid arguments");
2166  set_channel_variables(chan, details);
2167  return -1;
2168  }
2169  if (ast_strlen_zero(args.filename)) {
2170  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2171  ast_string_field_set(details, resultstr, "invalid arguments");
2172  set_channel_variables(chan, details);
2173  ast_log(LOG_WARNING, "%s requires an argument (filename[,options])\n", app_receivefax);
2174  return -1;
2175  }
2176 
2177  /* check for unsupported FAX application options */
2178  if (ast_test_flag(&opts, OPT_CALLERMODE) || ast_test_flag(&opts, OPT_CALLEDMODE)) {
2179  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2180  ast_string_field_set(details, resultstr, "invalid arguments");
2181  set_channel_variables(chan, details);
2182  ast_log(LOG_WARNING, "%s does not support polling\n", app_receivefax);
2183  return -1;
2184  }
2185 
2186  ast_atomic_fetchadd_int(&faxregistry.fax_rx_attempts, 1);
2187 
2188  pbx_builtin_setvar_helper(chan, "FAXERROR", "Channel Problems");
2189  pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "Error before FAX transmission started.");
2190 
2191  if (!(doc = ast_calloc(1, sizeof(*doc) + strlen(args.filename) + 1))) {
2192  ast_string_field_set(details, error, "MEMORY_ERROR");
2193  ast_string_field_set(details, resultstr, "error allocating memory");
2194  set_channel_variables(chan, details);
2195  ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
2196  return -1;
2197  }
2198 
2199  strcpy(doc->filename, args.filename);
2200  AST_LIST_INSERT_TAIL(&details->documents, doc, next);
2201 
2202  ast_verb(3, "Channel '%s' receiving FAX '%s'\n", ast_channel_name(chan), args.filename);
2203 
2204  details->caps = AST_FAX_TECH_RECEIVE;
2205  details->option.send_ced = AST_FAX_OPTFLAG_TRUE;
2206 
2207  /* check for debug */
2208  if (ast_test_flag(&opts, OPT_DEBUG) || global_fax_debug) {
2209  details->option.debug = AST_FAX_OPTFLAG_TRUE;
2210  }
2211 
2212  /* check for request for status events */
2213  if (ast_test_flag(&opts, OPT_STATUS)) {
2214  details->option.statusevents = AST_FAX_OPTFLAG_TRUE;
2215  }
2216 
2217  t38state = ast_channel_get_t38_state(chan);
2218  if ((t38state == T38_STATE_UNAVAILABLE) || (t38state == T38_STATE_REJECTED) ||
2219  ast_test_flag(&opts, OPT_ALLOWAUDIO) ||
2220  ast_test_flag(&opts, OPT_FORCE_AUDIO)) {
2221  details->option.allow_audio = AST_FAX_OPTFLAG_TRUE;
2222  }
2223 
2224  if (!(s = fax_session_reserve(details, &token))) {
2225  ast_string_field_set(details, resultstr, "error reserving fax session");
2226  set_channel_variables(chan, details);
2227  ast_log(LOG_ERROR, "Unable to reserve FAX session.\n");
2228  return -1;
2229  }
2230 
2231  /* make sure the channel is up */
2232  if (ast_channel_state(chan) != AST_STATE_UP) {
2233  if (ast_answer(chan)) {
2234  ast_string_field_set(details, resultstr, "error answering channel");
2235  set_channel_variables(chan, details);
2236  ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", ast_channel_name(chan));
2237  fax_session_release(s, token);
2238  return -1;
2239  }
2240  }
2241 
2242  if (!ast_test_flag(&opts, OPT_FORCE_AUDIO)) {
2243  if (set_fax_t38_caps(chan, details)) {
2244  ast_string_field_set(details, error, "T38_NEG_ERROR");
2245  ast_string_field_set(details, resultstr, "error negotiating T.38");
2246  set_channel_variables(chan, details);
2247  fax_session_release(s, token);
2248  return -1;
2249  }
2250  } else {
2251  details->caps |= AST_FAX_TECH_AUDIO;
2252  }
2253 
2254  if (!ast_test_flag(&opts, OPT_FORCE_AUDIO) && (details->caps & AST_FAX_TECH_T38)) {
2255  if (receivefax_t38_init(chan, details)) {
2256  ast_string_field_set(details, error, "T38_NEG_ERROR");
2257  ast_string_field_set(details, resultstr, "error negotiating T.38");
2258  set_channel_variables(chan, details);
2259  fax_session_release(s, token);
2260  ast_log(LOG_ERROR, "error initializing channel '%s' in T.38 mode\n", ast_channel_name(chan));
2261  return -1;
2262  }
2263  }
2264 
2265  if ((channel_alive = generic_fax_exec(chan, details, s, token)) < 0) {
2266  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
2267  }
2268 
2270  if (disable_t38(chan)) {
2271  ast_debug(1, "error disabling T.38 mode on %s\n", ast_channel_name(chan));
2272  }
2273  }
2274 
2275  if (report_receive_fax_status(chan, args.filename)) {
2276  ast_log(AST_LOG_ERROR, "Error publishing ReceiveFax status message\n");
2277  }
2278 
2279  /* If the channel hungup return -1; otherwise, return 0 to continue in the dialplan */
2280  return (!channel_alive) ? -1 : 0;
2281 }
static enum ast_t38_state ast_channel_get_t38_state(struct ast_channel *chan)
Retrieves the current T38 state of a channel.
Definition: channel.h:2873
static const struct ast_app_option fax_exec_options[128]
Definition: res_fax.c:575
static int receivefax_t38_init(struct ast_channel *chan, struct ast_fax_session_details *details)
Definition: res_fax.c:1856
#define ast_test_flag(p, flag)
Definition: utils.h:63
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
Definition: res_fax.c:1590
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
#define LOG_WARNING
Definition: logger.h:274
ast_channel_state
ast_channel states
Definition: channelstate.h:35
ast_t38_state
Possible T38 states on channels.
Definition: channel.h:879
t38state
T38 States for a call.
Definition: sip.h:665
const char * args
#define NULL
Definition: resample.c:96
#define ast_verb(level,...)
Definition: logger.h:463
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:755
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define AST_LOG_ERROR
Definition: logger.h:290
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
static int disable_t38(struct ast_channel *chan)
Definition: res_fax.c:1527
static int check_modem_rate(enum ast_fax_modems modems, unsigned int rate)
Definition: res_fax.c:938
static const char app_receivefax[]
Definition: res_fax.c:428
char filename[0]
Definition: res_fax.h:104
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
The data communicated between the high level applications and the generic fax function.
Definition: res_fax.h:110
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: main/app.c:2906
static int set_fax_t38_caps(struct ast_channel *chan, struct ast_fax_session_details *details)
Definition: res_fax.c:1491
static struct ast_fax_session_details * find_or_create_details(struct ast_channel *chan)
returns a reference counted details structure from the channel&#39;s fax datastore. If the datastore does...
Definition: res_fax.c:764
#define LOG_ERROR
Definition: logger.h:285
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
static void fax_session_release(struct ast_fax_session *s, struct ast_fax_tech_token *token)
Release a session token.
Definition: res_fax.c:1083
static void set_channel_variables(struct ast_channel *chan, struct ast_fax_session_details *details)
Set fax related channel variables.
Definition: res_fax.c:1447
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
static int global_fax_debug
Definition: res_fax.c:555
Structure used to handle boolean flags.
Definition: utils.h:199
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
static struct ast_fax_session * fax_session_reserve(struct ast_fax_session_details *details, struct ast_fax_tech_token **token)
Reserve a fax session.
Definition: res_fax.c:1146
static struct @460 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static int report_receive_fax_status(struct ast_channel *chan, const char *filename)
Report on the final state of a receive fax operation.
Definition: res_fax.c:2018
const char * ast_channel_name(const struct ast_channel *chan)
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2814
static PGresult * result
Definition: cel_pgsql.c:88
The data required to handle a fax session.
Definition: res_fax.h:202
int error(const char *format,...)
Definition: utils/frame.c:999
static int ast_fax_modem_to_str(enum ast_fax_modems bits, char *tbuf, size_t bufsize)
Definition: res_fax.c:905
static struct test_options options
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
#define AST_APP_ARG(name)
Define an application argument.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ receivefax_t38_init()

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

Definition at line 1856 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().

1857 {
1858  int timeout_ms;
1859  struct ast_frame *frame = NULL;
1860  struct ast_control_t38_parameters t38_parameters;
1861  struct timeval start;
1862  int ms;
1863 
1864  /* don't send any audio if we've already received a T.38 reinvite */
1866  /* generate 3 seconds of CED */
1867  if (ast_playtones_start(chan, 1024, "!2100/3000", 1)) {
1868  ast_log(LOG_ERROR, "error generating CED tone on %s\n", ast_channel_name(chan));
1869  return -1;
1870  }
1871 
1872  timeout_ms = 3000;
1873  start = ast_tvnow();
1874  while ((ms = ast_remaining_ms(start, timeout_ms))) {
1875  ms = ast_waitfor(chan, ms);
1876 
1877  if (ms < 0) {
1878  ast_log(LOG_ERROR, "error while generating CED tone on %s\n", ast_channel_name(chan));
1879  ast_playtones_stop(chan);
1880  return -1;
1881  }
1882 
1883  if (ms == 0) { /* all done, nothing happened */
1884  break;
1885  }
1886 
1887  if (!(frame = ast_read(chan))) {
1888  ast_log(LOG_ERROR, "error reading frame while generating CED tone on %s\n", ast_channel_name(chan));
1889  ast_playtones_stop(chan);
1890  return -1;
1891  }
1892 
1893  if ((frame->frametype == AST_FRAME_CONTROL) &&
1895  (frame->datalen == sizeof(t38_parameters))) {
1896  struct ast_control_t38_parameters *parameters = frame->data.ptr;
1897 
1898  switch (parameters->request_response) {
1900  /* the other end has requested a switch to T.38, so reply that we are willing, if we can
1901  * do T.38 as well
1902  */
1903  t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
1904  t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
1905  ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
1906  ast_playtones_stop(chan);
1907  break;
1908  case AST_T38_NEGOTIATED:
1909  ast_debug(1, "Negotiated T.38 for receive on %s\n", ast_channel_name(chan));
1910  t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
1911  details->caps &= ~AST_FAX_TECH_AUDIO;
1912  report_fax_status(chan, details, "T.38 Negotiated");
1913  break;
1914  default:
1915  break;
1916  }
1917  }
1918  ast_frfree(frame);
1919  }
1920 
1921  ast_playtones_stop(chan);
1922  }
1923 
1924  /* if T.38 was negotiated, we are done initializing */
1926  return 0;
1927  }
1928 
1929  /* request T.38 */
1930  ast_debug(1, "Negotiating T.38 for receive on %s\n", ast_channel_name(chan));
1931 
1932  /* wait for negotiation to complete */
1933  timeout_ms = details->t38timeout;
1934 
1935  /* set parameters based on the session's parameters */
1936  t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
1937  t38_parameters.request_response = AST_T38_REQUEST_NEGOTIATE;
1938  if ((ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0)) {
1939  return -1;
1940  }
1941 
1942  start = ast_tvnow();
1943  while ((ms = ast_remaining_ms(start, timeout_ms))) {
1944  int break_loop = 0;
1945 
1946  ms = ast_waitfor(chan, ms);
1947  if (ms < 0) {
1948  ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", ast_channel_name(chan));
1949  return -1;
1950  }
1951  if (ms == 0) { /* all done, nothing happened */
1952  ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 negotiation.\n", ast_channel_name(chan));
1953  details->caps &= ~AST_FAX_TECH_T38;
1954  break;
1955  }
1956 
1957  if (!(frame = ast_read(chan))) {
1958  ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", ast_channel_name(chan));
1959  return -1;
1960  }
1961 
1962  if ((frame->frametype == AST_FRAME_CONTROL) &&
1964  (frame->datalen == sizeof(t38_parameters))) {
1965  struct ast_control_t38_parameters *parameters = frame->data.ptr;
1966 
1967  switch (parameters->request_response) {
1969  t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
1970  t38_parameters.request_response = AST_T38_NEGOTIATED;
1971  ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
1972  break;
1973  case AST_T38_NEGOTIATED:
1974  ast_debug(1, "Negotiated T.38 for receive on %s\n", ast_channel_name(chan));
1975  t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
1976  details->caps &= ~AST_FAX_TECH_AUDIO;
1977  report_fax_status(chan, details, "T.38 Negotiated");
1978  break_loop = 1;
1979  break;
1980  case AST_T38_REFUSED:
1981  ast_log(LOG_WARNING, "channel '%s' refused to negotiate T.38\n", ast_channel_name(chan));
1982  details->caps &= ~AST_FAX_TECH_T38;
1983  break_loop = 1;
1984  break;
1985  default:
1986  ast_log(LOG_ERROR, "channel '%s' failed to negotiate T.38\n", ast_channel_name(chan));
1987  details->caps &= ~AST_FAX_TECH_T38;
1988  break_loop = 1;
1989  break;
1990  }
1991  }
1992  ast_frfree(frame);
1993  if (break_loop) {
1994  break;
1995  }
1996  }
1997 
1998  /* if T.38 was negotiated, we are done initializing */
2000  return 0;
2001  }
2002 
2003  /* if we made it here, then T.38 failed, check the 'f' flag */
2004  if (details->option.allow_audio != AST_FAX_OPTFLAG_TRUE) {
2005  ast_log(LOG_WARNING, "Audio FAX not allowed on channel '%s' and T.38 negotiation failed; aborting.\n", ast_channel_name(chan));
2006  return -1;
2007  }
2008 
2009  /* ok, audio fallback is allowed */
2010  details->caps |= AST_FAX_TECH_AUDIO;
2011 
2012  return 0;
2013 }
static enum ast_t38_state ast_channel_get_t38_state(struct ast_channel *chan)
Retrieves the current T38 state of a channel.
Definition: channel.h:2873
unsigned int t38timeout
Definition: res_fax.h:179
#define LOG_WARNING
Definition: logger.h:274
static void t38_parameters_ast_to_fax(struct ast_fax_t38_parameters *dst, const struct ast_control_t38_parameters *src)
Definition: res_fax.c:740
static void t38_parameters_fax_to_ast(struct ast_control_t38_parameters *dst, const struct ast_fax_t38_parameters *src)
Definition: res_fax.c:751
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4302
enum ast_control_t38 request_response
int ast_indicate_data(struct ast_channel *chan, int condition, const void *data, size_t datalen)
Indicates condition of channel, with payload.
Definition: channel.c:4698
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
void ast_playtones_stop(struct ast_channel *chan)
Stop playing tones on a channel.
Definition: indications.c:393
#define NULL
Definition: resample.c:96
struct ast_frame_subclass subclass
union ast_fax_session_details::@290 option
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
struct ast_fax_t38_parameters our_t38_parameters
Definition: res_fax.h:175
#define LOG_ERROR
Definition: logger.h:285
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
Definition: main/utils.c:2033
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3171
const char * ast_channel_name(const struct ast_channel *chan)
static int report_fax_status(struct ast_channel *chan, struct ast_fax_session_details *details, const char *status)
send a FAX status manager event
Definition: res_fax.c:1407
#define ast_frfree(fr)
Data structure associated with a single frame of data.
enum ast_fax_capabilities caps
Definition: res_fax.h:113
int ast_playtones_start(struct ast_channel *chan, int vol, const char *tonelist, int interruptible)
Start playing a list of tones on a channel.
Definition: indications.c:302
union ast_frame::@263 data
enum ast_frame_type frametype
struct ast_fax_t38_parameters their_t38_parameters
Definition: res_fax.h:177

◆ reload_module()

static int reload_module ( void  )
static

Definition at line 4854 of file res_fax.c.

References AST_MODFLAG_GLOBAL_SYMBOLS, AST_MODFLAG_LOAD_ORDER, AST_MODPRI_APP_DEPEND, AST_MODULE_INFO(), AST_MODULE_SUPPORT_CORE, ASTERISK_GPL_KEY, load_module(), reload(), set_config(), and unload_module().

4855 {
4856  set_config(1);
4857  return 0;
4858 }
static int set_config(int reload)
configure res_fax
Definition: res_fax.c:4422

◆ report_fax_status()

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 1407 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_JSON_UTF8_VALIDATE, 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().

1408 {
1409  RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
1411  struct ast_json *json_filenames = NULL;
1412 
1413  if (!details->option.statusevents) {
1414  return 0;
1415  }
1416 
1417  json_filenames = generate_filenames_json(details);
1418  if (!json_filenames) {
1419  return -1;
1420  }
1421 
1422  json_object = ast_json_pack("{s: s, s: s, s: s, s: s, s: o}",
1423  "type", "status",
1424  "operation", (details->caps & AST_FAX_TECH_GATEWAY)
1425  ? "gateway"
1426  : (details->caps & AST_FAX_TECH_RECEIVE) ? "receive" : "send",
1427  "status", status,
1428  "local_station_id", AST_JSON_UTF8_VALIDATE(details->localstationid),
1429  "filenames", json_filenames);
1430  if (!json_object) {
1431  return -1;
1432  }
1433 
1434  {
1435  SCOPED_CHANNELLOCK(lock, chan);
1436 
1438  if (!message) {
1439  return -1;
1440  }
1442  }
1443  return 0;
1444 }
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:591
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
static struct ast_json * generate_filenames_json(struct ast_fax_session_details *details)
Definition: res_fax.c:1330
#define NULL
Definition: resample.c:96
union ast_fax_session_details::@290 option
#define SCOPED_CHANNELLOCK(varname, chan)
scoped lock specialization for channels.
Definition: lock.h:617
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
ast_mutex_t lock
Definition: app_meetme.c:1091
const char * ast_channel_uniqueid(const struct ast_channel *chan)
struct stasis_topic * ast_channel_topic(struct ast_channel *chan)
A topic which publishes the events for a particular channel.
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic&#39;s subscribers.
Definition: stasis.c:1511
struct stasis_message * ast_channel_blob_create_from_cache(const char *uniqueid, struct stasis_message_type *type, struct ast_json *blob)
Create a ast_channel_blob message, pulling channel state from the cache.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
enum ast_fax_capabilities caps
Definition: res_fax.h:113
Abstract JSON element (object, array, string, int, ...).
const ast_string_field localstationid
Definition: res_fax.h:142
struct stasis_message_type * ast_channel_fax_type(void)
Message type for a fax operation.
#define AST_JSON_UTF8_VALIDATE(str)
Check str for UTF-8 and replace with an empty string if fails the check.
Definition: json.h:224
jack_status_t status
Definition: app_jack.c:146

◆ report_receive_fax_status()

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 2018 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_ref(), ast_json_string_create(), ast_json_unref(), AST_JSON_UTF8_VALIDATE, ast_strdupa, ast_strlen_zero, lock, NULL, pbx_builtin_getvar_helper(), RAII_VAR, S_OR, SCOPED_CHANNELLOCK, and stasis_publish().

Referenced by receivefax_exec().

2019 {
2020  RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
2022  RAII_VAR(struct ast_json *, json_array, ast_json_array_create(), ast_json_unref);
2023  struct ast_json *json_filename = ast_json_string_create(filename);
2024 
2025  if (!json_array || !json_filename) {
2026  ast_json_unref(json_filename);
2027  return -1;
2028  }
2029  ast_json_array_append(json_array, json_filename);
2030 
2031  {
2032  const char *remote_station_id;
2033  const char *local_station_id;
2034  const char *fax_pages;
2035  const char *fax_resolution;
2036  const char *fax_bitrate;
2037  SCOPED_CHANNELLOCK(lock, chan);
2038 
2039  remote_station_id = AST_JSON_UTF8_VALIDATE(pbx_builtin_getvar_helper(chan, "REMOTESTATIONID"));
2040  if (!ast_strlen_zero(remote_station_id)) {
2041  remote_station_id = ast_strdupa(remote_station_id);
2042  }
2043  local_station_id = AST_JSON_UTF8_VALIDATE(pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"));
2044  if (!ast_strlen_zero(local_station_id)) {
2045  local_station_id = ast_strdupa(local_station_id);
2046  }
2047  fax_pages = S_OR(pbx_builtin_getvar_helper(chan, "FAXPAGES"), "");
2048  if (!ast_strlen_zero(fax_pages)) {
2049  fax_pages = ast_strdupa(fax_pages);
2050  }
2051  fax_resolution = S_OR(pbx_builtin_getvar_helper(chan, "FAXRESOLUTION"), "");
2052  if (!ast_strlen_zero(fax_resolution)) {
2053  fax_resolution = ast_strdupa(fax_resolution);
2054  }
2055  fax_bitrate = S_OR(pbx_builtin_getvar_helper(chan, "FAXBITRATE"), "");
2056  if (!ast_strlen_zero(fax_bitrate)) {
2057  fax_bitrate = ast_strdupa(fax_bitrate);
2058  }
2059 
2060  json_object = ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: s, s: o}",
2061  "type", "receive",
2062  "remote_station_id", S_OR(remote_station_id, ""),
2063  "local_station_id", S_OR(local_station_id, ""),
2064  "fax_pages", S_OR(fax_pages, ""),
2065  "fax_resolution", S_OR(fax_resolution, ""),
2066  "fax_bitrate", S_OR(fax_bitrate, ""),
2067  "filenames", ast_json_ref(json_array));
2068  if (!json_object) {
2069  return -1;
2070  }
2071 
2073  if (!message) {
2074  return -1;
2075  }
2077  }
2078  return 0;
2079 }
struct ast_json * ast_json_ref(struct ast_json *value)
Increase refcount on value.
Definition: json.c:67
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:591
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
#define NULL
Definition: resample.c:96
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define SCOPED_CHANNELLOCK(varname, chan)
scoped lock specialization for channels.
Definition: lock.h:617
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
struct ast_json * ast_json_string_create(const char *value)
Construct a JSON string from value.
Definition: json.c:268
ast_mutex_t lock
Definition: app_meetme.c:1091
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
struct ast_json * ast_json_array_create(void)
Create a empty JSON array.
Definition: json.c:352
int ast_json_array_append(struct ast_json *array, struct ast_json *value)
Append to an array.
Definition: json.c:368
const char * ast_channel_uniqueid(const struct ast_channel *chan)
struct stasis_topic * ast_channel_topic(struct ast_channel *chan)
A topic which publishes the events for a particular channel.
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic&#39;s subscribers.
Definition: stasis.c:1511
struct stasis_message * ast_channel_blob_create_from_cache(const char *uniqueid, struct stasis_message_type *type, struct ast_json *blob)
Create a ast_channel_blob message, pulling channel state from the cache.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
Abstract JSON element (object, array, string, int, ...).
struct stasis_message_type * ast_channel_fax_type(void)
Message type for a fax operation.
#define AST_JSON_UTF8_VALIDATE(str)
Check str for UTF-8 and replace with an empty string if fails the check.
Definition: json.h:224

◆ report_send_fax_status()

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 2527 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_JSON_UTF8_VALIDATE, 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().

2528 {
2529  RAII_VAR(struct ast_json *, json_obj, NULL, ast_json_unref);
2531  struct ast_json *json_filenames;
2532 
2533  json_filenames = generate_filenames_json(details);
2534  if (!json_filenames) {
2535  return -1;
2536  }
2537 
2538  {
2539  const char *remote_station_id;
2540  const char *local_station_id;
2541  const char *fax_pages;
2542  const char *fax_resolution;
2543  const char *fax_bitrate;
2544  SCOPED_CHANNELLOCK(lock, chan);
2545 
2546  remote_station_id = AST_JSON_UTF8_VALIDATE(pbx_builtin_getvar_helper(chan, "REMOTESTATIONID"));
2547  if (!ast_strlen_zero(remote_station_id)) {
2548  remote_station_id = ast_strdupa(remote_station_id);
2549  }
2550  local_station_id = AST_JSON_UTF8_VALIDATE(pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"));
2551  if (!ast_strlen_zero(local_station_id)) {
2552  local_station_id = ast_strdupa(local_station_id);
2553  }
2554  fax_pages = S_OR(pbx_builtin_getvar_helper(chan, "FAXPAGES"), "");
2555  if (!ast_strlen_zero(fax_pages)) {
2556  fax_pages = ast_strdupa(fax_pages);
2557  }
2558  fax_resolution = S_OR(pbx_builtin_getvar_helper(chan, "FAXRESOLUTION"), "");
2559  if (!ast_strlen_zero(fax_resolution)) {
2560  fax_resolution = ast_strdupa(fax_resolution);
2561  }
2562  fax_bitrate = S_OR(pbx_builtin_getvar_helper(chan, "FAXBITRATE"), "");
2563  if (!ast_strlen_zero(fax_bitrate)) {
2564  fax_bitrate = ast_strdupa(fax_bitrate);
2565  }
2566  json_obj = ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: s, s: o}",
2567  "type", "send",
2568  "remote_station_id", S_OR(remote_station_id, ""),
2569  "local_station_id", S_OR(local_station_id, ""),
2570  "fax_pages", S_OR(fax_pages, ""),
2571  "fax_resolution", S_OR(fax_resolution, ""),
2572  "fax_bitrate", S_OR(fax_bitrate, ""),
2573  "filenames", json_filenames);
2574  if (!json_obj) {
2575  return -1;
2576  }
2577 
2579  if (!message) {
2580  return -1;
2581  }
2583  }
2584  return 0;
2585 }
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:591
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
static struct ast_json * generate_filenames_json(struct ast_fax_session_details *details)
Definition: res_fax.c:1330
#define NULL
Definition: resample.c:96
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define SCOPED_CHANNELLOCK(varname, chan)
scoped lock specialization for channels.
Definition: lock.h:617
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
ast_mutex_t lock
Definition: app_meetme.c:1091
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
const char * ast_channel_uniqueid(const struct ast_channel *chan)
struct stasis_topic * ast_channel_topic(struct ast_channel *chan)
A topic which publishes the events for a particular channel.
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic&#39;s subscribers.
Definition: stasis.c:1511
struct stasis_message * ast_channel_blob_create_from_cache(const char *uniqueid, struct stasis_message_type *type, struct ast_json *blob)
Create a ast_channel_blob message, pulling channel state from the cache.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
Abstract JSON element (object, array, string, int, ...).
struct stasis_message_type * ast_channel_fax_type(void)
Message type for a fax operation.
#define AST_JSON_UTF8_VALIDATE(str)
Check str for UTF-8 and replace with an empty string if fails the check.
Definition: json.h:224

◆ sendfax_exec()

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

initiate a send FAX session

Definition at line 2590 of file res_fax.c.

References ast_fax_session_details::allow_audio, ao2_cleanup, app_sendfax, 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, ast_fax_session_details::caps, check_modem_rate(), ast_fax_session_details::debug, disable_t38(), ast_fax_session_details::documents, error(), fax_exec_options, fax_session_release(), fax_session_reserve(), faxregistry, ast_fax_document::filename, find_or_create_details(), ast_fax_session_details::gateway_id, generate_filenames_string(), generic_fax_exec(), global_fax_debug, LOG_ERROR, LOG_WARNING, ast_fax_session_details::maxrate, ast_fax_session_details::minrate, ast_fax_session_details::modems, NULL, OPT_ALLOWAUDIO, OPT_CALLEDMODE, OPT_CALLERMODE, OPT_DEBUG, OPT_FORCE_AUDIO, OPT_REQUEST_T38, OPT_STATUS, ast_fax_session_details::option, options, parse(), pbx_builtin_setvar_helper(), RAII_VAR, report_send_fax_status(), ast_fax_session_details::request_t38, result, ast_fax_session_details::send_cng, sendfax_t38_init(), set_channel_variables(), set_fax_t38_caps(), ast_fax_session_details::statusevents, strsep(), T38_STATE_NEGOTIATED, T38_STATE_REJECTED, and T38_STATE_UNAVAILABLE.

Referenced by load_module().

2591 {
2592  char *parse, *filenames, *c, modems[128] = "";
2593  int channel_alive, file_count;
2594  RAII_VAR(struct ast_fax_session_details *, details, NULL, ao2_cleanup);
2595  RAII_VAR(struct ast_fax_session *, s, NULL, ao2_cleanup);
2596  struct ast_fax_tech_token *token = NULL;
2597  struct ast_fax_document *doc;
2599  AST_APP_ARG(filenames);
2601  );
2602  struct ast_flags opts = { 0, };
2603  enum ast_t38_state t38state;
2604 
2605  /* initialize output channel variables */
2606  pbx_builtin_setvar_helper(chan, "FAXSTATUS", "FAILED");
2607  pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", NULL);
2608  pbx_builtin_setvar_helper(chan, "FAXPAGES", "0");
2609  pbx_builtin_setvar_helper(chan, "FAXBITRATE", NULL);
2610  pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", NULL);
2611  pbx_builtin_setvar_helper(chan, "FAXMODE", NULL);
2612 
2613  /* Get a requirement structure and set it. This structure is used
2614  * to tell the FAX technology module about the higher level FAX session */
2615  if (!(details = find_or_create_details(chan))) {
2616  pbx_builtin_setvar_helper(chan, "FAXERROR", "MEMORY_ERROR");
2617  pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "error allocating memory");
2618  ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
2619  return -1;
2620  }
2621 
2622  ast_string_field_set(details, result, "FAILED");
2623  ast_string_field_set(details, resultstr, "error starting fax session");
2624  ast_string_field_set(details, error, "INIT_ERROR");
2625  set_channel_variables(chan, details);
2626 
2627  if (details->gateway_id > 0) {
2628  ast_string_field_set(details, resultstr, "can't send a fax on a channel with a T.38 gateway");
2629  set_channel_variables(chan, details);
2630  ast_log(LOG_ERROR, "executing SendFAX on a channel with a T.38 Gateway is not supported\n");
2631  return -1;
2632  }
2633 
2634  if (details->maxrate < details->minrate) {
2635  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2636  ast_string_field_set(details, resultstr, "maxrate is less than minrate");
2637  set_channel_variables(chan, details);
2638  ast_log(LOG_ERROR, "maxrate %u is less than minrate %u\n", details->maxrate, details->minrate);
2639  return -1;
2640  }
2641 
2642  if (check_modem_rate(details->modems, details->minrate)) {
2643  ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
2644  ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %u\n", modems, details->minrate);
2645  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2646  ast_string_field_set(details, resultstr, "incompatible 'modems' and 'minrate' settings");
2647  set_channel_variables(chan, details);
2648  return -1;
2649  }
2650 
2651  if (check_modem_rate(details->modems, details->maxrate)) {
2652  ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
2653  ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %u\n", modems, details->maxrate);
2654  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2655  ast_string_field_set(details, resultstr, "incompatible 'modems' and 'maxrate' settings");
2656  set_channel_variables(chan, details);
2657  return -1;
2658  }
2659 
2660  if (ast_strlen_zero(data)) {
2661  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2662  ast_string_field_set(details, resultstr, "invalid arguments");
2663  set_channel_variables(chan, details);
2664  ast_log(LOG_WARNING, "%s requires an argument (filename[&filename[&filename]][,options])\n", app_sendfax);
2665  return -1;
2666  }
2667  parse = ast_strdupa(data);
2668  AST_STANDARD_APP_ARGS(args, parse);
2669 
2670 
2671  if (!ast_strlen_zero(args.options) &&
2672  ast_app_parse_options(fax_exec_options, &opts, NULL, args.options)) {
2673  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2674  ast_string_field_set(details, resultstr, "invalid arguments");
2675  set_channel_variables(chan, details);
2676  return -1;
2677  }
2678  if (ast_strlen_zero(args.filenames)) {
2679  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2680  ast_string_field_set(details, resultstr, "invalid arguments");
2681  set_channel_variables(chan, details);
2682  ast_log(LOG_WARNING, "%s requires an argument (filename[&filename[&filename]],options])\n", app_sendfax);
2683  return -1;
2684  }
2685 
2686  /* check for unsupported FAX application options */
2687  if (ast_test_flag(&opts, OPT_CALLERMODE) || ast_test_flag(&opts, OPT_CALLEDMODE)) {
2688  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2689  ast_string_field_set(details, resultstr, "invalid arguments");
2690  set_channel_variables(chan, details);
2691  ast_log(LOG_WARNING, "%s does not support polling\n", app_sendfax);
2692  return -1;
2693  }
2694 
2695  ast_atomic_fetchadd_int(&faxregistry.fax_tx_attempts, 1);
2696 
2697  file_count = 0;
2698  filenames = args.filenames;
2699  while ((c = strsep(&filenames, "&"))) {
2700  if (access(c, (F_OK | R_OK)) < 0) {
2701  ast_string_field_set(details, error, "FILE_ERROR");
2702  ast_string_field_set(details, resultstr, "error reading file");
2703  set_channel_variables(chan, details);
2704  ast_log(LOG_ERROR, "access failure. Verify '%s' exists and check permissions.\n", args.filenames);
2705  return -1;
2706  }
2707 
2708  if (!(doc = ast_calloc(1, sizeof(*doc) + strlen(c) + 1))) {
2709  ast_string_field_set(details, error, "MEMORY_ERROR");
2710  ast_string_field_set(details, resultstr, "error allocating memory");
2711  set_channel_variables(chan, details);
2712  ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
2713  return -1;
2714  }
2715 
2716  strcpy(doc->filename, c);
2717  AST_LIST_INSERT_TAIL(&details->documents, doc, next);
2718  file_count++;
2719  }
2720 
2721  ast_verb(3, "Channel '%s' sending FAX:\n", ast_channel_name(chan));
2722  AST_LIST_TRAVERSE(&details->documents, doc, next) {
2723  ast_verb(3, " %s\n", doc->filename);
2724  }
2725 
2726  details->caps = AST_FAX_TECH_SEND;
2727 
2728  if (file_count > 1) {
2729  details->caps |= AST_FAX_TECH_MULTI_DOC;
2730  }
2731 
2732  /* check for debug */
2733  if (ast_test_flag(&opts, OPT_DEBUG) || global_fax_debug) {
2734  details->option.debug = AST_FAX_OPTFLAG_TRUE;
2735  }
2736 
2737  /* check for request for status events */
2738  if (ast_test_flag(&opts, OPT_STATUS)) {
2739  details->option.statusevents = AST_FAX_OPTFLAG_TRUE;
2740  }
2741 
2742  t38state = ast_channel_get_t38_state(chan);
2743  if ((t38state == T38_STATE_UNAVAILABLE) || (t38state == T38_STATE_REJECTED) ||
2744  ast_test_flag(&opts, OPT_ALLOWAUDIO) ||
2745  ast_test_flag(&opts, OPT_FORCE_AUDIO)) {
2746  details->option.allow_audio = AST_FAX_OPTFLAG_TRUE;
2747  }
2748 
2749  if (ast_test_flag(&opts, OPT_REQUEST_T38)) {
2750  details->option.request_t38 = AST_FAX_OPTFLAG_TRUE;
2751  }
2752 
2753  if (!(s = fax_session_reserve(details, &token))) {
2754  ast_string_field_set(details, resultstr, "error reserving fax session");
2755  set_channel_variables(chan, details);
2756  ast_log(LOG_ERROR, "Unable to reserve FAX session.\n");
2757  return -1;
2758  }
2759 
2760  /* make sure the channel is up */
2761  if (ast_channel_state(chan) != AST_STATE_UP) {
2762  if (ast_answer(chan)) {
2763  ast_string_field_set(details, resultstr, "error answering channel");
2764  set_channel_variables(chan, details);
2765  ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", ast_channel_name(chan));
2766  fax_session_release(s, token);
2767  return -1;
2768  }
2769  }
2770 
2771  if (!ast_test_flag(&opts, OPT_FORCE_AUDIO)) {
2772  if (set_fax_t38_caps(chan, details)) {
2773  ast_string_field_set(details, error, "T38_NEG_ERROR");
2774  ast_string_field_set(details, resultstr, "error negotiating T.38");
2775  set_channel_variables(chan, details);
2776  fax_session_release(s, token);
2777  return -1;
2778  }
2779  } else {
2780  details->caps |= AST_FAX_TECH_AUDIO;
2781  }
2782 
2783  if (!ast_test_flag(&opts, OPT_FORCE_AUDIO) && (details->caps & AST_FAX_TECH_T38)) {
2784  if (sendfax_t38_init(chan, details)) {
2785  ast_string_field_set(details, error, "T38_NEG_ERROR");
2786  ast_string_field_set(details, resultstr, "error negotiating T.38");
2787  set_channel_variables(chan, details);
2788  fax_session_release(s, token);
2789  ast_log(LOG_ERROR, "error initializing channel '%s' in T.38 mode\n", ast_channel_name(chan));
2790  return -1;
2791  }
2792  } else {
2793  details->option.send_cng = 1;
2794  }
2795 
2796  if ((channel_alive = generic_fax_exec(chan, details, s, token)) < 0) {
2797  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
2798  }
2799 
2801  if (disable_t38(chan)) {
2802  ast_debug(1, "error disabling T.38 mode on %s\n", ast_channel_name(chan));
2803  }
2804  }
2805 
2806  if (!(filenames = generate_filenames_string(details, "FileName: ", "\r\n"))) {
2807  ast_log(LOG_ERROR, "Error generating SendFAX manager event\n");
2808  return (!channel_alive) ? -1 : 0;
2809  }
2810 
2811  /* send out the AMI completion event */
2812  if (report_send_fax_status(chan, details)) {
2813  ast_log(AST_LOG_ERROR, "Error publishing SendFAX status message\n");
2814  }
2815 
2816  /* If the channel hungup return -1; otherwise, return 0 to continue in the dialplan */
2817  return (!channel_alive) ? -1 : 0;
2818 }
static enum ast_t38_state ast_channel_get_t38_state(struct ast_channel *chan)
Retrieves the current T38 state of a channel.
Definition: channel.h:2873
static const struct ast_app_option fax_exec_options[128]
Definition: res_fax.c:575
#define ast_test_flag(p, flag)
Definition: utils.h:63
static const char app_sendfax[]
Definition: res_fax.c:429
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
Definition: res_fax.c:1590
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
#define LOG_WARNING
Definition: logger.h:274
ast_channel_state
ast_channel states
Definition: channelstate.h:35
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.
Definition: res_fax.c:2527
ast_t38_state
Possible T38 states on channels.
Definition: channel.h:879
static struct test_val c
t38state
T38 States for a call.
Definition: sip.h:665
const char * args
#define NULL
Definition: resample.c:96
#define ast_verb(level,...)
Definition: logger.h:463
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:755
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define AST_LOG_ERROR
Definition: logger.h:290
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
static int disable_t38(struct ast_channel *chan)
Definition: res_fax.c:1527
static int check_modem_rate(enum ast_fax_modems modems, unsigned int rate)
Definition: res_fax.c:938
char filename[0]
Definition: res_fax.h:104
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
The data communicated between the high level applications and the generic fax function.
Definition: res_fax.h:110
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: main/app.c:2906
static int set_fax_t38_caps(struct ast_channel *chan, struct ast_fax_session_details *details)
Definition: res_fax.c:1491
static struct ast_fax_session_details * find_or_create_details(struct ast_channel *chan)
returns a reference counted details structure from the channel&#39;s fax datastore. If the datastore does...
Definition: res_fax.c:764
#define LOG_ERROR
Definition: logger.h:285
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
static void fax_session_release(struct ast_fax_session *s, struct ast_fax_tech_token *token)
Release a session token.
Definition: res_fax.c:1083
static void set_channel_variables(struct ast_channel *chan, struct ast_fax_session_details *details)
Set fax related channel variables.
Definition: res_fax.c:1447
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
static int global_fax_debug
Definition: res_fax.c:555
Structure used to handle boolean flags.
Definition: utils.h:199
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
static struct ast_fax_session * fax_session_reserve(struct ast_fax_session_details *details, struct ast_fax_tech_token **token)
Reserve a fax session.
Definition: res_fax.c:1146
char * strsep(char **str, const char *delims)
static struct @460 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
const char * ast_channel_name(const struct ast_channel *chan)
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2814
static PGresult * result
Definition: cel_pgsql.c:88
The data required to handle a fax session.
Definition: res_fax.h:202
int error(const char *format,...)
Definition: utils/frame.c:999
static int ast_fax_modem_to_str(enum ast_fax_modems bits, char *tbuf, size_t bufsize)
Definition: res_fax.c:905
static struct test_options options
static int sendfax_t38_init(struct ast_channel *chan, struct ast_fax_session_details *details)
Definition: res_fax.c:2283
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
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.
Definition: res_fax.c:1370
#define AST_APP_ARG(name)
Define an application argument.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ sendfax_t38_init()

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

Definition at line 2283 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().

2284 {
2285  int timeout_ms;
2286  struct ast_frame *frame = NULL;
2287  struct ast_control_t38_parameters t38_parameters;
2288  struct timeval start;
2289  int ms;
2290 
2291  /* send CNG tone while listening for the receiver to initiate a switch
2292  * to T.38 mode; if they do, stop sending the CNG tone and proceed with
2293  * the switch.
2294  *
2295  * 10500 is enough time for 3 CNG tones
2296  */
2297  timeout_ms = 10500;
2298 
2299  /* don't send any audio if we've already received a T.38 reinvite */
2301  if (ast_playtones_start(chan, 1024, "!1100/500,!0/3000,!1100/500,!0/3000,!1100/500,!0/3000", 1)) {
2302  ast_log(LOG_ERROR, "error generating CNG tone on %s\n", ast_channel_name(chan));
2303  return -1;
2304  }
2305  }
2306 
2307  start = ast_tvnow();
2308  while ((ms = ast_remaining_ms(start, timeout_ms))) {
2309  int break_loop = 0;
2310  ms = ast_waitfor(chan, ms);
2311 
2312  if (ms < 0) {
2313  ast_log(LOG_ERROR, "error while generating CNG tone on %s\n", ast_channel_name(chan));
2314  ast_playtones_stop(chan);
2315  return -1;
2316  }
2317 
2318  if (ms == 0) { /* all done, nothing happened */
2319  break;
2320  }
2321 
2322  if (!(frame = ast_read(chan))) {
2323  ast_log(LOG_ERROR, "error reading frame while generating CNG tone on %s\n", ast_channel_name(chan));
2324  ast_playtones_stop(chan);
2325  return -1;
2326  }
2327 
2328  if ((frame->frametype == AST_FRAME_CONTROL) &&
2330  (frame->datalen == sizeof(t38_parameters))) {
2331  struct ast_control_t38_parameters *parameters = frame->data.ptr;
2332 
2333  switch (parameters->request_response) {
2335  /* the other end has requested a switch to T.38, so reply that we are willing, if we can
2336  * do T.38 as well
2337  */
2338  t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
2339  t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
2340  ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
2341  ast_playtones_stop(chan);
2342  break;
2343  case AST_T38_NEGOTIATED:
2344  ast_debug(1, "Negotiated T.38 for send on %s\n", ast_channel_name(chan));
2345  t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
2346  details->caps &= ~AST_FAX_TECH_AUDIO;
2347  report_fax_status(chan, details, "T.38 Negotiated");
2348  break_loop = 1;
2349  break;
2350  default:
2351  break;
2352  }
2353  }
2354  ast_frfree(frame);
2355  if (break_loop) {
2356  break;
2357  }
2358  }
2359 
2360  ast_playtones_stop(chan);
2361 
2363  return 0;
2364  }
2365 
2366  /* T.38 negotiation did not happen, initiate a switch if requested */
2367  if (details->option.request_t38 == AST_FAX_OPTFLAG_TRUE) {
2368  ast_debug(1, "Negotiating T.38 for send on %s\n", ast_channel_name(chan));
2369 
2370  /* wait up to five seconds for negotiation to complete */
2371  timeout_ms = 5000;
2372 
2373  /* set parameters based on the session's parameters */
2374  t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
2375  t38_parameters.request_response = AST_T38_REQUEST_NEGOTIATE;
2376  if ((ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0)) {
2377  return -1;
2378  }
2379 
2380  start = ast_tvnow();
2381  while ((ms = ast_remaining_ms(start, timeout_ms))) {
2382  int break_loop = 0;
2383 
2384  ms = ast_waitfor(chan, ms);
2385  if (ms < 0) {
2386  ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", ast_channel_name(chan));
2387  return -1;
2388  }
2389  if (ms == 0) { /* all done, nothing happened */
2390  ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 negotiation.\n", ast_channel_name(chan));
2391  details->caps &= ~AST_FAX_TECH_T38;
2392  break;
2393  }
2394 
2395  if (!(frame = ast_read(chan))) {
2396  ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", ast_channel_name(chan));
2397  return -1;
2398  }
2399 
2400  if ((frame->frametype == AST_FRAME_CONTROL) &&
2402  (frame->datalen == sizeof(t38_parameters))) {
2403  struct ast_control_t38_parameters *parameters = frame->data.ptr;
2404 
2405  switch (parameters->request_response) {
2407  t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
2408  t38_parameters.request_response = AST_T38_NEGOTIATED;
2409  ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
2410  break;
2411  case AST_T38_NEGOTIATED:
2412  ast_debug(1, "Negotiated T.38 for receive on %s\n", ast_channel_name(chan));
2413  t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
2414  details->caps &= ~AST_FAX_TECH_AUDIO;
2415  report_fax_status(chan, details, "T.38 Negotiated");
2416  break_loop = 1;
2417  break;
2418  case AST_T38_REFUSED:
2419  ast_log(LOG_WARNING, "channel '%s' refused to negotiate T.38\n", ast_channel_name(chan));
2420  details->caps &= ~AST_FAX_TECH_T38;
2421  break_loop = 1;
2422  break;
2423  default:
2424  ast_log(LOG_ERROR, "channel '%s' failed to negotiate T.38\n", ast_channel_name(chan));
2425  details->caps &= ~AST_FAX_TECH_T38;
2426  break_loop = 1;
2427  break;
2428  }
2429  }
2430  ast_frfree(frame);
2431  if (break_loop) {
2432  break;
2433  }
2434  }
2435 
2436  /* if T.38 was negotiated, we are done initializing */
2438  return 0;
2439  }
2440 
2441  /* send one more CNG tone to get audio going again for some
2442  * carriers if we are going to fall back to audio mode */
2443  if (details->option.allow_audio == AST_FAX_OPTFLAG_TRUE) {
2444  if (ast_playtones_start(chan, 1024, "!1100/500,!0/3000", 1)) {
2445  ast_log(LOG_ERROR, "error generating second CNG tone on %s\n", ast_channel_name(chan));
2446  return -1;
2447  }
2448 
2449  timeout_ms = 3500;
2450  start = ast_tvnow();
2451  while ((ms = ast_remaining_ms(start, timeout_ms))) {
2452  int break_loop = 0;
2453 
2454  ms = ast_waitfor(chan, ms);
2455  if (ms < 0) {
2456  ast_log(LOG_ERROR, "error while generating second CNG tone on %s\n", ast_channel_name(chan));
2457  ast_playtones_stop(chan);
2458  return -1;
2459  }
2460  if (ms == 0) { /* all done, nothing happened */
2461  break;
2462  }
2463 
2464  if (!(frame = ast_read(chan))) {
2465  ast_log(LOG_ERROR, "error reading frame while generating second CNG tone on %s\n", ast_channel_name(chan));
2466  ast_playtones_stop(chan);
2467  return -1;
2468  }
2469 
2470  if ((frame->frametype == AST_FRAME_CONTROL) &&
2472  (frame->datalen == sizeof(t38_parameters))) {
2473  struct ast_control_t38_parameters *parameters = frame->data.ptr;
2474 
2475  switch (parameters->request_response) {
2477  /* the other end has requested a switch to T.38, so reply that we are willing, if we can
2478  * do T.38 as well
2479  */
2480  t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
2481  t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
2482  ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
2483  ast_playtones_stop(chan);
2484  break;
2485  case AST_T38_NEGOTIATED:
2486  ast_debug(1, "Negotiated T.38 for send on %s\n", ast_channel_name(chan));
2487  t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
2488  details->caps &= ~AST_FAX_TECH_AUDIO;
2489  report_fax_status(chan, details, "T.38 Negotiated");
2490  break_loop = 1;
2491  break;
2492  default:
2493  break;
2494  }
2495  }
2496  ast_frfree(frame);
2497  if (break_loop) {
2498  break;
2499  }
2500  }
2501 
2502  ast_playtones_stop(chan);
2503 
2504  /* if T.38 was negotiated, we are done initializing */
2506  return 0;
2507  }
2508  }
2509  }
2510 
2511  /* if we made it here, then T.38 failed, check the 'f' flag */
2512  if (details->option.allow_audio == AST_FAX_OPTFLAG_FALSE) {
2513  ast_log(LOG_WARNING, "Audio FAX not allowed on channel '%s' and T.38 negotiation failed; aborting.\n", ast_channel_name(chan));
2514  return -1;
2515  }
2516 
2517  /* ok, audio fallback is allowed */
2518  details->caps |= AST_FAX_TECH_AUDIO;
2519 
2520  return 0;
2521 }
static enum ast_t38_state ast_channel_get_t38_state(struct ast_channel *chan)
Retrieves the current T38 state of a channel.
Definition: channel.h:2873
#define LOG_WARNING
Definition: logger.h:274
static void t38_parameters_ast_to_fax(struct ast_fax_t38_parameters *dst, const struct ast_control_t38_parameters *src)
Definition: res_fax.c:740
static void t38_parameters_fax_to_ast(struct ast_control_t38_parameters *dst, const struct ast_fax_t38_parameters *src)
Definition: res_fax.c:751
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4302
enum ast_control_t38 request_response
int ast_indicate_data(struct ast_channel *chan, int condition, const void *data, size_t datalen)
Indicates condition of channel, with payload.
Definition: channel.c:4698
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
void ast_playtones_stop(struct ast_channel *chan)
Stop playing tones on a channel.
Definition: indications.c:393
#define NULL
Definition: resample.c:96
struct ast_frame_subclass subclass
union ast_fax_session_details::@290 option
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
struct ast_fax_t38_parameters our_t38_parameters
Definition: res_fax.h:175
#define LOG_ERROR
Definition: logger.h:285
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
Definition: main/utils.c:2033
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3171
const char * ast_channel_name(const struct ast_channel *chan)
static int report_fax_status(struct ast_channel *chan, struct ast_fax_session_details *details, const char *status)
send a FAX status manager event
Definition: res_fax.c:1407
#define ast_frfree(fr)
Data structure associated with a single frame of data.
enum ast_fax_capabilities caps
Definition: res_fax.h:113
int ast_playtones_start(struct ast_channel *chan, int vol, const char *tonelist, int interruptible)
Start playing a list of tones on a channel.
Definition: indications.c:302
union ast_frame::@263 data
enum ast_frame_type frametype
struct ast_fax_t38_parameters their_t38_parameters
Definition: res_fax.h:177

◆ session_cmp_cb()

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

compare callback for ao2

Definition at line 3935 of file res_fax.c.

References CMP_MATCH, CMP_STOP, and ast_fax_session::id.

Referenced by load_module().

3936 {
3937  struct ast_fax_session *lhs = obj, *rhs = arg;
3938 
3939  return (lhs->id == rhs->id) ? CMP_MATCH | CMP_STOP : 0;
3940 }
unsigned int id
Definition: res_fax.h:204
The data required to handle a fax session.
Definition: res_fax.h:202

◆ session_details_new()

static struct ast_fax_session_details* session_details_new ( void  )
static

create a FAX session details structure

Definition at line 696 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, ast_fax_session_details::ecm, fax_options::ecm, ast_fax_session_details::faxdetect_id, ast_fax_session_details::gateway_id, ast_fax_session_details::gateway_timeout, get_general_options(), ast_fax_session_details::maxrate, fax_options::maxrate, ast_fax_session_details::minrate, fax_options::minrate, ast_fax_session_details::modems, fax_options::modems, ast_fax_session_details::negotiate_both, NULL, ast_fax_session_details::option, ast_fax_session_details::request_t38, ast_fax_session_details::send_ced, ast_fax_session_details::send_cng, ast_fax_session_details::statusevents, fax_options::statusevents, ast_fax_session_details::t38timeout, and fax_options::t38timeout.

Referenced by fax_v21_session_new(), and find_or_create_details().

697 {
698  struct ast_fax_session_details *d;
699  struct fax_options options;
700 
701  if (!(d = ao2_alloc(sizeof(*d), destroy_session_details))) {
702  return NULL;
703  }
704 
705  if (ast_string_field_init(d, 512)) {
706  ao2_ref(d, -1);
707  return NULL;
708  }
709 
711 
713 
714  /* These options need to be set to the configured default and may be overridden by
715  * SendFAX, ReceiveFAX, or FAXOPT */
719  d->option.ecm = options.ecm;
720  d->option.statusevents = options.statusevents;
721  d->modems = options.modems;
722  d->minrate = options.minrate;
723  d->maxrate = options.maxrate;
724  d->t38timeout = options.t38timeout;
725  d->gateway_id = -1;
726  d->faxdetect_id = -1;
727  d->gateway_timeout = 0;
728  d->negotiate_both = 0;
729 
730  return d;
731 }
unsigned int t38timeout
Definition: res_fax.h:179
static void destroy_session_details(void *details)
destroy a FAX session details structure
Definition: res_fax.c:684
static struct test_val d
#define NULL
Definition: resample.c:96
union ast_fax_session_details::@290 option
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
#define ao2_ref(o, delta)
Definition: astobj2.h:464
The data communicated between the high level applications and the generic fax function.
Definition: res_fax.h:110
struct ast_fax_documents documents
Definition: res_fax.h:119
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
unsigned int minrate
Definition: res_fax.h:171
enum ast_fax_modems modems
Definition: res_fax.h:115
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:680
unsigned int maxrate
Definition: res_fax.h:173
static struct test_options options
static void get_general_options(struct fax_options *options)
Definition: res_fax.c:4397

◆ session_hash_cb()

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

hash callback for ao2

Definition at line 3927 of file res_fax.c.

References ast_fax_session::id.

Referenced by load_module().

3928 {
3929  const struct ast_fax_session *s = obj;
3930 
3931  return s->id;
3932 }
unsigned int id
Definition: res_fax.h:204
The data required to handle a fax session.
Definition: res_fax.h:202

◆ set_channel_variables()

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 AST_JSON_UTF8_VALIDATE, buf, ast_fax_session_details::error, ast_fax_session_details::is_t38_negotiated, 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().

1448 {
1449  char buf[10];
1450 
1451  pbx_builtin_setvar_helper(chan, "FAXSTATUS", S_OR(details->result, NULL));
1452  pbx_builtin_setvar_helper(chan, "FAXERROR", S_OR(details->error, NULL));
1453  pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", S_OR(details->resultstr, NULL));
1454  pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", AST_JSON_UTF8_VALIDATE(details->remotestationid));
1455  pbx_builtin_setvar_helper(chan, "LOCALSTATIONID", AST_JSON_UTF8_VALIDATE(details->localstationid));
1456  pbx_builtin_setvar_helper(chan, "FAXBITRATE", S_OR(details->transfer_rate, NULL));
1457  pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", S_OR(details->resolution, NULL));
1458 
1459  if (details->is_t38_negotiated) {
1460  pbx_builtin_setvar_helper(chan, "FAXMODE", "T38");
1461  } else {
1462  pbx_builtin_setvar_helper(chan, "FAXMODE", "audio");
1463  }
1464 
1465  snprintf(buf, sizeof(buf), "%u", details->pages_transferred);
1466  pbx_builtin_setvar_helper(chan, "FAXPAGES", buf);
1467 }
const ast_string_field result
Definition: res_fax.h:142
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
const ast_string_field transfer_rate
Definition: res_fax.h:142
#define NULL
Definition: resample.c:96
const ast_string_field remotestationid
Definition: res_fax.h:142
unsigned int pages_transferred
Definition: res_fax.h:144
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
const ast_string_field resultstr
Definition: res_fax.h:142
const ast_string_field localstationid
Definition: res_fax.h:142
const ast_string_field error
Definition: res_fax.h:142
#define AST_JSON_UTF8_VALIDATE(str)
Check str for UTF-8 and replace with an empty string if fails the check.
Definition: json.h:224
const ast_string_field resolution
Definition: res_fax.h:142

◆ set_config()

static int set_config ( int  reload)
static

configure res_fax

Definition at line 4422 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.

Referenced by load_module(), and reload_module().

4423 {
4424  struct ast_config *cfg;
4425  struct ast_variable *v;
4426  struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
4427  char modems[128] = "";
4428  struct fax_options options;
4429  int res = 0;
4430 
4432 
4433  /* When we're not reloading, we have to be certain to set the general options
4434  * to the defaults in case config loading goes wrong at some point. On a reload,
4435  * the general options need to stay the same as what they were prior to the
4436  * reload rather than being reset to the defaults.
4437  */
4438  if (!reload) {
4440  }
4441 
4442  /* read configuration */
4443  if (!(cfg = ast_config_load2(config, "res_fax", config_flags))) {
4444  ast_log(LOG_NOTICE, "Configuration file '%s' not found, %s options.\n",
4445  config, reload ? "not changing" : "using default");
4446  return 0;
4447  }
4448 
4449  if (cfg == CONFIG_STATUS_FILEINVALID) {
4450  ast_log(LOG_NOTICE, "Configuration file '%s' is invalid, %s options.\n",
4451  config, reload ? "not changing" : "using default");
4452  return 0;
4453  }
4454 
4455  if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
4456  return 0;
4457  }
4458 
4459  if (reload) {
4461  }
4462 
4463  /* create configuration */
4464  for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
4465  int rate;
4466 
4467  if (!strcasecmp(v->name, "minrate")) {
4468  ast_debug(3, "reading minrate '%s' from configuration file\n", v->value);
4469  if ((rate = fax_rate_str_to_int(v->value)) == 0) {
4470  res = -1;
4471  goto end;
4472  }
4473  options.minrate = rate;
4474  } else if (!strcasecmp(v->name, "maxrate")) {
4475  ast_debug(3, "reading maxrate '%s' from configuration file\n", v->value);
4476  if ((rate = fax_rate_str_to_int(v->value)) == 0) {
4477  res = -1;
4478  goto end;
4479  }
4480  options.maxrate = rate;
4481  } else if (!strcasecmp(v->name, "statusevents")) {
4482  ast_debug(3, "reading statusevents '%s' from configuration file\n", v->value);
4483  options.statusevents = ast_true(v->value);
4484  } else if (!strcasecmp(v->name, "ecm")) {
4485  ast_debug(3, "reading ecm '%s' from configuration file\n", v->value);
4486  options.ecm = ast_true(v->value);
4487  } else if ((!strcasecmp(v->name, "modem")) || (!strcasecmp(v->name, "modems"))) {
4488  options.modems = 0;
4489  update_modem_bits(&options.modems, v->value);
4490  } else if (!strcasecmp(v->name, "t38timeout")) {
4491  if (set_t38timeout(v->value, &options.t38timeout)) {
4492  res = -1;
4493  goto end;
4494  }
4495  }
4496  }
4497 
4498  if (options.maxrate < options.minrate) {
4499  ast_log(LOG_ERROR, "maxrate %u is less than minrate %u\n", options.maxrate, options.minrate);
4500  res = -1;
4501  goto end;
4502  }
4503 
4504  if (check_modem_rate(options.modems, options.minrate)) {
4505  ast_fax_modem_to_str(options.modems, modems, sizeof(modems));
4506  ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %u\n", modems, options.minrate);
4507  res = -1;
4508  goto end;
4509  }
4510 
4511  if (check_modem_rate(options.modems, options.maxrate)) {
4512  ast_fax_modem_to_str(options.modems, modems, sizeof(modems));
4513  ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %u\n", modems, options.maxrate);
4514  res = -1;
4515  goto end;
4516  }
4517 
4519 
4520 end:
4521  ast_config_destroy(cfg);
4522  return res;
4523 }
struct ast_variable * next
static unsigned int fax_rate_str_to_int(const char *ratestr)
convert a rate string to a rate
Definition: res_fax.c:1046
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1216
#define CONFIG_STATUS_FILEINVALID
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
Definition: main/config.c:3154
Structure for variables, used for configurations and for channel variables.
char * end
Definition: eagi_proxy.c:73
static int update_modem_bits(enum ast_fax_modems *bits, const char *value)
Definition: res_fax.c:812
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
static int check_modem_rate(enum ast_fax_modems modems, unsigned int rate)
Definition: res_fax.c:938
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
#define CONFIG_STATUS_FILEUNCHANGED
#define LOG_ERROR
Definition: logger.h:285
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: main/utils.c:1951
#define LOG_NOTICE
Definition: logger.h:263
static int reload(void)
Definition: cdr_mysql.c:741
static int set_t38timeout(const char *value, unsigned int *t38timeout)
Definition: res_fax.c:4404
Structure used to handle boolean flags.
Definition: utils.h:199
static const char * config
Definition: res_fax.c:553
static void set_general_options(const struct fax_options *options)
Definition: res_fax.c:4390
static int ast_fax_modem_to_str(enum ast_fax_modems bits, char *tbuf, size_t bufsize)
Definition: res_fax.c:905
static struct test_options options
static const struct fax_options default_options
Definition: res_fax.c:539

◆ set_fax_t38_caps()

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

Definition at line 1491 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().

1492 {
1493  switch (ast_channel_get_t38_state(chan)) {
1494  case T38_STATE_UNKNOWN:
1495  details->caps |= AST_FAX_TECH_T38;
1496  break;
1497  case T38_STATE_REJECTED:
1498  case T38_STATE_UNAVAILABLE:
1499  details->caps |= AST_FAX_TECH_AUDIO;
1500  break;
1501  case T38_STATE_NEGOTIATED:
1502  /* already in T.38 mode? This should not happen. */
1503  case T38_STATE_NEGOTIATING: {
1504  /* the other end already sent us a T.38 reinvite, so we need to prod the channel
1505  * driver into resending their parameters to us if it supports doing so... if
1506  * not, we can't proceed, because we can't create a proper reply without them.
1507  * if it does work, the channel driver will send an AST_CONTROL_T38_PARAMETERS
1508  * with a request of AST_T38_REQUEST_NEGOTIATE, which will be read by the function
1509  * that gets called after this one completes
1510  */
1512  if (ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &parameters, sizeof(parameters)) != AST_T38_REQUEST_PARMS) {
1513  ast_log(LOG_ERROR, "channel '%s' is in an unsupported T.38 negotiation state, cannot continue.\n", ast_channel_name(chan));
1514  return -1;
1515  }
1516  details->caps |= AST_FAX_TECH_T38;
1517  break;
1518  }
1519  default:
1520  ast_log(LOG_ERROR, "channel '%s' is in an unsupported T.38 negotiation state, cannot continue.\n", ast_channel_name(chan));
1521  return -1;
1522  }
1523 
1524  return 0;
1525 }
static enum ast_t38_state ast_channel_get_t38_state(struct ast_channel *chan)
Retrieves the current T38 state of a channel.
Definition: channel.h:2873
enum ast_control_t38 request_response
int ast_indicate_data(struct ast_channel *chan, int condition, const void *data, size_t datalen)
Indicates condition of channel, with payload.
Definition: channel.c:4698
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
const char * ast_channel_name(const struct ast_channel *chan)
enum ast_fax_capabilities caps
Definition: res_fax.h:113

◆ set_general_options()

static void set_general_options ( const struct fax_options options)
static

Definition at line 4390 of file res_fax.c.

References ast_rwlock_unlock, ast_rwlock_wrlock, general_options, options, and options_lock.

Referenced by set_config().

4391 {
4395 }
static ast_rwlock_t options_lock
Definition: res_fax.c:548
#define ast_rwlock_unlock(a)
Definition: lock.h:232
#define ast_rwlock_wrlock(a)
Definition: lock.h:234
static struct fax_options general_options
Definition: res_fax.c:537
static struct test_options options

◆ set_t38timeout()

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

Definition at line 4404 of file res_fax.c.

References ast_log, LOG_ERROR, and timeout.

Referenced by acf_faxopt_write(), and set_config().

4405 {
4406  unsigned int timeout;
4407 
4408  if (sscanf(value, "%u", &timeout) != 1) {
4409  ast_log(LOG_ERROR, "Unable to get timeout from '%s'\n", value);
4410  return -1;
4411  } else if (timeout) {
4412  *t38timeout = timeout;
4413  } else {
4414  ast_log(LOG_ERROR, "T.38 negotiation timeout must be non-zero\n");
4415  return -1;
4416  }
4417 
4418  return 0;
4419 }
static int timeout
Definition: cdr_mysql.c:86
int value
Definition: syslog.c:37
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285

◆ t38_parameters_ast_to_fax()

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

Definition at line 740 of file res_fax.c.

References ast_fax_t38_parameters::fill_bit_removal, ast_control_t38_parameters::fill_bit_removal, ast_fax_t38_parameters::max_ifp, ast_control_t38_parameters::max_ifp, ast_fax_t38_parameters::rate, ast_control_t38_parameters::rate, ast_fax_t38_parameters::rate_management, ast_control_t38_parameters::rate_management, ast_fax_t38_parameters::transcoding_jbig, ast_control_t38_parameters::transcoding_jbig, ast_fax_t38_parameters::transcoding_mmr, ast_control_t38_parameters::transcoding_mmr, ast_fax_t38_parameters::version, and ast_control_t38_parameters::version.

Referenced by fax_gateway_detect_t38(), find_or_create_details(), generic_fax_exec(), receivefax_t38_init(), and sendfax_t38_init().

741 {
742  dst->version = src->version;
743  dst->max_ifp = src->max_ifp;
744  dst->rate = src->rate;
745  dst->rate_management = src->rate_management;
747  dst->transcoding_mmr = src->transcoding_mmr;
749 }
enum ast_control_t38_rate rate
Definition: res_fax.h:95
enum ast_control_t38_rate rate
unsigned int transcoding_mmr
Definition: res_fax.h:98
unsigned int transcoding_jbig
Definition: res_fax.h:99
unsigned int max_ifp
Definition: res_fax.h:94
unsigned int version
Definition: res_fax.h:93
enum ast_control_t38_rate_management rate_management
enum ast_control_t38_rate_management rate_management
Definition: res_fax.h:96
unsigned int fill_bit_removal
Definition: res_fax.h:97

◆ t38_parameters_fax_to_ast()

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

Definition at line 751 of file res_fax.c.

References ast_fax_t38_parameters::fill_bit_removal, ast_control_t38_parameters::fill_bit_removal, ast_fax_t38_parameters::max_ifp, ast_control_t38_parameters::max_ifp, ast_fax_t38_parameters::rate, ast_control_t38_parameters::rate, ast_fax_t38_parameters::rate_management, ast_control_t38_parameters::rate_management, ast_fax_t38_parameters::transcoding_jbig, ast_control_t38_parameters::transcoding_jbig, ast_fax_t38_parameters::transcoding_mmr, ast_control_t38_parameters::transcoding_mmr, ast_fax_t38_parameters::version, and ast_control_t38_parameters::version.

Referenced by fax_gateway_detect_t38(), fax_gateway_request_t38(), generic_fax_exec(), receivefax_t38_init(), and sendfax_t38_init().

752 {
753  dst->version = src->version;
754  dst->max_ifp = src->max_ifp;
755  dst->rate = src->rate;
756  dst->rate_management = src->rate_management;
758  dst->transcoding_mmr = src->transcoding_mmr;
760 }
enum ast_control_t38_rate rate
Definition: res_fax.h:95
enum ast_control_t38_rate rate
unsigned int transcoding_mmr
Definition: res_fax.h:98
unsigned int transcoding_jbig
Definition: res_fax.h:99
unsigned int max_ifp
Definition: res_fax.h:94
unsigned int version
Definition: res_fax.h:93
enum ast_control_t38_rate_management rate_management
enum ast_control_t38_rate_management rate_management
Definition: res_fax.h:96
unsigned int fill_bit_removal
Definition: res_fax.h:97

◆ unload_module()

static int unload_module ( void  )
static

unload res_fax

Definition at line 4749 of file res_fax.c.

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

Referenced by reload_module().

4750 {
4752 
4754  ast_log(LOG_WARNING, "failed to unregister function '%s'\n", acf_faxopt.name);
4755  }
4756 
4758  ast_log(LOG_WARNING, "failed to unregister '%s'\n", app_sendfax);
4759  }
4760 
4762  ast_log(LOG_WARNING, "failed to unregister '%s'\n", app_receivefax);
4763  }
4764 
4765  ast_manager_unregister("FAXSessions");
4766  ast_manager_unregister("FAXSession");
4767  ast_manager_unregister("FAXStats");
4768 
4769  if (fax_logger_level != -1) {
4771  }
4772 
4773  ao2_ref(faxregistry.container, -1);
4774 
4775  return 0;
4776 }
const char * name
Definition: pbx.h:119
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
static const char app_sendfax[]
Definition: res_fax.c:429
#define LOG_WARNING
Definition: logger.h:274
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
void ast_logger_unregister_level(const char *name)
Unregister a previously registered logger level.
Definition: logger.c:2536
#define ast_log
Definition: astobj2.c:42
static const char app_receivefax[]
Definition: res_fax.c:428
#define ao2_ref(o, delta)
Definition: astobj2.h:464
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7258
static int fax_logger_level
Definition: res_fax.c:487
static struct @460 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.
static struct ast_cli_entry fax_cli[]
Definition: res_fax.c:4380
struct ast_custom_function acf_faxopt
FAXOPT dialplan function.
Definition: res_fax.c:4742

◆ update_modem_bits()

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

Definition at line 812 of file res_fax.c.

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

Referenced by acf_faxopt_write(), and set_config().

813 {
814  char *m[5], *tok, *v = (char *) value, *rest;
815  int i = 0, j;
816 
817  if (!strchr(v, ',')) {
818  m[i++] = v;
819  m[i] = NULL;
820  } else {
821  tok = strtok_r(v, ", ", &rest);
822  while (tok && i < ARRAY_LEN(m) - 1) {
823  m[i++] = tok;
824  tok = strtok_r(NULL, ", ", &rest);
825  }
826  m[i] = NULL;
827  }
828 
829  *bits = 0;
830  for (j = 0; j < i; j++) {
831  if (!strcasecmp(m[j], "v17")) {
832  *bits |= AST_FAX_MODEM_V17;
833  } else if (!strcasecmp(m[j], "v27")) {
834  *bits |= AST_FAX_MODEM_V27TER;
835  } else if (!strcasecmp(m[j], "v29")) {
836  *bits |= AST_FAX_MODEM_V29;
837  } else if (!strcasecmp(m[j], "v34")) {
838  *bits |= AST_FAX_MODEM_V34;
839  } else {
840  ast_log(LOG_WARNING, "ignoring invalid modem setting: '%s', valid options {v17 | v27 | v29 | v34}\n", m[j]);
841  }
842  }
843  return 0;
844 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
#define LOG_WARNING
Definition: logger.h:274
#define NULL
Definition: resample.c:96
int value
Definition: syslog.c:37
#define ast_log
Definition: astobj2.c:42

Variable Documentation

◆ __mod_info

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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .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 4867 of file res_fax.c.

◆ acf_faxopt

struct ast_custom_function acf_faxopt
Initial value:
= {
.name = "FAXOPT",
.read = acf_faxopt_read,
.write = acf_faxopt_write,
}
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.
Definition: res_fax.c:4601
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.
Definition: res_fax.c:4526

FAXOPT dialplan function.

Definition at line 4742 of file res_fax.c.

◆ active_sessions

int active_sessions

The number of active FAX sessions

Definition at line 498 of file res_fax.c.

◆ app_receivefax

const char app_receivefax[] = "ReceiveFAX"
static

Definition at line 428 of file res_fax.c.

Referenced by load_module(), receivefax_exec(), and unload_module().

◆ app_sendfax

const char app_sendfax[] = "SendFAX"
static

Definition at line 429 of file res_fax.c.

Referenced by load_module(), sendfax_exec(), and unload_module().

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 4867 of file res_fax.c.

◆ config

const char* config = "res_fax.conf"
static

Definition at line 553 of file res_fax.c.

Referenced by load_module(), and set_config().

◆ container

struct ao2_container* container

◆ default_options

const struct fax_options default_options
static

Definition at line 539 of file res_fax.c.

Referenced by set_config().

◆ fax_cli

struct ast_cli_entry fax_cli[]
static

Definition at line 4380 of file res_fax.c.

◆ fax_complete

int fax_complete

Number of successful FAX transmissions

Definition at line 508 of file res_fax.c.

◆ fax_datastore

const struct ast_datastore_info fax_datastore
static
Initial value:
= {
.type = "res_fax",
.destroy = destroy_callback,
.chan_fixup = fixup_callback,
}
static void fixup_callback(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
Copies fax detection and gateway framehooks during masquerades.
Definition: res_fax.c:636
static void destroy_callback(void *data)
Definition: res_fax.c:610

Definition at line 619 of file res_fax.c.

◆ fax_exec_options

const 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 575 of file res_fax.c.

Referenced by receivefax_exec(), and sendfax_exec().

◆ fax_failures

int fax_failures

Number of failed FAX transmissions

Definition at line 510 of file res_fax.c.

◆ fax_logger_level

int fax_logger_level = -1
static

Definition at line 487 of file res_fax.c.

Referenced by ast_fax_log(), load_module(), and unload_module().

◆ fax_rx_attempts

int fax_rx_attempts

Total number of Rx FAX attempts

Definition at line 506 of file res_fax.c.

◆ fax_tx_attempts

int fax_tx_attempts

Total number of Tx FAX attempts

Definition at line 504 of file res_fax.c.

◆ faxmodules

struct faxmodules faxmodules = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
static

◆ faxregistry

struct { ... } faxregistry

◆ general_options

struct fax_options general_options
static

Definition at line 537 of file res_fax.c.

Referenced by get_general_options(), and set_general_options().

◆ global_fax_debug

int global_fax_debug = 0
static

Definition at line 555 of file res_fax.c.

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

◆ nextsessionname

int nextsessionname

the next unique session name

Definition at line 512 of file res_fax.c.

◆ options_lock

ast_rwlock_t options_lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} }
static

Definition at line 548 of file res_fax.c.

Referenced by get_general_options(), and set_general_options().

◆ our_t38_parameters

struct ast_control_t38_parameters our_t38_parameters
static

Definition at line 733 of file res_fax.c.

◆ reserved_sessions

int reserved_sessions

The number of reserved FAX sessions

Definition at line 500 of file res_fax.c.