Asterisk - The Open Source Telephony Project  GIT-master-9ed6387
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"

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 = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_APP_DEPEND, }
 
struct ast_custom_function acf_faxopt
 FAXOPT dialplan function. 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
#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
union ast_fax_session_details::@282 option
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:2837
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
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:444
#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:1822
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:2838
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:1839
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
union ast_fax_session_details::@282 option
#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:1790
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:431
#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:455
#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:455
#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
static struct @449 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.
#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
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
static struct @449 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.
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
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
static struct @449 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.
#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

◆ 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.
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:455
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:1804
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:1473
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:1744
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
static struct @449 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.
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
#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:1744
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
static struct @449 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.
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
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
static struct @449 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_unlink(container, obj)
Definition: astobj2.h:1598
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:4251
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:4647
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
union ast_frame::@255 data
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#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:1904
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3137
const char * ast_channel_name(const struct ast_channel *chan)
#define ast_frfree(fr)
Data structure associated with a single frame of 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:2837
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:2838
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:2837
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:1484
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:455
struct ast_frame_subclass subclass
struct ast_format * ast_channel_readformat(struct ast_channel *chan)
Number structure.
Definition: app_followme.c:154
union ast_frame::@255 data
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#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:6656
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:5724
#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:851
#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:4170
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:2838
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:10598
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:7002
#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)
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:1719
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:48
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:1833
#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:1729
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:46

◆ 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:2837
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
#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:2838
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
union ast_fax_session_details::@282 option
#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:2765
#define ast_channel_lock(chan)
Definition: channel.h:2837
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:866
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
union ast_frame::@255 data
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#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:2838
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
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:2765
#define ast_channel_lock(chan)
Definition: channel.h:2837
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:866
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
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#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:2838
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:5068
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
union ast_fax_session_details::@282 option
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:2765
#define ast_channel_lock(chan)
Definition: channel.h:2837
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:866
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:559
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:444
#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:6656
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:5724
#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:851
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:5765
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:441
#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:2838
#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:2844
#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:10598
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:2837
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:4647
#define ast_channel_unlock(chan)
Definition: channel.h:2838
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:1234

◆ 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:444
#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:2837
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:2838
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:1719
#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
static struct @449 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.
#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:444
#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:1749
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
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
union ast_fax_session_details::@282 option
#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
static struct @449 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.
enum ast_fax_state state
Definition: res_fax.h:218

◆ 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