Asterisk - The Open Source Telephony Project  GIT-master-a24979a
Data Structures | Macros | Enumerations | Functions | Variables
res_fax.c File Reference

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

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

Go to the source code of this file.

Data Structures

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

Macros

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

Enumerations

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

Functions

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

Variables

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

◆ FAX_DETECT_MODE_CNG

#define FAX_DETECT_MODE_CNG   (1 << 0)

FAX Detect flags.

Definition at line 482 of file res_fax.c.

◆ FAX_DETECT_MODE_T38

#define FAX_DETECT_MODE_T38   (1 << 1)

Definition at line 483 of file res_fax.c.

◆ FAX_GATEWAY_TIMEOUT

#define FAX_GATEWAY_TIMEOUT   RES_FAX_TIMEOUT

Definition at line 492 of file res_fax.c.

◆ FAX_MAXBUCKETS

#define FAX_MAXBUCKETS   10

maximum buckets for res_fax ao2 containers

Definition at line 489 of file res_fax.c.

◆ 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)
const char * ast_channel_name(const struct ast_channel *chan)
#define LOG_ERROR

Definition at line 1484 of file res_fax.c.

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

◆ GENERIC_FAX_EXEC_SET_VARS

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

Definition at line 1468 of file res_fax.c.

◆ RES_FAX_MAXRATE

#define RES_FAX_MAXRATE   14400

Definition at line 522 of file res_fax.c.

◆ RES_FAX_MINRATE

#define RES_FAX_MINRATE   4800

Definition at line 521 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 524 of file res_fax.c.

◆ RES_FAX_STATUSEVENTS

#define RES_FAX_STATUSEVENTS   0

Definition at line 523 of file res_fax.c.

◆ RES_FAX_T38TIMEOUT

#define RES_FAX_T38TIMEOUT   5000

Definition at line 525 of file res_fax.c.

◆ RES_FAX_TIMEOUT

#define RES_FAX_TIMEOUT   10000

Definition at line 491 of file res_fax.c.

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

556  {
557  OPT_CALLEDMODE = (1 << 0),
558  OPT_CALLERMODE = (1 << 1),
559  OPT_DEBUG = (1 << 2),
560  OPT_STATUS = (1 << 3),
561  OPT_ALLOWAUDIO = (1 << 5),
562  OPT_REQUEST_T38 = (1 << 6),
563  OPT_FORCE_AUDIO = (1 << 7),
564 };
@ OPT_CALLEDMODE
Definition: res_fax.c:557
@ OPT_REQUEST_T38
Definition: res_fax.c:562
@ OPT_FORCE_AUDIO
Definition: res_fax.c:563
@ OPT_CALLERMODE
Definition: res_fax.c:558
@ OPT_ALLOWAUDIO
Definition: res_fax.c:561
@ OPT_STATUS
Definition: res_fax.c:560
@ OPT_DEBUG
Definition: res_fax.c:559

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 4866 of file res_fax.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 4866 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 4525 of file res_fax.c.

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

References ao2_ref, ast_channel_name(), ast_copy_string(), ast_fax_modem_to_str(), ast_free, AST_LIST_EMPTY, AST_LIST_FIRST, ast_log, buf, 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, len(), 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.

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

4601 {
4602  int res = 0;
4603  struct ast_fax_session_details *details;
4604 
4605  if (!(details = find_or_create_details(chan))) {
4606  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);
4607  return -1;
4608  }
4609  ast_debug(3, "channel '%s' setting FAXOPT(%s) to '%s'\n", ast_channel_name(chan), data, value);
4610 
4611  if (!strcasecmp(data, "ecm")) {
4612  const char *val = ast_skip_blanks(value);
4613  if (ast_true(val)) {
4614  details->option.ecm = AST_FAX_OPTFLAG_TRUE;
4615  } else if (ast_false(val)) {
4616  details->option.ecm = AST_FAX_OPTFLAG_FALSE;
4617  } else {
4618  ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(ecm).\n", value);
4619  }
4620  } else if (!strcasecmp(data, "t38gateway") || !strcasecmp(data, "gateway") ||
4621  !strcasecmp(data, "t38_gateway") || !strcasecmp(data, "faxgateway")) {
4622  const char *val = ast_skip_blanks(value);
4623  char *timeout = strchr(val, ',');
4624 
4625  if (timeout) {
4626  *timeout++ = '\0';
4627  }
4628 
4629  if (ast_true(val)) {
4630  if (details->gateway_id < 0) {
4631  details->gateway_timeout = 0;
4632  if (timeout) {
4633  unsigned int gwtimeout;
4634 
4635  if (sscanf(timeout, "%30u", &gwtimeout) == 1) {
4636  details->gateway_timeout = gwtimeout * 1000;
4637  } else {
4638  ast_log(LOG_WARNING, "Unsupported timeout '%s' passed to FAXOPT(%s).\n", timeout, data);
4639  }
4640  }
4641 
4642  details->gateway_id = fax_gateway_attach(chan, details);
4643  if (details->gateway_id < 0) {
4644  ast_log(LOG_ERROR, "Error attaching T.38 gateway to channel %s.\n", ast_channel_name(chan));
4645  res = -1;
4646  } else {
4647  ast_debug(1, "Attached T.38 gateway to channel %s.\n", ast_channel_name(chan));
4648  }
4649  } else {
4650  ast_log(LOG_WARNING, "Attempt to attach a T.38 gateway on channel (%s) with gateway already running.\n", ast_channel_name(chan));
4651  }
4652  } else if (ast_false(val)) {
4653  ast_channel_lock(chan);
4654  ast_framehook_detach(chan, details->gateway_id);
4655  ast_channel_unlock(chan);
4656  details->gateway_id = -1;
4657  } else {
4658  ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(%s).\n", value, data);
4659  }
4660  } else if (!strcasecmp(data, "faxdetect")) {
4661  const char *val = ast_skip_blanks(value);
4662  char *timeout = strchr(val, ',');
4663  unsigned int fdtimeout = 0;
4664  int flags;
4665  int faxdetect;
4666 
4667  if (timeout) {
4668  *timeout++ = '\0';
4669  }
4670 
4671  if (ast_true(val) || !strcasecmp(val, "t38") || !strcasecmp(val, "cng")) {
4672  if (details->faxdetect_id < 0) {
4673  if (timeout) {
4674  if (sscanf(timeout, "%30u", &fdtimeout) == 1) {
4675  fdtimeout *= 1000;
4676  } else {
4677  ast_log(LOG_WARNING, "Unsupported timeout '%s' passed to FAXOPT(%s).\n",
4678  timeout, data);
4679  }
4680  }
4681 
4682  if (!strcasecmp(val, "t38")) {
4683  flags = FAX_DETECT_MODE_T38;
4684  } else if (!strcasecmp(val, "cng")) {
4685  flags = FAX_DETECT_MODE_CNG;
4686  } else {
4687  flags = FAX_DETECT_MODE_BOTH;
4688  }
4689 
4690  faxdetect = fax_detect_attach(chan, fdtimeout, flags);
4691  if (faxdetect < 0) {
4692  ast_log(LOG_ERROR, "Error attaching FAX detect to channel %s.\n", ast_channel_name(chan));
4693  res = -1;
4694  } else {
4695  ast_debug(1, "Attached FAX detect to channel %s.\n", ast_channel_name(chan));
4696  }
4697  } else {
4698  ast_log(LOG_WARNING, "Attempt to attach a FAX detect on channel (%s) with FAX detect already running.\n", ast_channel_name(chan));
4699  }
4700  } else if (ast_false(val)) {
4701  ast_channel_lock(chan);
4702  ast_framehook_detach(chan, details->faxdetect_id);
4703  ast_channel_unlock(chan);
4704  details->faxdetect_id = -1;
4705  } else {
4706  ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(%s).\n", value, data);
4707  }
4708  } else if (!strcasecmp(data, "headerinfo")) {
4710  } else if (!strcasecmp(data, "localstationid")) {
4712  } else if (!strcasecmp(data, "maxrate")) {
4713  details->maxrate = fax_rate_str_to_int(value);
4714  if (!details->maxrate) {
4715  details->maxrate = ast_fax_maxrate();
4716  }
4717  } else if (!strcasecmp(data, "minrate")) {
4718  details->minrate = fax_rate_str_to_int(value);
4719  if (!details->minrate) {
4720  details->minrate = ast_fax_minrate();
4721  }
4722  } else if (!strcasecmp(data, "t38timeout")) {
4723  if (set_t38timeout(value, &details->t38timeout)) {
4724  res = -1;
4725  }
4726  } else if ((!strcasecmp(data, "modem")) || (!strcasecmp(data, "modems"))) {
4727  update_modem_bits(&details->modems, value);
4728  } else if (!strcasecmp(data, "negotiate_both")) {
4730  } else {
4731  ast_log(LOG_WARNING, "channel '%s' set FAXOPT(%s) to '%s' is unhandled!\n", ast_channel_name(chan), data, value);
4732  res = -1;
4733  }
4734 
4735  ao2_ref(details, -1);
4736 
4737  return res;
4738 }
static int fdtimeout
#define ast_channel_lock(chan)
Definition: channel.h:2922
#define ast_channel_unlock(chan)
Definition: channel.h:2923
int ast_framehook_detach(struct ast_channel *chan, int framehook_id)
Detach an framehook from a channel.
Definition: framehook.c:177
#define ast_debug(level,...)
Log a DEBUG message.
unsigned int ast_fax_minrate(void)
get the minimum supported fax rate
Definition: res_fax.c:803
static int update_modem_bits(enum ast_fax_modems *bits, const char *value)
Definition: res_fax.c:811
#define FAX_DETECT_MODE_BOTH
Definition: res_fax.c:484
static int set_t38timeout(const char *value, unsigned int *t38timeout)
Definition: res_fax.c:4403
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:3888
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:3625
#define FAX_DETECT_MODE_T38
Definition: res_fax.c:483
unsigned int ast_fax_maxrate(void)
get the maxiumum supported fax rate
Definition: res_fax.c:795
static struct ast_fax_session_details * find_or_create_details(struct ast_channel *chan)
returns a reference counted details structure from the channel's fax datastore. If the datastore does...
Definition: res_fax.c:763
static unsigned int fax_rate_str_to_int(const char *ratestr)
convert a rate string to a rate
Definition: res_fax.c:1045
#define FAX_DETECT_MODE_CNG
FAX Detect flags.
Definition: res_fax.c:482
@ AST_FAX_OPTFLAG_FALSE
Definition: res_fax.h:85
@ AST_FAX_OPTFLAG_TRUE
Definition: res_fax.h:87
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:521
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition: main/utils.c:2097
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:2114
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition: strings.h:161
Definition: ast_expr2.c:325
int value
Definition: syslog.c:37

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

846 {
847  char *out = buf;
848  size_t size = bufsize;
849  int first = 1;
850 
851  if (caps & AST_FAX_TECH_SEND) {
852  if (!first) {
853  ast_build_string(&buf, &size, ",");
854  }
855  ast_build_string(&buf, &size, "SEND");
856  first = 0;
857  }
858  if (caps & AST_FAX_TECH_RECEIVE) {
859  if (!first) {
860  ast_build_string(&buf, &size, ",");
861  }
862  ast_build_string(&buf, &size, "RECEIVE");
863  first = 0;
864  }
865  if (caps & AST_FAX_TECH_AUDIO) {
866  if (!first) {
867  ast_build_string(&buf, &size, ",");
868  }
869  ast_build_string(&buf, &size, "AUDIO");
870  first = 0;
871  }
872  if (caps & AST_FAX_TECH_T38) {
873  if (!first) {
874  ast_build_string(&buf, &size, ",");
875  }
876  ast_build_string(&buf, &size, "T38");
877  first = 0;
878  }
879  if (caps & AST_FAX_TECH_MULTI_DOC) {
880  if (!first) {
881  ast_build_string(&buf, &size, ",");
882  }
883  ast_build_string(&buf, &size, "MULTI_DOC");
884  first = 0;
885  }
886  if (caps & AST_FAX_TECH_GATEWAY) {
887  if (!first) {
888  ast_build_string(&buf, &size, ",");
889  }
890  ast_build_string(&buf, &size, "GATEWAY");
891  first = 0;
892  }
893  if (caps & AST_FAX_TECH_V21_DETECT) {
894  if (!first) {
895  ast_build_string(&buf, &size, ",");
896  }
897  ast_build_string(&buf, &size, "V21");
898  first = 0;
899  }
900 
901  return out;
902 }
struct sla_ringing_trunk * first
Definition: app_meetme.c:1094
@ AST_FAX_TECH_T38
Definition: res_fax.h:43
@ AST_FAX_TECH_AUDIO
Definition: res_fax.h:41
@ AST_FAX_TECH_RECEIVE
Definition: res_fax.h:39
@ AST_FAX_TECH_V21_DETECT
Definition: res_fax.h:49
@ AST_FAX_TECH_MULTI_DOC
Definition: res_fax.h:45
@ AST_FAX_TECH_SEND
Definition: res_fax.h:37
@ AST_FAX_TECH_GATEWAY
Definition: res_fax.h:47
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:2065
FILE * out
Definition: utils/frame.c:33

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

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

1036 {
1037  if (fax_logger_level != -1) {
1039  } else {
1040  ast_log(level, file, line, function, "%s", msg);
1041  }
1042 }
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
static int fax_logger_level
Definition: res_fax.c:486

References ast_log, ast_log_dynamic_level, fax_logger_level, and make_ari_stubs::file.

Referenced by spandsp_log().

◆ ast_fax_maxrate()

unsigned int ast_fax_maxrate ( void  )

get the maxiumum supported fax rate

Definition at line 795 of file res_fax.c.

796 {
797  struct fax_options options;
799 
800  return options.maxrate;
801 }
static void get_general_options(struct fax_options *options)
Definition: res_fax.c:4396
static struct test_options options

References get_general_options(), and options.

◆ ast_fax_minrate()

unsigned int ast_fax_minrate ( void  )

get the minimum supported fax rate

Definition at line 803 of file res_fax.c.

804 {
805  struct fax_options options;
807 
808  return options.minrate;
809 }

References get_general_options(), and options.

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

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

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

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

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

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

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

1013 {
1014  switch (state) {
1016  return "Uninitialized";
1018  return "Initialized";
1019  case AST_FAX_STATE_OPEN:
1020  return "Open";
1021  case AST_FAX_STATE_ACTIVE:
1022  return "Active";
1024  return "Complete";
1026  return "Reserved";
1028  return "Inactive";
1029  default:
1030  ast_log(LOG_WARNING, "unhandled FAX state: %u\n", state);
1031  return "Unknown";
1032  }
1033 }
@ AST_FAX_STATE_INITIALIZED
Definition: res_fax.h:69
@ AST_FAX_STATE_INACTIVE
Definition: res_fax.h:79
@ AST_FAX_STATE_ACTIVE
Definition: res_fax.h:73
@ AST_FAX_STATE_COMPLETE
Definition: res_fax.h:75
@ AST_FAX_STATE_OPEN
Definition: res_fax.h:71
@ AST_FAX_STATE_UNINITIALIZED
Definition: res_fax.h:67
@ AST_FAX_STATE_RESERVED
Definition: res_fax.h:77

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

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

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

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.

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

992 {
993  struct fax_module *fax;
994 
995  ast_verb(3, "Unregistering FAX module type '%s'\n", tech->type);
996 
999  if (fax->tech != tech) {
1000  continue;
1001  }
1003  ast_free(fax);
1004  ast_verb(4, "Unregistered FAX module type '%s'\n", tech->type);
1005  break;
1006  }
1009 }
#define AST_RWLIST_REMOVE_CURRENT
Definition: linkedlists.h:570
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:545
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:617

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

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 4866 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 937 of file res_fax.c.

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

References AST_FAX_MODEM_V17, AST_FAX_MODEM_V27TER, AST_FAX_MODEM_V29, AST_FAX_MODEM_V34, and fax_options::modems.

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

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

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

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

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

4038 {
4039  struct fax_module *fax;
4040  unsigned int num_modules = 0;
4041 
4042  switch (cmd) {
4043  case CLI_INIT:
4044  e->command = "fax show capabilities";
4045  e->usage =
4046  "Usage: fax show capabilities\n"
4047  " Shows the capabilities of the registered FAX technology modules\n";
4048  return NULL;
4049  case CLI_GENERATE:
4050  return NULL;
4051  }
4052 
4053  ast_cli(a->fd, "\n\nRegistered FAX Technology Modules:\n\n");
4055  AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
4056  ast_cli(a->fd, "%-15s : %s\n%-15s : %s\n%-15s : ", "Type", fax->tech->type, "Description", fax->tech->description, "Capabilities");
4057  fax->tech->cli_show_capabilities(a->fd);
4058  num_modules++;
4059  }
4061  ast_cli(a->fd, "%u registered modules\n\n", num_modules);
4062 
4063  return CLI_SUCCESS;
4064 }
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:78
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:494
char *(*const cli_show_capabilities)(int)
Definition: res_fax.h:267

References a, 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, NULL, fax_module::tech, ast_fax_tech::type, and ast_cli_entry::usage.

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

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

References a, ao2_find, ao2_ref, 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, LOG_ERROR, NULL, OBJ_POINTER, RESULT_SUCCESS, ast_fax_session::tech, tmp(), and ast_cli_entry::usage.

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

4273 {
4274  struct ast_fax_session *s;
4275  struct ao2_iterator i;
4276  int session_count;
4277  char *filenames;
4278 
4279  switch (cmd) {
4280  case CLI_INIT:
4281  e->command = "fax show sessions";
4282  e->usage =
4283  "Usage: fax show sessions\n"
4284  " Shows the current FAX sessions\n";
4285  return NULL;
4286  case CLI_GENERATE:
4287  return NULL;
4288  }
4289 
4290  ast_cli(a->fd, "\nCurrent FAX Sessions:\n\n");
4291  ast_cli(a->fd, "%-30.30s %-10.10s %-10.10s %-5.5s %-10.10s %-15.15s %-30.30s\n",
4292  "Channel", "Tech", "FAXID", "Type", "Operation", "State", "File(s)");
4293  i = ao2_iterator_init(faxregistry.container, 0);
4294  while ((s = ao2_iterator_next(&i))) {
4295  ao2_lock(s);
4296 
4297  filenames = generate_filenames_string(s->details, "", ", ");
4298 
4299  ast_cli(a->fd, "%-30.30s %-10.10s %-10u %-5.5s %-10.10s %-15.15s %-30s\n",
4300  s->channame, s->tech->type, s->id,
4301  fax_session_type(s),
4303  ast_fax_state_to_str(s->state), S_OR(filenames, ""));
4304 
4305  ast_free(filenames);
4306  ao2_unlock(s);
4307  ao2_ref(s, -1);
4308  }
4311  ast_cli(a->fd, "\n%d FAX sessions\n\n", session_count);
4312 
4313  return CLI_SUCCESS;
4314 }
#define ao2_iterator_next(iter)
Definition: astobj2.h:1911
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ao2_unlock(a)
Definition: astobj2.h:729
#define ao2_lock(a)
Definition: astobj2.h:717
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
static int session_count
Definition: http.c:109
const char * ast_fax_session_operation_str(struct ast_fax_session *s)
get string representation of a FAX session's operation
Definition: res_fax.c:4253
static const char * fax_session_type(struct ast_fax_session *s)
Definition: res_fax.c:4241
const char * ast_fax_state_to_str(enum ast_fax_state state)
convert a ast_fax_state to a string
Definition: res_fax.c:1012
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
unsigned int id
Definition: res_fax.h:204
enum ast_fax_state state
Definition: res_fax.h:218

References a, 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, 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.

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

4068 {
4069  struct fax_module *fax;
4070  char modems[128] = "";
4071  struct fax_options options;
4072 
4073  switch (cmd) {
4074  case CLI_INIT:
4075  e->command = "fax show settings";
4076  e->usage =
4077  "Usage: fax show settings\n"
4078  " Show the global settings and defaults of both the FAX core and technology modules\n";
4079  return NULL;
4080  case CLI_GENERATE:
4081  return NULL;
4082  }
4083 
4085 
4086  ast_cli(a->fd, "FAX For Asterisk Settings:\n");
4087  ast_cli(a->fd, "\tECM: %s\n", options.ecm ? "Enabled" : "Disabled");
4088  ast_cli(a->fd, "\tStatus Events: %s\n", options.statusevents ? "On" : "Off");
4089  ast_cli(a->fd, "\tMinimum Bit Rate: %u\n", options.minrate);
4090  ast_cli(a->fd, "\tMaximum Bit Rate: %u\n", options.maxrate);
4091  ast_fax_modem_to_str(options.modems, modems, sizeof(modems));
4092  ast_cli(a->fd, "\tModem Modulations Allowed: %s\n", modems);
4093  ast_cli(a->fd, "\tT.38 Negotiation Timeout: %u\n", options.t38timeout);
4094  ast_cli(a->fd, "\n\nFAX Technology Modules:\n\n");
4096  AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
4097  ast_cli(a->fd, "%s (%s) Settings:\n", fax->tech->type, fax->tech->description);
4098  fax->tech->cli_show_settings(a->fd);
4099  }
4101 
4102  return CLI_SUCCESS;
4103 }
char *(*const cli_show_settings)(int)
Definition: res_fax.h:276
enum ast_fax_modems modems
Definition: res_fax.c:528

References a, 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, get_general_options(), fax_options::modems, NULL, options, fax_module::tech, ast_fax_tech::type, and ast_cli_entry::usage.

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

4181 {
4182  struct fax_module *fax;
4183 
4184  switch (cmd) {
4185  case CLI_INIT:
4186  e->command = "fax show stats";
4187  e->usage =
4188  "Usage: fax show stats\n"
4189  " Shows a statistical summary of FAX transmissions\n";
4190  return NULL;
4191  case CLI_GENERATE:
4192  return NULL;
4193  }
4194 
4195  ast_cli(a->fd, "\nFAX Statistics:\n---------------\n\n");
4196  ast_cli(a->fd, "%-20.20s : %d\n", "Current Sessions", faxregistry.active_sessions);
4197  ast_cli(a->fd, "%-20.20s : %d\n", "Reserved Sessions", faxregistry.reserved_sessions);
4198  ast_cli(a->fd, "%-20.20s : %d\n", "Transmit Attempts", faxregistry.fax_tx_attempts);
4199  ast_cli(a->fd, "%-20.20s : %d\n", "Receive Attempts", faxregistry.fax_rx_attempts);
4200  ast_cli(a->fd, "%-20.20s : %d\n", "Completed FAXes", faxregistry.fax_complete);
4201  ast_cli(a->fd, "%-20.20s : %d\n", "Failed FAXes", faxregistry.fax_failures);
4203  AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
4204  fax->tech->cli_show_stats(a->fd);
4205  }
4207  ast_cli(a->fd, "\n\n");
4208 
4209  return CLI_SUCCESS;
4210 }
char *(*const cli_show_stats)(int)
Definition: res_fax.h:274

References a, 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, NULL, fax_module::tech, and ast_cli_entry::usage.

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

3971 {
3972  struct fax_module *fax;
3973 
3974  switch(cmd) {
3975  case CLI_INIT:
3976  e->command = "fax show version";
3977  e->usage =
3978  "Usage: fax show version\n"
3979  " Show versions of FAX For Asterisk components.\n";
3980  return NULL;
3981  case CLI_GENERATE:
3982  return NULL;
3983  }
3984 
3985  if (a->argc != 3) {
3986  return CLI_SHOWUSAGE;
3987  }
3988 
3989  ast_cli(a->fd, "FAX For Asterisk Components:\n");
3990  ast_cli(a->fd, "\tApplications: %s\n", ast_get_version());
3992  AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
3993  ast_cli(a->fd, "\t%s: %s\n", fax->tech->description, fax->tech->version);
3994  }
3996  ast_cli(a->fd, "\n");
3997 
3998  return CLI_SUCCESS;
3999 }
const char * ast_get_version(void)
Retrieve the Asterisk version string.
const char *const version
Definition: res_fax.h:241

References a, 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, NULL, fax_module::tech, ast_cli_entry::usage, and ast_fax_tech::version.

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

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

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

◆ destroy_callback()

static void destroy_callback ( void *  data)
static

Definition at line 609 of file res_fax.c.

610 {
611  if (data) {
612  ao2_ref(data, -1);
613  }
614 }

References ao2_ref.

◆ destroy_faxdetect()

static void destroy_faxdetect ( void *  data)
static

destroy a FAX detect structure

Definition at line 3675 of file res_fax.c.

3676 {
3677  struct fax_detect *faxdetect = data;
3678 
3679  if (faxdetect->dsp) {
3680  ast_dsp_free(faxdetect->dsp);
3681  faxdetect->dsp = NULL;
3682  }
3683  ao2_cleanup(faxdetect->details);
3684  ao2_cleanup(faxdetect->orig_format);
3685 }
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
void ast_dsp_free(struct ast_dsp *dsp)
Definition: dsp.c:1773
used for fax detect framehook
Definition: res_fax.c:468
struct ast_dsp * dsp
DSP Processor.
Definition: res_fax.c:472
struct ast_format * orig_format
original audio formats
Definition: res_fax.c:474
struct ast_fax_session_details * details
fax session details
Definition: res_fax.c:476

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

Referenced by fax_detect_new().

◆ destroy_gateway()

static void destroy_gateway ( void *  data)
static

destroy a FAX gateway session structure

Definition at line 2838 of file res_fax.c.

2839 {
2840  struct fax_gateway *gateway = data;
2841 
2842  destroy_v21_sessions(gateway);
2843 
2844  if (gateway->s) {
2845  fax_session_release(gateway->s, gateway->token);
2846  gateway->token = NULL;
2847 
2848  ao2_unlink(faxregistry.container, gateway->s);
2849 
2850  ao2_ref(gateway->s, -1);
2851  gateway->s = NULL;
2852  }
2853 
2854  ao2_cleanup(gateway->chan_read_format);
2855  ao2_cleanup(gateway->chan_write_format);
2856  ao2_cleanup(gateway->peer_read_format);
2857  ao2_cleanup(gateway->peer_write_format);
2858 }
#define ao2_unlink(container, obj)
Remove an object from a container.
Definition: astobj2.h:1578
static void fax_session_release(struct ast_fax_session *s, struct ast_fax_tech_token *token)
Release a session token.
Definition: res_fax.c:1082
static void destroy_v21_sessions(struct fax_gateway *gateway)
destroy the v21 detection parts of a fax gateway session
Definition: res_fax.c:2820
used for gateway framehook
Definition: res_fax.c:443
struct ast_format * chan_read_format
original audio formats
Definition: res_fax.c:461
struct ast_format * chan_write_format
Definition: res_fax.c:462
struct ast_format * peer_write_format
Definition: res_fax.c:464
struct ast_format * peer_read_format
Definition: res_fax.c:463
struct ast_fax_session * s
FAX Session.
Definition: res_fax.c:445
struct ast_fax_tech_token * token
reserved fax session token
Definition: res_fax.c:449

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

◆ destroy_session()

static void destroy_session ( void *  session)
static

destroy a FAX session structure

Definition at line 1095 of file res_fax.c.

1096 {
1097  struct ast_fax_session *s = session;
1098 
1099  if (s->tech) {
1101  if (s->tech_pvt) {
1102  s->tech->destroy_session(s);
1103  }
1105  }
1106 
1107  if (s->details) {
1108  if (s->details->caps & AST_FAX_TECH_GATEWAY) {
1110  }
1111  ao2_ref(s->details, -1);
1112  s->details = NULL;
1113  }
1114 
1115  if (s->debug_info) {
1117  ast_free(s->debug_info);
1118  }
1119 
1120  if (s->smoother) {
1122  }
1123 
1124  if (s->state != AST_FAX_STATE_INACTIVE) {
1125  ast_atomic_fetchadd_int(&faxregistry.active_sessions, -1);
1126  }
1127 
1128  ast_free(s->channame);
1129  ast_free(s->chan_uniqueid);
1130 }
static struct ast_mansession session
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:755
#define ast_module_unref(mod)
Release a reference to the module.
Definition: module.h:469
void ast_smoother_free(struct ast_smoother *s)
Definition: smoother.c:220
void * tech_pvt
Definition: res_fax.h:216
char * chan_uniqueid
Definition: res_fax.h:222
struct ast_smoother * smoother
Definition: res_fax.h:228
struct ast_module * module
Definition: res_fax.h:245
void(*const destroy_session)(struct ast_fax_session *)
Definition: res_fax.h:253

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

◆ destroy_session_details()

static void destroy_session_details ( void *  details)
static

destroy a FAX session details structure

Definition at line 683 of file res_fax.c.

684 {
685  struct ast_fax_session_details *d = details;
686  struct ast_fax_document *doc;
687 
688  while ((doc = AST_LIST_REMOVE_HEAD(&d->documents, next))) {
689  ast_free(doc);
690  }
692 }
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:374
struct ast_fax_document * next
Definition: res_fax.h:103
static struct test_val d

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

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

2821 {
2822  if (gateway->chan_v21_session) {
2823  ao2_unlink(faxregistry.container, gateway->chan_v21_session);
2824 
2825  ao2_ref(gateway->chan_v21_session, -1);
2826  gateway->chan_v21_session = NULL;
2827  }
2828 
2829  if (gateway->peer_v21_session) {
2830  ao2_unlink(faxregistry.container, gateway->peer_v21_session);
2831 
2832  ao2_ref(gateway->peer_v21_session, -1);
2833  gateway->peer_v21_session = NULL;
2834  }
2835 }
struct ast_fax_session * peer_v21_session
Definition: res_fax.c:446
struct ast_fax_session * chan_v21_session
Definition: res_fax.c:447

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

◆ disable_t38()

static int disable_t38 ( struct ast_channel chan)
static

Definition at line 1526 of file res_fax.c.

1527 {
1528  int timeout_ms;
1529  struct ast_frame *frame = NULL;
1531  struct timeval start;
1532  int ms;
1533 
1534  ast_debug(1, "Shutting down T.38 on %s\n", ast_channel_name(chan));
1535  if (ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0) {
1536  ast_debug(1, "error while disabling T.38 on channel '%s'\n", ast_channel_name(chan));
1537  return -1;
1538  }
1539 
1540  /* wait up to five seconds for negotiation to complete */
1541  timeout_ms = 5000;
1542  start = ast_tvnow();
1543  while ((ms = ast_remaining_ms(start, timeout_ms))) {
1544  ms = ast_waitfor(chan, ms);
1545 
1546  if (ms == 0) {
1547  break;
1548  }
1549  if (ms < 0) {
1550  ast_debug(1, "error while disabling T.38 on channel '%s'\n", ast_channel_name(chan));
1551  return -1;
1552  }
1553 
1554  if (!(frame = ast_read(chan))) {
1555  return -1;
1556  }
1557  if ((frame->frametype == AST_FRAME_CONTROL) &&
1559  (frame->datalen == sizeof(t38_parameters))) {
1560  struct ast_control_t38_parameters *parameters = frame->data.ptr;
1561 
1562  switch (parameters->request_response) {
1563  case AST_T38_TERMINATED:
1564  ast_debug(1, "Shut down T.38 on %s\n", ast_channel_name(chan));
1565  break;
1566  case AST_T38_REFUSED:
1567  ast_log(LOG_WARNING, "channel '%s' refused to disable T.38\n", ast_channel_name(chan));
1568  ast_frfree(frame);
1569  return -1;
1570  default:
1571  ast_log(LOG_ERROR, "channel '%s' failed to disable T.38\n", ast_channel_name(chan));
1572  ast_frfree(frame);
1573  return -1;
1574  }
1575  ast_frfree(frame);
1576  break;
1577  }
1578  ast_frfree(frame);
1579  }
1580 
1581  if (ms == 0) { /* all done, nothing happened */
1582  ast_debug(1, "channel '%s' timed-out during T.38 shutdown\n", ast_channel_name(chan));
1583  }
1584 
1585  return 0;
1586 }
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3163
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4292
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:4688
@ AST_T38_TERMINATED
@ AST_T38_REFUSED
@ AST_T38_REQUEST_TERMINATE
#define ast_frfree(fr)
@ AST_FRAME_CONTROL
@ AST_CONTROL_T38_PARAMETERS
enum ast_control_t38 request_response
Data structure associated with a single frame of data.
struct ast_frame_subclass subclass
union ast_frame::@254 data
enum ast_frame_type frametype
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
Definition: main/utils.c:2179

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(), and sendfax_exec().

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

3889 {
3890  struct fax_detect *faxdetect;
3891  struct ast_fax_session_details *details;
3892  struct ast_framehook_interface fr_hook = {
3894  .event_cb = fax_detect_framehook,
3895  .destroy_cb = fax_detect_framehook_destroy,
3896  };
3897 
3898  if (!(details = find_or_create_details(chan))) {
3899  ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
3900  return -1;
3901  }
3902 
3903  /* set up the frame hook*/
3904  faxdetect = fax_detect_new(chan, timeout, flags);
3905  if (!faxdetect) {
3906  ao2_ref(details, -1);
3907  return -1;
3908  }
3909 
3910  fr_hook.data = faxdetect;
3911  faxdetect->details = details;
3912  ast_channel_lock(chan);
3913  details->faxdetect_id = ast_framehook_attach(chan, &fr_hook);
3914  details->faxdetect_timeout = timeout;
3915  details->faxdetect_flags = flags;
3916  ast_channel_unlock(chan);
3917 
3918  if (details->faxdetect_id < 0) {
3919  ao2_ref(faxdetect, -1);
3920  }
3921 
3922  return details->faxdetect_id;
3923 }
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_FRAMEHOOK_INTERFACE_VERSION
Definition: framehook.h:227
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:3693
static void fax_detect_framehook_destroy(void *data)
Deref the faxdetect data structure when the faxdetect framehook is detached.
Definition: res_fax.c:3726
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:3744

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

Referenced by fixup_callback().

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

3745 {
3746  struct fax_detect *faxdetect = data;
3747  struct ast_fax_session_details *details;
3748  struct ast_control_t38_parameters *control_params;
3749  RAII_VAR(struct ast_channel *, peer, NULL, ao2_cleanup);
3750  RAII_VAR(struct ast_channel *, chan_ref, chan, ao2_cleanup);
3751  int result = 0;
3752 
3753  /* Ref bump the channel for when we have to unlock it */
3754  ao2_ref(chan, 1);
3755 
3756  details = faxdetect->details;
3757 
3758  switch (event) {
3760  /* Setup format for DSP on ATTACH*/
3761  ao2_replace(faxdetect->orig_format, ast_channel_readformat(chan));
3762 
3766  if (ast_set_read_format(chan, ast_format_slin)) {
3767  ast_framehook_detach(chan, details->faxdetect_id);
3768  details->faxdetect_id = -1;
3769  return f;
3770  }
3771  }
3772 
3773  return NULL;
3775  /* restore audio formats when we are detached */
3776  ast_set_read_format(chan, faxdetect->orig_format);
3777  ast_channel_unlock(chan);
3778  peer = ast_channel_bridge_peer(chan);
3779  if (peer) {
3780  ast_channel_make_compatible(chan, peer);
3781  }
3782  ast_channel_lock(chan);
3783  return NULL;
3785  if (f) {
3786  break;
3787  }
3788  default:
3789  return f;
3790  };
3791 
3792  if (details->faxdetect_id < 0) {
3793  return f;
3794  }
3795 
3796  if (!ast_tvzero(faxdetect->timeout_start)
3797  && ast_tvdiff_ms(ast_tvnow(), faxdetect->timeout_start) > details->faxdetect_timeout) {
3798  ast_debug(1, "FAXOPT(faxdetect) timeout on %s\n", ast_channel_name(chan));
3799  ast_framehook_detach(chan, details->faxdetect_id);
3800  details->faxdetect_id = -1;
3801  return f;
3802  }
3803 
3804  /* only handle VOICE and CONTROL frames*/
3805  switch (f->frametype) {
3806  case AST_FRAME_VOICE:
3807  /* we have no DSP this means we not detecting CNG */
3808  if (!faxdetect->dsp) {
3809  return f;
3810  }
3811  /* We can only process some formats*/
3815  return f;
3816  }
3817  break;
3818  case AST_FRAME_CONTROL:
3820  (faxdetect->flags & FAX_DETECT_MODE_T38)) {
3821  break;
3822  }
3823  return f;
3824  default:
3825  return f;
3826  }
3827 
3828  if (f->frametype == AST_FRAME_VOICE) {
3829  f = ast_dsp_process(chan, faxdetect->dsp, f);
3830  if (f->frametype == AST_FRAME_DTMF) {
3831  result = f->subclass.integer;
3832  }
3833  } else if ((f->frametype == AST_FRAME_CONTROL) && (f->datalen == sizeof(struct ast_control_t38_parameters))) {
3834  control_params = f->data.ptr;
3835  switch (control_params->request_response) {
3836  case AST_T38_NEGOTIATED:
3838  result = 't';
3839  break;
3840  default:
3841  break;
3842  }
3843  }
3844 
3845  if (result) {
3846  const char *target_context;
3847 
3848  switch (result) {
3849  case 'f':
3850  case 't':
3851  target_context = S_OR(ast_channel_macrocontext(chan), ast_channel_context(chan));
3852 
3853  ast_channel_unlock(chan);
3854  ast_frfree(f);
3855  f = &ast_null_frame;
3856  if (ast_exists_extension(chan, target_context, "fax", 1,
3857  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
3858  ast_verb(2, "Redirecting '%s' to fax extension due to %s detection\n",
3859  ast_channel_name(chan), (result == 'f') ? "CNG" : "T38");
3860  pbx_builtin_setvar_helper(chan, "FAXEXTEN", ast_channel_exten(chan));
3861  if (ast_async_goto(chan, target_context, "fax", 1)) {
3862  ast_log(LOG_NOTICE, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(chan), target_context);
3863  }
3864  } else {
3865  ast_log(LOG_NOTICE, "FAX %s detected but no fax extension in context (%s)\n",
3866  (result == 'f') ? "CNG" : "T38", target_context);
3867  }
3868  ast_channel_lock(chan);
3869 
3870  ast_framehook_detach(chan, details->faxdetect_id);
3871  details->faxdetect_id = -1;
3872  break;
3873  default:
3874  break;
3875  }
3876  }
3877 
3878  return f;
3879 }
#define ao2_replace(dst, src)
Replace one object reference with another cleaning up the original.
Definition: astobj2.h:501
static PGresult * result
Definition: cel_pgsql.c:84
int ast_channel_make_compatible(struct ast_channel *chan, struct ast_channel *peer)
Make the frame formats of two channels compatible.
Definition: channel.c:6798
const char * ast_channel_context(const struct ast_channel *chan)
int ast_set_read_format(struct ast_channel *chan, struct ast_format *format)
Sets read format on channel chan.
Definition: channel.c:5839
const char * ast_channel_exten(const struct ast_channel *chan)
struct ast_format * ast_channel_readformat(struct ast_channel *chan)
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
const char * ast_channel_macrocontext(const struct ast_channel *chan)
struct ast_channel * ast_channel_bridge_peer(struct ast_channel *chan)
Get the channel's bridge peer only if the bridge is two-party.
Definition: channel.c:10750
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:1497
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
@ AST_FORMAT_CMP_EQUAL
Definition: format.h:36
struct ast_format * ast_format_ulaw
Built-in cached ulaw format.
Definition: format_cache.c:86
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
struct ast_format * ast_format_alaw
Built-in cached alaw format.
Definition: format_cache.c:91
@ AST_FRAMEHOOK_EVENT_ATTACHED
Definition: framehook.h:154
@ AST_FRAMEHOOK_EVENT_DETACHED
Definition: framehook.h:155
@ AST_FRAMEHOOK_EVENT_READ
Definition: framehook.h:152
@ AST_T38_NEGOTIATED
@ AST_T38_REQUEST_NEGOTIATE
#define AST_FRAME_DTMF
@ AST_FRAME_VOICE
struct ast_frame ast_null_frame
Definition: main/frame.c:79
#define LOG_NOTICE
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:4182
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.
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.
#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:87
Main Channel structure associated with a channel.
struct ast_format * format
Definition: astman.c:222
struct timeval timeout_start
the start of our timeout counter
Definition: res_fax.c:470
int flags
mode
Definition: res_fax.c:478
Number structure.
Definition: app_followme.c:154
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:115
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:105
#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:936

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

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

3727 {
3728  struct fax_detect *faxdetect = data;
3729 
3730  ao2_ref(faxdetect, -1);
3731 }

References ao2_ref.

Referenced by fax_detect_attach().

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

3694 {
3695  struct fax_detect *faxdetect = ao2_alloc(sizeof(*faxdetect), destroy_faxdetect);
3696  if (!faxdetect) {
3697  return NULL;
3698  }
3699 
3700  faxdetect->flags = flags;
3701 
3702  if (timeout) {
3703  faxdetect->timeout_start = ast_tvnow();
3704  } else {
3705  faxdetect->timeout_start.tv_sec = 0;
3706  faxdetect->timeout_start.tv_usec = 0;
3707  }
3708 
3709  if (faxdetect->flags & FAX_DETECT_MODE_CNG) {
3710  faxdetect->dsp = ast_dsp_new();
3711  if (!faxdetect->dsp) {
3712  ao2_ref(faxdetect, -1);
3713  return NULL;
3714  }
3717  } else {
3718  faxdetect->dsp = NULL;
3719  }
3720 
3721  return faxdetect;
3722 }
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
Definition: dsp.c:1748
#define DSP_FEATURE_FAX_DETECT
Definition: dsp.h:29
#define DSP_FAXMODE_DETECT_SQUELCH
Definition: dsp.h:49
#define DSP_FAXMODE_DETECT_CNG
Definition: dsp.h:47
int ast_dsp_set_faxmode(struct ast_dsp *dsp, int faxmode)
Set fax mode.
Definition: dsp.c:1873
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
Definition: dsp.c:1758
static void destroy_faxdetect(void *data)
destroy a FAX detect structure
Definition: res_fax.c:3675

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

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

3626 {
3627  struct fax_gateway *gateway;
3628  struct ast_framehook_interface fr_hook = {
3630  .event_cb = fax_gateway_framehook,
3631  .destroy_cb = fax_gateway_framehook_destroy,
3632  .disable_inheritance = 1, /* Masquerade inheritance is handled through the datastore fixup */
3633  };
3634 
3635  if (global_fax_debug) {
3636  details->option.debug = AST_FAX_OPTFLAG_TRUE;
3637  }
3638 
3639  ast_string_field_set(details, result, "SUCCESS");
3640  ast_string_field_set(details, resultstr, "gateway operation started successfully");
3641  ast_string_field_set(details, error, "NO_ERROR");
3642  set_channel_variables(chan, details);
3643 
3644  /* set up the frame hook*/
3645  gateway = fax_gateway_new(chan, details);
3646  if (!gateway) {
3647  ast_string_field_set(details, result, "FAILED");
3648  ast_string_field_set(details, resultstr, "error initializing gateway session");
3649  ast_string_field_set(details, error, "INIT_ERROR");
3650  details->is_t38_negotiated = 0;
3651  set_channel_variables(chan, details);
3652  report_fax_status(chan, details, "No Available Resource");
3653  return -1;
3654  }
3655 
3656  fr_hook.data = gateway;
3657  ast_channel_lock(chan);
3658  gateway->framehook = ast_framehook_attach(chan, &fr_hook);
3659  ast_channel_unlock(chan);
3660 
3661  if (gateway->framehook < 0) {
3662  ao2_ref(gateway, -1);
3663  ast_string_field_set(details, result, "FAILED");
3664  ast_string_field_set(details, resultstr, "error attaching gateway to channel");
3665  ast_string_field_set(details, error, "INIT_ERROR");
3666  details->is_t38_negotiated = 0;
3667  set_channel_variables(chan, details);
3668  return -1;
3669  }
3670 
3671  return gateway->framehook;
3672 }
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:1406
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:2879
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:3382
static void fax_gateway_framehook_destroy(void *data)
Destroy the gateway data structure when the framehook is detached.
Definition: res_fax.c:3344
static void set_channel_variables(struct ast_channel *chan, struct ast_fax_session_details *details)
Set fax related channel variables.
Definition: res_fax.c:1446
int framehook
framehook used in gateway mode
Definition: res_fax.c:453
int error(const char *format,...)
Definition: utils/frame.c:999

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

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

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

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

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

3012 {
3013  struct ast_channel *other = (active == chan) ? peer : chan;
3014  struct ast_fax_session *active_v21_session = (active == chan) ? gateway->chan_v21_session : gateway->peer_v21_session;
3015 
3016  if (!active_v21_session || gateway->detected_v21) {
3017  return f;
3018  }
3019 
3020  if (active_v21_session->tech->write(active_v21_session, f) == 0 &&
3021  active_v21_session->details->option.v21_detected) {
3022  gateway->detected_v21 = 1;
3023  }
3024 
3025  if (gateway->detected_v21) {
3026  enum ast_t38_state state_other;
3027  enum ast_t38_state state_active;
3028  struct ast_frame *fp;
3029  struct ast_fax_session_details *details;
3030  int negotiate_both = 0;
3031 
3032  /*
3033  * The default behavior is to wait for the active endpoint to initiate negotiation.
3034  * Find out if this has been overridden. If so, instead of waiting have Asterisk
3035  * initiate the negotiation requests out to both endpoints.
3036  */
3037  details = find_or_create_details(active);
3038  if (details) {
3039  negotiate_both = details->negotiate_both;
3040  ao2_ref(details, -1);
3041  } else {
3042  ast_log(LOG_WARNING, "Detect v21 - no session details for channel '%s'\n",
3043  ast_channel_name(chan));
3044  }
3045 
3046  destroy_v21_sessions(gateway);
3047 
3048  ast_channel_unlock(chan);
3049  state_active = ast_channel_get_t38_state(active);
3050  state_other = ast_channel_get_t38_state(other);
3051  ast_channel_lock(chan);
3052 
3053  ast_debug(1, "detected v21 preamble from %s\n", ast_channel_name(active));
3054 
3055  if (state_active == T38_STATE_UNKNOWN || state_other == T38_STATE_UNKNOWN) {
3056  if (!(fp = fax_gateway_request_t38(gateway, chan))) {
3057  return f;
3058  }
3059  /* May be called endpoint is improperly configured to rely on the calling endpoint
3060  * to initiate T.38 re-INVITEs, send T.38 negotiation request to called endpoint */
3061  if (negotiate_both && state_active == T38_STATE_UNKNOWN) {
3062  ast_debug(1, "sending T.38 negotiation request to %s\n", ast_channel_name(active));
3063  if (active == chan) {
3064  ast_channel_unlock(chan);
3065  }
3066  ast_write(active, fp);
3067  if (active == chan) {
3068  ast_channel_lock(chan);
3069  }
3070  }
3071  if (state_other == T38_STATE_UNKNOWN) {
3072  ast_debug(1, "sending T.38 negotiation request to %s\n", ast_channel_name(other));
3073  return fp;
3074  }
3075  } else {
3076  ast_debug(1, "neither %s nor %s support T.38 for T.38 gateway session\n", ast_channel_name(active), ast_channel_name(other));
3077  }
3078  }
3079 
3080  return f;
3081 }
if(!yyg->yy_init)
Definition: ast_expr2f.c:868
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:5179
static struct ast_frame * fax_gateway_request_t38(struct fax_gateway *gateway, struct ast_channel *chan)
Definition: res_fax.c:2971
struct ast_channel * chan
Definition: res_fax.h:224
int(*const write)(struct ast_fax_session *, const struct ast_frame *)
Definition: res_fax.h:257
int detected_v21
1 if a v21 preamble has been detected
Definition: res_fax.c:457

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

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

3383 {
3384  struct fax_gateway *gateway = data;
3385  struct ast_channel *active;
3386  RAII_VAR(struct ast_fax_session_details *, details, NULL, ao2_cleanup);
3387  RAII_VAR(struct ast_channel *, peer, NULL, ao2_cleanup);
3388  RAII_VAR(struct ast_channel *, chan_ref, chan, ao2_cleanup);
3389 
3390  /* Ref bump channel for when we have to unlock it */
3391  ao2_ref(chan_ref, 1);
3392 
3393  if (gateway->s) {
3394  details = gateway->s->details;
3395  ao2_ref(details, 1);
3396  } else {
3397  if (!(details = find_details(chan))) {
3398  ast_log(LOG_ERROR, "no FAX session details found on chan %s for T.38 gateway session, odd\n", ast_channel_name(chan));
3399  ast_framehook_detach(chan, gateway->framehook);
3400  return f;
3401  }
3402  }
3403 
3404  /* restore audio formats when we are detached */
3406  set_channel_variables(chan, details);
3407 
3408  if (gateway->bridged) {
3409  ast_set_read_format(chan, gateway->chan_read_format);
3410  ast_set_write_format(chan, gateway->chan_write_format);
3411 
3412  ast_channel_unlock(chan);
3413  peer = ast_channel_bridge_peer(chan);
3414  if (peer) {
3415  ast_set_read_format(peer, gateway->peer_read_format);
3416  ast_set_write_format(peer, gateway->peer_write_format);
3417  ast_channel_make_compatible(chan, peer);
3418  }
3419  ast_channel_lock(chan);
3420  }
3421  return NULL;
3422  }
3423 
3424  if (!f || (event == AST_FRAMEHOOK_EVENT_ATTACHED)) {
3425  return NULL;
3426  };
3427 
3428  /* this frame was generated by the fax gateway, pass it on */
3430  return f;
3431  }
3432 
3433  /* If we aren't bridged or we don't have a peer, don't do anything */
3434  ast_channel_unlock(chan);
3435  peer = ast_channel_bridge_peer(chan);
3436  ast_channel_lock(chan);
3437  if (!peer) {
3438  return f;
3439  }
3440 
3441  if (!gateway->bridged) {
3442  enum ast_t38_state state_chan;
3443  enum ast_t38_state state_peer;
3444  int chan_is_hungup;
3445  int peer_is_hungup;
3446 
3447  chan_is_hungup = ast_check_hangup(chan);
3448  peer_is_hungup = ast_check_hangup(peer);
3449  /* Don't start a gateway if either channel is hung up */
3450  if (chan_is_hungup || peer_is_hungup) {
3451  return f;
3452  }
3453 
3454  ast_channel_unlock(chan);
3455  state_chan = ast_channel_get_t38_state(chan);
3456  state_peer = ast_channel_get_t38_state(peer);
3457  ast_channel_lock(chan);
3458 
3459  /* don't start a gateway if neither channel can handle T.38 */
3460  if (state_chan == T38_STATE_UNAVAILABLE && state_peer == T38_STATE_UNAVAILABLE) {
3461  ast_debug(1, "not starting gateway for %s and %s; neither channel supports T.38\n", ast_channel_name(chan), ast_channel_name(peer));
3462  ast_framehook_detach(chan, gateway->framehook);
3463  details->gateway_id = -1;
3464 
3465  ast_string_field_set(details, result, "FAILED");
3466  ast_string_field_set(details, resultstr, "neither channel supports T.38");
3467  ast_string_field_set(details, error, "T38_NEG_ERROR");
3468  details->is_t38_negotiated = 0;
3469  set_channel_variables(chan, details);
3470  return f;
3471  }
3472 
3473  if (details->gateway_timeout) {
3474  gateway->timeout_start = ast_tvnow();
3475  }
3476 
3477  ast_channel_unlock(chan);
3478  ast_channel_lock_both(chan, peer);
3479 
3480  /* we are bridged, change r/w formats to SLIN for v21 preamble
3481  * detection and T.30 */
3484 
3487 
3490 
3493 
3494  ast_channel_unlock(peer);
3495 
3496  gateway->bridged = 1;
3497  if (!(gateway->peer_v21_session = fax_v21_session_new(peer))) {
3498  ast_log(LOG_ERROR, "Can't create V21 session on chan %s for T.38 gateway session\n", ast_channel_name(peer));
3499  ast_framehook_detach(chan, gateway->framehook);
3500  return f;
3501  }
3502  }
3503 
3504  if (gateway->bridged && !ast_tvzero(gateway->timeout_start)) {
3505  if (ast_tvdiff_ms(ast_tvnow(), gateway->timeout_start) > details->gateway_timeout) {
3506  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);
3507  ast_framehook_detach(chan, gateway->framehook);
3508  details->gateway_id = -1;
3509 
3510  ast_string_field_set(details, result, "FAILED");
3511  ast_string_field_build(details, resultstr, "no fax activity after %d ms", details->gateway_timeout);
3512  ast_string_field_set(details, error, "TIMEOUT");
3513  details->is_t38_negotiated = 0;
3514  set_channel_variables(chan, details);
3515  return f;
3516  }
3517  }
3518 
3519  /* only handle VOICE, MODEM, and CONTROL frames*/
3520  switch (f->frametype) {
3521  case AST_FRAME_VOICE:
3525  return f;
3526  }
3527  break;
3528  case AST_FRAME_MODEM:
3529  if (f->subclass.integer == AST_MODEM_T38) {
3530  break;
3531  }
3532  return f;
3533  case AST_FRAME_CONTROL:
3535  break;
3536  }
3537  return f;
3538  default:
3539  return f;
3540  }
3541 
3542  /* detect the active channel */
3543  switch (event) {
3545  active = peer;
3546  break;
3548  active = chan;
3549  break;
3550  default:
3551  ast_log(LOG_WARNING, "unhandled framehook event %u\n", event);
3552  return f;
3553  }
3554 
3555  /* handle control frames */
3557  return fax_gateway_detect_t38(gateway, chan, peer, active, f);
3558  }
3559 
3560  if (!gateway->detected_v21 && gateway->t38_state == T38_STATE_UNAVAILABLE && f->frametype == AST_FRAME_VOICE) {
3561  /* not in gateway mode and have not detected v21 yet, listen
3562  * for v21 */
3563  return fax_gateway_detect_v21(gateway, chan, peer, active, f);
3564  }
3565 
3566  /* in gateway mode, gateway some packets */
3567  if (gateway->t38_state == T38_STATE_NEGOTIATED) {
3568  struct ast_trans_pvt *readtrans;
3569 
3570  if (!gateway->s || !gateway->s->tech_pvt) {
3571  ast_log(LOG_ERROR, "no FAX session on chan %s for T.38 gateway session, odd", ast_channel_name(chan));
3572  return f;
3573  }
3574 
3575  /* framehooks are called in __ast_read() before frame format
3576  * translation is done, so we need to translate here */
3578  && (readtrans = ast_channel_readtrans(active))) {
3579  if ((f = ast_translate(readtrans, f, event == AST_FRAMEHOOK_EVENT_WRITE ? 0 : 1)) == NULL) {
3580  f = &ast_null_frame;
3581  return f;
3582  }
3583  /* XXX we ignore the return value here, perhaps we should
3584  * disable the gateway if a write fails. I am not sure how a
3585  * write would fail, or even if a failure would be fatal so for
3586  * now we'll just ignore the return value. */
3587  gateway->s->tech->write(gateway->s, f);
3588  ast_frfree(f);
3589  } else {
3590  gateway->s->tech->write(gateway->s, f);
3591  }
3592 
3593  f = &ast_null_frame;
3594  return f;
3595  }
3596 
3597  /* force silence on the line if T.38 negotiation might be taking place */
3598  if (gateway->t38_state != T38_STATE_UNAVAILABLE && gateway->t38_state != T38_STATE_REJECTED) {
3599  if (f->frametype == AST_FRAME_VOICE &&
3601  short silence_buf[f->samples];
3602  struct ast_frame silence_frame = {
3604  .subclass.format = ast_format_slin,
3605  .data.ptr = silence_buf,
3606  .samples = f->samples,
3607  .datalen = sizeof(silence_buf),
3608  };
3609  memset(silence_buf, 0, sizeof(silence_buf));
3610  return ast_frisolate(&silence_frame);
3611  } else {
3612  return &ast_null_frame;
3613  }
3614  }
3615 
3616  return f;
3617 }
struct ast_format * ast_channel_writeformat(struct ast_channel *chan)
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
Definition: channel.h:2929
struct ast_trans_pvt * ast_channel_readtrans(const struct ast_channel *chan)
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:445
int ast_set_write_format(struct ast_channel *chan, struct ast_format *format)
Sets write format on channel chan.
Definition: channel.c:5880
@ AST_FRAMEHOOK_EVENT_WRITE
Definition: framehook.h:153
#define ast_frisolate(fr)
Makes a frame independent of any static storage.
#define AST_MODEM_T38
@ AST_FRAME_MODEM
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:3108
static struct ast_fax_session * fax_v21_session_new(struct ast_channel *chan)
Definition: res_fax.c:2860
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:3011
#define AST_FAX_FRFLAG_GATEWAY
Definition: res_fax.h:232
#define ast_string_field_build(x, field, fmt, args...)
Set a field to a complex (built) value.
Definition: stringfields.h:555
Default structure for translators, with the basic fields and buffers, all allocated as part of the sa...
Definition: translate.h:213
struct ast_frame f
Definition: translate.h:215
int bridged
bridged
Definition: res_fax.c:455
struct ast_frame * ast_translate(struct ast_trans_pvt *tr, struct ast_frame *f, int consume)
translates one or more frames Apply an input frame into the translator and receive zero or one output...
Definition: translate.c:565
#define ast_test_flag(p, flag)
Definition: utils.h:63

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(), fax_v21_session_new(), find_details(), ast_frame_subclass::format, fax_gateway::framehook, ast_frame::frametype, ast_frame_subclass::integer, LOG_ERROR, LOG_WARNING, NULL, fax_gateway::peer_read_format, fax_gateway::peer_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().

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

3345 {
3346  struct fax_gateway *gateway = data;
3347 
3348  if (gateway->s) {
3349  switch (gateway->s->state) {
3351  case AST_FAX_STATE_OPEN:
3352  case AST_FAX_STATE_ACTIVE:
3354  if (gateway->s->tech->cancel_session) {
3355  gateway->s->tech->cancel_session(gateway->s);
3356  }
3357  /* fall through */
3358  default:
3359  break;
3360  }
3361  }
3362 
3363  ao2_ref(gateway, -1);
3364 }
int(*const cancel_session)(struct ast_fax_session *)
Definition: res_fax.h:261

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

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

3085 {
3086  if (active == chan) {
3087  ast_channel_unlock(chan);
3088  ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, control_params, sizeof(*control_params));
3089  ast_channel_lock(chan);
3090  } else {
3091  ast_queue_control_data(chan, AST_CONTROL_T38_PARAMETERS, control_params, sizeof(*control_params));
3092  }
3093 }
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:1232

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

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

2880 {
2881  struct fax_gateway *gateway = ao2_alloc(sizeof(*gateway), destroy_gateway);
2882  if (!gateway) {
2883  return NULL;
2884  }
2885 
2886  if (!(gateway->chan_v21_session = fax_v21_session_new(chan))) {
2887  ast_log(LOG_ERROR, "Can't create V21 session on chan %s for T.38 gateway session\n", ast_channel_name(chan));
2888  ao2_ref(gateway, -1);
2889  return NULL;
2890  }
2891 
2892  gateway->framehook = -1;
2893 
2894  details->caps = AST_FAX_TECH_GATEWAY;
2895  if (details->gateway_timeout && !(gateway->s = fax_session_reserve(details, &gateway->token))) {
2896  details->caps &= ~AST_FAX_TECH_GATEWAY;
2897  ast_log(LOG_ERROR, "Can't reserve a FAX session, gateway attempt failed.\n");
2898  ao2_ref(gateway, -1);
2899  return NULL;
2900  }
2901 
2902  return gateway;
2903 }
static void destroy_gateway(void *data)
destroy a FAX gateway session structure
Definition: res_fax.c:2838
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:1145

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_v21_session_new(), fax_gateway::framehook, ast_fax_session_details::gateway_timeout, LOG_ERROR, NULL, fax_gateway::s, and fax_gateway::token.

Referenced by fax_gateway_attach().

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

2972 {
2973  struct ast_frame *fp;
2974  struct ast_control_t38_parameters t38_parameters = {
2976  };
2977  struct ast_frame control_frame = {
2978  .src = "res_fax",
2979  .frametype = AST_FRAME_CONTROL,
2980  .datalen = sizeof(t38_parameters),
2982  .data.ptr = &t38_parameters,
2983  };
2984 
2985  struct ast_fax_session_details *details = find_details(chan);
2986 
2987  if (!details) {
2988  ast_log(LOG_ERROR, "no FAX session details found on chan %s for T.38 gateway session, odd\n", ast_channel_name(chan));
2989  ast_framehook_detach(chan, gateway->framehook);
2990  return NULL;
2991  }
2992 
2993  t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
2994  ao2_ref(details, -1);
2995 
2996  if (!(fp = ast_frisolate(&control_frame))) {
2997  ast_log(LOG_ERROR, "error generating T.38 request control frame on chan %s for T.38 gateway session\n", ast_channel_name(chan));
2998  return NULL;
2999  }
3000 
3001  gateway->t38_state = T38_STATE_NEGOTIATING;
3002  gateway->timeout_start = ast_tvnow();
3003  details->is_t38_negotiated = 0;
3005 
3006  ast_debug(1, "requesting T.38 for gateway session for %s\n", ast_channel_name(chan));
3007  return fp;
3008 }
const char * src

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

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

2917 {
2918  struct ast_fax_session *s;
2919  int start_res;
2920 
2921  /* if the fax gateway is already started then do nothing */
2922  if (gateway->s &&
2923  gateway->s->state != AST_FAX_STATE_RESERVED && gateway->s->state != AST_FAX_STATE_INACTIVE) {
2924  return 0;
2925  }
2926 
2927  /* if we start gateway we don't need v21 detection sessions any more */
2928  destroy_v21_sessions(gateway);
2929 
2930  /* create the FAX session */
2931  if (!(s = fax_session_new(details, chan, gateway->s, gateway->token))) {
2932  gateway->token = NULL;
2933  ast_string_field_set(details, result, "FAILED");
2934  ast_string_field_set(details, resultstr, "error starting gateway session");
2935  ast_string_field_set(details, error, "INIT_ERROR");
2938  report_fax_status(chan, details, "No Available Resource");
2939  ast_log(LOG_ERROR, "Can't create a FAX session, gateway attempt failed.\n");
2940  return -1;
2941  }
2942  /* release the reference for the reserved session and replace it with
2943  * the real session */
2944  if (gateway->s) {
2945  ao2_ref(gateway->s, -1);
2946  }
2947  gateway->s = s;
2948  gateway->token = NULL;
2949 
2951  start_res = gateway->s->tech->start_session(gateway->s);
2953  if (start_res < 0) {
2954  ast_string_field_set(details, result, "FAILED");
2955  ast_string_field_set(details, resultstr, "error starting gateway session");
2956  ast_string_field_set(details, error, "INIT_ERROR");
2959  return -1;
2960  }
2961 
2962  gateway->timeout_start.tv_sec = 0;
2963  gateway->timeout_start.tv_usec = 0;
2964 
2965  report_fax_status(chan, details, "FAX Transmission In Progress");
2966 
2967  return 0;
2968 }
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:1214
int(*const start_session)(struct ast_fax_session *)
Definition: res_fax.h:259

References ao2_ref, ast_channel_lock, ast_channel_unlock, AST_FAX_STATE_INACTIVE, AST_FAX_STATE_RESERVED, ast_log, ast_string_field_set, ast_fax_session::chan, destroy_v21_sessions(), ast_fax_session::details, 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().

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

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

References ast_log, LOG_ERROR, and LOG_WARNING.

Referenced by set_config().

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

1215 {
1216  struct ast_fax_session *s = NULL;
1217  struct fax_module *faxmod;
1218 
1219  if (reserved) {
1220  s = reserved;
1221  ao2_ref(reserved, +1);
1222  ao2_unlink(faxregistry.container, reserved);
1223 
1224  /* NOTE: we don't consume the reference to the reserved
1225  * session. The session returned from fax_session_new() is a
1226  * new reference and must be derefed in addition to the
1227  * reserved session.
1228  */
1229 
1230  if (s->state == AST_FAX_STATE_RESERVED) {
1231  ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, -1);
1233  }
1234  }
1235 
1236  if (!s && !(s = ao2_alloc(sizeof(*s), destroy_session))) {
1237  return NULL;
1238  }
1239 
1240  ast_atomic_fetchadd_int(&faxregistry.active_sessions, 1);
1242 
1243  if (details->option.debug && (details->caps & AST_FAX_TECH_AUDIO)) {
1244  if (!(s->debug_info = ast_calloc(1, sizeof(*(s->debug_info))))) {
1245  fax_session_release(s, token);
1246  ao2_ref(s, -1);
1247  return NULL;
1248  }
1249  if (!(s->debug_info->dsp = ast_dsp_new())) {
1250  ast_free(s->debug_info);
1251  s->debug_info = NULL;
1252  fax_session_release(s, token);
1253  ao2_ref(s, -1);
1254  return NULL;
1255  }
1257  }
1258 
1259  if (!(s->channame = ast_strdup(ast_channel_name(chan)))) {
1260  fax_session_release(s, token);
1261  ao2_ref(s, -1);
1262  return NULL;
1263  }
1264 
1265  if (!(s->chan_uniqueid = ast_strdup(ast_channel_uniqueid(chan)))) {
1266  fax_session_release(s, token);
1267  ao2_ref(s, -1);
1268  return NULL;
1269  }
1270 
1271  s->chan = chan;
1272  if (!s->details) {
1273  s->details = details;
1274  ao2_ref(s->details, 1);
1275  }
1276 
1277  details->id = s->id = ast_atomic_fetchadd_int(&faxregistry.nextsessionname, 1);
1278 
1279  if (!token) {
1280  /* locate a FAX technology module that can handle said requirements */
1282  AST_RWLIST_TRAVERSE(&faxmodules, faxmod, list) {
1283  if ((faxmod->tech->caps & details->caps) != details->caps) {
1284  continue;
1285  }
1286  if (!ast_module_running_ref(faxmod->tech->module)) {
1287  continue;
1288  }
1289  ast_debug(4, "Requesting a new FAX session from '%s'.\n", faxmod->tech->description);
1290  if (reserved) {
1291  /* Balance module ref from reserved session */
1292  ast_module_unref(reserved->tech->module);
1293  }
1294  s->tech = faxmod->tech;
1295  break;
1296  }
1298 
1299  if (!faxmod) {
1300  char caps[128] = "";
1301  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)));
1302  ao2_ref(s, -1);
1303  return NULL;
1304  }
1305  }
1306 
1307  if (!(s->tech_pvt = s->tech->new_session(s, token))) {
1308  ast_log(LOG_ERROR, "FAX session failed to initialize.\n");
1309  ao2_ref(s, -1);
1310  return NULL;
1311  }
1312  /* link the session to the session container */
1313  if (!(ao2_link(faxregistry.container, s))) {
1314  ast_log(LOG_ERROR, "failed to add FAX session '%u' to container.\n", s->id);
1315  ao2_ref(s, -1);
1316  return NULL;
1317  }
1318  ast_debug(4, "channel '%s' using FAX session '%u'\n", s->channame, s->id);
1319 
1320  return s;
1321 }
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
const char * ast_channel_uniqueid(const struct ast_channel *chan)
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:1778
#define ast_module_running_ref(mod)
Hold a reference to the module if it is running.
Definition: module.h:455
static char * ast_fax_caps_to_str(enum ast_fax_capabilities caps, char *buf, size_t bufsize)
Definition: res_fax.c:845
static void destroy_session(void *session)
destroy a FAX session structure
Definition: res_fax.c:1095
enum ast_fax_capabilities caps
Definition: res_fax.h:243
void *(*const new_session)(struct ast_fax_session *, struct ast_fax_tech_token *)
Definition: res_fax.h:251

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

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

1083 {
1084  if (token) {
1085  s->tech->release_token(token);
1086  }
1087 
1088  if (s->state == AST_FAX_STATE_RESERVED) {
1089  ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, -1);
1091  }
1092 }
void(*const release_token)(struct ast_fax_tech_token *)
Definition: res_fax.h:249

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

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

1146 {
1147  struct ast_fax_session *s;
1148  struct fax_module *faxmod;
1149 
1150  if (!(s = ao2_alloc(sizeof(*s), destroy_session))) {
1151  return NULL;
1152  }
1153 
1155  s->details = details;
1156  ao2_ref(s->details, 1);
1157 
1158  /* locate a FAX technology module that can handle said requirements
1159  * Note: the requirements have not yet been finalized as T.38
1160  * negotiation has not yet occured. */
1162  AST_RWLIST_TRAVERSE(&faxmodules, faxmod, list) {
1163  if ((faxmod->tech->caps & details->caps) != details->caps) {
1164  continue;
1165  }
1166  if (!ast_module_running_ref(faxmod->tech->module)) {
1167  continue;
1168  }
1169  ast_debug(4, "Reserving a FAX session from '%s'.\n", faxmod->tech->description);
1170  s->tech = faxmod->tech;
1171  break;
1172  }
1174 
1175  if (!faxmod) {
1176  char caps[128] = "";
1177  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)));
1178  ao2_ref(s, -1);
1179  return NULL;
1180  }
1181 
1182  if (!s->tech->reserve_session) {
1183  ast_debug(1, "Selected FAX technology module (%s) does not support reserving sessions.\n", s->tech->description);
1184  return s;
1185  }
1186 
1187  if (!(*token = s->tech->reserve_session(s))) {
1188  ao2_ref(s, -1);
1189  return NULL;
1190  }
1191 
1193  ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, 1);
1194 
1195  return s;
1196 }
struct ast_fax_tech_token *(*const reserve_session)(struct ast_fax_session *)
Definition: res_fax.h:247

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

◆ fax_session_tab_complete()

static char* fax_session_tab_complete ( struct ast_cli_args a)
static

fax session tab completion

Definition at line 3942 of file res_fax.c.

3943 {
3944  int tklen;
3945  int wordnum = 0;
3946  char *name = NULL;
3947  struct ao2_iterator i;
3948  struct ast_fax_session *s;
3949  char tbuf[5];
3950 
3951  if (a->pos != 3) {
3952  return NULL;
3953  }
3954 
3955  tklen = strlen(a->word);
3956  i = ao2_iterator_init(faxregistry.container, 0);
3957  while ((s = ao2_iterator_next(&i))) {
3958  snprintf(tbuf, sizeof(tbuf), "%u", s->id);
3959  if (!strncasecmp(a->word, tbuf, tklen) && ++wordnum > a->n) {
3960  name = ast_strdup(tbuf);
3961  ao2_ref(s, -1);
3962  break;
3963  }
3964  ao2_ref(s, -1);
3965  }
3967  return name;
3968 }
static const char name[]
Definition: format_mp3.c:68

References a, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_strdup, faxregistry, ast_fax_session::id, name, and NULL.

Referenced by cli_fax_show_session().

◆ fax_session_type()

static const char* fax_session_type ( struct ast_fax_session s)
static

Definition at line 4241 of file res_fax.c.

4242 {
4243  if (s->details->caps & AST_FAX_TECH_AUDIO) {
4244  return "G.711";
4245  }
4246  if (s->details->caps & AST_FAX_TECH_T38) {
4247  return "T.38";
4248  }
4249 
4250  return "none";
4251 }

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

Referenced by cli_fax_show_sessions(), and manager_fax_sessions_entry().

◆ fax_v21_session_new()

static struct ast_fax_session * fax_v21_session_new ( struct ast_channel chan)
static

Definition at line 2860 of file res_fax.c.

2860  {
2861  struct ast_fax_session_details *v21_details;
2862  struct ast_fax_session *v21_session;
2863 
2864  if (!chan || !(v21_details = session_details_new())) {
2865  return NULL;
2866  }
2867 
2868  v21_details->caps = AST_FAX_TECH_V21_DETECT;
2869  v21_session = fax_session_new(v21_details, chan, NULL, NULL);
2870  ao2_ref(v21_details, -1);
2871  return v21_session;
2872 }
static struct ast_fax_session_details * session_details_new(void)
create a FAX session details structure
Definition: res_fax.c:695

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

Referenced by fax_gateway_framehook(), and fax_gateway_new().

◆ find_details()

static struct ast_fax_session_details* find_details ( struct ast_channel chan)
static

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

Definition at line 661 of file res_fax.c.

662 {
663  struct ast_fax_session_details *details;
664  struct ast_datastore *datastore;
665 
666  ast_channel_lock(chan);
667  if (!(datastore = ast_channel_datastore_find(chan, &fax_datastore, NULL))) {
668  ast_channel_unlock(chan);
669  return NULL;
670  }
671  if (!(details = datastore->data)) {
672  ast_log(LOG_WARNING, "Huh? channel '%s' has a FAX datastore without data!\n", ast_channel_name(chan));
673  ast_channel_unlock(chan);
674  return NULL;
675  }
676  ao2_ref(details, 1);
677  ast_channel_unlock(chan);
678 
679  return details;
680 }
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2398
static const struct ast_datastore_info fax_datastore
Definition: res_fax.c:618
Structure for a data store object.
Definition: datastore.h:64
void * data
Definition: datastore.h:66

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

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

◆ find_or_create_details()

static struct ast_fax_session_details * find_or_create_details ( struct ast_channel chan)
static

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

Definition at line 763 of file res_fax.c.

764 {
765  struct ast_fax_session_details *details;
766  struct ast_datastore *datastore;
767 
768  if ((details = find_details(chan))) {
769  return details;
770  }
771  /* channel does not have one so we must create one */
772  if (!(details = session_details_new())) {
773  ast_log(LOG_WARNING, "channel '%s' can't get a FAX details structure for the datastore!\n", ast_channel_name(chan));
774  return NULL;
775  }
776  if (!(datastore = ast_datastore_alloc(&fax_datastore, NULL))) {
777  ao2_ref(details, -1);
778  ast_log(LOG_WARNING, "channel '%s' can't get a datastore!\n", ast_channel_name(chan));
779  return NULL;
780  }
781  /* add the datastore to the channel and increment the refcount */
782  datastore->data = details;
783 
784  /* initialize default T.38 parameters */
787 
788  ao2_ref(details, 1);
789  ast_channel_lock(chan);
790  ast_channel_datastore_add(chan, datastore);
791  ast_channel_unlock(chan);
792  return details;
793 }
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2384
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:85
static struct ast_control_t38_parameters our_t38_parameters
Definition: res_fax.c:732

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

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

◆ fixup_callback()

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

Copies fax detection and gateway framehooks during masquerades.

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

Definition at line 635 of file res_fax.c.

636 {
637  struct ast_fax_session_details *old_details = data;
638  struct ast_datastore *datastore = ast_channel_datastore_find(old_chan, &fax_datastore, NULL);
639 
640  if (old_details->gateway_id >= 0) {
641  struct ast_fax_session_details *new_details = find_or_create_details(new_chan);
642 
643  ast_framehook_detach(old_chan, old_details->gateway_id);
644  new_details->is_t38_negotiated = old_details->is_t38_negotiated;
645  fax_gateway_attach(new_chan, new_details);
646  ao2_cleanup(new_details);
647  }
648 
649  if (old_details->faxdetect_id >= 0) {
650  ast_framehook_detach(old_chan, old_details->faxdetect_id);
651  fax_detect_attach(new_chan, old_details->faxdetect_timeout, old_details->faxdetect_flags);
652  }
653 
654  if (datastore) {
655  ast_channel_datastore_remove(old_chan, datastore);
656  ast_datastore_free(datastore);
657  }
658 }
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition: channel.c:2393
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68

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

◆ generate_filenames_json()

static struct ast_json* generate_filenames_json ( struct ast_fax_session_details details)
static

Definition at line 1329 of file res_fax.c.

1330 {
1331  RAII_VAR(struct ast_json *, json_array, ast_json_array_create(), ast_json_unref);
1332  struct ast_fax_document *doc;
1333 
1334  if (!details || !json_array) {
1335  return NULL;
1336  }
1337 
1338  /* don't process empty lists */
1339  if (AST_LIST_EMPTY(&details->documents)) {
1340  return NULL;
1341  }
1342 
1343  AST_LIST_TRAVERSE(&details->documents, doc, next) {
1345  if (!entry) {
1346  return NULL;
1347  }
1348  if (ast_json_array_append(json_array, entry)) {
1349  return NULL;
1350  }
1351  }
1352 
1353  ast_json_ref(json_array);
1354  return json_array;
1355 }
struct ast_json * ast_json_ref(struct ast_json *value)
Increase refcount on value.
Definition: json.c:67
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
int ast_json_array_append(struct ast_json *array, struct ast_json *value)
Append to an array.
Definition: json.c:368
struct ast_json * ast_json_array_create(void)
Create a empty JSON array.
Definition: json.c:352
struct ast_json * ast_json_string_create(const char *value)
Construct a JSON string from value.
Definition: json.c:268
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
char filename[0]
Definition: res_fax.h:104
Abstract JSON element (object, array, string, int, ...).
Definition: search.h:40

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

Referenced by report_fax_status(), and report_send_fax_status().

◆ generate_filenames_string()

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

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

Parameters
detailsthe fax session details
prefixthe prefix to each filename
separatorthe separator between filenames

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

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

Definition at line 1369 of file res_fax.c.

1370 {
1371  char *filenames, *c;
1372  size_t size = 0;
1373  int first = 1;
1374  struct ast_fax_document *doc;
1375 
1376  /* don't process empty lists */
1377  if (AST_LIST_EMPTY(&details->documents)) {
1378  return ast_strdup("");
1379  }
1380 
1381  /* Calculate the total length of all of the file names */
1382  AST_LIST_TRAVERSE(&details->documents, doc, next) {
1383  size += strlen(separator) + strlen(prefix) + strlen(doc->filename);
1384  }
1385  size += 1; /* add space for the terminating null */
1386 
1387  if (!(filenames = ast_malloc(size))) {
1388  return NULL;
1389  }
1390  c = filenames;
1391 
1392  ast_build_string(&c, &size, "%s%s", prefix, AST_LIST_FIRST(&details->documents)->filename);
1393  AST_LIST_TRAVERSE(&details->documents, doc, next) {
1394  if (first) {
1395  first = 0;
1396  continue;
1397  }
1398 
1399  ast_build_string(&c, &size, "%s%s%s", separator, prefix, doc->filename);
1400  }
1401 
1402  return filenames;
1403 }
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
static char prefix[MAX_PREFIX]
Definition: http.c:144
static struct test_val c

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

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

◆ generic_fax_exec()

static int generic_fax_exec ( struct ast_channel chan,
struct ast_fax_session_details details,
struct ast_fax_session reserved,
struct ast_fax_tech_token *  token 
)
static

this is the generic FAX session handling function

Definition at line 1589 of file res_fax.c.

1590 {
1591  int ms;
1592  int timeout = RES_FAX_TIMEOUT;
1593  int chancount;
1594  unsigned int expected_frametype = -1;
1595  struct ast_frame_subclass expected_framesubclass = { .integer = 0, };
1596  unsigned int t38negotiated = (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED);
1597  struct ast_control_t38_parameters t38_parameters;
1598  const char *tempvar;
1599  struct ast_fax_session *fax = NULL;
1600  struct ast_frame *frame = NULL;
1601  struct ast_channel *c = chan;
1602  RAII_VAR(struct ast_format *, orig_write_format, NULL, ao2_cleanup);
1603  RAII_VAR(struct ast_format *, orig_read_format, NULL, ao2_cleanup);
1604  int remaining_time;
1605  struct timeval start;
1606 
1607  chancount = 1;
1608 
1609  /* Make sure one or the other is set to avoid race condition */
1610  if (t38negotiated) {
1611  details->caps |= AST_FAX_TECH_T38;
1612  } else {
1613  details->caps |= AST_FAX_TECH_AUDIO;
1614  }
1615 
1616  /* create the FAX session */
1617  if (!(fax = fax_session_new(details, chan, reserved, token))) {
1618  ast_log(LOG_ERROR, "Can't create a FAX session, FAX attempt failed.\n");
1619  report_fax_status(chan, details, "No Available Resource");
1620  return -1;
1621  }
1622 
1623  ast_channel_lock(chan);
1624  /* update session details */
1625  if (ast_strlen_zero(details->headerinfo) && (tempvar = pbx_builtin_getvar_helper(chan, "LOCALHEADERINFO"))) {
1626  ast_string_field_set(details, headerinfo, tempvar);
1627  }
1628  if (ast_strlen_zero(details->localstationid)) {
1629  tempvar = pbx_builtin_getvar_helper(chan, "LOCALSTATIONID");
1630  ast_string_field_set(details, localstationid, tempvar ? tempvar : "unknown");
1631  }
1632  ast_channel_unlock(chan);
1633 
1634  report_fax_status(chan, details, "Allocating Resources");
1635 
1636  if (details->caps & AST_FAX_TECH_AUDIO) {
1637  expected_frametype = AST_FRAME_VOICE;
1638  expected_framesubclass.format = ast_format_slin;
1639  orig_write_format = ao2_bump(ast_channel_writeformat(chan));
1640  if (ast_set_write_format(chan, ast_format_slin) < 0) {
1641  ast_log(LOG_ERROR, "channel '%s' failed to set write format to signed linear'.\n", ast_channel_name(chan));
1642  ao2_unlink(faxregistry.container, fax);
1643  ao2_ref(fax, -1);
1644  return -1;
1645  }
1646  orig_read_format = ao2_bump(ast_channel_readformat(chan));
1647  if (ast_set_read_format(chan, ast_format_slin) < 0) {
1648  ast_log(LOG_ERROR, "channel '%s' failed to set read format to signed linear.\n", ast_channel_name(chan));
1649  ao2_unlink(faxregistry.container, fax);
1650  ao2_ref(fax, -1);
1651  return -1;
1652  }
1653  if (fax->smoother) {
1655  fax->smoother = NULL;
1656  }
1657  if (!(fax->smoother = ast_smoother_new(320))) {
1658  ast_log(LOG_WARNING, "Channel '%s' FAX session '%u' failed to obtain a smoother.\n", ast_channel_name(chan), fax->id);
1659  }
1660  } else {
1661  expected_frametype = AST_FRAME_MODEM;
1662  expected_framesubclass.integer = AST_MODEM_T38;
1663  }
1664 
1665  if (fax->debug_info) {
1666  fax->debug_info->base_tv = ast_tvnow();
1667  }
1668 
1669  /* reset our result fields just in case the fax tech driver wants to
1670  * set custom error messages */
1671  ast_string_field_set(details, result, "");
1672  ast_string_field_set(details, resultstr, "");
1673  ast_string_field_set(details, error, "");
1674  details->is_t38_negotiated = t38negotiated;
1675  set_channel_variables(chan, details);
1676 
1677  if (fax->tech->start_session(fax) < 0) {
1678  GENERIC_FAX_EXEC_ERROR(fax, chan, "INIT_ERROR", "failed to start FAX session");
1679  }
1680 
1681  report_fax_status(chan, details, "FAX Transmission In Progress");
1682 
1683  ast_debug(5, "channel %s will wait on FAX fd %d\n", ast_channel_name(chan), fax->fd);
1684 
1685  /* handle frames for the session */
1686  remaining_time = timeout;
1687  start = ast_tvnow();
1688  while (remaining_time > 0) {
1689  struct ast_channel *ready_chan;
1690  int ofd, exception;
1691 
1692  ms = 1000;
1693  errno = 0;
1694  ready_chan = ast_waitfor_nandfds(&c, chancount, &fax->fd, 1, &exception, &ofd, &ms);
1695  if (ready_chan) {
1696  if (!(frame = ast_read(chan))) {
1697  /* the channel is probably gone, so lets stop polling on it and let the
1698  * FAX session complete before we exit the application. if needed,
1699  * send the FAX stack silence so the modems can finish their session without
1700  * any problems */
1701  ast_debug(1, "Channel '%s' did not return a frame; probably hung up.\n", ast_channel_name(chan));
1702  GENERIC_FAX_EXEC_SET_VARS(fax, chan, "HANGUP", "remote channel hungup");
1703  c = NULL;
1704  chancount = 0;
1705  remaining_time = ast_remaining_ms(start, timeout);
1706  fax->tech->cancel_session(fax);
1707  if (fax->tech->generate_silence) {
1708  fax->tech->generate_silence(fax);
1709  }
1710  continue;
1711  }
1712 
1713  if ((frame->frametype == AST_FRAME_CONTROL) &&
1715  (frame->datalen == sizeof(t38_parameters))) {
1716  unsigned int was_t38 = t38negotiated;
1717  struct ast_control_t38_parameters *parameters = frame->data.ptr;
1718 
1719  switch (parameters->request_response) {
1721  /* the other end has requested a switch to T.38, so reply that we are willing, if we can
1722  * do T.38 as well
1723  */
1724  t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
1725  if (details->caps & AST_FAX_TECH_T38) {
1726  details->is_t38_negotiated = 1;
1727  t38_parameters.request_response = AST_T38_NEGOTIATED;
1728  } else {
1729  t38_parameters.request_response = AST_T38_REFUSED;
1730  }
1731  ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
1732  break;
1733  case AST_T38_NEGOTIATED:
1734  t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
1735  t38negotiated = 1;
1736  details->is_t38_negotiated = 1;
1737  break;
1738  default:
1739  break;
1740  }
1741  if (t38negotiated && !was_t38) {
1742  if (fax->tech->switch_to_t38(fax)) {
1743  GENERIC_FAX_EXEC_ERROR(fax, chan, "UNKNOWN", "T.38 switch failed");
1744  break;
1745  }
1746  details->caps &= ~AST_FAX_TECH_AUDIO;
1747  expected_frametype = AST_FRAME_MODEM;
1748  expected_framesubclass.integer = AST_MODEM_T38;
1749  if (fax->smoother) {
1751  fax->smoother = NULL;
1752  }
1753 
1754  report_fax_status(chan, details, "T.38 Negotiated");
1755 
1756  ast_verb(3, "Channel '%s' switched to T.38 FAX session '%u'.\n", ast_channel_name(chan), fax->id);
1757  }
1758  } else if ((frame->frametype == expected_frametype) && (expected_framesubclass.integer == frame->subclass.integer) &&
1759  ((!frame->subclass.format && !expected_framesubclass.format) ||
1760  (frame->subclass.format && expected_framesubclass.format &&
1761  (ast_format_cmp(frame->subclass.format, expected_framesubclass.format) != AST_FORMAT_CMP_NOT_EQUAL)))) {
1762  struct ast_frame *f;
1763 
1764  if (fax->smoother) {
1765  /* push the frame into a smoother */
1766  if (ast_smoother_feed(fax->smoother, frame) < 0) {
1767  GENERIC_FAX_EXEC_ERROR(fax, chan, "UNKNOWN", "Failed to feed the smoother");
1768  }
1769  while ((f = ast_smoother_read(fax->smoother)) && (f->data.ptr)) {
1770  if (fax->debug_info) {
1771  debug_check_frame_for_silence(fax, 1, f);
1772  }
1773  /* write the frame to the FAX stack */
1774  fax->tech->write(fax, f);
1775  fax->frames_received++;
1776  if (f != frame) {
1777  ast_frfree(f);
1778  }
1779  }
1780  } else {
1781  /* write the frame to the FAX stack */
1782  fax->tech->write(fax, frame);
1783  fax->frames_received++;
1784  }
1785  start = ast_tvnow();
1786  }
1787  ast_frfree(frame);
1788  } else if (ofd == fax->fd) {
1789  /* read a frame from the FAX stack and send it out the channel.
1790  * the FAX stack will return a NULL if the FAX session has already completed */
1791  if (!(frame = fax->tech->read(fax))) {
1792  break;
1793  }
1794 
1795  if (fax->debug_info && (frame->frametype == AST_FRAME_VOICE)) {
1796  debug_check_frame_for_silence(fax, 0, frame);
1797  }
1798 
1799  ast_write(chan, frame);
1800  fax->frames_sent++;
1801  ast_frfree(frame);
1802  start = ast_tvnow();
1803  } else {
1804  if (ms && (ofd < 0)) {
1805  if ((errno == 0) || (errno == EINTR)) {
1806  remaining_time = ast_remaining_ms(start, timeout);
1807  if (remaining_time <= 0)
1808  GENERIC_FAX_EXEC_ERROR(fax, chan, "TIMEOUT", "fax session timed-out");
1809  continue;
1810  } else {
1811  ast_log(LOG_WARNING, "something bad happened while channel '%s' was polling.\n", ast_channel_name(chan));
1812  GENERIC_FAX_EXEC_ERROR(fax, chan, "UNKNOWN", "error polling data");
1813  break;
1814  }
1815  } else {
1816  /* nothing happened */
1817  remaining_time = ast_remaining_ms(start, timeout);
1818  if (remaining_time <= 0) {
1819  GENERIC_FAX_EXEC_ERROR(fax, chan, "TIMEOUT", "fax session timed-out");
1820  break;
1821  }
1822  }
1823  }
1824  }
1825  ast_debug(3, "channel '%s' - event loop stopped { timeout: %d, remaining_time: %d }\n", ast_channel_name(chan), timeout, remaining_time);
1826 
1827  set_channel_variables(chan, details);
1828 
1829  ast_atomic_fetchadd_int(&faxregistry.fax_complete, 1);
1830  if (!strcasecmp(details->result, "FAILED")) {
1831  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1832  }
1833 
1834  if (fax) {
1835  ao2_unlink(faxregistry.container, fax);
1836  ao2_ref(fax, -1);
1837  }
1838 
1839  /* if the channel is still alive, and we changed its read/write formats,
1840  * restore them now
1841  */
1842  if (chancount) {
1843  if (orig_read_format) {
1844  ast_set_read_format(chan, orig_read_format);
1845  }
1846  if (orig_write_format) {
1847  ast_set_write_format(chan, orig_write_format);
1848  }
1849  }
1850 
1851  /* return the chancount so the calling function can determine if the channel hungup during this FAX session or not */
1852  return chancount;
1853 }
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
static int chancount
Definition: channel.c:93
struct ast_channel * ast_waitfor_nandfds(struct ast_channel **c, int n, int *fds, int nfds, int *exception, int *outfd, int *ms)
Waits for activity on a group of channels.
Definition: channel.c:2989
@ AST_FORMAT_CMP_NOT_EQUAL
Definition: format.h:38
int errno
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
static void debug_check_frame_for_silence(struct ast_fax_session *s, unsigned int c2s, struct ast_frame *frame)
Definition: res_fax.c:576
#define GENERIC_FAX_EXEC_ERROR(fax, chan, errorstr, reason)
Definition: res_fax.c:1484
#define GENERIC_FAX_EXEC_SET_VARS(fax, chan, errorstr, reason)
Definition: res_fax.c:1468
#define RES_FAX_TIMEOUT
Definition: res_fax.c:491
struct ast_smoother * ast_smoother_new(int bytes)
Definition: smoother.c:108
#define ast_smoother_feed(s, f)
Definition: smoother.h:75
struct ast_frame * ast_smoother_read(struct ast_smoother *s)
Definition: smoother.c:169
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
unsigned long frames_received
Definition: res_fax.h:210
unsigned long frames_sent
Definition: res_fax.h:212
int(*const generate_silence)(struct ast_fax_session *)
Definition: res_fax.h:263
int(*const switch_to_t38)(struct ast_fax_session *)
Definition: res_fax.h:265
struct ast_frame *(*const read)(struct ast_fax_session *)
Definition: res_fax.h:255
Definition of a media format.
Definition: format.c:43

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

Referenced by receivefax_exec(), and sendfax_exec().

◆ get_general_options()

static void get_general_options ( struct fax_options options)
static

Definition at line 4396 of file res_fax.c.

4397 {
4401 }
#define ast_rwlock_rdlock(a)
Definition: lock.h:233
#define ast_rwlock_unlock(a)
Definition: lock.h:232
static ast_rwlock_t options_lock
Definition: res_fax.c:547
static struct fax_options general_options
Definition: res_fax.c:536

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

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

◆ load_module()

static int load_module ( void  )
static

Load the module.

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

Definition at line 4787 of file res_fax.c.

4788 {
4789  int res;
4790 
4791  /* initialize the registry */
4792  faxregistry.active_sessions = 0;
4793  faxregistry.reserved_sessions = 0;
4796  if (!faxregistry.container) {
4797  return AST_MODULE_LOAD_DECLINE;
4798  }
4799 
4800  if (set_config(0) < 0) {
4801  ast_log(LOG_ERROR, "failed to load configuration file '%s'\n", config);
4802  ao2_ref(faxregistry.container, -1);
4803  return AST_MODULE_LOAD_DECLINE;
4804  }
4805 
4806  /* register CLI operations and applications */
4808  ast_log(LOG_WARNING, "failed to register '%s'.\n", app_sendfax);
4809  ao2_ref(faxregistry.container, -1);
4810  return AST_MODULE_LOAD_DECLINE;
4811  }
4813  ast_log(LOG_WARNING, "failed to register '%s'.\n", app_receivefax);
4815  ao2_ref(faxregistry.container, -1);
4816  return AST_MODULE_LOAD_DECLINE;
4817  }
4818 
4820  ast_log(LOG_WARNING, "failed to register 'FAXSessions' AMI command.\n");
4823  ao2_ref(faxregistry.container, -1);
4824  return AST_MODULE_LOAD_DECLINE;
4825  }
4826 
4828  ast_log(LOG_WARNING, "failed to register 'FAXSession' AMI command.\n");
4829  ast_manager_unregister("FAXSession");
4832  ao2_ref(faxregistry.container, -1);
4833  return AST_MODULE_LOAD_DECLINE;
4834  }
4835 
4837  ast_log(LOG_WARNING, "failed to register 'FAXStats' AMI command.\n");
4838  ast_manager_unregister("FAXSession");
4839  ast_manager_unregister("FAXSessions");
4842  ao2_ref(faxregistry.container, -1);
4843  return AST_MODULE_LOAD_DECLINE;
4844  }
4845 
4849 
4850  return res;
4851 }
@ AO2_ALLOC_OPT_LOCK_MUTEX
Definition: astobj2.h:363
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
Definition: astobj2.h:1303
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7268