Asterisk - The Open Source Telephony Project GIT-master-8f1982c
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
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 514 of file res_fax.c.

◆ FAX_DETECT_MODE_CNG

#define FAX_DETECT_MODE_CNG   (1 << 0)

FAX Detect flags.

Definition at line 512 of file res_fax.c.

◆ FAX_DETECT_MODE_T38

#define FAX_DETECT_MODE_T38   (1 << 1)

Definition at line 513 of file res_fax.c.

◆ FAX_GATEWAY_TIMEOUT

#define FAX_GATEWAY_TIMEOUT   RES_FAX_TIMEOUT

Definition at line 522 of file res_fax.c.

◆ FAX_MAXBUCKETS

#define FAX_MAXBUCKETS   10

maximum buckets for res_fax ao2 containers

Definition at line 519 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 1514 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 1509 of file res_fax.c.

◆ GENERIC_FAX_EXEC_SET_VARS

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

Definition at line 1498 of file res_fax.c.

◆ RES_FAX_MAXRATE

#define RES_FAX_MAXRATE   14400

Definition at line 552 of file res_fax.c.

◆ RES_FAX_MINRATE

#define RES_FAX_MINRATE   4800

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

◆ RES_FAX_STATUSEVENTS

#define RES_FAX_STATUSEVENTS   0

Definition at line 553 of file res_fax.c.

◆ RES_FAX_T38TIMEOUT

#define RES_FAX_T38TIMEOUT   5000

Definition at line 555 of file res_fax.c.

◆ RES_FAX_TIMEOUT

#define RES_FAX_TIMEOUT   10000

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

586 {
587 OPT_CALLEDMODE = (1 << 0),
588 OPT_CALLERMODE = (1 << 1),
589 OPT_DEBUG = (1 << 2),
590 OPT_STATUS = (1 << 3),
591 OPT_ALLOWAUDIO = (1 << 5),
592 OPT_REQUEST_T38 = (1 << 6),
593 OPT_FORCE_AUDIO = (1 << 7),
594};
@ OPT_CALLEDMODE
Definition: res_fax.c:587
@ OPT_REQUEST_T38
Definition: res_fax.c:592
@ OPT_FORCE_AUDIO
Definition: res_fax.c:593
@ OPT_CALLERMODE
Definition: res_fax.c:588
@ OPT_ALLOWAUDIO
Definition: res_fax.c:591
@ OPT_STATUS
Definition: res_fax.c:590
@ OPT_DEBUG
Definition: res_fax.c:589

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 4896 of file res_fax.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

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

4556{
4557 struct ast_fax_session_details *details = find_details(chan);
4558 int res = 0;
4559 char *filenames;
4560
4561 if (!details) {
4562 ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s) because it has never been written.\n", ast_channel_name(chan), data);
4563 return -1;
4564 }
4565 if (!strcasecmp(data, "ecm")) {
4566 ast_copy_string(buf, details->option.ecm ? "yes" : "no", len);
4567 } else if (!strcasecmp(data, "t38gateway") || !strcasecmp(data, "gateway") ||
4568 !strcasecmp(data, "t38_gateway") || !strcasecmp(data, "faxgateway")) {
4569 ast_copy_string(buf, details->gateway_id != -1 ? "yes" : "no", len);
4570 } else if (!strcasecmp(data, "faxdetect")) {
4571 ast_copy_string(buf, details->faxdetect_id != -1 ? "yes" : "no", len);
4572 } else if (!strcasecmp(data, "error")) {
4573 ast_copy_string(buf, details->error, len);
4574 } else if (!strcasecmp(data, "filename")) {
4575 if (AST_LIST_EMPTY(&details->documents)) {
4576 ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s) because it has never been written.\n", ast_channel_name(chan), data);
4577 res = -1;
4578 } else {
4579 ast_copy_string(buf, AST_LIST_FIRST(&details->documents)->filename, len);
4580 }
4581 } else if (!strcasecmp(data, "filenames")) {
4582 if (AST_LIST_EMPTY(&details->documents)) {
4583 ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s) because it has never been written.\n", ast_channel_name(chan), data);
4584 res = -1;
4585 } else if ((filenames = generate_filenames_string(details, "", ","))) {
4586 ast_copy_string(buf, filenames, len);
4587 ast_free(filenames);
4588 } else {
4589 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);
4590 res = -1;
4591 }
4592 } else if (!strcasecmp(data, "headerinfo")) {
4593 ast_copy_string(buf, details->headerinfo, len);
4594 } else if (!strcasecmp(data, "localstationid")) {
4596 } else if (!strcasecmp(data, "maxrate")) {
4597 snprintf(buf, len, "%u", details->maxrate);
4598 } else if (!strcasecmp(data, "minrate")) {
4599 snprintf(buf, len, "%u", details->minrate);
4600 } else if (!strcasecmp(data, "pages")) {
4601 snprintf(buf, len, "%u", details->pages_transferred);
4602 } else if (!strcasecmp(data, "rate")) {
4604 } else if (!strcasecmp(data, "remotestationid")) {
4606 } else if (!strcasecmp(data, "resolution")) {
4607 ast_copy_string(buf, details->resolution, len);
4608 } else if (!strcasecmp(data, "sessionid")) {
4609 snprintf(buf, len, "%u", details->id);
4610 } else if (!strcasecmp(data, "status")) {
4611 ast_copy_string(buf, details->result, len);
4612 } else if (!strcasecmp(data, "statusstr")) {
4613 ast_copy_string(buf, details->resultstr, len);
4614 } else if ((!strcasecmp(data, "modem")) || (!strcasecmp(data, "modems"))) {
4615 ast_fax_modem_to_str(details->modems, buf, len);
4616 } else if (!strcasecmp(data, "t38timeout")) {
4617 snprintf(buf, len, "%u", details->t38timeout);
4618 } else if (!strcasecmp(data, "negotiate_both")) {
4619 ast_copy_string(buf, details->negotiate_both != -1 ? "yes" : "no", len);
4620 } else {
4621 ast_log(LOG_WARNING, "channel '%s' can't read FAXOPT(%s) because it is unhandled!\n", ast_channel_name(chan), data);
4622 res = -1;
4623 }
4624 ao2_ref(details, -1);
4625
4626 return res;
4627}
#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 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:691
static int ast_fax_modem_to_str(enum ast_fax_modems bits, char *tbuf, size_t bufsize)
Definition: res_fax.c:934
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:1399
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
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
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
union ast_fax_session_details::@253 option

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

4631{
4632 int res = 0;
4633 struct ast_fax_session_details *details;
4634
4635 if (!(details = find_or_create_details(chan))) {
4636 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);
4637 return -1;
4638 }
4639 ast_debug(3, "channel '%s' setting FAXOPT(%s) to '%s'\n", ast_channel_name(chan), data, value);
4640
4641 if (!strcasecmp(data, "ecm")) {
4642 const char *val = ast_skip_blanks(value);
4643 if (ast_true(val)) {
4644 details->option.ecm = AST_FAX_OPTFLAG_TRUE;
4645 } else if (ast_false(val)) {
4646 details->option.ecm = AST_FAX_OPTFLAG_FALSE;
4647 } else {
4648 ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(ecm).\n", value);
4649 }
4650 } else if (!strcasecmp(data, "t38gateway") || !strcasecmp(data, "gateway") ||
4651 !strcasecmp(data, "t38_gateway") || !strcasecmp(data, "faxgateway")) {
4652 const char *val = ast_skip_blanks(value);
4653 char *timeout = strchr(val, ',');
4654
4655 if (timeout) {
4656 *timeout++ = '\0';
4657 }
4658
4659 if (ast_true(val)) {
4660 if (details->gateway_id < 0) {
4661 details->gateway_timeout = 0;
4662 if (timeout) {
4663 unsigned int gwtimeout;
4664
4665 if (sscanf(timeout, "%30u", &gwtimeout) == 1) {
4666 details->gateway_timeout = gwtimeout * 1000;
4667 } else {
4668 ast_log(LOG_WARNING, "Unsupported timeout '%s' passed to FAXOPT(%s).\n", timeout, data);
4669 }
4670 }
4671
4672 details->gateway_id = fax_gateway_attach(chan, details);
4673 if (details->gateway_id < 0) {
4674 ast_log(LOG_ERROR, "Error attaching T.38 gateway to channel %s.\n", ast_channel_name(chan));
4675 res = -1;
4676 } else {
4677 ast_debug(1, "Attached T.38 gateway to channel %s.\n", ast_channel_name(chan));
4678 }
4679 } else {
4680 ast_log(LOG_WARNING, "Attempt to attach a T.38 gateway on channel (%s) with gateway already running.\n", ast_channel_name(chan));
4681 }
4682 } else if (ast_false(val)) {
4683 ast_channel_lock(chan);
4684 ast_framehook_detach(chan, details->gateway_id);
4685 ast_channel_unlock(chan);
4686 details->gateway_id = -1;
4687 } else {
4688 ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(%s).\n", value, data);
4689 }
4690 } else if (!strcasecmp(data, "faxdetect")) {
4691 const char *val = ast_skip_blanks(value);
4692 char *timeout = strchr(val, ',');
4693 unsigned int fdtimeout = 0;
4694 int flags;
4695 int faxdetect;
4696
4697 if (timeout) {
4698 *timeout++ = '\0';
4699 }
4700
4701 if (ast_true(val) || !strcasecmp(val, "t38") || !strcasecmp(val, "cng")) {
4702 if (details->faxdetect_id < 0) {
4703 if (timeout) {
4704 if (sscanf(timeout, "%30u", &fdtimeout) == 1) {
4705 fdtimeout *= 1000;
4706 } else {
4707 ast_log(LOG_WARNING, "Unsupported timeout '%s' passed to FAXOPT(%s).\n",
4708 timeout, data);
4709 }
4710 }
4711
4712 if (!strcasecmp(val, "t38")) {
4713 flags = FAX_DETECT_MODE_T38;
4714 } else if (!strcasecmp(val, "cng")) {
4715 flags = FAX_DETECT_MODE_CNG;
4716 } else {
4717 flags = FAX_DETECT_MODE_BOTH;
4718 }
4719
4720 faxdetect = fax_detect_attach(chan, fdtimeout, flags);
4721 if (faxdetect < 0) {
4722 ast_log(LOG_ERROR, "Error attaching FAX detect to channel %s.\n", ast_channel_name(chan));
4723 res = -1;
4724 } else {
4725 ast_debug(1, "Attached FAX detect to channel %s.\n", ast_channel_name(chan));
4726 }
4727 } else {
4728 ast_log(LOG_WARNING, "Attempt to attach a FAX detect on channel (%s) with FAX detect already running.\n", ast_channel_name(chan));
4729 }
4730 } else if (ast_false(val)) {
4731 ast_channel_lock(chan);
4732 ast_framehook_detach(chan, details->faxdetect_id);
4733 ast_channel_unlock(chan);
4734 details->faxdetect_id = -1;
4735 } else {
4736 ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(%s).\n", value, data);
4737 }
4738 } else if (!strcasecmp(data, "headerinfo")) {
4740 } else if (!strcasecmp(data, "localstationid")) {
4742 } else if (!strcasecmp(data, "maxrate")) {
4743 details->maxrate = fax_rate_str_to_int(value);
4744 if (!details->maxrate) {
4745 details->maxrate = ast_fax_maxrate();
4746 }
4747 } else if (!strcasecmp(data, "minrate")) {
4748 details->minrate = fax_rate_str_to_int(value);
4749 if (!details->minrate) {
4750 details->minrate = ast_fax_minrate();
4751 }
4752 } else if (!strcasecmp(data, "t38timeout")) {
4753 if (set_t38timeout(value, &details->t38timeout)) {
4754 res = -1;
4755 }
4756 } else if ((!strcasecmp(data, "modem")) || (!strcasecmp(data, "modems"))) {
4757 update_modem_bits(&details->modems, value);
4758 } else if (!strcasecmp(data, "negotiate_both")) {
4760 } else {
4761 ast_log(LOG_WARNING, "channel '%s' set FAXOPT(%s) to '%s' is unhandled!\n", ast_channel_name(chan), data, value);
4762 res = -1;
4763 }
4764
4765 ao2_ref(details, -1);
4766
4767 return res;
4768}
static int fdtimeout
#define ast_channel_lock(chan)
Definition: channel.h:2972
#define ast_channel_unlock(chan)
Definition: channel.h:2973
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:833
static int update_modem_bits(enum ast_fax_modems *bits, const char *value)
Definition: res_fax.c:841
#define FAX_DETECT_MODE_BOTH
Definition: res_fax.c:514
static int set_t38timeout(const char *value, unsigned int *t38timeout)
Definition: res_fax.c:4433
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:3918
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:3655
#define FAX_DETECT_MODE_T38
Definition: res_fax.c:513
unsigned int ast_fax_maxrate(void)
get the maxiumum supported fax rate
Definition: res_fax.c:825
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:793
static unsigned int fax_rate_str_to_int(const char *ratestr)
convert a rate string to a rate
Definition: res_fax.c:1075
#define FAX_DETECT_MODE_CNG
FAX Detect flags.
Definition: res_fax.c:512
@ 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: utils.c:2199
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"....
Definition: utils.c:2216
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

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

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

876{
877 char *out = buf;
878 size_t size = bufsize;
879 int first = 1;
880
881 if (caps & AST_FAX_TECH_SEND) {
882 if (!first) {
883 ast_build_string(&buf, &size, ",");
884 }
885 ast_build_string(&buf, &size, "SEND");
886 first = 0;
887 }
888 if (caps & AST_FAX_TECH_RECEIVE) {
889 if (!first) {
890 ast_build_string(&buf, &size, ",");
891 }
892 ast_build_string(&buf, &size, "RECEIVE");
893 first = 0;
894 }
895 if (caps & AST_FAX_TECH_AUDIO) {
896 if (!first) {
897 ast_build_string(&buf, &size, ",");
898 }
899 ast_build_string(&buf, &size, "AUDIO");
900 first = 0;
901 }
902 if (caps & AST_FAX_TECH_T38) {
903 if (!first) {
904 ast_build_string(&buf, &size, ",");
905 }
906 ast_build_string(&buf, &size, "T38");
907 first = 0;
908 }
909 if (caps & AST_FAX_TECH_MULTI_DOC) {
910 if (!first) {
911 ast_build_string(&buf, &size, ",");
912 }
913 ast_build_string(&buf, &size, "MULTI_DOC");
914 first = 0;
915 }
916 if (caps & AST_FAX_TECH_GATEWAY) {
917 if (!first) {
918 ast_build_string(&buf, &size, ",");
919 }
920 ast_build_string(&buf, &size, "GATEWAY");
921 first = 0;
922 }
923 if (caps & AST_FAX_TECH_V21_DETECT) {
924 if (!first) {
925 ast_build_string(&buf, &size, ",");
926 }
927 ast_build_string(&buf, &size, "V21");
928 first = 0;
929 }
930
931 return out;
932}
struct sla_ringing_trunk * first
Definition: app_sla.c:338
@ 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: utils.c:2167
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 1065 of file res_fax.c.

1066{
1067 if (fax_logger_level != -1) {
1069 } else {
1070 ast_log(level, file, line, function, "%s", msg);
1071 }
1072}
#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:516

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

826{
827 struct fax_options options;
829
830 return options.maxrate;
831}
static void get_general_options(struct fax_options *options)
Definition: res_fax.c:4426
static struct test_options options

References get_general_options(), and options.

Referenced by acf_faxopt_write().

◆ ast_fax_minrate()

unsigned int ast_fax_minrate ( void  )

get the minimum supported fax rate

Definition at line 833 of file res_fax.c.

834{
835 struct fax_options options;
837
838 return options.minrate;
839}

References get_general_options(), and options.

Referenced by acf_faxopt_write().

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

935{
936 int count = 0;
937
938 if (bits & AST_FAX_MODEM_V17) {
939 strcat(tbuf, "V17");
940 count++;
941 }
942 if (bits & AST_FAX_MODEM_V27TER) {
943 if (count) {
944 strcat(tbuf, ",");
945 }
946 strcat(tbuf, "V27");
947 count++;
948 }
949 if (bits & AST_FAX_MODEM_V29) {
950 if (count) {
951 strcat(tbuf, ",");
952 }
953 strcat(tbuf, "V29");
954 count++;
955 }
956 if (bits & AST_FAX_MODEM_V34) {
957 if (count) {
958 strcat(tbuf, ",");
959 }
960 strcat(tbuf, "V34");
961 count++;
962 }
963
964 return 0;
965}
@ 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 4283 of file res_fax.c.

4284{
4285 if (s->details->caps & AST_FAX_TECH_GATEWAY) {
4286 return "gateway";
4287 }
4288 if (s->details->caps & AST_FAX_TECH_SEND) {
4289 return "send";
4290 }
4291 if (s->details->caps & AST_FAX_TECH_RECEIVE) {
4292 return "receive";
4293 }
4295 return "V.21";
4296 }
4297
4298 return "none";
4299}
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 1042 of file res_fax.c.

1043{
1044 switch (state) {
1046 return "Uninitialized";
1048 return "Initialized";
1049 case AST_FAX_STATE_OPEN:
1050 return "Open";
1052 return "Active";
1054 return "Complete";
1056 return "Reserved";
1058 return "Inactive";
1059 default:
1060 ast_log(LOG_WARNING, "unhandled FAX state: %u\n", state);
1061 return "Unknown";
1062 }
1063}
@ 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 1003 of file res_fax.c.

1004{
1005 struct fax_module *fax;
1006
1007 if (!(fax = ast_calloc(1, sizeof(*fax)))) {
1008 return -1;
1009 }
1010 fax->tech = tech;
1014
1015 ast_verb(3, "Registered handler for '%s' (%s)\n", fax->tech->type, fax->tech->description);
1016
1017 return 0;
1018}
#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:545
const struct ast_fax_tech * tech
Definition: res_fax.c:546

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

Referenced by load_module().

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

1022{
1023 struct fax_module *fax;
1024
1025 ast_verb(3, "Unregistering FAX module type '%s'\n", tech->type);
1026
1029 if (fax->tech != tech) {
1030 continue;
1031 }
1033 ast_free(fax);
1034 ast_verb(4, "Unregistered FAX module type '%s'\n", tech->type);
1035 break;
1036 }
1039}
#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 4896 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 967 of file res_fax.c.

968{
969 switch (rate) {
970 case 2400:
971 case 4800:
972 if (!(modems & (AST_FAX_MODEM_V27TER | AST_FAX_MODEM_V34))) {
973 return 1;
974 }
975 break;
976 case 7200:
977 case 9600:
979 return 1;
980 }
981 break;
982 case 12000:
983 case 14400:
984 if (!(modems & (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V34))) {
985 return 1;
986 }
987 break;
988 case 28800:
989 case 33600:
990 if (!(modems & AST_FAX_MODEM_V34)) {
991 return 1;
992 }
993 break;
994 default:
995 /* this should never happen */
996 return 1;
997 }
998
999 return 0;
1000}

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

4033{
4034 int flag;
4035 const char *what;
4036
4037 switch (cmd) {
4038 case CLI_INIT:
4039 e->command = "fax set debug {on|off}";
4040 e->usage =
4041 "Usage: fax set debug { on | off }\n"
4042 " Enable/Disable FAX debugging on new FAX sessions. The basic FAX debugging will result in\n"
4043 " additional events sent to manager sessions with 'call' class permissions. When\n"
4044 " verbosity is greater than '5' events will be displayed to the console and audio versus\n"
4045 " energy analysis will be performed and displayed to the console.\n";
4046 return NULL;
4047 case CLI_GENERATE:
4048 return NULL;
4049 }
4050
4051 what = a->argv[e->args-1]; /* guaranteed to exist */
4052 if (!strcasecmp(what, "on")) {
4053 flag = 1;
4054 } else if (!strcasecmp(what, "off")) {
4055 flag = 0;
4056 } else {
4057 return CLI_SHOWUSAGE;
4058 }
4059
4061 ast_cli(a->fd, "\n\nFAX Debug %s\n\n", (flag) ? "Enabled" : "Disabled");
4062
4063 return CLI_SUCCESS;
4064}
#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:584
#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 4067 of file res_fax.c.

4068{
4069 struct fax_module *fax;
4070 unsigned int num_modules = 0;
4071
4072 switch (cmd) {
4073 case CLI_INIT:
4074 e->command = "fax show capabilities";
4075 e->usage =
4076 "Usage: fax show capabilities\n"
4077 " Shows the capabilities of the registered FAX technology modules\n";
4078 return NULL;
4079 case CLI_GENERATE:
4080 return NULL;
4081 }
4082
4083 ast_cli(a->fd, "\n\nRegistered FAX Technology Modules:\n\n");
4085 AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
4086 ast_cli(a->fd, "%-15s : %s\n%-15s : %s\n%-15s : ", "Type", fax->tech->type, "Description", fax->tech->description, "Capabilities");
4087 fax->tech->cli_show_capabilities(a->fd);
4088 num_modules++;
4089 }
4091 ast_cli(a->fd, "%u registered modules\n\n", num_modules);
4092
4093 return CLI_SUCCESS;
4094}
#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 4136 of file res_fax.c.

4137{
4138 struct ast_fax_session *s, tmp;
4139
4140 switch (cmd) {
4141 case CLI_INIT:
4142 e->command = "fax show session";
4143 e->usage =
4144 "Usage: fax show session <session number>\n"
4145 " Shows status of the named FAX session\n";
4146 return NULL;
4147 case CLI_GENERATE:
4149 }
4150
4151 if (a->argc != 4) {
4152 return CLI_SHOWUSAGE;
4153 }
4154
4155 if (sscanf(a->argv[3], "%u", &tmp.id) != 1) {
4156 ast_log(LOG_ERROR, "invalid session id: '%s'\n", a->argv[3]);
4157 return RESULT_SUCCESS;
4158 }
4159
4160 ast_cli(a->fd, "\nFAX Session Details:\n--------------------\n\n");
4161 s = ao2_find(faxregistry.container, &tmp, OBJ_POINTER);
4162 if (s) {
4163 ast_cli(a->fd, "%-22s : %s\n", "channel", s->channame);
4164 s->tech->cli_show_session(s, a->fd);
4165 ao2_ref(s, -1);
4166 }
4167 ast_cli(a->fd, "\n\n");
4168
4169 return CLI_SUCCESS;
4170}
#define OBJ_POINTER
Definition: astobj2.h:1150
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1736
#define RESULT_SUCCESS
Definition: cli.h:40
static struct @438 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:3972
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
unsigned int id
Definition: res_fax.h:204
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, ast_fax_session::id, LOG_ERROR, NULL, OBJ_POINTER, RESULT_SUCCESS, ast_fax_session::tech, 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 4302 of file res_fax.c.

4303{
4304 struct ast_fax_session *s;
4305 struct ao2_iterator i;
4306 int session_count;
4307 char *filenames;
4308
4309 switch (cmd) {
4310 case CLI_INIT:
4311 e->command = "fax show sessions";
4312 e->usage =
4313 "Usage: fax show sessions\n"
4314 " Shows the current FAX sessions\n";
4315 return NULL;
4316 case CLI_GENERATE:
4317 return NULL;
4318 }
4319
4320 ast_cli(a->fd, "\nCurrent FAX Sessions:\n\n");
4321 ast_cli(a->fd, "%-30.30s %-10.10s %-10.10s %-5.5s %-10.10s %-15.15s %-30.30s\n",
4322 "Channel", "Tech", "FAXID", "Type", "Operation", "State", "File(s)");
4323 i = ao2_iterator_init(faxregistry.container, 0);
4324 while ((s = ao2_iterator_next(&i))) {
4325 ao2_lock(s);
4326
4327 filenames = generate_filenames_string(s->details, "", ", ");
4328
4329 ast_cli(a->fd, "%-30.30s %-10.10s %-10u %-5.5s %-10.10s %-15.15s %-30s\n",
4330 s->channame, s->tech->type, s->id,
4333 ast_fax_state_to_str(s->state), S_OR(filenames, ""));
4334
4335 ast_free(filenames);
4336 ao2_unlock(s);
4337 ao2_ref(s, -1);
4338 }
4341 ast_cli(a->fd, "\n%d FAX sessions\n\n", session_count);
4342
4343 return CLI_SUCCESS;
4344}
#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_state_to_str(enum ast_fax_state state)
convert a ast_fax_state to a string
Definition: res_fax.c:1042
static const char * fax_session_type(struct ast_fax_session *s)
Definition: res_fax.c:4271
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:4283
#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
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 4097 of file res_fax.c.

4098{
4099 struct fax_module *fax;
4100 char modems[128] = "";
4101 struct fax_options options;
4102
4103 switch (cmd) {
4104 case CLI_INIT:
4105 e->command = "fax show settings";
4106 e->usage =
4107 "Usage: fax show settings\n"
4108 " Show the global settings and defaults of both the FAX core and technology modules\n";
4109 return NULL;
4110 case CLI_GENERATE:
4111 return NULL;
4112 }
4113
4115
4116 ast_cli(a->fd, "FAX For Asterisk Settings:\n");
4117 ast_cli(a->fd, "\tECM: %s\n", options.ecm ? "Enabled" : "Disabled");
4118 ast_cli(a->fd, "\tStatus Events: %s\n", options.statusevents ? "On" : "Off");
4119 ast_cli(a->fd, "\tMinimum Bit Rate: %u\n", options.minrate);
4120 ast_cli(a->fd, "\tMaximum Bit Rate: %u\n", options.maxrate);
4121 ast_fax_modem_to_str(options.modems, modems, sizeof(modems));
4122 ast_cli(a->fd, "\tModem Modulations Allowed: %s\n", modems);
4123 ast_cli(a->fd, "\tT.38 Negotiation Timeout: %u\n", options.t38timeout);
4124 ast_cli(a->fd, "\n\nFAX Technology Modules:\n\n");
4126 AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
4127 ast_cli(a->fd, "%s (%s) Settings:\n", fax->tech->type, fax->tech->description);
4128 fax->tech->cli_show_settings(a->fd);
4129 }
4131
4132 return CLI_SUCCESS;
4133}
char *(*const cli_show_settings)(int)
Definition: res_fax.h:276
enum ast_fax_modems modems
Definition: res_fax.c:558

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

4211{
4212 struct fax_module *fax;
4213
4214 switch (cmd) {
4215 case CLI_INIT:
4216 e->command = "fax show stats";
4217 e->usage =
4218 "Usage: fax show stats\n"
4219 " Shows a statistical summary of FAX transmissions\n";
4220 return NULL;
4221 case CLI_GENERATE:
4222 return NULL;
4223 }
4224
4225 ast_cli(a->fd, "\nFAX Statistics:\n---------------\n\n");
4226 ast_cli(a->fd, "%-20.20s : %d\n", "Current Sessions", faxregistry.active_sessions);
4227 ast_cli(a->fd, "%-20.20s : %d\n", "Reserved Sessions", faxregistry.reserved_sessions);
4228 ast_cli(a->fd, "%-20.20s : %d\n", "Transmit Attempts", faxregistry.fax_tx_attempts);
4229 ast_cli(a->fd, "%-20.20s : %d\n", "Receive Attempts", faxregistry.fax_rx_attempts);
4230 ast_cli(a->fd, "%-20.20s : %d\n", "Completed FAXes", faxregistry.fax_complete);
4231 ast_cli(a->fd, "%-20.20s : %d\n", "Failed FAXes", faxregistry.fax_failures);
4233 AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
4234 fax->tech->cli_show_stats(a->fd);
4235 }
4237 ast_cli(a->fd, "\n\n");
4238
4239 return CLI_SUCCESS;
4240}
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 4000 of file res_fax.c.

4001{
4002 struct fax_module *fax;
4003
4004 switch(cmd) {
4005 case CLI_INIT:
4006 e->command = "fax show version";
4007 e->usage =
4008 "Usage: fax show version\n"
4009 " Show versions of FAX For Asterisk components.\n";
4010 return NULL;
4011 case CLI_GENERATE:
4012 return NULL;
4013 }
4014
4015 if (a->argc != 3) {
4016 return CLI_SHOWUSAGE;
4017 }
4018
4019 ast_cli(a->fd, "FAX For Asterisk Components:\n");
4020 ast_cli(a->fd, "\tApplications: %s\n", ast_get_version());
4022 AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
4023 ast_cli(a->fd, "\t%s: %s\n", fax->tech->description, fax->tech->version);
4024 }
4026 ast_cli(a->fd, "\n");
4027
4028 return CLI_SUCCESS;
4029}
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 606 of file res_fax.c.

607{
608 struct debug_info_history *history = c2s ? &s->debug_info->c2s : &s->debug_info->s2c;
609 int dspsilence;
610 unsigned int last_consec_frames, last_consec_ms;
611 unsigned char wassil;
612 struct timeval diff;
613
614 diff = ast_tvsub(ast_tvnow(), s->debug_info->base_tv);
615
617 ast_dsp_silence(s->debug_info->dsp, frame, &dspsilence);
618
619 wassil = history->silence;
620 history->silence = (dspsilence != 0) ? 1 : 0;
621 if (history->silence != wassil) {
622 last_consec_frames = history->consec_frames;
623 last_consec_ms = history->consec_ms;
624 history->consec_frames = 0;
625 history->consec_ms = 0;
626
627 if ((last_consec_frames != 0)) {
628 ast_verb(0, "Channel '%s' fax session '%u', [ %.3ld.%.6ld ], %s sent %u frames (%u ms) of %s.\n",
629 s->channame, s->id, (long) diff.tv_sec, (long int) diff.tv_usec,
630 (c2s) ? "channel" : "stack", last_consec_frames, last_consec_ms,
631 (wassil) ? "silence" : "energy");
632 }
633 }
634
635 history->consec_frames++;
636 history->consec_ms += (frame->samples / 8);
637}
int ast_dsp_silence(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
Process the audio frame for silence.
Definition: dsp.c:1488
void ast_dsp_reset(struct ast_dsp *dsp)
Reset total silence count.
Definition: dsp.c:1843
struct debug_info_history c2s s2c
Definition: res_fax.c:468
struct timeval base_tv
Definition: res_fax.c:467
struct ast_dsp * dsp
Definition: res_fax.c:469
struct ast_fax_debug_info * debug_info
Definition: res_fax.h:226
unsigned int consec_ms
Definition: res_fax.c:462
unsigned int consec_frames
Definition: res_fax.c:461
unsigned char silence
Definition: res_fax.c:463
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:159

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

640{
641 if (data) {
642 ao2_ref(data, -1);
643 }
644}

References ao2_ref.

◆ destroy_faxdetect()

static void destroy_faxdetect ( void *  data)
static

destroy a FAX detect structure

Definition at line 3705 of file res_fax.c.

3706{
3707 struct fax_detect *faxdetect = data;
3708
3709 if (faxdetect->dsp) {
3710 ast_dsp_free(faxdetect->dsp);
3711 faxdetect->dsp = NULL;
3712 }
3713 ao2_cleanup(faxdetect->details);
3714 ao2_cleanup(faxdetect->orig_format);
3715}
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
void ast_dsp_free(struct ast_dsp *dsp)
Definition: dsp.c:1783
used for fax detect framehook
Definition: res_fax.c:498
struct ast_dsp * dsp
DSP Processor.
Definition: res_fax.c:502
struct ast_format * orig_format
original audio formats
Definition: res_fax.c:504
struct ast_fax_session_details * details
fax session details
Definition: res_fax.c:506

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

2869{
2870 struct fax_gateway *gateway = data;
2871
2872 destroy_v21_sessions(gateway);
2873
2874 if (gateway->s) {
2875 fax_session_release(gateway->s, gateway->token);
2876 gateway->token = NULL;
2877
2878 ao2_unlink(faxregistry.container, gateway->s);
2879
2880 ao2_ref(gateway->s, -1);
2881 gateway->s = NULL;
2882 }
2883
2884 ao2_cleanup(gateway->chan_read_format);
2886 ao2_cleanup(gateway->peer_read_format);
2888}
#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:1112
static void destroy_v21_sessions(struct fax_gateway *gateway)
destroy the v21 detection parts of a fax gateway session
Definition: res_fax.c:2850
used for gateway framehook
Definition: res_fax.c:473
struct ast_format * chan_read_format
original audio formats
Definition: res_fax.c:491
struct ast_format * chan_write_format
Definition: res_fax.c:492
struct ast_format * peer_write_format
Definition: res_fax.c:494
struct ast_format * peer_read_format
Definition: res_fax.c:493
struct ast_fax_session * s
FAX Session.
Definition: res_fax.c:475
struct ast_fax_tech_token * token
reserved fax session token
Definition: res_fax.c:479

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

1126{
1127 struct ast_fax_session *s = session;
1128
1129 if (s->tech) {
1131 if (s->tech_pvt) {
1132 s->tech->destroy_session(s);
1133 }
1135 }
1136
1137 if (s->details) {
1138 if (s->details->caps & AST_FAX_TECH_GATEWAY) {
1139 s->details->caps &= ~AST_FAX_TECH_GATEWAY;
1140 }
1141 ao2_ref(s->details, -1);
1142 s->details = NULL;
1143 }
1144
1145 if (s->debug_info) {
1147 ast_free(s->debug_info);
1148 }
1149
1150 if (s->smoother) {
1152 }
1153
1154 if (s->state != AST_FAX_STATE_INACTIVE) {
1155 ast_atomic_fetchadd_int(&faxregistry.active_sessions, -1);
1156 }
1157
1158 ast_free(s->channame);
1160}
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:764
#define ast_module_unref(mod)
Release a reference to the module.
Definition: module.h:483
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
void(*const destroy_session)(struct ast_fax_session *)
Definition: res_fax.h:253
struct ast_module * module
Definition: res_fax.h:245

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

714{
715 struct ast_fax_session_details *d = details;
716 struct ast_fax_document *doc;
717
718 while ((doc = AST_LIST_REMOVE_HEAD(&d->documents, next))) {
719 ast_free(doc);
720 }
722}
#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.

Referenced by session_details_new().

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

2851{
2852 if (gateway->chan_v21_session) {
2853 ao2_unlink(faxregistry.container, gateway->chan_v21_session);
2854
2855 ao2_ref(gateway->chan_v21_session, -1);
2856 gateway->chan_v21_session = NULL;
2857 }
2858
2859 if (gateway->peer_v21_session) {
2860 ao2_unlink(faxregistry.container, gateway->peer_v21_session);
2861
2862 ao2_ref(gateway->peer_v21_session, -1);
2863 gateway->peer_v21_session = NULL;
2864 }
2865}
struct ast_fax_session * peer_v21_session
Definition: res_fax.c:476
struct ast_fax_session * chan_v21_session
Definition: res_fax.c:477

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

1557{
1558 int timeout_ms;
1559 struct ast_frame *frame = NULL;
1561 struct timeval start;
1562 int ms;
1563
1564 ast_debug(1, "Shutting down T.38 on %s\n", ast_channel_name(chan));
1565 if (ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0) {
1566 ast_debug(1, "error while disabling T.38 on channel '%s'\n", ast_channel_name(chan));
1567 return -1;
1568 }
1569
1570 /* wait up to five seconds for negotiation to complete */
1571 timeout_ms = 5000;
1572 start = ast_tvnow();
1573 while ((ms = ast_remaining_ms(start, timeout_ms))) {
1574 ms = ast_waitfor(chan, ms);
1575
1576 if (ms == 0) {
1577 break;
1578 }
1579 if (ms < 0) {
1580 ast_debug(1, "error while disabling T.38 on channel '%s'\n", ast_channel_name(chan));
1581 return -1;
1582 }
1583
1584 if (!(frame = ast_read(chan))) {
1585 return -1;
1586 }
1587 if ((frame->frametype == AST_FRAME_CONTROL) &&
1589 (frame->datalen == sizeof(t38_parameters))) {
1590 struct ast_control_t38_parameters *parameters = frame->data.ptr;
1591
1592 switch (parameters->request_response) {
1593 case AST_T38_TERMINATED:
1594 ast_debug(1, "Shut down T.38 on %s\n", ast_channel_name(chan));
1595 break;
1596 case AST_T38_REFUSED:
1597 ast_log(LOG_WARNING, "channel '%s' refused to disable T.38\n", ast_channel_name(chan));
1598 ast_frfree(frame);
1599 return -1;
1600 default:
1601 ast_log(LOG_ERROR, "channel '%s' failed to disable T.38\n", ast_channel_name(chan));
1602 ast_frfree(frame);
1603 return -1;
1604 }
1605 ast_frfree(frame);
1606 break;
1607 }
1608 ast_frfree(frame);
1609 }
1610
1611 if (ms == 0) { /* all done, nothing happened */
1612 ast_debug(1, "channel '%s' timed-out during T.38 shutdown\n", ast_channel_name(chan));
1613 }
1614
1615 return 0;
1616}
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3130
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4214
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:4612
@ 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.
union ast_frame::@228 data
struct ast_frame_subclass subclass
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: utils.c:2281

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

3919{
3920 struct fax_detect *faxdetect;
3921 struct ast_fax_session_details *details;
3922 struct ast_framehook_interface fr_hook = {
3924 .event_cb = fax_detect_framehook,
3925 .destroy_cb = fax_detect_framehook_destroy,
3926 };
3927
3928 if (!(details = find_or_create_details(chan))) {
3929 ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
3930 return -1;
3931 }
3932
3933 /* set up the frame hook*/
3934 faxdetect = fax_detect_new(chan, timeout, flags);
3935 if (!faxdetect) {
3936 ao2_ref(details, -1);
3937 return -1;
3938 }
3939
3940 fr_hook.data = faxdetect;
3941 faxdetect->details = details;
3942 ast_channel_lock(chan);
3943 details->faxdetect_id = ast_framehook_attach(chan, &fr_hook);
3944 details->faxdetect_timeout = timeout;
3945 details->faxdetect_flags = flags;
3946 ast_channel_unlock(chan);
3947
3948 if (details->faxdetect_id < 0) {
3949 ao2_ref(faxdetect, -1);
3950 }
3951
3952 return details->faxdetect_id;
3953}
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 void fax_detect_framehook_destroy(void *data)
Deref the faxdetect data structure when the faxdetect framehook is detached.
Definition: res_fax.c:3756
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:3723
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:3774

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

Referenced by acf_faxopt_write(), and fixup_callback().

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

3775{
3776 struct fax_detect *faxdetect = data;
3777 struct ast_fax_session_details *details;
3778 struct ast_control_t38_parameters *control_params;
3779 RAII_VAR(struct ast_channel *, peer, NULL, ao2_cleanup);
3780 RAII_VAR(struct ast_channel *, chan_ref, chan, ao2_cleanup);
3781 int result = 0;
3782
3783 /* Ref bump the channel for when we have to unlock it */
3784 ao2_ref(chan, 1);
3785
3786 details = faxdetect->details;
3787
3788 switch (event) {
3790 /* Setup format for DSP on ATTACH*/
3792
3797 ast_framehook_detach(chan, details->faxdetect_id);
3798 details->faxdetect_id = -1;
3799 return f;
3800 }
3801 }
3802
3803 return NULL;
3805 /* restore audio formats when we are detached */
3806 ast_set_read_format(chan, faxdetect->orig_format);
3807 ast_channel_unlock(chan);
3808 peer = ast_channel_bridge_peer(chan);
3809 if (peer) {
3810 ast_channel_make_compatible(chan, peer);
3811 }
3812 ast_channel_lock(chan);
3813 return NULL;
3815 if (f) {
3816 break;
3817 }
3818 default:
3819 return f;
3820 };
3821
3822 if (details->faxdetect_id < 0) {
3823 return f;
3824 }
3825
3826 if (!ast_tvzero(faxdetect->timeout_start)
3827 && ast_tvdiff_ms(ast_tvnow(), faxdetect->timeout_start) > details->faxdetect_timeout) {
3828 ast_debug(1, "FAXOPT(faxdetect) timeout on %s\n", ast_channel_name(chan));
3829 ast_framehook_detach(chan, details->faxdetect_id);
3830 details->faxdetect_id = -1;
3831 return f;
3832 }
3833
3834 /* only handle VOICE and CONTROL frames*/
3835 switch (f->frametype) {
3836 case AST_FRAME_VOICE:
3837 /* we have no DSP this means we not detecting CNG */
3838 if (!faxdetect->dsp) {
3839 return f;
3840 }
3841 /* We can only process some formats*/
3845 return f;
3846 }
3847 break;
3848 case AST_FRAME_CONTROL:
3850 (faxdetect->flags & FAX_DETECT_MODE_T38)) {
3851 break;
3852 }
3853 return f;
3854 default:
3855 return f;
3856 }
3857
3858 if (f->frametype == AST_FRAME_VOICE) {
3859 f = ast_dsp_process(chan, faxdetect->dsp, f);
3860 if (f->frametype == AST_FRAME_DTMF) {
3861 result = f->subclass.integer;
3862 }
3863 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->datalen == sizeof(struct ast_control_t38_parameters))) {
3864 control_params = f->data.ptr;
3865 switch (control_params->request_response) {
3866 case AST_T38_NEGOTIATED:
3868 result = 't';
3869 break;
3870 default:
3871 break;
3872 }
3873 }
3874
3875 if (result) {
3876 const char *target_context;
3877
3878 switch (result) {
3879 case 'f':
3880 case 't':
3881 target_context = ast_channel_context(chan);
3882
3883 ast_channel_unlock(chan);
3884 ast_frfree(f);
3885 f = &ast_null_frame;
3886 if (ast_exists_extension(chan, target_context, "fax", 1,
3887 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
3888 ast_verb(2, "Redirecting '%s' to fax extension due to %s detection\n",
3889 ast_channel_name(chan), (result == 'f') ? "CNG" : "T38");
3890 pbx_builtin_setvar_helper(chan, "FAXEXTEN", ast_channel_exten(chan));
3891 if (ast_async_goto(chan, target_context, "fax", 1)) {
3892 ast_log(LOG_NOTICE, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(chan), target_context);
3893 }
3894 } else {
3895 ast_log(LOG_NOTICE, "FAX %s detected but no fax extension in context (%s)\n",
3896 (result == 'f') ? "CNG" : "T38", target_context);
3897 }
3898 ast_channel_lock(chan);
3899
3900 ast_framehook_detach(chan, details->faxdetect_id);
3901 details->faxdetect_id = -1;
3902 break;
3903 default:
3904 break;
3905 }
3906 }
3907
3908 return f;
3909}
#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
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:10569
int ast_channel_make_compatible(struct ast_channel *chan, struct ast_channel *peer)
Make the frame formats of two channels compatible.
Definition: channel.c:6679
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:5721
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
const char * ast_channel_exten(const struct ast_channel *chan)
struct ast_format * ast_channel_readformat(struct ast_channel *chan)
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:1499
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:4190
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.
Definition: pbx.c:6984
#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:500
int flags
mode
Definition: res_fax.c:508
Number structure.
Definition: app_followme.c:157
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:117
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:107
#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:941

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_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, 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 3756 of file res_fax.c.

3757{
3758 struct fax_detect *faxdetect = data;
3759
3760 ao2_ref(faxdetect, -1);
3761}

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

3724{
3725 struct fax_detect *faxdetect = ao2_alloc(sizeof(*faxdetect), destroy_faxdetect);
3726 if (!faxdetect) {
3727 return NULL;
3728 }
3729
3730 faxdetect->flags = flags;
3731
3732 if (timeout) {
3733 faxdetect->timeout_start = ast_tvnow();
3734 } else {
3735 faxdetect->timeout_start.tv_sec = 0;
3736 faxdetect->timeout_start.tv_usec = 0;
3737 }
3738
3739 if (faxdetect->flags & FAX_DETECT_MODE_CNG) {
3740 faxdetect->dsp = ast_dsp_new();
3741 if (!faxdetect->dsp) {
3742 ao2_ref(faxdetect, -1);
3743 return NULL;
3744 }
3747 } else {
3748 faxdetect->dsp = NULL;
3749 }
3750
3751 return faxdetect;
3752}
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
#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:1883
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
Definition: dsp.c:1768
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
Definition: dsp.c:1758
static void destroy_faxdetect(void *data)
destroy a FAX detect structure
Definition: res_fax.c:3705

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

3656{
3657 struct fax_gateway *gateway;
3658 struct ast_framehook_interface fr_hook = {
3660 .event_cb = fax_gateway_framehook,
3661 .destroy_cb = fax_gateway_framehook_destroy,
3662 .disable_inheritance = 1, /* Masquerade inheritance is handled through the datastore fixup */
3663 };
3664
3665 if (global_fax_debug) {
3667 }
3668
3669 ast_string_field_set(details, result, "SUCCESS");
3670 ast_string_field_set(details, resultstr, "gateway operation started successfully");
3671 ast_string_field_set(details, error, "NO_ERROR");
3672 set_channel_variables(chan, details);
3673
3674 /* set up the frame hook*/
3675 gateway = fax_gateway_new(chan, details);
3676 if (!gateway) {
3677 ast_string_field_set(details, result, "FAILED");
3678 ast_string_field_set(details, resultstr, "error initializing gateway session");
3679 ast_string_field_set(details, error, "INIT_ERROR");
3680 details->is_t38_negotiated = 0;
3681 set_channel_variables(chan, details);
3682 report_fax_status(chan, details, "No Available Resource");
3683 return -1;
3684 }
3685
3686 fr_hook.data = gateway;
3687 ast_channel_lock(chan);
3688 gateway->framehook = ast_framehook_attach(chan, &fr_hook);
3689 ast_channel_unlock(chan);
3690
3691 if (gateway->framehook < 0) {
3692 ao2_ref(gateway, -1);
3693 ast_string_field_set(details, result, "FAILED");
3694 ast_string_field_set(details, resultstr, "error attaching gateway to channel");
3695 ast_string_field_set(details, error, "INIT_ERROR");
3696 details->is_t38_negotiated = 0;
3697 set_channel_variables(chan, details);
3698 return -1;
3699 }
3700
3701 return gateway->framehook;
3702}
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:1436
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:3412
static void fax_gateway_framehook_destroy(void *data)
Destroy the gateway data structure when the framehook is detached.
Definition: res_fax.c:3374
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:2909
static void set_channel_variables(struct ast_channel *chan, struct ast_fax_session_details *details)
Set fax related channel variables.
Definition: res_fax.c:1476
int framehook
framehook used in gateway mode
Definition: res_fax.c:483
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 acf_faxopt_write(), and 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 3138 of file res_fax.c.

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

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

3042{
3043 struct ast_channel *other = (active == chan) ? peer : chan;
3044 struct ast_fax_session *active_v21_session = (active == chan) ? gateway->chan_v21_session : gateway->peer_v21_session;
3045
3046 if (!active_v21_session || gateway->detected_v21) {
3047 return f;
3048 }
3049
3050 if (active_v21_session->tech->write(active_v21_session, f) == 0 &&
3051 active_v21_session->details->option.v21_detected) {
3052 gateway->detected_v21 = 1;
3053 }
3054
3055 if (gateway->detected_v21) {
3056 enum ast_t38_state state_other;
3057 enum ast_t38_state state_active;
3058 struct ast_frame *fp;
3059 struct ast_fax_session_details *details;
3060 int negotiate_both = 0;
3061
3062 /*
3063 * The default behavior is to wait for the active endpoint to initiate negotiation.
3064 * Find out if this has been overridden. If so, instead of waiting have Asterisk
3065 * initiate the negotiation requests out to both endpoints.
3066 */
3067 details = find_or_create_details(active);
3068 if (details) {
3069 negotiate_both = details->negotiate_both;
3070 ao2_ref(details, -1);
3071 } else {
3072 ast_log(LOG_WARNING, "Detect v21 - no session details for channel '%s'\n",
3073 ast_channel_name(chan));
3074 }
3075
3076 destroy_v21_sessions(gateway);
3077
3078 ast_channel_unlock(chan);
3079 state_active = ast_channel_get_t38_state(active);
3080 state_other = ast_channel_get_t38_state(other);
3081 ast_channel_lock(chan);
3082
3083 ast_debug(1, "detected v21 preamble from %s\n", ast_channel_name(active));
3084
3085 if (state_active == T38_STATE_UNKNOWN || state_other == T38_STATE_UNKNOWN) {
3086 if (!(fp = fax_gateway_request_t38(gateway, chan))) {
3087 return f;
3088 }
3089 /* May be called endpoint is improperly configured to rely on the calling endpoint
3090 * to initiate T.38 re-INVITEs, send T.38 negotiation request to called endpoint */
3091 if (negotiate_both && state_active == T38_STATE_UNKNOWN) {
3092 ast_debug(1, "sending T.38 negotiation request to %s\n", ast_channel_name(active));
3093 if (active == chan) {
3094 ast_channel_unlock(chan);
3095 }
3096 ast_write(active, fp);
3097 if (active == chan) {
3098 ast_channel_lock(chan);
3099 }
3100 }
3101 if (state_other == T38_STATE_UNKNOWN) {
3102 ast_debug(1, "sending T.38 negotiation request to %s\n", ast_channel_name(other));
3103 return fp;
3104 }
3105 } else {
3106 ast_debug(1, "neither %s nor %s support T.38 for T.38 gateway session\n", ast_channel_name(active), ast_channel_name(other));
3107 }
3108 }
3109
3110 return f;
3111}
if(!yyg->yy_init)
Definition: ast_expr2f.c:854
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:5103
static struct ast_frame * fax_gateway_request_t38(struct fax_gateway *gateway, struct ast_channel *chan)
Definition: res_fax.c:3001
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:487

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

3413{
3414 struct fax_gateway *gateway = data;
3415 struct ast_channel *active;
3416 RAII_VAR(struct ast_fax_session_details *, details, NULL, ao2_cleanup);
3417 RAII_VAR(struct ast_channel *, peer, NULL, ao2_cleanup);
3418 RAII_VAR(struct ast_channel *, chan_ref, chan, ao2_cleanup);
3419
3420 /* Ref bump channel for when we have to unlock it */
3421 ao2_ref(chan_ref, 1);
3422
3423 if (gateway->s) {
3424 details = gateway->s->details;
3425 ao2_ref(details, 1);
3426 } else {
3427 if (!(details = find_details(chan))) {
3428 ast_log(LOG_ERROR, "no FAX session details found on chan %s for T.38 gateway session, odd\n", ast_channel_name(chan));
3429 ast_framehook_detach(chan, gateway->framehook);
3430 return f;
3431 }
3432 }
3433
3434 /* restore audio formats when we are detached */
3436 set_channel_variables(chan, details);
3437
3438 if (gateway->bridged) {
3439 ast_set_read_format(chan, gateway->chan_read_format);
3441
3442 ast_channel_unlock(chan);
3443 peer = ast_channel_bridge_peer(chan);
3444 if (peer) {
3445 ast_set_read_format(peer, gateway->peer_read_format);
3447 ast_channel_make_compatible(chan, peer);
3448 }
3449 ast_channel_lock(chan);
3450 }
3451 return NULL;
3452 }
3453
3454 if (!f || (event == AST_FRAMEHOOK_EVENT_ATTACHED)) {
3455 return NULL;
3456 };
3457
3458 /* this frame was generated by the fax gateway, pass it on */
3460 return f;
3461 }
3462
3463 /* If we aren't bridged or we don't have a peer, don't do anything */
3464 ast_channel_unlock(chan);
3465 peer = ast_channel_bridge_peer(chan);
3466 ast_channel_lock(chan);
3467 if (!peer) {
3468 return f;
3469 }
3470
3471 if (!gateway->bridged) {
3472 enum ast_t38_state state_chan;
3473 enum ast_t38_state state_peer;
3474 int chan_is_hungup;
3475 int peer_is_hungup;
3476
3477 chan_is_hungup = ast_check_hangup(chan);
3478 peer_is_hungup = ast_check_hangup(peer);
3479 /* Don't start a gateway if either channel is hung up */
3480 if (chan_is_hungup || peer_is_hungup) {
3481 return f;
3482 }
3483
3484 ast_channel_unlock(chan);
3485 state_chan = ast_channel_get_t38_state(chan);
3486 state_peer = ast_channel_get_t38_state(peer);
3487 ast_channel_lock(chan);
3488
3489 /* don't start a gateway if neither channel can handle T.38 */
3490 if (state_chan == T38_STATE_UNAVAILABLE && state_peer == T38_STATE_UNAVAILABLE) {
3491 ast_debug(1, "not starting gateway for %s and %s; neither channel supports T.38\n", ast_channel_name(chan), ast_channel_name(peer));
3492 ast_framehook_detach(chan, gateway->framehook);
3493 details->gateway_id = -1;
3494
3495 ast_string_field_set(details, result, "FAILED");
3496 ast_string_field_set(details, resultstr, "neither channel supports T.38");
3497 ast_string_field_set(details, error, "T38_NEG_ERROR");
3498 details->is_t38_negotiated = 0;
3499 set_channel_variables(chan, details);
3500 return f;
3501 }
3502
3503 if (details->gateway_timeout) {
3504 gateway->timeout_start = ast_tvnow();
3505 }
3506
3507 ast_channel_unlock(chan);
3508 ast_channel_lock_both(chan, peer);
3509
3510 /* we are bridged, change r/w formats to SLIN for v21 preamble
3511 * detection and T.30 */
3514
3517
3520
3523
3524 ast_channel_unlock(peer);
3525
3526 gateway->bridged = 1;
3527 if (!(gateway->peer_v21_session = fax_v21_session_new(peer))) {
3528 ast_log(LOG_ERROR, "Can't create V21 session on chan %s for T.38 gateway session\n", ast_channel_name(peer));
3529 ast_framehook_detach(chan, gateway->framehook);
3530 return f;
3531 }
3532 }
3533
3534 if (gateway->bridged && !ast_tvzero(gateway->timeout_start)) {
3535 if (ast_tvdiff_ms(ast_tvnow(), gateway->timeout_start) > details->gateway_timeout) {
3536 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);
3537 ast_framehook_detach(chan, gateway->framehook);
3538 details->gateway_id = -1;
3539
3540 ast_string_field_set(details, result, "FAILED");
3541 ast_string_field_build(details, resultstr, "no fax activity after %d ms", details->gateway_timeout);
3542 ast_string_field_set(details, error, "TIMEOUT");
3543 details->is_t38_negotiated = 0;
3544 set_channel_variables(chan, details);
3545 return f;
3546 }
3547 }
3548
3549 /* only handle VOICE, MODEM, and CONTROL frames*/
3550 switch (f->frametype) {
3551 case AST_FRAME_VOICE:
3555 return f;
3556 }
3557 break;
3558 case AST_FRAME_MODEM:
3559 if (f->subclass.integer == AST_MODEM_T38) {
3560 break;
3561 }
3562 return f;
3563 case AST_FRAME_CONTROL:
3565 break;
3566 }
3567 return f;
3568 default:
3569 return f;
3570 }
3571
3572 /* detect the active channel */
3573 switch (event) {
3575 active = peer;
3576 break;
3578 active = chan;
3579 break;
3580 default:
3581 ast_log(LOG_WARNING, "unhandled framehook event %u\n", event);
3582 return f;
3583 }
3584
3585 /* handle control frames */
3587 return fax_gateway_detect_t38(gateway, chan, peer, active, f);
3588 }
3589
3590 if (!gateway->detected_v21 && gateway->t38_state == T38_STATE_UNAVAILABLE && f->frametype == AST_FRAME_VOICE) {
3591 /* not in gateway mode and have not detected v21 yet, listen
3592 * for v21 */
3593 return fax_gateway_detect_v21(gateway, chan, peer, active, f);
3594 }
3595
3596 /* in gateway mode, gateway some packets */
3597 if (gateway->t38_state == T38_STATE_NEGOTIATED) {
3598 struct ast_trans_pvt *readtrans;
3599
3600 if (!gateway->s || !gateway->s->tech_pvt) {
3601 ast_log(LOG_ERROR, "no FAX session on chan %s for T.38 gateway session, odd", ast_channel_name(chan));
3602 return f;
3603 }
3604
3605 /* framehooks are called in __ast_read() before frame format
3606 * translation is done, so we need to translate here */
3608 && (readtrans = ast_channel_readtrans(active))) {
3609 if ((f = ast_translate(readtrans, f, event == AST_FRAMEHOOK_EVENT_WRITE ? 0 : 1)) == NULL) {
3610 f = &ast_null_frame;
3611 return f;
3612 }
3613 /* XXX we ignore the return value here, perhaps we should
3614 * disable the gateway if a write fails. I am not sure how a
3615 * write would fail, or even if a failure would be fatal so for
3616 * now we'll just ignore the return value. */
3617 gateway->s->tech->write(gateway->s, f);
3618 ast_frfree(f);
3619 } else {
3620 gateway->s->tech->write(gateway->s, f);
3621 }
3622
3623 f = &ast_null_frame;
3624 return f;
3625 }
3626
3627 /* force silence on the line if T.38 negotiation might be taking place */
3628 if (gateway->t38_state != T38_STATE_UNAVAILABLE && gateway->t38_state != T38_STATE_REJECTED) {
3629 if (f->frametype == AST_FRAME_VOICE &&
3631 short silence_buf[f->samples];
3632 struct ast_frame silence_frame = {
3634 .subclass.format = ast_format_slin,
3635 .data.ptr = silence_buf,
3636 .samples = f->samples,
3637 .datalen = sizeof(silence_buf),
3638 };
3639 memset(silence_buf, 0, sizeof(silence_buf));
3640 return ast_frisolate(&silence_frame);
3641 } else {
3642 return &ast_null_frame;
3643 }
3644 }
3645
3646 return f;
3647}
struct ast_trans_pvt * ast_channel_readtrans(const struct ast_channel *chan)
#define ast_channel_lock_both(chan1, chan2)
Lock two channels.
Definition: channel.h:2979
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:444
struct ast_format * ast_channel_writeformat(struct ast_channel *chan)
int ast_set_write_format(struct ast_channel *chan, struct ast_format *format)
Sets write format on channel chan.
Definition: channel.c:5762
@ 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_fax_session * fax_v21_session_new(struct ast_channel *chan)
Definition: res_fax.c:2890
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:3041
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:3138
#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:485
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:566
#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 3374 of file res_fax.c.

3375{
3376 struct fax_gateway *gateway = data;
3377
3378 if (gateway->s) {
3379 switch (gateway->s->state) {
3381 case AST_FAX_STATE_OPEN:
3384 if (gateway->s->tech->cancel_session) {
3385 gateway->s->tech->cancel_session(gateway->s);
3386 }
3387 /* fall through */
3388 default:
3389 break;
3390 }
3391 }
3392
3393 ao2_ref(gateway, -1);
3394}
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 3114 of file res_fax.c.

3115{
3116 if (active == chan) {
3117 ast_channel_unlock(chan);
3118 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, control_params, sizeof(*control_params));
3119 ast_channel_lock(chan);
3120 } else {
3121 ast_queue_control_data(chan, AST_CONTROL_T38_PARAMETERS, control_params, sizeof(*control_params));
3122 }
3123}
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:1276

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

2910{
2911 struct fax_gateway *gateway = ao2_alloc(sizeof(*gateway), destroy_gateway);
2912 if (!gateway) {
2913 return NULL;
2914 }
2915
2916 if (!(gateway->chan_v21_session = fax_v21_session_new(chan))) {
2917 ast_log(LOG_ERROR, "Can't create V21 session on chan %s for T.38 gateway session\n", ast_channel_name(chan));
2918 ao2_ref(gateway, -1);
2919 return NULL;
2920 }
2921
2922 gateway->framehook = -1;
2923
2924 details->caps = AST_FAX_TECH_GATEWAY;
2925 if (details->gateway_timeout && !(gateway->s = fax_session_reserve(details, &gateway->token))) {
2926 details->caps &= ~AST_FAX_TECH_GATEWAY;
2927 ast_log(LOG_ERROR, "Can't reserve a FAX session, gateway attempt failed.\n");
2928 ao2_ref(gateway, -1);
2929 return NULL;
2930 }
2931
2932 return gateway;
2933}
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:1175
static void destroy_gateway(void *data)
destroy a FAX gateway session structure
Definition: res_fax.c:2868

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

3002{
3003 struct ast_frame *fp;
3004 struct ast_control_t38_parameters t38_parameters = {
3006 };
3007 struct ast_frame control_frame = {
3008 .src = "res_fax",
3009 .frametype = AST_FRAME_CONTROL,
3010 .datalen = sizeof(t38_parameters),
3012 .data.ptr = &t38_parameters,
3013 };
3014
3015 struct ast_fax_session_details *details = find_details(chan);
3016
3017 if (!details) {
3018 ast_log(LOG_ERROR, "no FAX session details found on chan %s for T.38 gateway session, odd\n", ast_channel_name(chan));
3019 ast_framehook_detach(chan, gateway->framehook);
3020 return NULL;
3021 }
3022
3023 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
3024 ao2_ref(details, -1);
3025
3026 if (!(fp = ast_frisolate(&control_frame))) {
3027 ast_log(LOG_ERROR, "error generating T.38 request control frame on chan %s for T.38 gateway session\n", ast_channel_name(chan));
3028 return NULL;
3029 }
3030
3032 gateway->timeout_start = ast_tvnow();
3033 details->is_t38_negotiated = 0;
3035
3036 ast_debug(1, "requesting T.38 for gateway session for %s\n", ast_channel_name(chan));
3037 return fp;
3038}
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 2946 of file res_fax.c.

2947{
2948 struct ast_fax_session *s;
2949 int start_res;
2950
2951 /* if the fax gateway is already started then do nothing */
2952 if (gateway->s &&
2953 gateway->s->state != AST_FAX_STATE_RESERVED && gateway->s->state != AST_FAX_STATE_INACTIVE) {
2954 return 0;
2955 }
2956
2957 /* if we start gateway we don't need v21 detection sessions any more */
2958 destroy_v21_sessions(gateway);
2959
2960 /* create the FAX session */
2961 if (!(s = fax_session_new(details, chan, gateway->s, gateway->token))) {
2962 gateway->token = NULL;
2964 ast_string_field_set(details, resultstr, "error starting gateway session");
2965 ast_string_field_set(details, error, "INIT_ERROR");
2968 report_fax_status(chan, details, "No Available Resource");
2969 ast_log(LOG_ERROR, "Can't create a FAX session, gateway attempt failed.\n");
2970 return -1;
2971 }
2972 /* release the reference for the reserved session and replace it with
2973 * the real session */
2974 if (gateway->s) {
2975 ao2_ref(gateway->s, -1);
2976 }
2977 gateway->s = s;
2978 gateway->token = NULL;
2979
2981 start_res = gateway->s->tech->start_session(gateway->s);
2983 if (start_res < 0) {
2985 ast_string_field_set(details, resultstr, "error starting gateway session");
2986 ast_string_field_set(details, error, "INIT_ERROR");
2989 return -1;
2990 }
2991
2992 gateway->timeout_start.tv_sec = 0;
2993 gateway->timeout_start.tv_usec = 0;
2994
2995 report_fax_status(chan, details, "FAX Transmission In Progress");
2996
2997 return 0;
2998}
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:1244
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 1075 of file res_fax.c.

1076{
1077 int rate;
1078
1079 if (sscanf(ratestr, "%d", &rate) != 1) {
1080 ast_log(LOG_ERROR, "failed to sscanf '%s' to rate\n", ratestr);
1081 return 0;
1082 }
1083 switch (rate) {
1084 case 2400:
1085 case 4800:
1086 case 7200:
1087 case 9600:
1088 case 12000:
1089 case 14400:
1090 case 28800:
1091 case 33600:
1092 return rate;
1093 default:
1094 ast_log(LOG_WARNING, "ignoring invalid rate '%s'. Valid options are {2400 | 4800 | 7200 | 9600 | 12000 | 14400 | 28800 | 33600}\n", ratestr);
1095 return 0;
1096 }
1097}

References ast_log, LOG_ERROR, and LOG_WARNING.

Referenced by acf_faxopt_write(), and 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 1244 of file res_fax.c.

1245{
1246 struct ast_fax_session *s = NULL;
1247 struct fax_module *faxmod;
1248
1249 if (reserved) {
1250 s = reserved;
1251 ao2_ref(reserved, +1);
1252 ao2_unlink(faxregistry.container, reserved);
1253
1254 /* NOTE: we don't consume the reference to the reserved
1255 * session. The session returned from fax_session_new() is a
1256 * new reference and must be derefed in addition to the
1257 * reserved session.
1258 */
1259
1260 if (s->state == AST_FAX_STATE_RESERVED) {
1261 ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, -1);
1263 }
1264 }
1265
1266 if (!s && !(s = ao2_alloc(sizeof(*s), destroy_session))) {
1267 return NULL;
1268 }
1269
1270 ast_atomic_fetchadd_int(&faxregistry.active_sessions, 1);
1272
1273 if (details->option.debug && (details->caps & AST_FAX_TECH_AUDIO)) {
1274 if (!(s->debug_info = ast_calloc(1, sizeof(*(s->debug_info))))) {
1275 fax_session_release(s, token);
1276 ao2_ref(s, -1);
1277 return NULL;
1278 }
1279 if (!(s->debug_info->dsp = ast_dsp_new())) {
1280 ast_free(s->debug_info);
1281 s->debug_info = NULL;
1282 fax_session_release(s, token);
1283 ao2_ref(s, -1);
1284 return NULL;
1285 }
1287 }
1288
1289 if (!(s->channame = ast_strdup(ast_channel_name(chan)))) {
1290 fax_session_release(s, token);
1291 ao2_ref(s, -1);
1292 return NULL;
1293 }
1294
1295 if (!(s->chan_uniqueid = ast_strdup(ast_channel_uniqueid(chan)))) {
1296 fax_session_release(s, token);
1297 ao2_ref(s, -1);
1298 return NULL;
1299 }
1300
1301 s->chan = chan;
1302 if (!s->details) {
1303 s->details = details;
1304 ao2_ref(s->details, 1);
1305 }
1306
1307 details->id = s->id = ast_atomic_fetchadd_int(&faxregistry.nextsessionname, 1);
1308
1309 if (!token) {
1310 /* locate a FAX technology module that can handle said requirements */
1312 AST_RWLIST_TRAVERSE(&faxmodules, faxmod, list) {
1313 if ((faxmod->tech->caps & details->caps) != details->caps) {
1314 continue;
1315 }
1316 if (!ast_module_running_ref(faxmod->tech->module)) {
1317 continue;
1318 }
1319 ast_debug(4, "Requesting a new FAX session from '%s'.\n", faxmod->tech->description);
1320 if (reserved) {
1321 /* Balance module ref from reserved session */
1322 ast_module_unref(reserved->tech->module);
1323 }
1324 s->tech = faxmod->tech;
1325 break;
1326 }
1328
1329 if (!faxmod) {
1330 char caps[128] = "";
1331 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)));
1332 ao2_ref(s, -1);
1333 return NULL;
1334 }
1335 }
1336
1337 if (!(s->tech_pvt = s->tech->new_session(s, token))) {
1338 ast_log(LOG_ERROR, "FAX session failed to initialize.\n");
1339 ao2_ref(s, -1);
1340 return NULL;
1341 }
1342 /* link the session to the session container */
1343 if (!(ao2_link(faxregistry.container, s))) {
1344 ast_log(LOG_ERROR, "failed to add FAX session '%u' to container.\n", s->id);
1345 ao2_ref(s, -1);
1346 return NULL;
1347 }
1348 ast_debug(4, "channel '%s' using FAX session '%u'\n", s->channame, s->id);
1349
1350 return s;
1351}
#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:1788
#define ast_module_running_ref(mod)
Hold a reference to the module if it is running.
Definition: module.h:469
static char * ast_fax_caps_to_str(enum ast_fax_capabilities caps, char *buf, size_t bufsize)
Definition: res_fax.c:875
static void destroy_session(void *session)
destroy a FAX session structure
Definition: res_fax.c:1125
void *(*const new_session)(struct ast_fax_session *, struct ast_fax_tech_token *)
Definition: res_fax.h:251
enum ast_fax_capabilities caps
Definition: res_fax.h:243

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

1113{
1114 if (token) {
1115 s->tech->release_token(token);
1116 }
1117
1118 if (s->state == AST_FAX_STATE_RESERVED) {
1119 ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, -1);
1121 }
1122}
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 1175 of file res_fax.c.

1176{
1177 struct ast_fax_session *s;
1178 struct fax_module *faxmod;
1179
1180 if (!(s = ao2_alloc(sizeof(*s), destroy_session))) {
1181 return NULL;
1182 }
1183
1185 s->details = details;
1186 ao2_ref(s->details, 1);
1187
1188 /* locate a FAX technology module that can handle said requirements
1189 * Note: the requirements have not yet been finalized as T.38
1190 * negotiation has not yet occured. */
1192 AST_RWLIST_TRAVERSE(&faxmodules, faxmod, list) {
1193 if ((faxmod->tech->caps & details->caps) != details->caps) {
1194 continue;
1195 }
1196 if (!ast_module_running_ref(faxmod->tech->module)) {
1197 continue;
1198 }
1199 ast_debug(4, "Reserving a FAX session from '%s'.\n", faxmod->tech->description);
1200 s->tech = faxmod->tech;
1201 break;
1202 }
1204
1205 if (!faxmod) {
1206 char caps[128] = "";
1207 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)));
1208 ao2_ref(s, -1);
1209 return NULL;
1210 }
1211
1212 if (!s->tech->reserve_session) {
1213 ast_debug(1, "Selected FAX technology module (%s) does not support reserving sessions.\n", s->tech->description);
1214 return s;
1215 }
1216
1217 if (!(*token = s->tech->reserve_session(s))) {
1218 ao2_ref(s, -1);
1219 return NULL;
1220 }
1221
1223 ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, 1);
1224
1225 return s;
1226}
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 3972 of file res_fax.c.

3973{
3974 int tklen;
3975 int wordnum = 0;
3976 char *name = NULL;
3977 struct ao2_iterator i;
3978 struct ast_fax_session *s;
3979 char tbuf[5];
3980
3981 if (a->pos != 3) {
3982 return NULL;
3983 }
3984
3985 tklen = strlen(a->word);
3986 i = ao2_iterator_init(faxregistry.container, 0);
3987 while ((s = ao2_iterator_next(&i))) {
3988 snprintf(tbuf, sizeof(tbuf), "%u", s->id);
3989 if (!strncasecmp(a->word, tbuf, tklen) && ++wordnum > a->n) {
3990 name = ast_strdup(tbuf);
3991 ao2_ref(s, -1);
3992 break;
3993 }
3994 ao2_ref(s, -1);
3995 }
3997 return name;
3998}
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 4271 of file res_fax.c.

4272{
4273 if (s->details->caps & AST_FAX_TECH_AUDIO) {
4274 return "G.711";
4275 }
4276 if (s->details->caps & AST_FAX_TECH_T38) {
4277 return "T.38";
4278 }
4279
4280 return "none";
4281}

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

2890 {
2891 struct ast_fax_session_details *v21_details;
2892 struct ast_fax_session *v21_session;
2893
2894 if (!chan || !(v21_details = session_details_new())) {
2895 return NULL;
2896 }
2897
2898 v21_details->caps = AST_FAX_TECH_V21_DETECT;
2899 v21_session = fax_session_new(v21_details, chan, NULL, NULL);
2900 ao2_ref(v21_details, -1);
2901 return v21_session;
2902}
static struct ast_fax_session_details * session_details_new(void)
create a FAX session details structure
Definition: res_fax.c:725

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

692{
693 struct ast_fax_session_details *details;
694 struct ast_datastore *datastore;
695
696 ast_channel_lock(chan);
697 if (!(datastore = ast_channel_datastore_find(chan, &fax_datastore, NULL))) {
698 ast_channel_unlock(chan);
699 return NULL;
700 }
701 if (!(details = datastore->data)) {
702 ast_log(LOG_WARNING, "Huh? channel '%s' has a FAX datastore without data!\n", ast_channel_name(chan));
703 ast_channel_unlock(chan);
704 return NULL;
705 }
706 ao2_ref(details, 1);
707 ast_channel_unlock(chan);
708
709 return details;
710}
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:2368
static const struct ast_datastore_info fax_datastore
Definition: res_fax.c:648
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 793 of file res_fax.c.

794{
795 struct ast_fax_session_details *details;
796 struct ast_datastore *datastore;
797
798 if ((details = find_details(chan))) {
799 return details;
800 }
801 /* channel does not have one so we must create one */
802 if (!(details = session_details_new())) {
803 ast_log(LOG_WARNING, "channel '%s' can't get a FAX details structure for the datastore!\n", ast_channel_name(chan));
804 return NULL;
805 }
806 if (!(datastore = ast_datastore_alloc(&fax_datastore, NULL))) {
807 ao2_ref(details, -1);
808 ast_log(LOG_WARNING, "channel '%s' can't get a datastore!\n", ast_channel_name(chan));
809 return NULL;
810 }
811 /* add the datastore to the channel and increment the refcount */
812 datastore->data = details;
813
814 /* initialize default T.38 parameters */
817
818 ao2_ref(details, 1);
819 ast_channel_lock(chan);
820 ast_channel_datastore_add(chan, datastore);
821 ast_channel_unlock(chan);
822 return details;
823}
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2354
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:85
static struct ast_control_t38_parameters our_t38_parameters
Definition: res_fax.c:762

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 acf_faxopt_write(), 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 665 of file res_fax.c.

666{
667 struct ast_fax_session_details *old_details = data;
668 struct ast_datastore *datastore = ast_channel_datastore_find(old_chan, &fax_datastore, NULL);
669
670 if (old_details->gateway_id >= 0) {
671 struct ast_fax_session_details *new_details = find_or_create_details(new_chan);
672
673 ast_framehook_detach(old_chan, old_details->gateway_id);
674 new_details->is_t38_negotiated = old_details->is_t38_negotiated;
675 fax_gateway_attach(new_chan, new_details);
676 ao2_cleanup(new_details);
677 }
678
679 if (old_details->faxdetect_id >= 0) {
680 ast_framehook_detach(old_chan, old_details->faxdetect_id);
681 fax_detect_attach(new_chan, old_details->faxdetect_timeout, old_details->faxdetect_flags);
682 }
683
684 if (datastore) {
685 ast_channel_datastore_remove(old_chan, datastore);
686 ast_datastore_free(datastore);
687 }
688}
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition: channel.c:2363
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 1359 of file res_fax.c.

1360{
1361 RAII_VAR(struct ast_json *, json_array, ast_json_array_create(), ast_json_unref);
1362 struct ast_fax_document *doc;
1363
1364 if (!details || !json_array) {
1365 return NULL;
1366 }
1367
1368 /* don't process empty lists */
1369 if (AST_LIST_EMPTY(&details->documents)) {
1370 return NULL;
1371 }
1372
1373 AST_LIST_TRAVERSE(&details->documents, doc, next) {
1374 struct ast_json *entry = ast_json_string_create(doc->filename);
1375 if (!entry) {
1376 return NULL;
1377 }
1378 if (ast_json_array_append(json_array, entry)) {
1379 return NULL;
1380 }
1381 }
1382
1383 ast_json_ref(json_array);
1384 return json_array;
1385}
struct ast_json * ast_json_string_create(const char *value)
Construct a JSON string from value.
Definition: json.c:278
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:378
struct ast_json * ast_json_array_create(void)
Create a empty JSON array.
Definition: json.c:362
struct ast_json * ast_json_ref(struct ast_json *value)
Increase refcount on value.
Definition: json.c:67
#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, ...).

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

1400{
1401 char *filenames, *c;
1402 size_t size = 0;
1403 int first = 1;
1404 struct ast_fax_document *doc;
1405
1406 /* don't process empty lists */
1407 if (AST_LIST_EMPTY(&details->documents)) {
1408 return ast_strdup("");
1409 }
1410
1411 /* Calculate the total length of all of the file names */
1412 AST_LIST_TRAVERSE(&details->documents, doc, next) {
1413 size += strlen(separator) + strlen(prefix) + strlen(doc->filename);
1414 }
1415 size += 1; /* add space for the terminating null */
1416
1417 if (!(filenames = ast_malloc(size))) {
1418 return NULL;
1419 }
1420 c = filenames;
1421
1422 ast_build_string(&c, &size, "%s%s", prefix, AST_LIST_FIRST(&details->documents)->filename);
1423 AST_LIST_TRAVERSE(&details->documents, doc, next) {
1424 if (first) {
1425 first = 0;
1426 continue;
1427 }
1428
1429 ast_build_string(&c, &size, "%s%s%s", separator, prefix, doc->filename);
1430 }
1431
1432 return filenames;
1433}
#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 1619 of file res_fax.c.

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

4427{
4431}
#define ast_rwlock_rdlock(a)
Definition: lock.h:242
#define ast_rwlock_unlock(a)
Definition: lock.h:241
static ast_rwlock_t options_lock
Definition: res_fax.c:577
static struct fax_options general_options
Definition: res_fax.c:566

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

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

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

4818{
4819 int res;
4820
4821 /* initialize the registry */
4822 faxregistry.active_sessions = 0;
4823 faxregistry.reserved_sessions = 0;
4826 if (!faxregistry.container) {
4828 }
4829
4830 if (set_config(0) < 0) {
4831 ast_log(LOG_ERROR, "failed to load configuration file '%s'\n", config);
4832 ao2_ref(faxregistry.container, -1);
4834 }
4835
4836 /* register CLI operations and applications */
4838 ast_log(LOG_WARNING, "failed to register '%s'.\n", app_sendfax);
4839 ao2_ref(faxregistry.container, -1);
4841 }
4843 ast_log(LOG_WARNING, "failed to register '%s'.\n", app_receivefax);
4845 ao2_ref(faxregistry.container, -1);
4847 }
4848
4850 ast_log(LOG_WARNING, "failed to register 'FAXSessions' AMI command.\n");
4853 ao2_ref(faxregistry.container, -1);
4855 }
4856
4858 ast_log(LOG_WARNING, "failed to register 'FAXSession' AMI command.\n");
4859 ast_manager_unregister("FAXSession");
4862 ao2_ref(faxregistry.container, -1);
4864 }
4865
4867 ast_log(LOG_WARNING, "failed to register 'FAXStats' AMI command.\n");
4868 ast_manager_unregister("FAXSession");
4869 ast_manager_unregister("FAXSessions");
4872 ao2_ref(faxregistry.container, -1);
4874 }
4875
4879
4880 return res;
4881}
@ 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:7697
int ast_logger_register_level(const char *name)
Register a new logger level.
Definition: logger.c:2826
#define EVENT_FLAG_REPORTING
Definition: manager.h:84
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:192
#define EVENT_FLAG_CALL
Definition: manager.h:76
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:640
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1559
static int session_cmp_cb(void *obj, void *arg, int flags)
compare callback for ao2
Definition: res_fax.c:3964
static int session_hash_cb(const void *obj, const int flags)
hash callback for ao2
Definition: res_fax.c:3956
static const char app_receivefax[]
Definition: res_fax.c:457
static struct ast_custom_function acf_faxopt
FAXOPT dialplan function.
Definition: res_fax.c:4771
static const char * config
Definition: res_fax.c:582
static int sendfax_exec(struct ast_channel *chan, const char *data)
initiate a send FAX session
Definition: res_fax.c:2619
#define FAX_MAXBUCKETS
maximum buckets for res_fax ao2 containers
Definition: res_fax.c:519
static int receivefax_exec(struct ast_channel *chan, const char *data)
initiate a receive FAX session
Definition: res_fax.c:2111
static int set_config(int reload)
configure res_fax
Definition: res_fax.c:4451
static const char app_sendfax[]
Definition: res_fax.c:458
static int manager_fax_session(struct mansession *s, const struct message *m)
Definition: res_fax.c:4172
static int manager_fax_stats(struct mansession *s, const struct message *m)
Definition: res_fax.c:4242
static struct ast_cli_entry fax_cli[]
Definition: res_fax.c:4409
static int manager_fax_sessions(struct mansession *s, const struct message *m)
Definition: res_fax.c:4378
#define ARRAY_LEN(a)
Definition: utils.h:666

References acf_faxopt, AO2_ALLOC_OPT_LOCK_MUTEX, ao2_container_alloc_hash, ao2_ref, app_receivefax, app_sendfax, ARRAY_LEN, ast_cli_register_multiple, ast_custom_function_register, ast_log, ast_logger_register_level(), ast_manager_register_xml, ast_manager_unregister(), AST_MODULE_LOAD_DECLINE, ast_register_application_xml, ast_unregister_application(), config, EVENT_FLAG_CALL, EVENT_FLAG_REPORTING, fax_cli, fax_logger_level, FAX_MAXBUCKETS, faxregistry, LOG_ERROR, LOG_WARNING, manager_fax_session(), manager_fax_sessions(), manager_fax_stats(), NULL, receivefax_exec(), sendfax_exec(), session_cmp_cb(), session_hash_cb(), and set_config().

◆ manager_fax_session()

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

Definition at line 4172 of file res_fax.c.

4173{
4174 const char *action_id = astman_get_header(m, "ActionID");
4175 const char *session_number = astman_get_header(m, "SessionNumber");
4176 char id_text[256] = "";
4177 struct ast_fax_session *session;
4179
4180 if (sscanf(session_number, "%30u", &find_session.id) != 1) {
4181 astman_send_error(s, m, "Invalid session ID");
4182 return 0;
4183 }
4184
4186 if (!session) {
4187 astman_send_error(s, m, "Session not found");
4188 return 0;
4189 }
4190
4191 if (!session->tech->manager_fax_session) {
4192 astman_send_error(s, m, "Fax technology doesn't provide a handler for FAXSession");
4193 ao2_ref(session, -1);
4194 return 0;
4195 }
4196
4197 if (!ast_strlen_zero(action_id)) {
4198 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", action_id);
4199 }
4200
4201 astman_send_ack(s, m, "FAXSession event will follow");
4202
4203 session->tech->manager_fax_session(s, id_text, session);
4204 ao2_ref(session, -1);
4205
4206 return 0;
4207}
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:1986
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:2018
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:1647
static struct mansession_session * find_session(uint32_t ident, int incinuse)
Definition: manager.c:7926

References ao2_find, ao2_ref, ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), faxregistry, find_session(), OBJ_POINTER, and session.

Referenced by load_module().

◆ manager_fax_sessions()

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

Definition at line 4378 of file res_fax.c.

4379{
4380 const char *action_id = astman_get_header(m, "ActionID");
4381 char id_text[256];
4382 struct ast_fax_session *session;
4383 struct ao2_iterator iter;
4384 int session_count = 0;
4385
4386 id_text[0] = '\0';
4387 if (!ast_strlen_zero(action_id)) {
4388 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", action_id);
4389 }
4390
4391 astman_send_listack(s, m, "FAXSessionsEntry event list will follow", "Start");
4392
4393 iter = ao2_iterator_init(faxregistry.container, 0);
4394 while ((session = ao2_iterator_next(&iter))) {
4395 if (!manager_fax_sessions_entry(s, session, id_text)) {
4396 session_count++;
4397 }
4398 ao2_ref(session, -1);
4399 }
4400 ao2_iterator_destroy(&iter);
4401
4402 astman_send_list_complete_start(s, m, "FAXSessionsComplete", session_count);
4403 astman_append(s, "Total: %d\r\n", session_count);
4405
4406 return 0;
4407}
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
Definition: manager.c:2028
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
Definition: manager.c:2064
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:2072
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:1907
static int manager_fax_sessions_entry(struct mansession *s, struct ast_fax_session *session, const char *id_text)
Definition: res_fax.c:4346

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

Referenced by load_module().

◆ manager_fax_sessions_entry()

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

Definition at line 4346 of file res_fax.c.

4348{
4349 char *filenames;
4350
4352 filenames = generate_filenames_string(session->details, "", ",");
4353
4354 if (!filenames) {
4355 ast_log(LOG_ERROR, "Error generating Files string");
4357 return -1;
4358 }
4359
4360 astman_append(s, "Event: FAXSessionsEntry\r\n"
4361 "%s" /* ActionID if present */
4362 "Channel: %s\r\n" /* Channel name */
4363 "Technology: %s\r\n" /* Fax session technology */
4364 "SessionNumber: %u\r\n" /* Session ID */
4365 "SessionType: %s\r\n" /* G711 or T38 */
4366 "Operation: %s\r\n"
4367 "State: %s\r\n"
4368 "Files: %s\r\n"
4369 "\r\n",
4370 id_text, session->channame, session->tech->type, session->id,
4372 ast_fax_state_to_str(session->state), S_OR(filenames, ""));
4373 ast_free(filenames);
4375 return 0;
4376}

References ao2_lock, ao2_unlock, ast_fax_session_operation_str(), ast_fax_state_to_str(), ast_free, ast_log, astman_append(), fax_session_type(), generate_filenames_string(), LOG_ERROR, S_OR, and session.

Referenced by manager_fax_sessions().

◆ manager_fax_stats()

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

Definition at line 4242 of file res_fax.c.

4243{
4244 const char *action_id = astman_get_header(m, "ActionID");
4245
4246 char id_text[256] = "";
4247
4248 astman_send_ack(s, m, "FAXStats event will follow");
4249
4250 if (!ast_strlen_zero(action_id)) {
4251 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", action_id);
4252 }
4253
4254 astman_append(s, "Event: FAXStats\r\n"
4255 "%s"
4256 "CurrentSessions: %d\r\n"
4257 "ReservedSessions: %d\r\n"
4258 "TransmitAttempts: %d\r\n"
4259 "ReceiveAttempts: %d\r\n"
4260 "CompletedFAXes: %d\r\n"
4261 "FailedFAXes: %d\r\n"
4262 "\r\n",
4263 id_text,
4264 faxregistry.active_sessions, faxregistry.reserved_sessions,
4265 faxregistry.fax_tx_attempts, faxregistry.fax_rx_attempts,
4266 faxregistry.fax_complete, faxregistry.fax_failures);
4267
4268 return 0;
4269}

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

Referenced by load_module().

◆ receivefax_exec()

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

initiate a receive FAX session

Definition at line 2111 of file res_fax.c.

2112{
2113 char *parse, modems[128] = "";
2114 int channel_alive;
2116 RAII_VAR(struct ast_fax_session_details *, details, NULL, ao2_cleanup);
2117 struct ast_fax_tech_token *token = NULL;
2118 struct ast_fax_document *doc;
2122 );
2123 struct ast_flags opts = { 0, };
2124 enum ast_t38_state t38state;
2125
2126 /* initialize output channel variables */
2127 pbx_builtin_setvar_helper(chan, "FAXSTATUS", "FAILED");
2128 pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", NULL);
2129 pbx_builtin_setvar_helper(chan, "FAXPAGES", "0");
2130 pbx_builtin_setvar_helper(chan, "FAXBITRATE", NULL);
2131 pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", NULL);
2132 pbx_builtin_setvar_helper(chan, "FAXMODE", NULL);
2133
2134 /* Get a FAX session details structure from the channel's FAX datastore and create one if
2135 * it does not already exist. */
2136 if (!(details = find_or_create_details(chan))) {
2137 pbx_builtin_setvar_helper(chan, "FAXERROR", "MEMORY_ERROR");
2138 pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "error allocating memory");
2139 ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
2140 return -1;
2141 }
2142
2143 ast_string_field_set(details, result, "FAILED");
2144 ast_string_field_set(details, resultstr, "error starting fax session");
2145 ast_string_field_set(details, error, "INIT_ERROR");
2146 set_channel_variables(chan, details);
2147
2148 if (details->gateway_id > 0) {
2149 ast_string_field_set(details, resultstr, "can't receive a fax on a channel with a T.38 gateway");
2150 set_channel_variables(chan, details);
2151 ast_log(LOG_ERROR, "executing ReceiveFAX on a channel with a T.38 Gateway is not supported\n");
2152 return -1;
2153 }
2154
2155 if (details->maxrate < details->minrate) {
2156 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2157 ast_string_field_set(details, resultstr, "maxrate is less than minrate");
2158 set_channel_variables(chan, details);
2159 ast_log(LOG_ERROR, "maxrate %u is less than minrate %u\n", details->maxrate, details->minrate);
2160 return -1;
2161 }
2162
2163 if (check_modem_rate(details->modems, details->minrate)) {
2164 ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
2165 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %u\n", modems, details->minrate);
2166 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2167 ast_string_field_set(details, resultstr, "incompatible 'modems' and 'minrate' settings");
2168 set_channel_variables(chan, details);
2169 return -1;
2170 }
2171
2172 if (check_modem_rate(details->modems, details->maxrate)) {
2173 ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
2174 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %u\n", modems, details->maxrate);
2175 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2176 ast_string_field_set(details, resultstr, "incompatible 'modems' and 'maxrate' settings");
2177 set_channel_variables(chan, details);
2178 return -1;
2179 }
2180
2181 if (ast_strlen_zero(data)) {
2182 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2183 ast_string_field_set(details, resultstr, "invalid arguments");
2184 set_channel_variables(chan, details);
2185 ast_log(LOG_WARNING, "%s requires an argument (filename[,options])\n", app_receivefax);
2186 return -1;
2187 }
2188 parse = ast_strdupa(data);
2190
2191 if (!ast_strlen_zero(args.options) &&
2192 ast_app_parse_options(fax_exec_options, &opts, NULL, args.options)) {
2193 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2194 ast_string_field_set(details, resultstr, "invalid arguments");
2195 set_channel_variables(chan, details);
2196 return -1;
2197 }
2198 if (ast_strlen_zero(args.filename)) {
2199 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2200 ast_string_field_set(details, resultstr, "invalid arguments");
2201 set_channel_variables(chan, details);
2202 ast_log(LOG_WARNING, "%s requires an argument (filename[,options])\n", app_receivefax);
2203 return -1;
2204 }
2205
2206 /* check for unsupported FAX application options */
2208 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2209 ast_string_field_set(details, resultstr, "invalid arguments");
2210 set_channel_variables(chan, details);
2211 ast_log(LOG_WARNING, "%s does not support polling\n", app_receivefax);
2212 return -1;
2213 }
2214
2215 ast_atomic_fetchadd_int(&faxregistry.fax_rx_attempts, 1);
2216
2217 pbx_builtin_setvar_helper(chan, "FAXERROR", "Channel Problems");
2218 pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "Error before FAX transmission started.");
2219
2220 if (!(doc = ast_calloc(1, sizeof(*doc) + strlen(args.filename) + 1))) {
2221 ast_string_field_set(details, error, "MEMORY_ERROR");
2222 ast_string_field_set(details, resultstr, "error allocating memory");
2223 set_channel_variables(chan, details);
2224 ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
2225 return -1;
2226 }
2227
2228 strcpy(doc->filename, args.filename);
2229 AST_LIST_INSERT_TAIL(&details->documents, doc, next);
2230
2231 ast_verb(3, "Channel '%s' receiving FAX '%s'\n", ast_channel_name(chan), args.filename);
2232
2233 details->caps = AST_FAX_TECH_RECEIVE;
2234 details->option.send_ced = AST_FAX_OPTFLAG_TRUE;
2235
2236 /* check for debug */
2237 if (ast_test_flag(&opts, OPT_DEBUG) || global_fax_debug) {
2238 details->option.debug = AST_FAX_OPTFLAG_TRUE;
2239 }
2240
2241 /* check for request for status events */
2242 if (ast_test_flag(&opts, OPT_STATUS)) {
2243 details->option.statusevents = AST_FAX_OPTFLAG_TRUE;
2244 }
2245
2246 t38state = ast_channel_get_t38_state(chan);
2247 if ((t38state == T38_STATE_UNAVAILABLE) || (t38state == T38_STATE_REJECTED) ||
2248 ast_test_flag(&opts, OPT_ALLOWAUDIO) ||
2250 details->option.allow_audio = AST_FAX_OPTFLAG_TRUE;
2251 }
2252
2253 if (!(s = fax_session_reserve(details, &token))) {
2254 ast_string_field_set(details, resultstr, "error reserving fax session");
2255 set_channel_variables(chan, details);
2256 ast_log(LOG_ERROR, "Unable to reserve FAX session.\n");
2257 return -1;
2258 }
2259
2260 /* make sure the channel is up */
2261 if (ast_channel_state(chan) != AST_STATE_UP) {
2262 if (ast_answer(chan)) {
2263 ast_string_field_set(details, resultstr, "error answering channel");
2264 set_channel_variables(chan, details);
2265 ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", ast_channel_name(chan));
2266 fax_session_release(s, token);
2267 return -1;
2268 }
2269 }
2270
2271 if (!ast_test_flag(&opts, OPT_FORCE_AUDIO)) {
2272 if (set_fax_t38_caps(chan, details)) {
2273 ast_string_field_set(details, error, "T38_NEG_ERROR");
2274 ast_string_field_set(details, resultstr, "error negotiating T.38");
2275 set_channel_variables(chan, details);
2276 fax_session_release(s, token);
2277 return -1;
2278 }
2279 } else {
2280 details->caps |= AST_FAX_TECH_AUDIO;
2281 }
2282
2283 if (!ast_test_flag(&opts, OPT_FORCE_AUDIO) && (details->caps & AST_FAX_TECH_T38)) {
2284 if (receivefax_t38_init(chan, details)) {
2285 ast_string_field_set(details, error, "T38_NEG_ERROR");
2286 ast_string_field_set(details, resultstr, "error negotiating T.38");
2287 set_channel_variables(chan, details);
2288 fax_session_release(s, token);
2289 ast_log(LOG_ERROR, "error initializing channel '%s' in T.38 mode\n", ast_channel_name(chan));
2290 return -1;
2291 }
2292 }
2293
2294 if ((channel_alive = generic_fax_exec(chan, details, s, token)) < 0) {
2295 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
2296 }
2297
2299 if (disable_t38(chan)) {
2300 ast_debug(1, "error disabling T.38 mode on %s\n", ast_channel_name(chan));
2301 }
2302 }
2303
2304 if (report_receive_fax_status(chan, args.filename)) {
2305 ast_log(AST_LOG_ERROR, "Error publishing ReceiveFAX status message\n");
2306 }
2307
2308 /* If the channel hungup return -1; otherwise, return 0 to continue in the dialplan */
2309 return (!channel_alive) ? -1 : 0;
2310}
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2774
ast_channel_state
ast_channel states
Definition: channelstate.h:35
@ AST_STATE_UP
Definition: channelstate.h:42
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: main/app.c:3066
#define AST_LOG_ERROR
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
static int receivefax_t38_init(struct ast_channel *chan, struct ast_fax_session_details *details)
Definition: res_fax.c:1885
static const struct ast_app_option fax_exec_options[128]
Definition: res_fax.c:604
static int check_modem_rate(enum ast_fax_modems modems, unsigned int rate)
Definition: res_fax.c:967
static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_details *details, struct ast_fax_session *reserved, struct ast_fax_tech_token *token)
this is the generic FAX session handling function
Definition: res_fax.c:1619
static int set_fax_t38_caps(struct ast_channel *chan, struct ast_fax_session_details *details)
Definition: res_fax.c:1520
static int disable_t38(struct ast_channel *chan)
Definition: res_fax.c:1556
static int report_receive_fax_status(struct ast_channel *chan, const char *filename)
Report on the final state of a receive fax operation.
Definition: res_fax.c:2047
Structure used to handle boolean flags.
Definition: utils.h:199
const char * args

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

Referenced by load_module().

◆ receivefax_t38_init()

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

Definition at line 1885 of file res_fax.c.

1886{
1887 int timeout_ms;
1888 struct ast_frame *frame = NULL;
1889 struct ast_control_t38_parameters t38_parameters;
1890 struct timeval start;
1891 int ms;
1892
1893 /* don't send any audio if we've already received a T.38 reinvite */
1895 /* generate 3 seconds of CED */
1896 if (ast_playtones_start(chan, 1024, "!2100/3000", 1)) {
1897 ast_log(LOG_ERROR, "error generating CED tone on %s\n", ast_channel_name(chan));
1898 return -1;
1899 }
1900
1901 timeout_ms = 3000;
1902 start = ast_tvnow();
1903 while ((ms = ast_remaining_ms(start, timeout_ms))) {
1904 ms = ast_waitfor(chan, ms);
1905
1906 if (ms < 0) {
1907 ast_log(LOG_ERROR, "error while generating CED tone on %s\n", ast_channel_name(chan));
1908 ast_playtones_stop(chan);
1909 return -1;
1910 }
1911
1912 if (ms == 0) { /* all done, nothing happened */
1913 break;
1914 }
1915
1916 if (!(frame = ast_read(chan))) {
1917 ast_log(LOG_ERROR, "error reading frame while generating CED tone on %s\n", ast_channel_name(chan));
1918 ast_playtones_stop(chan);
1919 return -1;
1920 }
1921
1922 if ((frame->frametype == AST_FRAME_CONTROL) &&
1924 (frame->datalen == sizeof(t38_parameters))) {
1925 struct ast_control_t38_parameters *parameters = frame->data.ptr;
1926
1927 switch (parameters->request_response) {
1929 /* the other end has requested a switch to T.38, so reply that we are willing, if we can
1930 * do T.38 as well
1931 */
1932 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
1933 t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
1934 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
1935 ast_playtones_stop(chan);
1936 break;
1937 case AST_T38_NEGOTIATED:
1938 ast_debug(1, "Negotiated T.38 for receive on %s\n", ast_channel_name(chan));
1939 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
1940 details->caps &= ~AST_FAX_TECH_AUDIO;
1941 report_fax_status(chan, details, "T.38 Negotiated");
1942 break;
1943 default:
1944 break;
1945 }
1946 }
1947 ast_frfree(frame);
1948 }
1949
1950 ast_playtones_stop(chan);
1951 }
1952
1953 /* if T.38 was negotiated, we are done initializing */
1955 return 0;
1956 }
1957
1958 /* request T.38 */
1959 ast_debug(1, "Negotiating T.38 for receive on %s\n", ast_channel_name(chan));
1960
1961 /* wait for negotiation to complete */
1962 timeout_ms = details->t38timeout;
1963
1964 /* set parameters based on the session's parameters */
1965 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
1966 t38_parameters.request_response = AST_T38_REQUEST_NEGOTIATE;
1967 if ((ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0)) {
1968 return -1;
1969 }
1970
1971 start = ast_tvnow();
1972 while ((ms = ast_remaining_ms(start, timeout_ms))) {
1973 int break_loop = 0;
1974
1975 ms = ast_waitfor(chan, ms);
1976 if (ms < 0) {
1977 ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", ast_channel_name(chan));
1978 return -1;
1979 }
1980 if (ms == 0) { /* all done, nothing happened */
1981 ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 negotiation.\n", ast_channel_name(chan));
1982 details->caps &= ~AST_FAX_TECH_T38;
1983 break;
1984 }
1985
1986 if (!(frame = ast_read(chan))) {
1987 ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", ast_channel_name(chan));
1988 return -1;
1989 }
1990
1991 if ((frame->frametype == AST_FRAME_CONTROL) &&
1993 (frame->datalen == sizeof(t38_parameters))) {
1994 struct ast_control_t38_parameters *parameters = frame->data.ptr;
1995
1996 switch (parameters->request_response) {
1998 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
1999 t38_parameters.request_response = AST_T38_NEGOTIATED;
2000 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
2001 break;
2002 case AST_T38_NEGOTIATED:
2003 ast_debug(1, "Negotiated T.38 for receive on %s\n", ast_channel_name(chan));
2004 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
2005 details->caps &= ~AST_FAX_TECH_AUDIO;
2006 report_fax_status(chan, details, "T.38 Negotiated");
2007 break_loop = 1;
2008 break;
2009 case AST_T38_REFUSED:
2010 ast_log(LOG_WARNING, "channel '%s' refused to negotiate T.38\n", ast_channel_name(chan));
2011 details->caps &= ~AST_FAX_TECH_T38;
2012 break_loop = 1;
2013 break;
2014 default:
2015 ast_log(LOG_ERROR, "channel '%s' failed to negotiate T.38\n", ast_channel_name(chan));
2016 details->caps &= ~AST_FAX_TECH_T38;
2017 break_loop = 1;
2018 break;
2019 }
2020 }
2021 ast_frfree(frame);
2022 if (break_loop) {
2023 break;
2024 }
2025 }
2026
2027 /* if T.38 was negotiated, we are done initializing */
2029 return 0;
2030 }
2031
2032 /* if we made it here, then T.38 failed, check the 'f' flag */
2033 if (details->option.allow_audio != AST_FAX_OPTFLAG_TRUE) {
2034 ast_log(LOG_WARNING, "Audio FAX not allowed on channel '%s' and T.38 negotiation failed; aborting.\n", ast_channel_name(chan));
2035 return -1;
2036 }
2037
2038 /* ok, audio fallback is allowed */
2039 details->caps |= AST_FAX_TECH_AUDIO;
2040
2041 return 0;
2042}
int ast_playtones_start(struct ast_channel *chan, int vol, const char *tonelist, int interruptible)
Start playing a list of tones on a channel.
Definition: indications.c:302
void ast_playtones_stop(struct ast_channel *chan)
Stop playing tones on a channel.
Definition: indications.c:393

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

Referenced by receivefax_exec().

◆ reload_module()

static int reload_module ( void  )
static

Definition at line 4883 of file res_fax.c.

4884{
4885 set_config(1);
4886 return 0;
4887}

References set_config().

◆ report_fax_status()

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

send a FAX status manager event

Definition at line 1436 of file res_fax.c.

1437{
1438 RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
1440 struct ast_json *json_filenames = NULL;
1441
1442 if (!details->option.statusevents) {
1443 return 0;
1444 }
1445
1446 json_filenames = generate_filenames_json(details);
1447 if (!json_filenames) {
1448 return -1;
1449 }
1450
1451 json_object = ast_json_pack("{s: s, s: s, s: s, s: s, s: o}",
1452 "type", "status",
1453 "operation", (details->caps & AST_FAX_TECH_GATEWAY)
1454 ? "gateway"
1455 : (details->caps & AST_FAX_TECH_RECEIVE) ? "receive" : "send",
1456 "status", status,
1457 "local_station_id", AST_JSON_UTF8_VALIDATE(details->localstationid),
1458 "filenames", json_filenames);
1459 if (!json_object) {
1460 return -1;
1461 }
1462
1463 {
1464 SCOPED_CHANNELLOCK(lock, chan);
1465
1467 if (!message) {
1468 return -1;
1469 }
1471 }
1472 return 0;
1473}
jack_status_t status
Definition: app_jack.c:149
ast_mutex_t lock
Definition: app_sla.c:337
struct stasis_topic * ast_channel_topic(struct ast_channel *chan)
A topic which publishes the events for a particular channel.
struct stasis_message * ast_channel_blob_create_from_cache(const char *uniqueid, struct stasis_message_type *type, struct ast_json *blob)
Create a ast_channel_blob message, pulling channel state from the cache.
struct stasis_message_type * ast_channel_fax_type(void)
Message type for a fax operation.
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:612
#define AST_JSON_UTF8_VALIDATE(str)
Check str for UTF-8 and replace with an empty string if fails the check.
Definition: json.h:224
#define SCOPED_CHANNELLOCK(varname, chan)
scoped lock specialization for channels.
Definition: lock.h:626
static struct ast_json * generate_filenames_json(struct ast_fax_session_details *details)
Definition: res_fax.c:1359
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
Definition: stasis.c:1538

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

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

◆ report_receive_fax_status()

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

Report on the final state of a receive fax operation.

Note
This will lock the ast_channel

Definition at line 2047 of file res_fax.c.

2048{
2049 RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
2051 RAII_VAR(struct ast_json *, json_array, ast_json_array_create(), ast_json_unref);
2052 struct ast_json *json_filename = ast_json_string_create(filename);
2053
2054 if (!json_array || !json_filename) {
2055 ast_json_unref(json_filename);
2056 return -1;
2057 }
2058 ast_json_array_append(json_array, json_filename);
2059
2060 {
2061 const char *remote_station_id;
2062 const char *local_station_id;
2063 const char *fax_pages;
2064 const char *fax_resolution;
2065 const char *fax_bitrate;
2066 SCOPED_CHANNELLOCK(lock, chan);
2067
2068 remote_station_id = AST_JSON_UTF8_VALIDATE(pbx_builtin_getvar_helper(chan, "REMOTESTATIONID"));
2069 if (!ast_strlen_zero(remote_station_id)) {
2070 remote_station_id = ast_strdupa(remote_station_id);
2071 }
2072 local_station_id = AST_JSON_UTF8_VALIDATE(pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"));
2073 if (!ast_strlen_zero(local_station_id)) {
2074 local_station_id = ast_strdupa(local_station_id);
2075 }
2076 fax_pages = S_OR(pbx_builtin_getvar_helper(chan, "FAXPAGES"), "");
2077 if (!ast_strlen_zero(fax_pages)) {
2078 fax_pages = ast_strdupa(fax_pages);
2079 }
2080 fax_resolution = S_OR(pbx_builtin_getvar_helper(chan, "FAXRESOLUTION"), "");
2081 if (!ast_strlen_zero(fax_resolution)) {
2082 fax_resolution = ast_strdupa(fax_resolution);
2083 }
2084 fax_bitrate = S_OR(pbx_builtin_getvar_helper(chan, "FAXBITRATE"), "");
2085 if (!ast_strlen_zero(fax_bitrate)) {
2086 fax_bitrate = ast_strdupa(fax_bitrate);
2087 }
2088
2089 json_object = ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: s, s: o}",
2090 "type", "receive",
2091 "remote_station_id", S_OR(remote_station_id, ""),
2092 "local_station_id", S_OR(local_station_id, ""),
2093 "fax_pages", S_OR(fax_pages, ""),
2094 "fax_resolution", S_OR(fax_resolution, ""),
2095 "fax_bitrate", S_OR(fax_bitrate, ""),
2096 "filenames", ast_json_ref(json_array));
2097 if (!json_object) {
2098 return -1;
2099 }
2100
2102 if (!message) {
2103 return -1;
2104 }
2106 }
2107 return 0;
2108}

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

Referenced by receivefax_exec().

◆ report_send_fax_status()

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

Report on the status of a completed fax send attempt.

Note
This will lock the ast_channel

Definition at line 2556 of file res_fax.c.

2557{
2558 RAII_VAR(struct ast_json *, json_obj, NULL, ast_json_unref);
2560 struct ast_json *json_filenames;
2561
2562 json_filenames = generate_filenames_json(details);
2563 if (!json_filenames) {
2564 return -1;
2565 }
2566
2567 {
2568 const char *remote_station_id;
2569 const char *local_station_id;
2570 const char *fax_pages;
2571 const char *fax_resolution;
2572 const char *fax_bitrate;
2573 SCOPED_CHANNELLOCK(lock, chan);
2574
2575 remote_station_id = AST_JSON_UTF8_VALIDATE(pbx_builtin_getvar_helper(chan, "REMOTESTATIONID"));
2576 if (!ast_strlen_zero(remote_station_id)) {
2577 remote_station_id = ast_strdupa(remote_station_id);
2578 }
2579 local_station_id = AST_JSON_UTF8_VALIDATE(pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"));
2580 if (!ast_strlen_zero(local_station_id)) {
2581 local_station_id = ast_strdupa(local_station_id);
2582 }
2583 fax_pages = S_OR(pbx_builtin_getvar_helper(chan, "FAXPAGES"), "");
2584 if (!ast_strlen_zero(fax_pages)) {
2585 fax_pages = ast_strdupa(fax_pages);
2586 }
2587 fax_resolution = S_OR(pbx_builtin_getvar_helper(chan, "FAXRESOLUTION"), "");
2588 if (!ast_strlen_zero(fax_resolution)) {
2589 fax_resolution = ast_strdupa(fax_resolution);
2590 }
2591 fax_bitrate = S_OR(pbx_builtin_getvar_helper(chan, "FAXBITRATE"), "");
2592 if (!ast_strlen_zero(fax_bitrate)) {
2593 fax_bitrate = ast_strdupa(fax_bitrate);
2594 }
2595 json_obj = ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: s, s: o}",
2596 "type", "send",
2597 "remote_station_id", S_OR(remote_station_id, ""),
2598 "local_station_id", S_OR(local_station_id, ""),
2599 "fax_pages", S_OR(fax_pages, ""),
2600 "fax_resolution", S_OR(fax_resolution, ""),
2601 "fax_bitrate", S_OR(fax_bitrate, ""),
2602 "filenames", json_filenames);
2603 if (!json_obj) {
2604 return -1;
2605 }
2606
2608 if (!message) {
2609 return -1;
2610 }
2612 }
2613 return 0;
2614}

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

Referenced by sendfax_exec().

◆ sendfax_exec()

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

initiate a send FAX session

Definition at line 2619 of file res_fax.c.

2620{
2621 char *parse, *filenames, *c, modems[128] = "";
2622 int channel_alive, file_count;
2623 RAII_VAR(struct ast_fax_session_details *, details, NULL, ao2_cleanup);
2625 struct ast_fax_tech_token *token = NULL;
2626 struct ast_fax_document *doc;
2628 AST_APP_ARG(filenames);
2630 );
2631 struct ast_flags opts = { 0, };
2632 enum ast_t38_state t38state;
2633
2634 /* initialize output channel variables */
2635 pbx_builtin_setvar_helper(chan, "FAXSTATUS", "FAILED");
2636 pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", NULL);
2637 pbx_builtin_setvar_helper(chan, "FAXPAGES", "0");
2638 pbx_builtin_setvar_helper(chan, "FAXBITRATE", NULL);
2639 pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", NULL);
2640 pbx_builtin_setvar_helper(chan, "FAXMODE", NULL);
2641
2642 /* Get a requirement structure and set it. This structure is used
2643 * to tell the FAX technology module about the higher level FAX session */
2644 if (!(details = find_or_create_details(chan))) {
2645 pbx_builtin_setvar_helper(chan, "FAXERROR", "MEMORY_ERROR");
2646 pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "error allocating memory");
2647 ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
2648 return -1;
2649 }
2650
2651 ast_string_field_set(details, result, "FAILED");
2652 ast_string_field_set(details, resultstr, "error starting fax session");
2653 ast_string_field_set(details, error, "INIT_ERROR");
2654 set_channel_variables(chan, details);
2655
2656 if (details->gateway_id > 0) {
2657 ast_string_field_set(details, resultstr, "can't send a fax on a channel with a T.38 gateway");
2658 set_channel_variables(chan, details);
2659 ast_log(LOG_ERROR, "executing SendFAX on a channel with a T.38 Gateway is not supported\n");
2660 return -1;
2661 }
2662
2663 if (details->maxrate < details->minrate) {
2664 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2665 ast_string_field_set(details, resultstr, "maxrate is less than minrate");
2666 set_channel_variables(chan, details);
2667 ast_log(LOG_ERROR, "maxrate %u is less than minrate %u\n", details->maxrate, details->minrate);
2668 return -1;
2669 }
2670
2671 if (check_modem_rate(details->modems, details->minrate)) {
2672 ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
2673 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %u\n", modems, details->minrate);
2674 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2675 ast_string_field_set(details, resultstr, "incompatible 'modems' and 'minrate' settings");
2676 set_channel_variables(chan, details);
2677 return -1;
2678 }
2679
2680 if (check_modem_rate(details->modems, details->maxrate)) {
2681 ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
2682 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %u\n", modems, details->maxrate);
2683 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2684 ast_string_field_set(details, resultstr, "incompatible 'modems' and 'maxrate' settings");
2685 set_channel_variables(chan, details);
2686 return -1;
2687 }
2688
2689 if (ast_strlen_zero(data)) {
2690 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2691 ast_string_field_set(details, resultstr, "invalid arguments");
2692 set_channel_variables(chan, details);
2693 ast_log(LOG_WARNING, "%s requires an argument (filename[&filename[&filename]][,options])\n", app_sendfax);
2694 return -1;
2695 }
2696 parse = ast_strdupa(data);
2698
2699
2700 if (!ast_strlen_zero(args.options) &&
2701 ast_app_parse_options(fax_exec_options, &opts, NULL, args.options)) {
2702 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2703 ast_string_field_set(details, resultstr, "invalid arguments");
2704 set_channel_variables(chan, details);
2705 return -1;
2706 }
2707 if (ast_strlen_zero(args.filenames)) {
2708 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2709 ast_string_field_set(details, resultstr, "invalid arguments");
2710 set_channel_variables(chan, details);
2711 ast_log(LOG_WARNING, "%s requires an argument (filename[&filename[&filename]],options])\n", app_sendfax);
2712 return -1;
2713 }
2714
2715 /* check for unsupported FAX application options */
2717 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2718 ast_string_field_set(details, resultstr, "invalid arguments");
2719 set_channel_variables(chan, details);
2720 ast_log(LOG_WARNING, "%s does not support polling\n", app_sendfax);
2721 return -1;
2722 }
2723
2724 ast_atomic_fetchadd_int(&faxregistry.fax_tx_attempts, 1);
2725
2726 file_count = 0;
2727 filenames = args.filenames;
2728 while ((c = strsep(&filenames, "&"))) {
2729 if (access(c, (F_OK | R_OK)) < 0) {
2730 ast_string_field_set(details, error, "FILE_ERROR");
2731 ast_string_field_set(details, resultstr, "error reading file");
2732 set_channel_variables(chan, details);
2733 ast_log(LOG_ERROR, "access failure. Verify '%s' exists and check permissions.\n", args.filenames);
2734 return -1;
2735 }
2736
2737 if (!(doc = ast_calloc(1, sizeof(*doc) + strlen(c) + 1))) {
2738 ast_string_field_set(details, error, "MEMORY_ERROR");
2739 ast_string_field_set(details, resultstr, "error allocating memory");
2740 set_channel_variables(chan, details);
2741 ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
2742 return -1;
2743 }
2744
2745 strcpy(doc->filename, c);
2746 AST_LIST_INSERT_TAIL(&details->documents, doc, next);
2747 file_count++;
2748 }
2749
2750 ast_verb(3, "Channel '%s' sending FAX:\n", ast_channel_name(chan));
2751 AST_LIST_TRAVERSE(&details->documents, doc, next) {
2752 ast_verb(3, " %s\n", doc->filename);
2753 }
2754
2755 details->caps = AST_FAX_TECH_SEND;
2756
2757 if (file_count > 1) {
2758 details->caps |= AST_FAX_TECH_MULTI_DOC;
2759 }
2760
2761 /* check for debug */
2762 if (ast_test_flag(&opts, OPT_DEBUG) || global_fax_debug) {
2763 details->option.debug = AST_FAX_OPTFLAG_TRUE;
2764 }
2765
2766 /* check for request for status events */
2767 if (ast_test_flag(&opts, OPT_STATUS)) {
2768 details->option.statusevents = AST_FAX_OPTFLAG_TRUE;
2769 }
2770
2771 t38state = ast_channel_get_t38_state(chan);
2772 if ((t38state == T38_STATE_UNAVAILABLE) || (t38state == T38_STATE_REJECTED) ||
2773 ast_test_flag(&opts, OPT_ALLOWAUDIO) ||
2775 details->option.allow_audio = AST_FAX_OPTFLAG_TRUE;
2776 }
2777
2778 if (ast_test_flag(&opts, OPT_REQUEST_T38)) {
2779 details->option.request_t38 = AST_FAX_OPTFLAG_TRUE;
2780 }
2781
2782 if (!(s = fax_session_reserve(details, &token))) {
2783 ast_string_field_set(details, resultstr, "error reserving fax session");
2784 set_channel_variables(chan, details);
2785 ast_log(LOG_ERROR, "Unable to reserve FAX session.\n");
2786 return -1;
2787 }
2788
2789 /* make sure the channel is up */
2790 if (ast_channel_state(chan) != AST_STATE_UP) {
2791 if (ast_answer(chan)) {
2792 ast_string_field_set(details, resultstr, "error answering channel");
2793 set_channel_variables(chan, details);
2794 ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", ast_channel_name(chan));
2795 fax_session_release(s, token);
2796 return -1;
2797 }
2798 }
2799
2800 if (!ast_test_flag(&opts, OPT_FORCE_AUDIO)) {
2801 if (set_fax_t38_caps(chan, details)) {
2802 ast_string_field_set(details, error, "T38_NEG_ERROR");
2803 ast_string_field_set(details, resultstr, "error negotiating T.38");
2804 set_channel_variables(chan, details);
2805 fax_session_release(s, token);
2806 return -1;
2807 }
2808 } else {
2809 details->caps |= AST_FAX_TECH_AUDIO;
2810 }
2811
2812 if (!ast_test_flag(&opts, OPT_FORCE_AUDIO) && (details->caps & AST_FAX_TECH_T38)) {
2813 if (sendfax_t38_init(chan, details)) {
2814 ast_string_field_set(details, error, "T38_NEG_ERROR");
2815 ast_string_field_set(details, resultstr, "error negotiating T.38");
2816 set_channel_variables(chan, details);
2817 fax_session_release(s, token);
2818 ast_log(LOG_ERROR, "error initializing channel '%s' in T.38 mode\n", ast_channel_name(chan));
2819 return -1;
2820 }
2821 } else {
2822 details->option.send_cng = 1;
2823 }
2824
2825 if ((channel_alive = generic_fax_exec(chan, details, s, token)) < 0) {
2826 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
2827 }
2828
2830 if (disable_t38(chan)) {
2831 ast_debug(1, "error disabling T.38 mode on %s\n", ast_channel_name(chan));
2832 }
2833 }
2834
2835 if (!(filenames = generate_filenames_string(details, "FileName: ", "\r\n"))) {
2836 ast_log(LOG_ERROR, "Error generating SendFAX manager event\n");
2837 return (!channel_alive) ? -1 : 0;
2838 }
2839
2840 /* send out the AMI completion event */
2841 if (report_send_fax_status(chan, details)) {
2842 ast_log(AST_LOG_ERROR, "Error publishing SendFAX status message\n");
2843 }
2844
2845 /* If the channel hungup return -1; otherwise, return 0 to continue in the dialplan */
2846 return (!channel_alive) ? -1 : 0;
2847}
char * strsep(char **str, const char *delims)
static int sendfax_t38_init(struct ast_channel *chan, struct ast_fax_session_details *details)
Definition: res_fax.c:2312
static int report_send_fax_status(struct ast_channel *chan, struct ast_fax_session_details *details)
Report on the status of a completed fax send attempt.
Definition: res_fax.c:2556

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

Referenced by load_module().

◆ sendfax_t38_init()

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

Definition at line 2312 of file res_fax.c.

2313{
2314 int timeout_ms;
2315 struct ast_frame *frame = NULL;
2316 struct ast_control_t38_parameters t38_parameters;
2317 struct timeval start;
2318 int ms;
2319
2320 /* send CNG tone while listening for the receiver to initiate a switch
2321 * to T.38 mode; if they do, stop sending the CNG tone and proceed with
2322 * the switch.
2323 *
2324 * 10500 is enough time for 3 CNG tones
2325 */
2326 timeout_ms = 10500;
2327
2328 /* don't send any audio if we've already received a T.38 reinvite */
2330 if (ast_playtones_start(chan, 1024, "!1100/500,!0/3000,!1100/500,!0/3000,!1100/500,!0/3000", 1)) {
2331 ast_log(LOG_ERROR, "error generating CNG tone on %s\n", ast_channel_name(chan));
2332 return -1;
2333 }
2334 }
2335
2336 start = ast_tvnow();
2337 while ((ms = ast_remaining_ms(start, timeout_ms))) {
2338 int break_loop = 0;
2339 ms = ast_waitfor(chan, ms);
2340
2341 if (ms < 0) {
2342 ast_log(LOG_ERROR, "error while generating CNG tone on %s\n", ast_channel_name(chan));
2343 ast_playtones_stop(chan);
2344 return -1;
2345 }
2346
2347 if (ms == 0) { /* all done, nothing happened */
2348 break;
2349 }
2350
2351 if (!(frame = ast_read(chan))) {
2352 ast_log(LOG_ERROR, "error reading frame while generating CNG tone on %s\n", ast_channel_name(chan));
2353 ast_playtones_stop(chan);
2354 return -1;
2355 }
2356
2357 if ((frame->frametype == AST_FRAME_CONTROL) &&
2359 (frame->datalen == sizeof(t38_parameters))) {
2360 struct ast_control_t38_parameters *parameters = frame->data.ptr;
2361
2362 switch (parameters->request_response) {
2364 /* the other end has requested a switch to T.38, so reply that we are willing, if we can
2365 * do T.38 as well
2366 */
2367 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
2368 t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
2369 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
2370 ast_playtones_stop(chan);
2371 break;
2372 case AST_T38_NEGOTIATED:
2373 ast_debug(1, "Negotiated T.38 for send on %s\n", ast_channel_name(chan));
2374 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
2375 details->caps &= ~AST_FAX_TECH_AUDIO;
2376 report_fax_status(chan, details, "T.38 Negotiated");
2377 break_loop = 1;
2378 break;
2379 default:
2380 break;
2381 }
2382 }
2383 ast_frfree(frame);
2384 if (break_loop) {
2385 break;
2386 }
2387 }
2388
2389 ast_playtones_stop(chan);
2390
2392 return 0;
2393 }
2394
2395 /* T.38 negotiation did not happen, initiate a switch if requested */
2396 if (details->option.request_t38 == AST_FAX_OPTFLAG_TRUE) {
2397 ast_debug(1, "Negotiating T.38 for send on %s\n", ast_channel_name(chan));
2398
2399 /* wait up to five seconds for negotiation to complete */
2400 timeout_ms = 5000;
2401
2402 /* set parameters based on the session's parameters */
2403 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
2404 t38_parameters.request_response = AST_T38_REQUEST_NEGOTIATE;
2405 if ((ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0)) {
2406 return -1;
2407 }
2408
2409 start = ast_tvnow();
2410 while ((ms = ast_remaining_ms(start, timeout_ms))) {
2411 int break_loop = 0;
2412
2413 ms = ast_waitfor(chan, ms);
2414 if (ms < 0) {
2415 ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", ast_channel_name(chan));
2416 return -1;
2417 }
2418 if (ms == 0) { /* all done, nothing happened */
2419 ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 negotiation.\n", ast_channel_name(chan));
2420 details->caps &= ~AST_FAX_TECH_T38;
2421 break;
2422 }
2423
2424 if (!(frame = ast_read(chan))) {
2425 ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", ast_channel_name(chan));
2426 return -1;
2427 }
2428
2429 if ((frame->frametype == AST_FRAME_CONTROL) &&
2431 (frame->datalen == sizeof(t38_parameters))) {
2432 struct ast_control_t38_parameters *parameters = frame->data.ptr;
2433
2434 switch (parameters->request_response) {
2436 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
2437 t38_parameters.request_response = AST_T38_NEGOTIATED;
2438 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
2439 break;
2440 case AST_T38_NEGOTIATED:
2441 ast_debug(1, "Negotiated T.38 for receive on %s\n", ast_channel_name(chan));
2442 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
2443 details->caps &= ~AST_FAX_TECH_AUDIO;
2444 report_fax_status(chan, details, "T.38 Negotiated");
2445 break_loop = 1;
2446 break;
2447 case AST_T38_REFUSED:
2448 ast_log(LOG_WARNING, "channel '%s' refused to negotiate T.38\n", ast_channel_name(chan));
2449 details->caps &= ~AST_FAX_TECH_T38;
2450 break_loop = 1;
2451 break;
2452 default:
2453 ast_log(LOG_ERROR, "channel '%s' failed to negotiate T.38\n", ast_channel_name(chan));
2454 details->caps &= ~AST_FAX_TECH_T38;
2455 break_loop = 1;
2456 break;
2457 }
2458 }
2459 ast_frfree(frame);
2460 if (break_loop) {
2461 break;
2462 }
2463 }
2464
2465 /* if T.38 was negotiated, we are done initializing */
2467 return 0;
2468 }
2469
2470 /* send one more CNG tone to get audio going again for some
2471 * carriers if we are going to fall back to audio mode */
2472 if (details->option.allow_audio == AST_FAX_OPTFLAG_TRUE) {
2473 if (ast_playtones_start(chan, 1024, "!1100/500,!0/3000", 1)) {
2474 ast_log(LOG_ERROR, "error generating second CNG tone on %s\n", ast_channel_name(chan));
2475 return -1;
2476 }
2477
2478 timeout_ms = 3500;
2479 start = ast_tvnow();
2480 while ((ms = ast_remaining_ms(start, timeout_ms))) {
2481 int break_loop = 0;
2482
2483 ms = ast_waitfor(chan, ms);
2484 if (ms < 0) {
2485 ast_log(LOG_ERROR, "error while generating second CNG tone on %s\n", ast_channel_name(chan));
2486 ast_playtones_stop(chan);
2487 return -1;
2488 }
2489 if (ms == 0) { /* all done, nothing happened */
2490 break;
2491 }
2492
2493 if (!(frame = ast_read(chan))) {
2494 ast_log(LOG_ERROR, "error reading frame while generating second CNG tone on %s\n", ast_channel_name(chan));
2495 ast_playtones_stop(chan);
2496 return -1;
2497 }
2498
2499 if ((frame->frametype == AST_FRAME_CONTROL) &&
2501 (frame->datalen == sizeof(t38_parameters))) {
2502 struct ast_control_t38_parameters *parameters = frame->data.ptr;
2503
2504 switch (parameters->request_response) {
2506 /* the other end has requested a switch to T.38, so reply that we are willing, if we can
2507 * do T.38 as well
2508 */
2509 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
2510 t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
2511 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
2512 ast_playtones_stop(chan);
2513 break;
2514 case AST_T38_NEGOTIATED:
2515 ast_debug(1, "Negotiated T.38 for send on %s\n", ast_channel_name(chan));
2516 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
2517 details->caps &= ~AST_FAX_TECH_AUDIO;
2518 report_fax_status(chan, details, "T.38 Negotiated");
2519 break_loop = 1;
2520 break;
2521 default:
2522 break;
2523 }
2524 }
2525 ast_frfree(frame);
2526 if (break_loop) {
2527 break;
2528 }
2529 }
2530
2531 ast_playtones_stop(chan);
2532
2533 /* if T.38 was negotiated, we are done initializing */
2535 return 0;
2536 }
2537 }
2538 }
2539
2540 /* if we made it here, then T.38 failed, check the 'f' flag */
2541 if (details->option.allow_audio == AST_FAX_OPTFLAG_FALSE) {
2542 ast_log(LOG_WARNING, "Audio FAX not allowed on channel '%s' and T.38 negotiation failed; aborting.\n", ast_channel_name(chan));
2543 return -1;
2544 }
2545
2546 /* ok, audio fallback is allowed */
2547 details->caps |= AST_FAX_TECH_AUDIO;
2548
2549 return 0;
2550}

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

Referenced by sendfax_exec().

◆ session_cmp_cb()

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

compare callback for ao2

Definition at line 3964 of file res_fax.c.

3965{
3966 struct ast_fax_session *lhs = obj, *rhs = arg;
3967
3968 return (lhs->id == rhs->id) ? CMP_MATCH | CMP_STOP : 0;
3969}
@ CMP_MATCH
Definition: astobj2.h:1027
@ CMP_STOP
Definition: astobj2.h:1028

References CMP_MATCH, CMP_STOP, and ast_fax_session::id.

Referenced by load_module().

◆ session_details_new()

static struct ast_fax_session_details * session_details_new ( void  )
static

create a FAX session details structure

Definition at line 725 of file res_fax.c.

726{
728 struct fax_options options;
729
730 if (!(d = ao2_alloc(sizeof(*d), destroy_session_details))) {
731 return NULL;
732 }
733
734 if (ast_string_field_init(d, 512)) {
735 ao2_ref(d, -1);
736 return NULL;
737 }
738
740
741 AST_LIST_HEAD_INIT_NOLOCK(&d->documents);
742
743 /* These options need to be set to the configured default and may be overridden by
744 * SendFAX, ReceiveFAX, or FAXOPT */
745 d->option.request_t38 = AST_FAX_OPTFLAG_FALSE;
746 d->option.send_cng = AST_FAX_OPTFLAG_FALSE;
747 d->option.send_ced = AST_FAX_OPTFLAG_FALSE;
748 d->option.ecm = options.ecm;
749 d->option.statusevents = options.statusevents;
750 d->modems = options.modems;
751 d->minrate = options.minrate;
752 d->maxrate = options.maxrate;
753 d->t38timeout = options.t38timeout;
754 d->gateway_id = -1;
755 d->faxdetect_id = -1;
756 d->gateway_timeout = 0;
757 d->negotiate_both = 0;
758
759 return d;
760}
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:681
static void destroy_session_details(void *details)
destroy a FAX session details structure
Definition: res_fax.c:713
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:359

References ao2_alloc, ao2_ref, AST_FAX_OPTFLAG_FALSE, AST_LIST_HEAD_INIT_NOLOCK, ast_string_field_init, d, destroy_session_details(), get_general_options(), NULL, and options.

Referenced by fax_v21_session_new(), and find_or_create_details().

◆ session_hash_cb()

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

hash callback for ao2

Definition at line 3956 of file res_fax.c.

3957{
3958 const struct ast_fax_session *s = obj;
3959
3960 return s->id;
3961}

References ast_fax_session::id.

Referenced by load_module().

◆ set_channel_variables()

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

Set fax related channel variables.

Definition at line 1476 of file res_fax.c.

1477{
1478 char buf[10];
1479
1480 pbx_builtin_setvar_helper(chan, "FAXSTATUS", S_OR(details->result, NULL));
1481 pbx_builtin_setvar_helper(chan, "FAXERROR", S_OR(details->error, NULL));
1482 pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", S_OR(details->resultstr, NULL));
1483 pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", AST_JSON_UTF8_VALIDATE(details->remotestationid));
1484 pbx_builtin_setvar_helper(chan, "LOCALSTATIONID", AST_JSON_UTF8_VALIDATE(details->localstationid));
1485 pbx_builtin_setvar_helper(chan, "FAXBITRATE", S_OR(details->transfer_rate, NULL));
1486 pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", S_OR(details->resolution, NULL));
1487
1488 if (details->is_t38_negotiated) {
1489 pbx_builtin_setvar_helper(chan, "FAXMODE", "T38");
1490 } else {
1491 pbx_builtin_setvar_helper(chan, "FAXMODE", "audio");
1492 }
1493
1494 snprintf(buf, sizeof(buf), "%u", details->pages_transferred);
1495 pbx_builtin_setvar_helper(chan, "FAXPAGES", buf);
1496}

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

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

◆ set_config()

static int set_config ( int  reload)
static

configure res_fax

Definition at line 4451 of file res_fax.c.

4452{
4453 struct ast_config *cfg;
4454 struct ast_variable *v;
4455 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
4456 char modems[128] = "";
4457 struct fax_options options;
4458 int res = 0;
4459
4461
4462 /* When we're not reloading, we have to be certain to set the general options
4463 * to the defaults in case config loading goes wrong at some point. On a reload,
4464 * the general options need to stay the same as what they were prior to the
4465 * reload rather than being reset to the defaults.
4466 */
4467 if (!reload) {
4469 }
4470
4471 /* read configuration */
4472 if (!(cfg = ast_config_load2(config, "res_fax", config_flags))) {
4473 ast_log(LOG_NOTICE, "Configuration file '%s' not found, %s options.\n",
4474 config, reload ? "not changing" : "using default");
4475 return 0;
4476 }
4477
4478 if (cfg == CONFIG_STATUS_FILEINVALID) {
4479 ast_log(LOG_NOTICE, "Configuration file '%s' is invalid, %s options.\n",
4480 config, reload ? "not changing" : "using default");
4481 return 0;
4482 }
4483
4484 if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
4485 return 0;
4486 }
4487
4488 if (reload) {
4490 }
4491
4492 /* create configuration */
4493 for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
4494 int rate;
4495
4496 if (!strcasecmp(v->name, "minrate")) {
4497 ast_debug(3, "reading minrate '%s' from configuration file\n", v->value);
4498 if ((rate = fax_rate_str_to_int(v->value)) == 0) {
4499 res = -1;
4500 goto end;
4501 }
4502 options.minrate = rate;
4503 } else if (!strcasecmp(v->name, "maxrate")) {
4504 ast_debug(3, "reading maxrate '%s' from configuration file\n", v->value);
4505 if ((rate = fax_rate_str_to_int(v->value)) == 0) {
4506 res = -1;
4507 goto end;
4508 }
4509 options.maxrate = rate;
4510 } else if (!strcasecmp(v->name, "statusevents")) {
4511 ast_debug(3, "reading statusevents '%s' from configuration file\n", v->value);
4512 options.statusevents = ast_true(v->value);
4513 } else if (!strcasecmp(v->name, "ecm")) {
4514 ast_debug(3, "reading ecm '%s' from configuration file\n", v->value);
4515 options.ecm = ast_true(v->value);
4516 } else if ((!strcasecmp(v->name, "modem")) || (!strcasecmp(v->name, "modems"))) {
4517 options.modems = 0;
4518 update_modem_bits(&options.modems, v->value);
4519 } else if (!strcasecmp(v->name, "t38timeout")) {
4520 if (set_t38timeout(v->value, &options.t38timeout)) {
4521 res = -1;
4522 goto end;
4523 }
4524 }
4525 }
4526
4527 if (options.maxrate < options.minrate) {
4528 ast_log(LOG_ERROR, "maxrate %u is less than minrate %u\n", options.maxrate, options.minrate);
4529 res = -1;
4530 goto end;
4531 }
4532
4533 if (check_modem_rate(options.modems, options.minrate)) {
4534 ast_fax_modem_to_str(options.modems, modems, sizeof(modems));
4535 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %u\n", modems, options.minrate);
4536 res = -1;
4537 goto end;
4538 }
4539
4540 if (check_modem_rate(options.modems, options.maxrate)) {
4541 ast_fax_modem_to_str(options.modems, modems, sizeof(modems));
4542 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %u\n", modems, options.maxrate);
4543 res = -1;
4544 goto end;
4545 }
4546
4548
4549end:
4550 ast_config_destroy(cfg);
4551 return res;
4552}
char * end
Definition: eagi_proxy.c:73
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
Definition: main/config.c:3541
@ CONFIG_FLAG_FILEUNCHANGED
#define CONFIG_STATUS_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1289
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1215
static int reload(void)
static void set_general_options(const struct fax_options *options)
Definition: res_fax.c:4419
static const struct fax_options default_options
Definition: res_fax.c:568
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next

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

Referenced by load_module(), and reload_module().

◆ set_fax_t38_caps()

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

Definition at line 1520 of file res_fax.c.

1521{
1522 switch (ast_channel_get_t38_state(chan)) {
1523 case T38_STATE_UNKNOWN:
1524 details->caps |= AST_FAX_TECH_T38;
1525 break;
1526 case T38_STATE_REJECTED:
1528 details->caps |= AST_FAX_TECH_AUDIO;
1529 break;
1531 /* already in T.38 mode? This should not happen. */
1532 case T38_STATE_NEGOTIATING: {
1533 /* the other end already sent us a T.38 reinvite, so we need to prod the channel
1534 * driver into resending their parameters to us if it supports doing so... if
1535 * not, we can't proceed, because we can't create a proper reply without them.
1536 * if it does work, the channel driver will send an AST_CONTROL_T38_PARAMETERS
1537 * with a request of AST_T38_REQUEST_NEGOTIATE, which will be read by the function
1538 * that gets called after this one completes
1539 */
1541 if (ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &parameters, sizeof(parameters)) != AST_T38_REQUEST_PARMS) {
1542 ast_log(LOG_ERROR, "channel '%s' is in an unsupported T.38 negotiation state, cannot continue.\n", ast_channel_name(chan));
1543 return -1;
1544 }
1545 details->caps |= AST_FAX_TECH_T38;
1546 break;
1547 }
1548 default:
1549 ast_log(LOG_ERROR, "channel '%s' is in an unsupported T.38 negotiation state, cannot continue.\n", ast_channel_name(chan));
1550 return -1;
1551 }
1552
1553 return 0;
1554}
@ AST_T38_REQUEST_PARMS

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

Referenced by receivefax_exec(), and sendfax_exec().

◆ set_general_options()

static void set_general_options ( const struct fax_options options)
static

Definition at line 4419 of file res_fax.c.

4420{
4424}
#define ast_rwlock_wrlock(a)
Definition: lock.h:243

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

Referenced by set_config().

◆ set_t38timeout()

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

Definition at line 4433 of file res_fax.c.

4434{
4435 unsigned int timeout;
4436
4437 if (sscanf(value, "%u", &timeout) != 1) {
4438 ast_log(LOG_ERROR, "Unable to get timeout from '%s'\n", value);
4439 return -1;
4440 } else if (timeout) {
4441 *t38timeout = timeout;
4442 } else {
4443 ast_log(LOG_ERROR, "T.38 negotiation timeout must be non-zero\n");
4444 return -1;
4445 }
4446
4447 return 0;
4448}

References ast_log, LOG_ERROR, and value.

Referenced by acf_faxopt_write(), and set_config().

◆ t38_parameters_ast_to_fax()

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

Definition at line 769 of file res_fax.c.

770{
771 dst->version = src->version;
772 dst->max_ifp = src->max_ifp;
773 dst->rate = src->rate;
778}
enum ast_control_t38_rate rate
enum ast_control_t38_rate_management rate_management
unsigned int transcoding_jbig
Definition: res_fax.h:99
enum ast_control_t38_rate rate
Definition: res_fax.h:95
unsigned int version
Definition: res_fax.h:93
unsigned int max_ifp
Definition: res_fax.h:94
unsigned int transcoding_mmr
Definition: res_fax.h:98
enum ast_control_t38_rate_management rate_management
Definition: res_fax.h:96
unsigned int fill_bit_removal
Definition: res_fax.h:97

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

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

◆ t38_parameters_fax_to_ast()

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

◆ unload_module()

static int unload_module ( void  )
static

unload res_fax

Definition at line 4778 of file res_fax.c.

4779{
4781
4783 ast_log(LOG_WARNING, "failed to unregister function '%s'\n", acf_faxopt.name);
4784 }
4785
4787 ast_log(LOG_WARNING, "failed to unregister '%s'\n", app_sendfax);
4788 }
4789
4791 ast_log(LOG_WARNING, "failed to unregister '%s'\n", app_receivefax);
4792 }
4793
4794 ast_manager_unregister("FAXSessions");
4795 ast_manager_unregister("FAXSession");
4796 ast_manager_unregister("FAXStats");
4797
4798 if (fax_logger_level != -1) {
4800 }
4801
4802 ao2_ref(faxregistry.container, -1);
4803
4804 return 0;
4805}
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
void ast_logger_unregister_level(const char *name)
Unregister a previously registered logger level.
Definition: logger.c:2884
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
const char * name
Definition: pbx.h:119

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

◆ update_modem_bits()

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

Definition at line 841 of file res_fax.c.

842{
843 char *m[5], *tok, *v = (char *) value, *rest;
844 int i = 0, j;
845
846 if (!strchr(v, ',')) {
847 m[i++] = v;
848 m[i] = NULL;
849 } else {
850 tok = strtok_r(v, ", ", &rest);
851 while (tok && i < ARRAY_LEN(m) - 1) {
852 m[i++] = tok;
853 tok = strtok_r(NULL, ", ", &rest);
854 }
855 m[i] = NULL;
856 }
857
858 *bits = 0;
859 for (j = 0; j < i; j++) {
860 if (!strcasecmp(m[j], "v17")) {
861 *bits |= AST_FAX_MODEM_V17;
862 } else if (!strcasecmp(m[j], "v27")) {
863 *bits |= AST_FAX_MODEM_V27TER;
864 } else if (!strcasecmp(m[j], "v29")) {
865 *bits |= AST_FAX_MODEM_V29;
866 } else if (!strcasecmp(m[j], "v34")) {
867 *bits |= AST_FAX_MODEM_V34;
868 } else {
869 ast_log(LOG_WARNING, "ignoring invalid modem setting: '%s', valid options {v17 | v27 | v29 | v34}\n", m[j]);
870 }
871 }
872 return 0;
873}

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

Referenced by acf_faxopt_write(), and set_config().

Variable Documentation

◆ __mod_info

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

Definition at line 4896 of file res_fax.c.

◆ acf_faxopt

struct ast_custom_function acf_faxopt
static
Initial value:
= {
.name = "FAXOPT",
.read = acf_faxopt_read,
.write = acf_faxopt_write,
}
static int acf_faxopt_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
FAXOPT write function modifies the contents of a FAX option.
Definition: res_fax.c:4630
static int acf_faxopt_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
FAXOPT read function returns the contents of a FAX option.
Definition: res_fax.c:4555

FAXOPT dialplan function.

Definition at line 4771 of file res_fax.c.

Referenced by load_module(), and unload_module().

◆ active_sessions

int active_sessions

The number of active FAX sessions

Definition at line 527 of file res_fax.c.

◆ app_receivefax

const char app_receivefax[] = "ReceiveFAX"
static

Definition at line 457 of file res_fax.c.

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

◆ app_sendfax

const char app_sendfax[] = "SendFAX"
static

Definition at line 458 of file res_fax.c.

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

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 4896 of file res_fax.c.

◆ config

const char* config = "res_fax.conf"
static

Definition at line 582 of file res_fax.c.

Referenced by load_module(), and set_config().

◆ container

struct ao2_container* container

◆ default_options

const struct fax_options default_options
static

Definition at line 568 of file res_fax.c.

Referenced by set_config().

◆ fax_cli

struct ast_cli_entry fax_cli[]
static

Definition at line 4409 of file res_fax.c.

Referenced by load_module(), and unload_module().

◆ fax_complete

int fax_complete

Number of successful FAX transmissions

Definition at line 537 of file res_fax.c.

◆ fax_datastore

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

Definition at line 648 of file res_fax.c.

Referenced by find_details(), find_or_create_details(), and fixup_callback().

◆ fax_exec_options

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

Definition at line 604 of file res_fax.c.

Referenced by receivefax_exec(), and sendfax_exec().

◆ fax_failures

int fax_failures

Number of failed FAX transmissions

Definition at line 539 of file res_fax.c.

◆ fax_logger_level

int fax_logger_level = -1
static

Definition at line 516 of file res_fax.c.

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

◆ fax_rx_attempts

int fax_rx_attempts

Total number of Rx FAX attempts

Definition at line 535 of file res_fax.c.

◆ fax_tx_attempts

int fax_tx_attempts

Total number of Tx FAX attempts

Definition at line 533 of file res_fax.c.

◆ faxmodules

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

◆ 

struct { ... } faxregistry

◆ general_options

struct fax_options general_options
static

Definition at line 566 of file res_fax.c.

Referenced by get_general_options(), and set_general_options().

◆ global_fax_debug

int global_fax_debug = 0
static

Definition at line 584 of file res_fax.c.

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

◆ nextsessionname

int nextsessionname

the next unique session name

Definition at line 541 of file res_fax.c.

◆ options_lock

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

Definition at line 577 of file res_fax.c.

Referenced by get_general_options(), and set_general_options().

◆ our_t38_parameters

struct ast_control_t38_parameters our_t38_parameters
static

Definition at line 762 of file res_fax.c.

Referenced by find_or_create_details().

◆ reserved_sessions

int reserved_sessions

The number of reserved FAX sessions

Definition at line 529 of file res_fax.c.