Asterisk - The Open Source Telephony Project GIT-master-a63eec2
Loading...
Searching...
No Matches
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.
 
#define FAX_DETECT_MODE_T38   (1 << 1)
 
#define FAX_GATEWAY_TIMEOUT   RES_FAX_TIMEOUT
 
#define FAX_MAXBUCKETS   10
 maximum buckets for res_fax ao2 containers
 
#define GENERIC_FAX_EXEC_ERROR(fax, chan, errorstr, reason)
 
#define GENERIC_FAX_EXEC_ERROR_QUIET(fax, chan, errorstr, reason)
 
#define GENERIC_FAX_EXEC_SET_VARS(fax, chan, errorstr, reason)
 
#define RES_FAX_MAXRATE   14400
 
#define RES_FAX_MINRATE   4800
 
#define RES_FAX_MODEM   (AST_FAX_MODEM_V17 | AST_FAX_MODEM_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.
 
static int acf_faxopt_write (struct ast_channel *chan, const char *cmd, char *data, const char *value)
 FAXOPT write function modifies the contents of a FAX option.
 
static char * ast_fax_caps_to_str (enum ast_fax_capabilities caps, char *buf, size_t bufsize)
 
void ast_fax_log (int level, const char *file, const int line, const char *function, const char *msg)
 Log message at FAX or recommended level.
 
unsigned int ast_fax_maxrate (void)
 get the maxiumum supported fax rate
 
unsigned int ast_fax_minrate (void)
 get the minimum supported fax rate
 
static int ast_fax_modem_to_str (enum ast_fax_modems bits, char *tbuf, size_t bufsize)
 
const char * ast_fax_session_operation_str (struct ast_fax_session *s)
 get string representation of a FAX session's operation
 
const char * ast_fax_state_to_str (enum ast_fax_state state)
 convert a ast_fax_state to a string
 
int ast_fax_tech_register (struct ast_fax_tech *tech)
 register a FAX technology module
 
void ast_fax_tech_unregister (struct ast_fax_tech *tech)
 unregister a FAX technology module
 
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
 
static char * cli_fax_show_capabilities (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 display registered FAX capabilities
 
static char * cli_fax_show_session (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 display details of a specified fax session
 
static char * cli_fax_show_sessions (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 display fax sessions
 
static char * cli_fax_show_settings (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 display global defaults and settings
 
static char * cli_fax_show_stats (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 display fax stats
 
static char * cli_fax_show_version (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static void debug_check_frame_for_silence (struct ast_fax_session *s, unsigned int c2s, struct ast_frame *frame)
 
static void destroy_callback (void *data)
 
static void destroy_faxdetect (void *data)
 destroy a FAX detect structure
 
static void destroy_gateway (void *data)
 destroy a FAX gateway session structure
 
static void destroy_session (void *session)
 destroy a FAX session structure
 
static void destroy_session_details (void *details)
 destroy a FAX session details structure
 
static void destroy_v21_sessions (struct fax_gateway *gateway)
 destroy the v21 detection parts of a fax gateway session
 
static int disable_t38 (struct ast_channel *chan)
 
static int fax_detect_attach (struct ast_channel *chan, int timeout, int flags)
 Attach a faxdetect framehook object to a channel.
 
static struct ast_framefax_detect_framehook (struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data)
 Fax Detect Framehook.
 
static void fax_detect_framehook_destroy (void *data)
 Deref the faxdetect data structure when the faxdetect framehook is detached.
 
static struct fax_detectfax_detect_new (struct ast_channel *chan, int timeout, int flags)
 Create a new fax detect object.
 
static int fax_gateway_attach (struct ast_channel *chan, struct ast_fax_session_details *details)
 Attach a gateway framehook object to a channel.
 
static struct ast_framefax_gateway_detect_t38 (struct fax_gateway *gateway, struct ast_channel *chan, struct ast_channel *peer, struct ast_channel *active, struct ast_frame *f)
 T38 Gateway Negotiate t38 parameters.
 
static struct ast_framefax_gateway_detect_v21 (struct fax_gateway *gateway, struct ast_channel *chan, struct ast_channel *peer, struct ast_channel *active, struct ast_frame *f)
 
static struct ast_framefax_gateway_framehook (struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data)
 T.30<->T.38 gateway framehook.
 
static void fax_gateway_framehook_destroy (void *data)
 Destroy the gateway data structure when the framehook is detached.
 
static 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.
 
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.
 
static unsigned int fax_rate_str_to_int (const char *ratestr)
 convert a rate string to a rate
 
static struct ast_fax_sessionfax_session_new (struct ast_fax_session_details *details, struct ast_channel *chan, struct ast_fax_session *reserved, struct ast_fax_tech_token *token)
 create a FAX session
 
static void fax_session_release (struct ast_fax_session *s, struct ast_fax_tech_token *token)
 Release a session token.
 
static struct ast_fax_sessionfax_session_reserve (struct ast_fax_session_details *details, struct ast_fax_tech_token **token)
 Reserve a fax session.
 
static char * fax_session_tab_complete (struct ast_cli_args *a)
 fax session tab completion
 
static const char * fax_session_type (struct ast_fax_session *s)
 
static struct ast_fax_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
 
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
 
static void fixup_callback (void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
 Copies fax detection and gateway framehooks during masquerades.
 
static struct ast_jsongenerate_filenames_json (struct ast_fax_session_details *details)
 
static char * generate_filenames_string (struct ast_fax_session_details *details, char *prefix, char *separator)
 Generate a string of filenames using the given prefix and separator.
 
static int generic_fax_exec (struct ast_channel *chan, struct ast_fax_session_details *details, struct ast_fax_session *reserved, struct ast_fax_tech_token *token)
 this is the generic FAX session handling function
 
static void get_general_options (struct fax_options *options)
 
static int load_module (void)
 Load the module.
 
static int manager_fax_session (struct mansession *s, const struct message *m)
 
static int manager_fax_sessions (struct mansession *s, const struct message *m)
 
static int manager_fax_sessions_entry (struct mansession *s, struct ast_fax_session *session, const char *id_text)
 
static int manager_fax_stats (struct mansession *s, const struct message *m)
 
static int receivefax_exec (struct ast_channel *chan, const char *data)
 initiate a receive FAX session
 
static int receivefax_t38_init (struct ast_channel *chan, struct ast_fax_session_details *details)
 
static int reload_module (void)
 
static int report_fax_status (struct ast_channel *chan, struct ast_fax_session_details *details, const char *status)
 send a FAX status manager event
 
static int report_receive_fax_status (struct ast_channel *chan, const char *filename)
 Report on the final state of a receive fax operation.
 
static int report_send_fax_status (struct ast_channel *chan, struct ast_fax_session_details *details)
 Report on the status of a completed fax send attempt.
 
static int sendfax_exec (struct ast_channel *chan, const char *data)
 initiate a send FAX session
 
static int sendfax_t38_init (struct ast_channel *chan, struct ast_fax_session_details *details)
 
static int session_cmp_cb (void *obj, void *arg, int flags)
 compare callback for ao2
 
static struct ast_fax_session_detailssession_details_new (void)
 create a FAX session details structure
 
static int session_hash_cb (const void *obj, const int flags)
 hash callback for ao2
 
static void set_channel_variables (struct ast_channel *chan, struct ast_fax_session_details *details)
 Set fax related channel variables.
 
static int set_config (int reload)
 configure res_fax
 
static int set_fax_t38_caps (struct ast_channel *chan, struct ast_fax_session_details *details)
 
static void set_general_options (const struct fax_options *options)
 
static int set_t38timeout (const char *value, unsigned int *t38timeout)
 
static void t38_parameters_ast_to_fax (struct ast_fax_t38_parameters *dst, const struct ast_control_t38_parameters *src)
 
static void t38_parameters_fax_to_ast (struct ast_control_t38_parameters *dst, const struct ast_fax_t38_parameters *src)
 
static int unload_module (void)
 unload res_fax
 
static int update_modem_bits (enum ast_fax_modems *bits, const char *value)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "Generic FAX Applications" , .key = ASTERISK_GPL_KEY , .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.
 
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 = AST_RWLIST_HEAD_INIT_VALUE
 
struct { 
 
   int   active_sessions 
 
   struct ao2_container *   container 
 
   int   fax_complete 
 
   int   fax_failures 
 
   int   fax_rx_attempts 
 
   int   fax_tx_attempts 
 
   int   nextsessionname 
 
   int   reserved_sessions 
 
faxregistry 
 The faxregistry is used to manage information and statistics for all FAX sessions.
 
static struct fax_options general_options
 
static int global_fax_debug = 0
 
static ast_rwlock_t options_lock = AST_RWLOCK_INIT_VALUE
 
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 586 of file res_fax.c.

◆ FAX_DETECT_MODE_CNG

#define FAX_DETECT_MODE_CNG   (1 << 0)

FAX Detect flags.

Definition at line 584 of file res_fax.c.

◆ FAX_DETECT_MODE_T38

#define FAX_DETECT_MODE_T38   (1 << 1)

Definition at line 585 of file res_fax.c.

◆ FAX_GATEWAY_TIMEOUT

#define FAX_GATEWAY_TIMEOUT   RES_FAX_TIMEOUT

Definition at line 594 of file res_fax.c.

◆ FAX_MAXBUCKETS

#define FAX_MAXBUCKETS   10

maximum buckets for res_fax ao2 containers

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

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

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

1582 { \
1583 GENERIC_FAX_EXEC_SET_VARS(fax, chan, errorstr, reason); \
1584 } while (0)

◆ GENERIC_FAX_EXEC_SET_VARS

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

Definition at line 1570 of file res_fax.c.

1571 { \
1572 if (ast_strlen_zero(fax->details->result)) \
1573 ast_string_field_set(fax->details, result, "FAILED"); \
1574 if (ast_strlen_zero(fax->details->resultstr)) \
1575 ast_string_field_set(fax->details, resultstr, reason); \
1576 if (ast_strlen_zero(fax->details->error)) \
1577 ast_string_field_set(fax->details, error, errorstr); \
1578 set_channel_variables(chan, fax->details); \
1579 } while (0)
static PGresult * result
Definition cel_pgsql.c:84
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition strings.h:65

◆ RES_FAX_MAXRATE

#define RES_FAX_MAXRATE   14400

Definition at line 624 of file res_fax.c.

◆ RES_FAX_MINRATE

#define RES_FAX_MINRATE   4800

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

◆ RES_FAX_STATUSEVENTS

#define RES_FAX_STATUSEVENTS   0

Definition at line 625 of file res_fax.c.

◆ RES_FAX_T38TIMEOUT

#define RES_FAX_T38TIMEOUT   5000

Definition at line 627 of file res_fax.c.

◆ RES_FAX_TIMEOUT

#define RES_FAX_TIMEOUT   10000

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

658 {
659 OPT_CALLEDMODE = (1 << 0),
660 OPT_CALLERMODE = (1 << 1),
661 OPT_DEBUG = (1 << 2),
662 OPT_STATUS = (1 << 3),
663 OPT_ALLOWAUDIO = (1 << 5),
664 OPT_REQUEST_T38 = (1 << 6),
665 OPT_FORCE_AUDIO = (1 << 7),
666};
@ OPT_CALLEDMODE
Definition res_fax.c:659
@ OPT_REQUEST_T38
Definition res_fax.c:664
@ OPT_FORCE_AUDIO
Definition res_fax.c:665
@ OPT_CALLERMODE
Definition res_fax.c:660
@ OPT_ALLOWAUDIO
Definition res_fax.c:663
@ OPT_STATUS
Definition res_fax.c:662
@ OPT_DEBUG
Definition res_fax.c:661

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 4968 of file res_fax.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

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

4628{
4629 struct ast_fax_session_details *details = find_details(chan);
4630 int res = 0;
4631 char *filenames;
4632
4633 if (!details) {
4634 ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s) because it has never been written.\n", ast_channel_name(chan), data);
4635 return -1;
4636 }
4637 if (!strcasecmp(data, "ecm")) {
4638 ast_copy_string(buf, details->option.ecm ? "yes" : "no", len);
4639 } else if (!strcasecmp(data, "t38gateway") || !strcasecmp(data, "gateway") ||
4640 !strcasecmp(data, "t38_gateway") || !strcasecmp(data, "faxgateway")) {
4641 ast_copy_string(buf, details->gateway_id != -1 ? "yes" : "no", len);
4642 } else if (!strcasecmp(data, "faxdetect")) {
4643 ast_copy_string(buf, details->faxdetect_id != -1 ? "yes" : "no", len);
4644 } else if (!strcasecmp(data, "error")) {
4645 ast_copy_string(buf, details->error, len);
4646 } else if (!strcasecmp(data, "filename")) {
4647 if (AST_LIST_EMPTY(&details->documents)) {
4648 ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s) because it has never been written.\n", ast_channel_name(chan), data);
4649 res = -1;
4650 } else {
4651 ast_copy_string(buf, AST_LIST_FIRST(&details->documents)->filename, len);
4652 }
4653 } else if (!strcasecmp(data, "filenames")) {
4654 if (AST_LIST_EMPTY(&details->documents)) {
4655 ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s) because it has never been written.\n", ast_channel_name(chan), data);
4656 res = -1;
4657 } else if ((filenames = generate_filenames_string(details, "", ","))) {
4658 ast_copy_string(buf, filenames, len);
4659 ast_free(filenames);
4660 } else {
4661 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);
4662 res = -1;
4663 }
4664 } else if (!strcasecmp(data, "headerinfo")) {
4665 ast_copy_string(buf, details->headerinfo, len);
4666 } else if (!strcasecmp(data, "localstationid")) {
4668 } else if (!strcasecmp(data, "maxrate")) {
4669 snprintf(buf, len, "%u", details->maxrate);
4670 } else if (!strcasecmp(data, "minrate")) {
4671 snprintf(buf, len, "%u", details->minrate);
4672 } else if (!strcasecmp(data, "pages")) {
4673 snprintf(buf, len, "%u", details->pages_transferred);
4674 } else if (!strcasecmp(data, "rate")) {
4676 } else if (!strcasecmp(data, "remotestationid")) {
4678 } else if (!strcasecmp(data, "resolution")) {
4679 ast_copy_string(buf, details->resolution, len);
4680 } else if (!strcasecmp(data, "sessionid")) {
4681 snprintf(buf, len, "%u", details->id);
4682 } else if (!strcasecmp(data, "status")) {
4683 ast_copy_string(buf, details->result, len);
4684 } else if (!strcasecmp(data, "statusstr")) {
4685 ast_copy_string(buf, details->resultstr, len);
4686 } else if ((!strcasecmp(data, "modem")) || (!strcasecmp(data, "modems"))) {
4687 ast_fax_modem_to_str(details->modems, buf, len);
4688 } else if (!strcasecmp(data, "t38timeout")) {
4689 snprintf(buf, len, "%u", details->t38timeout);
4690 } else if (!strcasecmp(data, "negotiate_both")) {
4691 ast_copy_string(buf, details->negotiate_both != -1 ? "yes" : "no", len);
4692 } else {
4693 ast_log(LOG_WARNING, "channel '%s' can't read FAXOPT(%s) because it is unhandled!\n", ast_channel_name(chan), data);
4694 res = -1;
4695 }
4696 ao2_ref(details, -1);
4697
4698 return res;
4699}
#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.
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
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:763
static int ast_fax_modem_to_str(enum ast_fax_modems bits, char *tbuf, size_t bufsize)
Definition res_fax.c:1006
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:1471
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
union ast_fax_session_details::@267 option
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 pages_transferred
Definition res_fax.h:144
const ast_string_field resolution
Definition res_fax.h:142
const ast_string_field remotestationid
Definition res_fax.h:142
const ast_string_field transfer_rate
Definition res_fax.h:142

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

◆ acf_faxopt_write()

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

FAXOPT write function modifies the contents of a FAX option.

Definition at line 4702 of file res_fax.c.

4703{
4704 int res = 0;
4705 struct ast_fax_session_details *details;
4706
4707 if (!(details = find_or_create_details(chan))) {
4708 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);
4709 return -1;
4710 }
4711 ast_debug(3, "channel '%s' setting FAXOPT(%s) to '%s'\n", ast_channel_name(chan), data, value);
4712
4713 if (!strcasecmp(data, "ecm")) {
4714 const char *val = ast_skip_blanks(value);
4715 if (ast_true(val)) {
4716 details->option.ecm = AST_FAX_OPTFLAG_TRUE;
4717 } else if (ast_false(val)) {
4718 details->option.ecm = AST_FAX_OPTFLAG_FALSE;
4719 } else {
4720 ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(ecm).\n", value);
4721 }
4722 } else if (!strcasecmp(data, "t38gateway") || !strcasecmp(data, "gateway") ||
4723 !strcasecmp(data, "t38_gateway") || !strcasecmp(data, "faxgateway")) {
4724 const char *val = ast_skip_blanks(value);
4725 char *timeout = strchr(val, ',');
4726
4727 if (timeout) {
4728 *timeout++ = '\0';
4729 }
4730
4731 if (ast_true(val)) {
4732 if (details->gateway_id < 0) {
4733 details->gateway_timeout = 0;
4734 if (timeout) {
4735 unsigned int gwtimeout;
4736
4737 if (sscanf(timeout, "%30u", &gwtimeout) == 1) {
4738 details->gateway_timeout = gwtimeout * 1000;
4739 } else {
4740 ast_log(LOG_WARNING, "Unsupported timeout '%s' passed to FAXOPT(%s).\n", timeout, data);
4741 }
4742 }
4743
4744 details->gateway_id = fax_gateway_attach(chan, details);
4745 if (details->gateway_id < 0) {
4746 ast_log(LOG_ERROR, "Error attaching T.38 gateway to channel %s.\n", ast_channel_name(chan));
4747 res = -1;
4748 } else {
4749 ast_debug(1, "Attached T.38 gateway to channel %s.\n", ast_channel_name(chan));
4750 }
4751 } else {
4752 ast_log(LOG_WARNING, "Attempt to attach a T.38 gateway on channel (%s) with gateway already running.\n", ast_channel_name(chan));
4753 }
4754 } else if (ast_false(val)) {
4755 ast_channel_lock(chan);
4756 ast_framehook_detach(chan, details->gateway_id);
4757 ast_channel_unlock(chan);
4758 details->gateway_id = -1;
4759 } else {
4760 ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(%s).\n", value, data);
4761 }
4762 } else if (!strcasecmp(data, "faxdetect")) {
4763 const char *val = ast_skip_blanks(value);
4764 char *timeout = strchr(val, ',');
4765 unsigned int fdtimeout = 0;
4766 int flags;
4767 int faxdetect;
4768
4769 if (timeout) {
4770 *timeout++ = '\0';
4771 }
4772
4773 if (ast_true(val) || !strcasecmp(val, "t38") || !strcasecmp(val, "cng")) {
4774 if (details->faxdetect_id < 0) {
4775 if (timeout) {
4776 if (sscanf(timeout, "%30u", &fdtimeout) == 1) {
4777 fdtimeout *= 1000;
4778 } else {
4779 ast_log(LOG_WARNING, "Unsupported timeout '%s' passed to FAXOPT(%s).\n",
4780 timeout, data);
4781 }
4782 }
4783
4784 if (!strcasecmp(val, "t38")) {
4785 flags = FAX_DETECT_MODE_T38;
4786 } else if (!strcasecmp(val, "cng")) {
4787 flags = FAX_DETECT_MODE_CNG;
4788 } else {
4789 flags = FAX_DETECT_MODE_BOTH;
4790 }
4791
4792 faxdetect = fax_detect_attach(chan, fdtimeout, flags);
4793 if (faxdetect < 0) {
4794 ast_log(LOG_ERROR, "Error attaching FAX detect to channel %s.\n", ast_channel_name(chan));
4795 res = -1;
4796 } else {
4797 ast_debug(1, "Attached FAX detect to channel %s.\n", ast_channel_name(chan));
4798 }
4799 } else {
4800 ast_log(LOG_WARNING, "Attempt to attach a FAX detect on channel (%s) with FAX detect already running.\n", ast_channel_name(chan));
4801 }
4802 } else if (ast_false(val)) {
4803 ast_channel_lock(chan);
4804 ast_framehook_detach(chan, details->faxdetect_id);
4805 ast_channel_unlock(chan);
4806 details->faxdetect_id = -1;
4807 } else {
4808 ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(%s).\n", value, data);
4809 }
4810 } else if (!strcasecmp(data, "headerinfo")) {
4812 } else if (!strcasecmp(data, "localstationid")) {
4814 } else if (!strcasecmp(data, "maxrate")) {
4815 details->maxrate = fax_rate_str_to_int(value);
4816 if (!details->maxrate) {
4817 details->maxrate = ast_fax_maxrate();
4818 }
4819 } else if (!strcasecmp(data, "minrate")) {
4820 details->minrate = fax_rate_str_to_int(value);
4821 if (!details->minrate) {
4822 details->minrate = ast_fax_minrate();
4823 }
4824 } else if (!strcasecmp(data, "t38timeout")) {
4825 if (set_t38timeout(value, &details->t38timeout)) {
4826 res = -1;
4827 }
4828 } else if ((!strcasecmp(data, "modem")) || (!strcasecmp(data, "modems"))) {
4829 update_modem_bits(&details->modems, value);
4830 } else if (!strcasecmp(data, "negotiate_both")) {
4832 } else {
4833 ast_log(LOG_WARNING, "channel '%s' set FAXOPT(%s) to '%s' is unhandled!\n", ast_channel_name(chan), data, value);
4834 res = -1;
4835 }
4836
4837 ao2_ref(details, -1);
4838
4839 return res;
4840}
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:905
static int update_modem_bits(enum ast_fax_modems *bits, const char *value)
Definition res_fax.c:913
#define FAX_DETECT_MODE_BOTH
Definition res_fax.c:586
static int set_t38timeout(const char *value, unsigned int *t38timeout)
Definition res_fax.c:4505
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:3990
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:3727
#define FAX_DETECT_MODE_T38
Definition res_fax.c:585
unsigned int ast_fax_maxrate(void)
get the maxiumum supported fax rate
Definition res_fax.c:897
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:865
static unsigned int fax_rate_str_to_int(const char *ratestr)
convert a rate string to a rate
Definition res_fax.c:1147
#define FAX_DETECT_MODE_CNG
FAX Detect flags.
Definition res_fax.c:584
@ 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.
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:2235
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:2252
char *attribute_pure ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition strings.h:161
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 947 of file res_fax.c.

948{
949 char *out = buf;
950 size_t size = bufsize;
951 int first = 1;
952
953 if (caps & AST_FAX_TECH_SEND) {
954 if (!first) {
955 ast_build_string(&buf, &size, ",");
956 }
957 ast_build_string(&buf, &size, "SEND");
958 first = 0;
959 }
960 if (caps & AST_FAX_TECH_RECEIVE) {
961 if (!first) {
962 ast_build_string(&buf, &size, ",");
963 }
964 ast_build_string(&buf, &size, "RECEIVE");
965 first = 0;
966 }
967 if (caps & AST_FAX_TECH_AUDIO) {
968 if (!first) {
969 ast_build_string(&buf, &size, ",");
970 }
971 ast_build_string(&buf, &size, "AUDIO");
972 first = 0;
973 }
974 if (caps & AST_FAX_TECH_T38) {
975 if (!first) {
976 ast_build_string(&buf, &size, ",");
977 }
978 ast_build_string(&buf, &size, "T38");
979 first = 0;
980 }
981 if (caps & AST_FAX_TECH_MULTI_DOC) {
982 if (!first) {
983 ast_build_string(&buf, &size, ",");
984 }
985 ast_build_string(&buf, &size, "MULTI_DOC");
986 first = 0;
987 }
988 if (caps & AST_FAX_TECH_GATEWAY) {
989 if (!first) {
990 ast_build_string(&buf, &size, ",");
991 }
992 ast_build_string(&buf, &size, "GATEWAY");
993 first = 0;
994 }
995 if (caps & AST_FAX_TECH_V21_DETECT) {
996 if (!first) {
997 ast_build_string(&buf, &size, ",");
998 }
999 ast_build_string(&buf, &size, "V21");
1000 first = 0;
1001 }
1002
1003 return out;
1004}
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:2203
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 1137 of file res_fax.c.

1138{
1139 if (fax_logger_level != -1) {
1141 } else {
1142 ast_log(level, file, line, function, "%s", msg);
1143 }
1144}
#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:588

References ast_log, ast_log_dynamic_level, and fax_logger_level.

Referenced by spandsp_log().

◆ ast_fax_maxrate()

unsigned int ast_fax_maxrate ( void  )

get the maxiumum supported fax rate

Definition at line 897 of file res_fax.c.

898{
899 struct fax_options options;
901
902 return options.maxrate;
903}
static void get_general_options(struct fax_options *options)
Definition res_fax.c:4498
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 905 of file res_fax.c.

906{
907 struct fax_options options;
909
910 return options.minrate;
911}

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

1007{
1008 int count = 0;
1009
1010 if (bits & AST_FAX_MODEM_V17) {
1011 strcat(tbuf, "V17");
1012 count++;
1013 }
1014 if (bits & AST_FAX_MODEM_V27TER) {
1015 if (count) {
1016 strcat(tbuf, ",");
1017 }
1018 strcat(tbuf, "V27");
1019 count++;
1020 }
1021 if (bits & AST_FAX_MODEM_V29) {
1022 if (count) {
1023 strcat(tbuf, ",");
1024 }
1025 strcat(tbuf, "V29");
1026 count++;
1027 }
1028 if (bits & AST_FAX_MODEM_V34) {
1029 if (count) {
1030 strcat(tbuf, ",");
1031 }
1032 strcat(tbuf, "V34");
1033 count++;
1034 }
1035
1036 return 0;
1037}
@ 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 4355 of file res_fax.c.

4356{
4357 if (s->details->caps & AST_FAX_TECH_GATEWAY) {
4358 return "gateway";
4359 }
4360 if (s->details->caps & AST_FAX_TECH_SEND) {
4361 return "send";
4362 }
4363 if (s->details->caps & AST_FAX_TECH_RECEIVE) {
4364 return "receive";
4365 }
4367 return "V.21";
4368 }
4369
4370 return "none";
4371}
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 1114 of file res_fax.c.

1115{
1116 switch (state) {
1118 return "Uninitialized";
1120 return "Initialized";
1121 case AST_FAX_STATE_OPEN:
1122 return "Open";
1124 return "Active";
1126 return "Complete";
1128 return "Reserved";
1130 return "Inactive";
1131 default:
1132 ast_log(LOG_WARNING, "unhandled FAX state: %u\n", state);
1133 return "Unknown";
1134 }
1135}
@ 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 1075 of file res_fax.c.

1076{
1077 struct fax_module *fax;
1078
1079 if (!(fax = ast_calloc(1, sizeof(*fax)))) {
1080 return -1;
1081 }
1082 fax->tech = tech;
1086
1087 ast_verb(3, "Registered handler for '%s' (%s)\n", fax->tech->type, fax->tech->description);
1088
1089 return 0;
1090}
#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.
#define AST_RWLIST_INSERT_TAIL
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:617
const struct ast_fax_tech * tech
Definition res_fax.c:618
struct fax_module::@473 list

References ast_calloc, AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, ast_fax_tech::description, fax_module::list, 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 1093 of file res_fax.c.

1094{
1095 struct fax_module *fax;
1096
1097 ast_verb(3, "Unregistering FAX module type '%s'\n", tech->type);
1098
1101 if (fax->tech != tech) {
1102 continue;
1103 }
1105 ast_free(fax);
1106 ast_verb(4, "Unregistered FAX module type '%s'\n", tech->type);
1107 break;
1108 }
1111}
#define AST_RWLIST_REMOVE_CURRENT
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
#define AST_RWLIST_TRAVERSE_SAFE_END

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::list, 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 4968 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 1039 of file res_fax.c.

1040{
1041 switch (rate) {
1042 case 2400:
1043 case 4800:
1044 if (!(modems & (AST_FAX_MODEM_V27TER | AST_FAX_MODEM_V34))) {
1045 return 1;
1046 }
1047 break;
1048 case 7200:
1049 case 9600:
1051 return 1;
1052 }
1053 break;
1054 case 12000:
1055 case 14400:
1056 if (!(modems & (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V34))) {
1057 return 1;
1058 }
1059 break;
1060 case 28800:
1061 case 33600:
1062 if (!(modems & AST_FAX_MODEM_V34)) {
1063 return 1;
1064 }
1065 break;
1066 default:
1067 /* this should never happen */
1068 return 1;
1069 }
1070
1071 return 0;
1072}

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

4105{
4106 int flag;
4107 const char *what;
4108
4109 switch (cmd) {
4110 case CLI_INIT:
4111 e->command = "fax set debug {on|off}";
4112 e->usage =
4113 "Usage: fax set debug { on | off }\n"
4114 " Enable/Disable FAX debugging on new FAX sessions. The basic FAX debugging will result in\n"
4115 " additional events sent to manager sessions with 'call' class permissions. When\n"
4116 " verbosity is greater than '5' events will be displayed to the console and audio versus\n"
4117 " energy analysis will be performed and displayed to the console.\n";
4118 return NULL;
4119 case CLI_GENERATE:
4120 return NULL;
4121 }
4122
4123 what = a->argv[e->args-1]; /* guaranteed to exist */
4124 if (!strcasecmp(what, "on")) {
4125 flag = 1;
4126 } else if (!strcasecmp(what, "off")) {
4127 flag = 0;
4128 } else {
4129 return CLI_SHOWUSAGE;
4130 }
4131
4133 ast_cli(a->fd, "\n\nFAX Debug %s\n\n", (flag) ? "Enabled" : "Disabled");
4134
4135 return CLI_SUCCESS;
4136}
#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:656
#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 4139 of file res_fax.c.

4140{
4141 struct fax_module *fax;
4142 unsigned int num_modules = 0;
4143
4144 switch (cmd) {
4145 case CLI_INIT:
4146 e->command = "fax show capabilities";
4147 e->usage =
4148 "Usage: fax show capabilities\n"
4149 " Shows the capabilities of the registered FAX technology modules\n";
4150 return NULL;
4151 case CLI_GENERATE:
4152 return NULL;
4153 }
4154
4155 ast_cli(a->fd, "\n\nRegistered FAX Technology Modules:\n\n");
4158 ast_cli(a->fd, "%-15s : %s\n%-15s : %s\n%-15s : ", "Type", fax->tech->type, "Description", fax->tech->description, "Capabilities");
4159 fax->tech->cli_show_capabilities(a->fd);
4160 num_modules++;
4161 }
4163 ast_cli(a->fd, "%u registered modules\n\n", num_modules);
4164
4165 return CLI_SUCCESS;
4166}
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition linkedlists.h:78
#define AST_RWLIST_TRAVERSE
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, fax_module::list, 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 4208 of file res_fax.c.

4209{
4210 struct ast_fax_session *s, tmp;
4211
4212 switch (cmd) {
4213 case CLI_INIT:
4214 e->command = "fax show session";
4215 e->usage =
4216 "Usage: fax show session <session number>\n"
4217 " Shows status of the named FAX session\n";
4218 return NULL;
4219 case CLI_GENERATE:
4221 }
4222
4223 if (a->argc != 4) {
4224 return CLI_SHOWUSAGE;
4225 }
4226
4227 if (sscanf(a->argv[3], "%u", &tmp.id) != 1) {
4228 ast_log(LOG_ERROR, "invalid session id: '%s'\n", a->argv[3]);
4229 return RESULT_SUCCESS;
4230 }
4231
4232 ast_cli(a->fd, "\nFAX Session Details:\n--------------------\n\n");
4233 s = ao2_find(faxregistry.container, &tmp, OBJ_POINTER);
4234 if (s) {
4235 ast_cli(a->fd, "%-22s : %s\n", "channel", s->channame);
4236 s->tech->cli_show_session(s, a->fd);
4237 ao2_ref(s, -1);
4238 }
4239 ast_cli(a->fd, "\n\n");
4240
4241 return CLI_SUCCESS;
4242}
#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 @471 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:4044
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 4374 of file res_fax.c.

4375{
4376 struct ast_fax_session *s;
4377 struct ao2_iterator i;
4378 int session_count;
4379 char *filenames;
4380
4381 switch (cmd) {
4382 case CLI_INIT:
4383 e->command = "fax show sessions";
4384 e->usage =
4385 "Usage: fax show sessions\n"
4386 " Shows the current FAX sessions\n";
4387 return NULL;
4388 case CLI_GENERATE:
4389 return NULL;
4390 }
4391
4392 ast_cli(a->fd, "\nCurrent FAX Sessions:\n\n");
4393 ast_cli(a->fd, "%-30.30s %-10.10s %-10.10s %-5.5s %-10.10s %-15.15s %-30.30s\n",
4394 "Channel", "Tech", "FAXID", "Type", "Operation", "State", "File(s)");
4395 i = ao2_iterator_init(faxregistry.container, 0);
4396 while ((s = ao2_iterator_next(&i))) {
4397 ao2_lock(s);
4398
4399 filenames = generate_filenames_string(s->details, "", ", ");
4400
4401 ast_cli(a->fd, "%-30.30s %-10.10s %-10u %-5.5s %-10.10s %-15.15s %-30s\n",
4402 s->channame, s->tech->type, s->id,
4405 ast_fax_state_to_str(s->state), S_OR(filenames, ""));
4406
4407 ast_free(filenames);
4408 ao2_unlock(s);
4409 ao2_ref(s, -1);
4410 }
4413 ast_cli(a->fd, "\n%d FAX sessions\n\n", session_count);
4414
4415 return CLI_SUCCESS;
4416}
#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:1114
static const char * fax_session_type(struct ast_fax_session *s)
Definition res_fax.c:4343
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:4355
#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 4169 of file res_fax.c.

4170{
4171 struct fax_module *fax;
4172 char modems[128] = "";
4173 struct fax_options options;
4174
4175 switch (cmd) {
4176 case CLI_INIT:
4177 e->command = "fax show settings";
4178 e->usage =
4179 "Usage: fax show settings\n"
4180 " Show the global settings and defaults of both the FAX core and technology modules\n";
4181 return NULL;
4182 case CLI_GENERATE:
4183 return NULL;
4184 }
4185
4187
4188 ast_cli(a->fd, "FAX For Asterisk Settings:\n");
4189 ast_cli(a->fd, "\tECM: %s\n", options.ecm ? "Enabled" : "Disabled");
4190 ast_cli(a->fd, "\tStatus Events: %s\n", options.statusevents ? "On" : "Off");
4191 ast_cli(a->fd, "\tMinimum Bit Rate: %u\n", options.minrate);
4192 ast_cli(a->fd, "\tMaximum Bit Rate: %u\n", options.maxrate);
4193 ast_fax_modem_to_str(options.modems, modems, sizeof(modems));
4194 ast_cli(a->fd, "\tModem Modulations Allowed: %s\n", modems);
4195 ast_cli(a->fd, "\tT.38 Negotiation Timeout: %u\n", options.t38timeout);
4196 ast_cli(a->fd, "\n\nFAX Technology Modules:\n\n");
4198 AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
4199 ast_cli(a->fd, "%s (%s) Settings:\n", fax->tech->type, fax->tech->description);
4200 fax->tech->cli_show_settings(a->fd);
4201 }
4203
4204 return CLI_SUCCESS;
4205}
char *(*const cli_show_settings)(int)
Definition res_fax.h:276
enum ast_fax_modems modems
Definition res_fax.c:630

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

4283{
4284 struct fax_module *fax;
4285
4286 switch (cmd) {
4287 case CLI_INIT:
4288 e->command = "fax show stats";
4289 e->usage =
4290 "Usage: fax show stats\n"
4291 " Shows a statistical summary of FAX transmissions\n";
4292 return NULL;
4293 case CLI_GENERATE:
4294 return NULL;
4295 }
4296
4297 ast_cli(a->fd, "\nFAX Statistics:\n---------------\n\n");
4298 ast_cli(a->fd, "%-20.20s : %d\n", "Current Sessions", faxregistry.active_sessions);
4299 ast_cli(a->fd, "%-20.20s : %d\n", "Reserved Sessions", faxregistry.reserved_sessions);
4300 ast_cli(a->fd, "%-20.20s : %d\n", "Transmit Attempts", faxregistry.fax_tx_attempts);
4301 ast_cli(a->fd, "%-20.20s : %d\n", "Receive Attempts", faxregistry.fax_rx_attempts);
4302 ast_cli(a->fd, "%-20.20s : %d\n", "Completed FAXes", faxregistry.fax_complete);
4303 ast_cli(a->fd, "%-20.20s : %d\n", "Failed FAXes", faxregistry.fax_failures);
4306 fax->tech->cli_show_stats(a->fd);
4307 }
4309 ast_cli(a->fd, "\n\n");
4310
4311 return CLI_SUCCESS;
4312}
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, fax_module::list, 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 4072 of file res_fax.c.

4073{
4074 struct fax_module *fax;
4075
4076 switch(cmd) {
4077 case CLI_INIT:
4078 e->command = "fax show version";
4079 e->usage =
4080 "Usage: fax show version\n"
4081 " Show versions of FAX For Asterisk components.\n";
4082 return NULL;
4083 case CLI_GENERATE:
4084 return NULL;
4085 }
4086
4087 if (a->argc != 3) {
4088 return CLI_SHOWUSAGE;
4089 }
4090
4091 ast_cli(a->fd, "FAX For Asterisk Components:\n");
4092 ast_cli(a->fd, "\tApplications: %s\n", ast_get_version());
4095 ast_cli(a->fd, "\t%s: %s\n", fax->tech->description, fax->tech->version);
4096 }
4098 ast_cli(a->fd, "\n");
4099
4100 return CLI_SUCCESS;
4101}
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, fax_module::list, 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 678 of file res_fax.c.

679{
680 struct debug_info_history *history = c2s ? &s->debug_info->c2s : &s->debug_info->s2c;
681 int dspsilence;
682 unsigned int last_consec_frames, last_consec_ms;
683 unsigned char wassil;
684 struct timeval diff;
685
686 diff = ast_tvsub(ast_tvnow(), s->debug_info->base_tv);
687
689 ast_dsp_silence(s->debug_info->dsp, frame, &dspsilence);
690
691 wassil = history->silence;
692 history->silence = (dspsilence != 0) ? 1 : 0;
693 if (history->silence != wassil) {
694 last_consec_frames = history->consec_frames;
695 last_consec_ms = history->consec_ms;
696 history->consec_frames = 0;
697 history->consec_ms = 0;
698
699 if ((last_consec_frames != 0)) {
700 ast_verb(0, "Channel '%s' fax session '%u', [ %.3ld.%.6ld ], %s sent %u frames (%u ms) of %s.\n",
701 s->channame, s->id, (long) diff.tv_sec, (long int) diff.tv_usec,
702 (c2s) ? "channel" : "stack", last_consec_frames, last_consec_ms,
703 (wassil) ? "silence" : "energy");
704 }
705 }
706
707 history->consec_frames++;
708 history->consec_ms += (frame->samples / 8);
709}
int ast_dsp_silence(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
Process the audio frame for silence.
Definition dsp.c:1492
void ast_dsp_reset(struct ast_dsp *dsp)
Reset total silence count.
Definition dsp.c:1847
struct debug_info_history c2s s2c
Definition res_fax.c:540
struct timeval base_tv
Definition res_fax.c:539
struct ast_dsp * dsp
Definition res_fax.c:541
struct ast_fax_debug_info * debug_info
Definition res_fax.h:226
unsigned int consec_ms
Definition res_fax.c:534
unsigned int consec_frames
Definition res_fax.c:533
unsigned char silence
Definition res_fax.c:535
struct timeval ast_tvsub(struct timeval a, struct timeval b)
Returns the difference of two timevals a - b.
Definition extconf.c:2295
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 711 of file res_fax.c.

712{
713 if (data) {
714 ao2_ref(data, -1);
715 }
716}

References ao2_ref.

◆ destroy_faxdetect()

static void destroy_faxdetect ( void *  data)
static

destroy a FAX detect structure

Definition at line 3777 of file res_fax.c.

3778{
3779 struct fax_detect *faxdetect = data;
3780
3781 if (faxdetect->dsp) {
3782 ast_dsp_free(faxdetect->dsp);
3783 faxdetect->dsp = NULL;
3784 }
3785 ao2_cleanup(faxdetect->details);
3786 ao2_cleanup(faxdetect->orig_format);
3787}
#define ao2_cleanup(obj)
Definition astobj2.h:1934
void ast_dsp_free(struct ast_dsp *dsp)
Definition dsp.c:1787
used for fax detect framehook
Definition res_fax.c:570
struct ast_dsp * dsp
DSP Processor.
Definition res_fax.c:574
struct ast_format * orig_format
original audio formats
Definition res_fax.c:576
struct ast_fax_session_details * details
fax session details
Definition res_fax.c:578

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

2941{
2942 struct fax_gateway *gateway = data;
2943
2944 destroy_v21_sessions(gateway);
2945
2946 if (gateway->s) {
2947 fax_session_release(gateway->s, gateway->token);
2948 gateway->token = NULL;
2949
2950 ao2_unlink(faxregistry.container, gateway->s);
2951
2952 ao2_ref(gateway->s, -1);
2953 gateway->s = NULL;
2954 }
2955
2956 ao2_cleanup(gateway->chan_read_format);
2958 ao2_cleanup(gateway->peer_read_format);
2960}
#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:1184
static void destroy_v21_sessions(struct fax_gateway *gateway)
destroy the v21 detection parts of a fax gateway session
Definition res_fax.c:2922
used for gateway framehook
Definition res_fax.c:545
struct ast_format * chan_read_format
original audio formats
Definition res_fax.c:563
struct ast_format * chan_write_format
Definition res_fax.c:564
struct ast_format * peer_write_format
Definition res_fax.c:566
struct ast_format * peer_read_format
Definition res_fax.c:565
struct ast_fax_session * s
FAX Session.
Definition res_fax.c:547
struct ast_fax_tech_token * token
reserved fax session token
Definition res_fax.c:551

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

1198{
1199 struct ast_fax_session *s = session;
1200
1201 if (s->tech) {
1203 if (s->tech_pvt) {
1204 s->tech->destroy_session(s);
1205 }
1206 ast_module_unref(s->tech->module);
1207 }
1208
1209 if (s->details) {
1210 if (s->details->caps & AST_FAX_TECH_GATEWAY) {
1211 s->details->caps &= ~AST_FAX_TECH_GATEWAY;
1212 }
1213 ao2_ref(s->details, -1);
1214 s->details = NULL;
1215 }
1216
1217 if (s->debug_info) {
1219 ast_free(s->debug_info);
1220 }
1221
1222 if (s->smoother) {
1224 }
1225
1226 if (s->state != AST_FAX_STATE_INACTIVE) {
1227 ast_atomic_fetchadd_int(&faxregistry.active_sessions, -1);
1228 }
1229
1230 ast_free(s->channame);
1232}
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

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

786{
787 struct ast_fax_session_details *d = details;
788 struct ast_fax_document *doc;
789
790 while ((doc = AST_LIST_REMOVE_HEAD(&d->documents, next))) {
791 ast_free(doc);
792 }
794}
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
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 2922 of file res_fax.c.

2923{
2924 if (gateway->chan_v21_session) {
2925 ao2_unlink(faxregistry.container, gateway->chan_v21_session);
2926
2927 ao2_ref(gateway->chan_v21_session, -1);
2928 gateway->chan_v21_session = NULL;
2929 }
2930
2931 if (gateway->peer_v21_session) {
2932 ao2_unlink(faxregistry.container, gateway->peer_v21_session);
2933
2934 ao2_ref(gateway->peer_v21_session, -1);
2935 gateway->peer_v21_session = NULL;
2936 }
2937}
struct ast_fax_session * peer_v21_session
Definition res_fax.c:548
struct ast_fax_session * chan_v21_session
Definition res_fax.c:549

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

1629{
1630 int timeout_ms;
1631 struct ast_frame *frame = NULL;
1633 struct timeval start;
1634 int ms;
1635
1636 ast_debug(1, "Shutting down T.38 on %s\n", ast_channel_name(chan));
1637 if (ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0) {
1638 ast_debug(1, "error while disabling T.38 on channel '%s'\n", ast_channel_name(chan));
1639 return -1;
1640 }
1641
1642 /* wait up to five seconds for negotiation to complete */
1643 timeout_ms = 5000;
1644 start = ast_tvnow();
1645 while ((ms = ast_remaining_ms(start, timeout_ms))) {
1646 ms = ast_waitfor(chan, ms);
1647
1648 if (ms == 0) {
1649 break;
1650 }
1651 if (ms < 0) {
1652 ast_debug(1, "error while disabling T.38 on channel '%s'\n", ast_channel_name(chan));
1653 return -1;
1654 }
1655
1656 if (!(frame = ast_read(chan))) {
1657 return -1;
1658 }
1659 if ((frame->frametype == AST_FRAME_CONTROL) &&
1661 (frame->datalen == sizeof(t38_parameters))) {
1662 struct ast_control_t38_parameters *parameters = frame->data.ptr;
1663
1664 switch (parameters->request_response) {
1665 case AST_T38_TERMINATED:
1666 ast_debug(1, "Shut down T.38 on %s\n", ast_channel_name(chan));
1667 break;
1668 case AST_T38_REFUSED:
1669 ast_log(LOG_WARNING, "channel '%s' refused to disable T.38\n", ast_channel_name(chan));
1670 ast_frfree(frame);
1671 return -1;
1672 default:
1673 ast_log(LOG_ERROR, "channel '%s' failed to disable T.38\n", ast_channel_name(chan));
1674 ast_frfree(frame);
1675 return -1;
1676 }
1677 ast_frfree(frame);
1678 break;
1679 }
1680 ast_frfree(frame);
1681 }
1682
1683 if (ms == 0) { /* all done, nothing happened */
1684 ast_debug(1, "channel '%s' timed-out during T.38 shutdown\n", ast_channel_name(chan));
1685 }
1686
1687 return 0;
1688}
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition channel.c:3132
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition channel.c:4223
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:4621
@ AST_T38_TERMINATED
@ AST_T38_REQUEST_TERMINATE
#define ast_frfree(fr)
@ AST_FRAME_CONTROL
@ AST_CONTROL_T38_PARAMETERS
enum ast_control_t38 request_response
Data structure associated with a single frame of data.
struct ast_frame_subclass subclass
enum ast_frame_type frametype
union ast_frame::@239 data
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
Definition utils.c:2317

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

3991{
3992 struct fax_detect *faxdetect;
3993 struct ast_fax_session_details *details;
3994 struct ast_framehook_interface fr_hook = {
3996 .event_cb = fax_detect_framehook,
3997 .destroy_cb = fax_detect_framehook_destroy,
3998 };
3999
4000 if (!(details = find_or_create_details(chan))) {
4001 ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
4002 return -1;
4003 }
4004
4005 /* set up the frame hook*/
4006 faxdetect = fax_detect_new(chan, timeout, flags);
4007 if (!faxdetect) {
4008 ao2_ref(details, -1);
4009 return -1;
4010 }
4011
4012 fr_hook.data = faxdetect;
4013 faxdetect->details = details;
4014 ast_channel_lock(chan);
4015 details->faxdetect_id = ast_framehook_attach(chan, &fr_hook);
4016 details->faxdetect_timeout = timeout;
4017 details->faxdetect_flags = flags;
4018 ast_channel_unlock(chan);
4019
4020 if (details->faxdetect_id < 0) {
4021 ao2_ref(faxdetect, -1);
4022 }
4023
4024 return details->faxdetect_id;
4025}
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:3828
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:3795
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:3846

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

3847{
3848 struct fax_detect *faxdetect = data;
3849 struct ast_fax_session_details *details;
3850 struct ast_control_t38_parameters *control_params;
3851 RAII_VAR(struct ast_channel *, peer, NULL, ao2_cleanup);
3852 RAII_VAR(struct ast_channel *, chan_ref, chan, ao2_cleanup);
3853 int result = 0;
3854
3855 /* Ref bump the channel for when we have to unlock it */
3856 ao2_ref(chan, 1);
3857
3858 details = faxdetect->details;
3859
3860 switch (event) {
3862 /* Setup format for DSP on ATTACH*/
3864
3869 ast_framehook_detach(chan, details->faxdetect_id);
3870 details->faxdetect_id = -1;
3871 return f;
3872 }
3873 }
3874
3875 return NULL;
3877 /* restore audio formats when we are detached */
3878 ast_set_read_format(chan, faxdetect->orig_format);
3879 ast_channel_unlock(chan);
3880 peer = ast_channel_bridge_peer(chan);
3881 if (peer) {
3882 ast_channel_make_compatible(chan, peer);
3883 }
3884 ast_channel_lock(chan);
3885 return NULL;
3887 if (f) {
3888 break;
3889 }
3890 default:
3891 return f;
3892 };
3893
3894 if (details->faxdetect_id < 0) {
3895 return f;
3896 }
3897
3898 if (!ast_tvzero(faxdetect->timeout_start)
3899 && ast_tvdiff_ms(ast_tvnow(), faxdetect->timeout_start) > details->faxdetect_timeout) {
3900 ast_debug(1, "FAXOPT(faxdetect) timeout on %s\n", ast_channel_name(chan));
3901 ast_framehook_detach(chan, details->faxdetect_id);
3902 details->faxdetect_id = -1;
3903 return f;
3904 }
3905
3906 /* only handle VOICE and CONTROL frames*/
3907 switch (f->frametype) {
3908 case AST_FRAME_VOICE:
3909 /* we have no DSP this means we not detecting CNG */
3910 if (!faxdetect->dsp) {
3911 return f;
3912 }
3913 /* We can only process some formats*/
3917 return f;
3918 }
3919 break;
3920 case AST_FRAME_CONTROL:
3922 (faxdetect->flags & FAX_DETECT_MODE_T38)) {
3923 break;
3924 }
3925 return f;
3926 default:
3927 return f;
3928 }
3929
3930 if (f->frametype == AST_FRAME_VOICE) {
3931 f = ast_dsp_process(chan, faxdetect->dsp, f);
3932 if (f->frametype == AST_FRAME_DTMF) {
3933 result = f->subclass.integer;
3934 }
3935 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->datalen == sizeof(struct ast_control_t38_parameters))) {
3936 control_params = f->data.ptr;
3937 switch (control_params->request_response) {
3938 case AST_T38_NEGOTIATED:
3940 result = 't';
3941 break;
3942 default:
3943 break;
3944 }
3945 }
3946
3947 if (result) {
3948 const char *target_context;
3949
3950 switch (result) {
3951 case 'f':
3952 case 't':
3953 target_context = ast_channel_context(chan);
3954
3955 ast_channel_unlock(chan);
3956 ast_frfree(f);
3957 f = &ast_null_frame;
3958 if (ast_exists_extension(chan, target_context, "fax", 1,
3959 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
3960 ast_verb(2, "Redirecting '%s' to fax extension due to %s detection\n",
3961 ast_channel_name(chan), (result == 'f') ? "CNG" : "T38");
3962 pbx_builtin_setvar_helper(chan, "FAXEXTEN", ast_channel_exten(chan));
3963 if (ast_async_goto(chan, target_context, "fax", 1)) {
3964 ast_log(LOG_NOTICE, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(chan), target_context);
3965 }
3966 } else {
3967 ast_log(LOG_NOTICE, "FAX %s detected but no fax extension in context (%s)\n",
3968 (result == 'f') ? "CNG" : "T38", target_context);
3969 }
3970 ast_channel_lock(chan);
3971
3972 ast_framehook_detach(chan, details->faxdetect_id);
3973 details->faxdetect_id = -1;
3974 break;
3975 default:
3976 break;
3977 }
3978 }
3979
3980 return f;
3981}
#define ao2_replace(dst, src)
Replace one object reference with another cleaning up the original.
Definition astobj2.h:501
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:10578
int ast_channel_make_compatible(struct ast_channel *chan, struct ast_channel *peer)
Make the frame formats of two channels compatible.
Definition channel.c:6688
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:5730
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:1503
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.
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
struct ast_format * ast_format_alaw
Built-in cached alaw format.
@ 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
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:4196
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:6994
#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
struct timeval timeout_start
the start of our timeout counter
Definition res_fax.c:572
int flags
mode
Definition res_fax.c:580
Number structure.
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:978

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

3829{
3830 struct fax_detect *faxdetect = data;
3831
3832 ao2_ref(faxdetect, -1);
3833}

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

3796{
3797 struct fax_detect *faxdetect = ao2_alloc(sizeof(*faxdetect), destroy_faxdetect);
3798 if (!faxdetect) {
3799 return NULL;
3800 }
3801
3802 faxdetect->flags = flags;
3803
3804 if (timeout) {
3805 faxdetect->timeout_start = ast_tvnow();
3806 } else {
3807 faxdetect->timeout_start.tv_sec = 0;
3808 faxdetect->timeout_start.tv_usec = 0;
3809 }
3810
3811 if (faxdetect->flags & FAX_DETECT_MODE_CNG) {
3812 faxdetect->dsp = ast_dsp_new();
3813 if (!faxdetect->dsp) {
3814 ao2_ref(faxdetect, -1);
3815 return NULL;
3816 }
3819 } else {
3820 faxdetect->dsp = NULL;
3821 }
3822
3823 return faxdetect;
3824}
#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:1887
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
Definition dsp.c:1772
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
Definition dsp.c:1762
static void destroy_faxdetect(void *data)
destroy a FAX detect structure
Definition res_fax.c:3777

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

3728{
3729 struct fax_gateway *gateway;
3730 struct ast_framehook_interface fr_hook = {
3732 .event_cb = fax_gateway_framehook,
3733 .destroy_cb = fax_gateway_framehook_destroy,
3734 .disable_inheritance = 1, /* Masquerade inheritance is handled through the datastore fixup */
3735 };
3736
3737 if (global_fax_debug) {
3739 }
3740
3741 ast_string_field_set(details, result, "SUCCESS");
3742 ast_string_field_set(details, resultstr, "gateway operation started successfully");
3743 ast_string_field_set(details, error, "NO_ERROR");
3744 set_channel_variables(chan, details);
3745
3746 /* set up the frame hook*/
3747 gateway = fax_gateway_new(chan, details);
3748 if (!gateway) {
3749 ast_string_field_set(details, result, "FAILED");
3750 ast_string_field_set(details, resultstr, "error initializing gateway session");
3751 ast_string_field_set(details, error, "INIT_ERROR");
3752 details->is_t38_negotiated = 0;
3753 set_channel_variables(chan, details);
3754 report_fax_status(chan, details, "No Available Resource");
3755 return -1;
3756 }
3757
3758 fr_hook.data = gateway;
3759 ast_channel_lock(chan);
3760 gateway->framehook = ast_framehook_attach(chan, &fr_hook);
3761 ast_channel_unlock(chan);
3762
3763 if (gateway->framehook < 0) {
3764 ao2_ref(gateway, -1);
3765 ast_string_field_set(details, result, "FAILED");
3766 ast_string_field_set(details, resultstr, "error attaching gateway to channel");
3767 ast_string_field_set(details, error, "INIT_ERROR");
3768 details->is_t38_negotiated = 0;
3769 set_channel_variables(chan, details);
3770 return -1;
3771 }
3772
3773 return gateway->framehook;
3774}
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:1508
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:3484
static void fax_gateway_framehook_destroy(void *data)
Destroy the gateway data structure when the framehook is detached.
Definition res_fax.c:3446
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:2981
static void set_channel_variables(struct ast_channel *chan, struct ast_fax_session_details *details)
Set fax related channel variables.
Definition res_fax.c:1548
int framehook
framehook used in gateway mode
Definition res_fax.c:555

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

3211{
3212 struct ast_control_t38_parameters *control_params = f->data.ptr;
3213 struct ast_channel *other = (active == chan) ? peer : chan;
3214 struct ast_fax_session_details *details;
3215 enum ast_t38_state state_other;
3216
3217 if (f->datalen != sizeof(struct ast_control_t38_parameters)) {
3218 /* invalaid AST_CONTROL_T38_PARAMETERS frame, we can't
3219 * do anything with it, pass it on */
3220 return f;
3221 }
3222
3223 /* ignore frames from ourselves */
3224 if ((gateway->t38_state == T38_STATE_NEGOTIATED && control_params->request_response == AST_T38_NEGOTIATED)
3225 || (gateway->t38_state == T38_STATE_REJECTED && control_params->request_response == AST_T38_REFUSED)
3226 || (gateway->t38_state == T38_STATE_NEGOTIATING && control_params->request_response == AST_T38_REQUEST_TERMINATE)) {
3227
3228 return f;
3229 }
3230
3231 if (!(details = find_details(chan))) {
3232 ast_log(LOG_ERROR, "no FAX session details found on chan %s for T.38 gateway session, odd\n", ast_channel_name(chan));
3233 ast_framehook_detach(chan, gateway->framehook);
3234 return f;
3235 }
3236
3237 if (control_params->request_response == AST_T38_REQUEST_NEGOTIATE) {
3238 ast_channel_unlock(chan);
3239 state_other = ast_channel_get_t38_state(other);
3240 ast_channel_lock(chan);
3241
3242 if (state_other == T38_STATE_UNKNOWN) {
3243 /* we detected a request to negotiate T.38 and the
3244 * other channel appears to support T.38, we'll pass
3245 * the request through and only step in if the other
3246 * channel rejects the request */
3247 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));
3248 t38_parameters_ast_to_fax(&details->their_t38_parameters, control_params);
3249 gateway->t38_state = T38_STATE_UNKNOWN;
3250 gateway->timeout_start = ast_tvnow();
3251 details->is_t38_negotiated = 0;
3253 ao2_ref(details, -1);
3254 return f;
3255 } else if (state_other == T38_STATE_UNAVAILABLE || state_other == T38_STATE_REJECTED) {
3256 /* the other channel does not support T.38, we need to
3257 * step in here */
3258 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));
3259 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));
3260
3261 t38_parameters_ast_to_fax(&details->their_t38_parameters, control_params);
3262 t38_parameters_fax_to_ast(control_params, &details->our_t38_parameters);
3263
3264 if (fax_gateway_start(gateway, details, chan)) {
3265 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));
3266 gateway->t38_state = T38_STATE_REJECTED;
3267 details->is_t38_negotiated = 0;
3268 control_params->request_response = AST_T38_REFUSED;
3269
3270 ast_framehook_detach(chan, details->gateway_id);
3271 details->gateway_id = -1;
3272 } else {
3274 details->is_t38_negotiated = chan == active;
3275 control_params->request_response = AST_T38_NEGOTIATED;
3276 report_fax_status(chan, details, "T.38 Negotiated");
3277 }
3278
3279 fax_gateway_indicate_t38(chan, active, control_params);
3280
3281 ao2_ref(details, -1);
3282 return &ast_null_frame;
3283 } else if (gateway->t38_state == T38_STATE_NEGOTIATING) {
3284 /* we got a request to negotiate T.38 after we already
3285 * sent one to the other party based on v21 preamble
3286 * detection. We'll just pretend we passed this request
3287 * through in the first place. */
3288
3289 t38_parameters_ast_to_fax(&details->their_t38_parameters, control_params);
3290 gateway->t38_state = T38_STATE_UNKNOWN;
3291 gateway->timeout_start = ast_tvnow();
3292 details->is_t38_negotiated = 0;
3294
3295 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));
3296 ao2_ref(details, -1);
3297 return &ast_null_frame;
3298 } else if (gateway->t38_state == T38_STATE_NEGOTIATED) {
3299 /* we got a request to negotiate T.38 after we already
3300 * sent one to the other party based on v21 preamble
3301 * detection and received a response. We need to
3302 * respond to this and shut down the gateway. */
3303
3304 t38_parameters_fax_to_ast(control_params, &details->their_t38_parameters);
3305 ast_framehook_detach(chan, details->gateway_id);
3306 details->gateway_id = -1;
3307
3308 control_params->request_response = AST_T38_NEGOTIATED;
3309
3310 fax_gateway_indicate_t38(chan, active, control_params);
3311
3312 ast_string_field_set(details, result, "SUCCESS");
3313 ast_string_field_set(details, resultstr, "no gateway necessary");
3314 ast_string_field_set(details, error, "NATIVE_T38");
3315 details->is_t38_negotiated = 1;
3316 set_channel_variables(chan, details);
3317
3318 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));
3319 ao2_ref(details, -1);
3320 return &ast_null_frame;
3321 } else {
3322 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));
3323 ao2_ref(details, -1);
3324 return f;
3325 }
3326 } else if (gateway->t38_state == T38_STATE_NEGOTIATING
3327 && control_params->request_response == AST_T38_REFUSED) {
3328
3329 ast_debug(1, "unable to negotiate T.38 on %s for fax gateway\n", ast_channel_name(active));
3330 details->is_t38_negotiated = 0;
3331
3332 /* our request to negotiate T.38 was refused, if the other
3333 * channel supports T.38, they might still reinvite and save
3334 * the day. Otherwise disable the gateway. */
3335 ast_channel_unlock(chan);
3336 state_other = ast_channel_get_t38_state(other);
3337 ast_channel_lock(chan);
3338 if (state_other == T38_STATE_UNKNOWN) {
3340 } else if (state_other != T38_STATE_NEGOTIATING) {
3341 ast_framehook_detach(chan, details->gateway_id);
3342 details->gateway_id = -1;
3343
3344 ast_string_field_set(details, result, "FAILED");
3345 ast_string_field_set(details, resultstr, "unable to negotiate T.38");
3346 ast_string_field_set(details, error, "T38_NEG_ERROR");
3347 set_channel_variables(chan, details);
3348 }
3349
3350 ao2_ref(details, -1);
3351 return &ast_null_frame;
3352 } else if (gateway->t38_state == T38_STATE_NEGOTIATING
3353 && control_params->request_response == AST_T38_NEGOTIATED) {
3354
3355 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));
3356
3357 t38_parameters_ast_to_fax(&details->their_t38_parameters, control_params);
3358
3359 if (fax_gateway_start(gateway, details, chan)) {
3360 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));
3362 details->is_t38_negotiated = 0;
3364
3365 fax_gateway_indicate_t38(chan, active, control_params);
3366 } else {
3368 details->is_t38_negotiated = chan == active;
3369 report_fax_status(chan, details, "T.38 Negotiated");
3370 }
3371
3372 ao2_ref(details, -1);
3373 return &ast_null_frame;
3374 } else if (control_params->request_response == AST_T38_REFUSED) {
3375 /* the other channel refused the request to negotiate T.38,
3376 * we'll step in here and pretend the request was accepted */
3377
3378 ast_debug(1, "%s attempted to negotiate T.38 but %s refused the request\n", ast_channel_name(other), ast_channel_name(active));
3379 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));
3380
3381 t38_parameters_fax_to_ast(control_params, &details->our_t38_parameters);
3382
3383 if (fax_gateway_start(gateway, details, chan)) {
3384 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));
3385 gateway->t38_state = T38_STATE_REJECTED;
3386 details->is_t38_negotiated = 0;
3387 control_params->request_response = AST_T38_REFUSED;
3388
3389 ast_framehook_detach(chan, details->gateway_id);
3390 details->gateway_id = -1;
3391 } else {
3393 details->is_t38_negotiated = chan == other;
3394 control_params->request_response = AST_T38_NEGOTIATED;
3395 }
3396
3397 ao2_ref(details, -1);
3398 return f;
3399 } else if (control_params->request_response == AST_T38_REQUEST_TERMINATE) {
3400 /* the channel wishes to end our short relationship, we shall
3401 * oblige */
3402
3403 ast_debug(1, "T.38 channel %s is requesting a shutdown of T.38, disabling the gateway\n", ast_channel_name(active));
3404
3405 ast_framehook_detach(chan, details->gateway_id);
3406 details->gateway_id = -1;
3407
3408 gateway->t38_state = T38_STATE_REJECTED;
3409 details->is_t38_negotiated = 0;
3410 control_params->request_response = AST_T38_TERMINATED;
3411
3412 fax_gateway_indicate_t38(chan, active, control_params);
3413
3414 ao2_ref(details, -1);
3415 return &ast_null_frame;
3416 } else if (control_params->request_response == AST_T38_NEGOTIATED) {
3417 ast_debug(1, "T.38 successfully negotiated between %s and %s, no gateway necessary\n", ast_channel_name(active), ast_channel_name(other));
3418
3419 ast_framehook_detach(chan, details->gateway_id);
3420 details->gateway_id = -1;
3421
3422 ast_string_field_set(details, result, "SUCCESS");
3423 ast_string_field_set(details, resultstr, "no gateway necessary");
3424 ast_string_field_set(details, error, "NATIVE_T38");
3425 details->is_t38_negotiated = 1;
3426 set_channel_variables(chan, details);
3427
3428 ao2_ref(details, -1);
3429 return f;
3430 } else if (control_params->request_response == AST_T38_TERMINATED) {
3431 ast_debug(1, "T.38 disabled on channel %s\n", ast_channel_name(active));
3432
3433 ast_framehook_detach(chan, details->gateway_id);
3434 details->gateway_id = -1;
3435
3436 ao2_ref(details, -1);
3437 return &ast_null_frame;
3438 }
3439
3440 ao2_ref(details, -1);
3441 return f;
3442}
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:3018
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:3186
static void t38_parameters_fax_to_ast(struct ast_control_t38_parameters *dst, const struct ast_fax_t38_parameters *src)
Definition res_fax.c:852
static void t38_parameters_ast_to_fax(struct ast_fax_t38_parameters *dst, const struct ast_control_t38_parameters *src)
Definition res_fax.c:841
#define FAX_GATEWAY_TIMEOUT
Definition res_fax.c:594
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:553
enum ast_t38_state t38_state
a flag to track the state of our negotiation
Definition res_fax.c:561

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, ast_fax_session_details::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 3113 of file res_fax.c.

3114{
3115 struct ast_channel *other = (active == chan) ? peer : chan;
3116 struct ast_fax_session *active_v21_session = (active == chan) ? gateway->chan_v21_session : gateway->peer_v21_session;
3117
3118 if (!active_v21_session || gateway->detected_v21) {
3119 return f;
3120 }
3121
3122 if (active_v21_session->tech->write(active_v21_session, f) == 0 &&
3123 active_v21_session->details->option.v21_detected) {
3124 gateway->detected_v21 = 1;
3125 }
3126
3127 if (gateway->detected_v21) {
3128 enum ast_t38_state state_other;
3129 enum ast_t38_state state_active;
3130 struct ast_frame *fp;
3131 struct ast_fax_session_details *details;
3132 int negotiate_both = 0;
3133
3134 /*
3135 * The default behavior is to wait for the active endpoint to initiate negotiation.
3136 * Find out if this has been overridden. If so, instead of waiting have Asterisk
3137 * initiate the negotiation requests out to both endpoints.
3138 */
3139 details = find_or_create_details(active);
3140 if (details) {
3141 negotiate_both = details->negotiate_both;
3142 ao2_ref(details, -1);
3143 } else {
3144 ast_log(LOG_WARNING, "Detect v21 - no session details for channel '%s'\n",
3145 ast_channel_name(chan));
3146 }
3147
3148 destroy_v21_sessions(gateway);
3149
3150 ast_channel_unlock(chan);
3151 state_active = ast_channel_get_t38_state(active);
3152 state_other = ast_channel_get_t38_state(other);
3153 ast_channel_lock(chan);
3154
3155 ast_debug(1, "detected v21 preamble from %s\n", ast_channel_name(active));
3156
3157 if (state_active == T38_STATE_UNKNOWN || state_other == T38_STATE_UNKNOWN) {
3158 if (!(fp = fax_gateway_request_t38(gateway, chan))) {
3159 return f;
3160 }
3161 /* May be called endpoint is improperly configured to rely on the calling endpoint
3162 * to initiate T.38 re-INVITEs, send T.38 negotiation request to called endpoint */
3163 if (negotiate_both && state_active == T38_STATE_UNKNOWN) {
3164 ast_debug(1, "sending T.38 negotiation request to %s\n", ast_channel_name(active));
3165 if (active == chan) {
3166 ast_channel_unlock(chan);
3167 }
3168 ast_write(active, fp);
3169 if (active == chan) {
3170 ast_channel_lock(chan);
3171 }
3172 }
3173 if (state_other == T38_STATE_UNKNOWN) {
3174 ast_debug(1, "sending T.38 negotiation request to %s\n", ast_channel_name(other));
3175 return fp;
3176 }
3177 } else {
3178 ast_debug(1, "neither %s nor %s support T.38 for T.38 gateway session\n", ast_channel_name(active), ast_channel_name(other));
3179 }
3180 }
3181
3182 return f;
3183}
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:5112
static struct ast_frame * fax_gateway_request_t38(struct fax_gateway *gateway, struct ast_channel *chan)
Definition res_fax.c:3073
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:559

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

3485{
3486 struct fax_gateway *gateway = data;
3487 struct ast_channel *active;
3488 RAII_VAR(struct ast_fax_session_details *, details, NULL, ao2_cleanup);
3489 RAII_VAR(struct ast_channel *, peer, NULL, ao2_cleanup);
3490 RAII_VAR(struct ast_channel *, chan_ref, chan, ao2_cleanup);
3491
3492 /* Ref bump channel for when we have to unlock it */
3493 ao2_ref(chan_ref, 1);
3494
3495 if (gateway->s) {
3496 details = gateway->s->details;
3497 ao2_ref(details, 1);
3498 } else {
3499 if (!(details = find_details(chan))) {
3500 ast_log(LOG_ERROR, "no FAX session details found on chan %s for T.38 gateway session, odd\n", ast_channel_name(chan));
3501 ast_framehook_detach(chan, gateway->framehook);
3502 return f;
3503 }
3504 }
3505
3506 /* restore audio formats when we are detached */
3508 set_channel_variables(chan, details);
3509
3510 if (gateway->bridged) {
3511 ast_set_read_format(chan, gateway->chan_read_format);
3513
3514 ast_channel_unlock(chan);
3515 peer = ast_channel_bridge_peer(chan);
3516 if (peer) {
3517 ast_set_read_format(peer, gateway->peer_read_format);
3519 ast_channel_make_compatible(chan, peer);
3520 }
3521 ast_channel_lock(chan);
3522 }
3523 return NULL;
3524 }
3525
3526 if (!f || (event == AST_FRAMEHOOK_EVENT_ATTACHED)) {
3527 return NULL;
3528 };
3529
3530 /* this frame was generated by the fax gateway, pass it on */
3532 return f;
3533 }
3534
3535 /* If we aren't bridged or we don't have a peer, don't do anything */
3536 ast_channel_unlock(chan);
3537 peer = ast_channel_bridge_peer(chan);
3538 ast_channel_lock(chan);
3539 if (!peer) {
3540 return f;
3541 }
3542
3543 if (!gateway->bridged) {
3544 enum ast_t38_state state_chan;
3545 enum ast_t38_state state_peer;
3546 int chan_is_hungup;
3547 int peer_is_hungup;
3548
3549 chan_is_hungup = ast_check_hangup(chan);
3550 peer_is_hungup = ast_check_hangup(peer);
3551 /* Don't start a gateway if either channel is hung up */
3552 if (chan_is_hungup || peer_is_hungup) {
3553 return f;
3554 }
3555
3556 ast_channel_unlock(chan);
3557 state_chan = ast_channel_get_t38_state(chan);
3558 state_peer = ast_channel_get_t38_state(peer);
3559 ast_channel_lock(chan);
3560
3561 /* don't start a gateway if neither channel can handle T.38 */
3562 if (state_chan == T38_STATE_UNAVAILABLE && state_peer == T38_STATE_UNAVAILABLE) {
3563 ast_debug(1, "not starting gateway for %s and %s; neither channel supports T.38\n", ast_channel_name(chan), ast_channel_name(peer));
3564 ast_framehook_detach(chan, gateway->framehook);
3565 details->gateway_id = -1;
3566
3567 ast_string_field_set(details, result, "FAILED");
3568 ast_string_field_set(details, resultstr, "neither channel supports T.38");
3569 ast_string_field_set(details, error, "T38_NEG_ERROR");
3570 details->is_t38_negotiated = 0;
3571 set_channel_variables(chan, details);
3572 return f;
3573 }
3574
3575 if (details->gateway_timeout) {
3576 gateway->timeout_start = ast_tvnow();
3577 }
3578
3579 ast_channel_unlock(chan);
3580 ast_channel_lock_both(chan, peer);
3581
3582 /* we are bridged, change r/w formats to SLIN for v21 preamble
3583 * detection and T.30 */
3586
3589
3592
3595
3596 ast_channel_unlock(peer);
3597
3598 gateway->bridged = 1;
3599 if (!(gateway->peer_v21_session = fax_v21_session_new(peer))) {
3600 ast_log(LOG_ERROR, "Can't create V21 session on chan %s for T.38 gateway session\n", ast_channel_name(peer));
3601 ast_framehook_detach(chan, gateway->framehook);
3602 return f;
3603 }
3604 }
3605
3606 if (gateway->bridged && !ast_tvzero(gateway->timeout_start)) {
3607 if (ast_tvdiff_ms(ast_tvnow(), gateway->timeout_start) > details->gateway_timeout) {
3608 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);
3609 ast_framehook_detach(chan, gateway->framehook);
3610 details->gateway_id = -1;
3611
3612 ast_string_field_set(details, result, "FAILED");
3613 ast_string_field_build(details, resultstr, "no fax activity after %d ms", details->gateway_timeout);
3614 ast_string_field_set(details, error, "TIMEOUT");
3615 details->is_t38_negotiated = 0;
3616 set_channel_variables(chan, details);
3617 return f;
3618 }
3619 }
3620
3621 /* only handle VOICE, MODEM, and CONTROL frames*/
3622 switch (f->frametype) {
3623 case AST_FRAME_VOICE:
3627 return f;
3628 }
3629 break;
3630 case AST_FRAME_MODEM:
3631 if (f->subclass.integer == AST_MODEM_T38) {
3632 break;
3633 }
3634 return f;
3635 case AST_FRAME_CONTROL:
3637 break;
3638 }
3639 return f;
3640 default:
3641 return f;
3642 }
3643
3644 /* detect the active channel */
3645 switch (event) {
3647 active = peer;
3648 break;
3650 active = chan;
3651 break;
3652 default:
3653 ast_log(LOG_WARNING, "unhandled framehook event %u\n", event);
3654 return f;
3655 }
3656
3657 /* handle control frames */
3659 return fax_gateway_detect_t38(gateway, chan, peer, active, f);
3660 }
3661
3662 if (!gateway->detected_v21 && gateway->t38_state == T38_STATE_UNAVAILABLE && f->frametype == AST_FRAME_VOICE) {
3663 /* not in gateway mode and have not detected v21 yet, listen
3664 * for v21 */
3665 return fax_gateway_detect_v21(gateway, chan, peer, active, f);
3666 }
3667
3668 /* in gateway mode, gateway some packets */
3669 if (gateway->t38_state == T38_STATE_NEGOTIATED) {
3670 struct ast_trans_pvt *readtrans;
3671
3672 if (!gateway->s || !gateway->s->tech_pvt) {
3673 ast_log(LOG_ERROR, "no FAX session on chan %s for T.38 gateway session, odd", ast_channel_name(chan));
3674 return f;
3675 }
3676
3677 /* framehooks are called in __ast_read() before frame format
3678 * translation is done, so we need to translate here */
3680 && (readtrans = ast_channel_readtrans(active))) {
3681 if ((f = ast_translate(readtrans, f, event == AST_FRAMEHOOK_EVENT_WRITE ? 0 : 1)) == NULL) {
3682 f = &ast_null_frame;
3683 return f;
3684 }
3685 /* XXX we ignore the return value here, perhaps we should
3686 * disable the gateway if a write fails. I am not sure how a
3687 * write would fail, or even if a failure would be fatal so for
3688 * now we'll just ignore the return value. */
3689 gateway->s->tech->write(gateway->s, f);
3690 ast_frfree(f);
3691 } else {
3692 gateway->s->tech->write(gateway->s, f);
3693 }
3694
3695 f = &ast_null_frame;
3696 return f;
3697 }
3698
3699 /* force silence on the line if T.38 negotiation might be taking place */
3700 if (gateway->t38_state != T38_STATE_UNAVAILABLE && gateway->t38_state != T38_STATE_REJECTED) {
3701 if (f->frametype == AST_FRAME_VOICE &&
3703 short silence_buf[f->samples];
3704 struct ast_frame silence_frame = {
3706 .subclass.format = ast_format_slin,
3707 .data.ptr = silence_buf,
3708 .samples = f->samples,
3709 .datalen = sizeof(silence_buf),
3710 };
3711 memset(silence_buf, 0, sizeof(silence_buf));
3712 return ast_frisolate(&silence_frame);
3713 } else {
3714 return &ast_null_frame;
3715 }
3716 }
3717
3718 return f;
3719}
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:445
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:5771
@ AST_FRAMEHOOK_EVENT_WRITE
Definition framehook.h:153
#define ast_frisolate(fr)
Makes a frame independent of any static storage.
#define AST_MODEM_T38
static struct ast_fax_session * fax_v21_session_new(struct ast_channel *chan)
Definition res_fax.c:2962
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:3113
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:3210
#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.
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:557
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 3446 of file res_fax.c.

3447{
3448 struct fax_gateway *gateway = data;
3449
3450 if (gateway->s) {
3451 switch (gateway->s->state) {
3453 case AST_FAX_STATE_OPEN:
3456 if (gateway->s->tech->cancel_session) {
3457 gateway->s->tech->cancel_session(gateway->s);
3458 }
3459 /* fall through */
3460 default:
3461 break;
3462 }
3463 }
3464
3465 ao2_ref(gateway, -1);
3466}
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 3186 of file res_fax.c.

3187{
3188 if (active == chan) {
3189 ast_channel_unlock(chan);
3190 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, control_params, sizeof(*control_params));
3191 ast_channel_lock(chan);
3192 } else {
3193 ast_queue_control_data(chan, AST_CONTROL_T38_PARAMETERS, control_params, sizeof(*control_params));
3194 }
3195}
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:1277

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

2982{
2983 struct fax_gateway *gateway = ao2_alloc(sizeof(*gateway), destroy_gateway);
2984 if (!gateway) {
2985 return NULL;
2986 }
2987
2988 if (!(gateway->chan_v21_session = fax_v21_session_new(chan))) {
2989 ast_log(LOG_ERROR, "Can't create V21 session on chan %s for T.38 gateway session\n", ast_channel_name(chan));
2990 ao2_ref(gateway, -1);
2991 return NULL;
2992 }
2993
2994 gateway->framehook = -1;
2995
2996 details->caps = AST_FAX_TECH_GATEWAY;
2997 if (details->gateway_timeout && !(gateway->s = fax_session_reserve(details, &gateway->token))) {
2998 details->caps &= ~AST_FAX_TECH_GATEWAY;
2999 ast_log(LOG_ERROR, "Can't reserve a FAX session, gateway attempt failed.\n");
3000 ao2_ref(gateway, -1);
3001 return NULL;
3002 }
3003
3004 return gateway;
3005}
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:1247
static void destroy_gateway(void *data)
destroy a FAX gateway session structure
Definition res_fax.c:2940

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

3074{
3075 struct ast_frame *fp;
3076 struct ast_control_t38_parameters t38_parameters = {
3078 };
3079 struct ast_frame control_frame = {
3080 .src = "res_fax",
3081 .frametype = AST_FRAME_CONTROL,
3082 .datalen = sizeof(t38_parameters),
3084 .data.ptr = &t38_parameters,
3085 };
3086
3087 struct ast_fax_session_details *details = find_details(chan);
3088
3089 if (!details) {
3090 ast_log(LOG_ERROR, "no FAX session details found on chan %s for T.38 gateway session, odd\n", ast_channel_name(chan));
3091 ast_framehook_detach(chan, gateway->framehook);
3092 return NULL;
3093 }
3094
3095 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
3096 ao2_ref(details, -1);
3097
3098 if (!(fp = ast_frisolate(&control_frame))) {
3099 ast_log(LOG_ERROR, "error generating T.38 request control frame on chan %s for T.38 gateway session\n", ast_channel_name(chan));
3100 return NULL;
3101 }
3102
3104 gateway->timeout_start = ast_tvnow();
3105 details->is_t38_negotiated = 0;
3107
3108 ast_debug(1, "requesting T.38 for gateway session for %s\n", ast_channel_name(chan));
3109 return fp;
3110}

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

3019{
3020 struct ast_fax_session *s;
3021 int start_res;
3022
3023 /* if the fax gateway is already started then do nothing */
3024 if (gateway->s &&
3025 gateway->s->state != AST_FAX_STATE_RESERVED && gateway->s->state != AST_FAX_STATE_INACTIVE) {
3026 return 0;
3027 }
3028
3029 /* if we start gateway we don't need v21 detection sessions any more */
3030 destroy_v21_sessions(gateway);
3031
3032 /* create the FAX session */
3033 if (!(s = fax_session_new(details, chan, gateway->s, gateway->token))) {
3034 gateway->token = NULL;
3036 ast_string_field_set(details, resultstr, "error starting gateway session");
3037 ast_string_field_set(details, error, "INIT_ERROR");
3040 report_fax_status(chan, details, "No Available Resource");
3041 ast_log(LOG_ERROR, "Can't create a FAX session, gateway attempt failed.\n");
3042 return -1;
3043 }
3044 /* release the reference for the reserved session and replace it with
3045 * the real session */
3046 if (gateway->s) {
3047 ao2_ref(gateway->s, -1);
3048 }
3049 gateway->s = s;
3050 gateway->token = NULL;
3051
3053 start_res = gateway->s->tech->start_session(gateway->s);
3055 if (start_res < 0) {
3057 ast_string_field_set(details, resultstr, "error starting gateway session");
3058 ast_string_field_set(details, error, "INIT_ERROR");
3061 return -1;
3062 }
3063
3064 gateway->timeout_start.tv_sec = 0;
3065 gateway->timeout_start.tv_usec = 0;
3066
3067 report_fax_status(chan, details, "FAX Transmission In Progress");
3068
3069 return 0;
3070}
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:1316
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 1147 of file res_fax.c.

1148{
1149 int rate;
1150
1151 if (sscanf(ratestr, "%d", &rate) != 1) {
1152 ast_log(LOG_ERROR, "failed to sscanf '%s' to rate\n", ratestr);
1153 return 0;
1154 }
1155 switch (rate) {
1156 case 2400:
1157 case 4800:
1158 case 7200:
1159 case 9600:
1160 case 12000:
1161 case 14400:
1162 case 28800:
1163 case 33600:
1164 return rate;
1165 default:
1166 ast_log(LOG_WARNING, "ignoring invalid rate '%s'. Valid options are {2400 | 4800 | 7200 | 9600 | 12000 | 14400 | 28800 | 33600}\n", ratestr);
1167 return 0;
1168 }
1169}

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

1317{
1318 struct ast_fax_session *s = NULL;
1319 struct fax_module *faxmod;
1320
1321 if (reserved) {
1322 s = reserved;
1323 ao2_ref(reserved, +1);
1324 ao2_unlink(faxregistry.container, reserved);
1325
1326 /* NOTE: we don't consume the reference to the reserved
1327 * session. The session returned from fax_session_new() is a
1328 * new reference and must be derefed in addition to the
1329 * reserved session.
1330 */
1331
1332 if (s->state == AST_FAX_STATE_RESERVED) {
1333 ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, -1);
1335 }
1336 }
1337
1338 if (!s && !(s = ao2_alloc(sizeof(*s), destroy_session))) {
1339 return NULL;
1340 }
1341
1342 ast_atomic_fetchadd_int(&faxregistry.active_sessions, 1);
1344
1345 if (details->option.debug && (details->caps & AST_FAX_TECH_AUDIO)) {
1346 if (!(s->debug_info = ast_calloc(1, sizeof(*(s->debug_info))))) {
1347 fax_session_release(s, token);
1348 ao2_ref(s, -1);
1349 return NULL;
1350 }
1351 if (!(s->debug_info->dsp = ast_dsp_new())) {
1352 ast_free(s->debug_info);
1353 s->debug_info = NULL;
1354 fax_session_release(s, token);
1355 ao2_ref(s, -1);
1356 return NULL;
1357 }
1359 }
1360
1361 if (!(s->channame = ast_strdup(ast_channel_name(chan)))) {
1362 fax_session_release(s, token);
1363 ao2_ref(s, -1);
1364 return NULL;
1365 }
1366
1367 if (!(s->chan_uniqueid = ast_strdup(ast_channel_uniqueid(chan)))) {
1368 fax_session_release(s, token);
1369 ao2_ref(s, -1);
1370 return NULL;
1371 }
1372
1373 s->chan = chan;
1374 if (!s->details) {
1375 s->details = details;
1376 ao2_ref(s->details, 1);
1377 }
1378
1379 details->id = s->id = ast_atomic_fetchadd_int(&faxregistry.nextsessionname, 1);
1380
1381 if (!token) {
1382 /* locate a FAX technology module that can handle said requirements */
1385 if ((faxmod->tech->caps & details->caps) != details->caps) {
1386 continue;
1387 }
1388 if (!ast_module_running_ref(faxmod->tech->module)) {
1389 continue;
1390 }
1391 ast_debug(4, "Requesting a new FAX session from '%s'.\n", faxmod->tech->description);
1392 if (reserved) {
1393 /* Balance module ref from reserved session */
1394 ast_module_unref(reserved->tech->module);
1395 }
1396 s->tech = faxmod->tech;
1397 break;
1398 }
1400
1401 if (!faxmod) {
1402 char caps[128] = "";
1403 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)));
1404 ao2_ref(s, -1);
1405 return NULL;
1406 }
1407 }
1408
1409 if (!(s->tech_pvt = s->tech->new_session(s, token))) {
1410 ast_log(LOG_ERROR, "FAX session failed to initialize.\n");
1411 ao2_ref(s, -1);
1412 return NULL;
1413 }
1414 /* link the session to the session container */
1415 if (!(ao2_link(faxregistry.container, s))) {
1416 ast_log(LOG_ERROR, "failed to add FAX session '%u' to container.\n", s->id);
1417 ao2_ref(s, -1);
1418 return NULL;
1419 }
1420 ast_debug(4, "channel '%s' using FAX session '%u'\n", s->channame, s->id);
1421
1422 return s;
1423}
#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:1792
#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:947
static void destroy_session(void *session)
destroy a FAX session structure
Definition res_fax.c:1197
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, fax_module::list, LOG_ERROR, 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 1184 of file res_fax.c.

1185{
1186 if (token) {
1187 s->tech->release_token(token);
1188 }
1189
1190 if (s->state == AST_FAX_STATE_RESERVED) {
1191 ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, -1);
1193 }
1194}
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 1247 of file res_fax.c.

1248{
1249 struct ast_fax_session *s;
1250 struct fax_module *faxmod;
1251
1252 if (!(s = ao2_alloc(sizeof(*s), destroy_session))) {
1253 return NULL;
1254 }
1255
1257 s->details = details;
1258 ao2_ref(s->details, 1);
1259
1260 /* locate a FAX technology module that can handle said requirements
1261 * Note: the requirements have not yet been finalized as T.38
1262 * negotiation has not yet occured. */
1265 if ((faxmod->tech->caps & details->caps) != details->caps) {
1266 continue;
1267 }
1268 if (!ast_module_running_ref(faxmod->tech->module)) {
1269 continue;
1270 }
1271 ast_debug(4, "Reserving a FAX session from '%s'.\n", faxmod->tech->description);
1272 s->tech = faxmod->tech;
1273 break;
1274 }
1276
1277 if (!faxmod) {
1278 char caps[128] = "";
1279 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)));
1280 ao2_ref(s, -1);
1281 return NULL;
1282 }
1283
1284 if (!s->tech->reserve_session) {
1285 ast_debug(1, "Selected FAX technology module (%s) does not support reserving sessions.\n", s->tech->description);
1286 return s;
1287 }
1288
1289 if (!(*token = s->tech->reserve_session(s))) {
1290 ao2_ref(s, -1);
1291 return NULL;
1292 }
1293
1295 ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, 1);
1296
1297 return s;
1298}
struct ast_module *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, fax_module::list, LOG_ERROR, 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 4044 of file res_fax.c.

4045{
4046 int tklen;
4047 int wordnum = 0;
4048 char *name = NULL;
4049 struct ao2_iterator i;
4050 struct ast_fax_session *s;
4051 char tbuf[5];
4052
4053 if (a->pos != 3) {
4054 return NULL;
4055 }
4056
4057 tklen = strlen(a->word);
4058 i = ao2_iterator_init(faxregistry.container, 0);
4059 while ((s = ao2_iterator_next(&i))) {
4060 snprintf(tbuf, sizeof(tbuf), "%u", s->id);
4061 if (!strncasecmp(a->word, tbuf, tklen) && ++wordnum > a->n) {
4062 name = ast_strdup(tbuf);
4063 ao2_ref(s, -1);
4064 break;
4065 }
4066 ao2_ref(s, -1);
4067 }
4069 return name;
4070}
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 4343 of file res_fax.c.

4344{
4345 if (s->details->caps & AST_FAX_TECH_AUDIO) {
4346 return "G.711";
4347 }
4348 if (s->details->caps & AST_FAX_TECH_T38) {
4349 return "T.38";
4350 }
4351
4352 return "none";
4353}

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

2962 {
2963 struct ast_fax_session_details *v21_details;
2964 struct ast_fax_session *v21_session;
2965
2966 if (!chan || !(v21_details = session_details_new())) {
2967 return NULL;
2968 }
2969
2970 v21_details->caps = AST_FAX_TECH_V21_DETECT;
2971 v21_session = fax_session_new(v21_details, chan, NULL, NULL);
2972 ao2_ref(v21_details, -1);
2973 return v21_session;
2974}
static struct ast_fax_session_details * session_details_new(void)
create a FAX session details structure
Definition res_fax.c:797

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

764{
765 struct ast_fax_session_details *details;
766 struct ast_datastore *datastore;
767
768 ast_channel_lock(chan);
769 if (!(datastore = ast_channel_datastore_find(chan, &fax_datastore, NULL))) {
770 ast_channel_unlock(chan);
771 return NULL;
772 }
773 if (!(details = datastore->data)) {
774 ast_log(LOG_WARNING, "Huh? channel '%s' has a FAX datastore without data!\n", ast_channel_name(chan));
775 ast_channel_unlock(chan);
776 return NULL;
777 }
778 ao2_ref(details, 1);
779 ast_channel_unlock(chan);
780
781 return details;
782}
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:2369
static const struct ast_datastore_info fax_datastore
Definition res_fax.c:720
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 865 of file res_fax.c.

866{
867 struct ast_fax_session_details *details;
868 struct ast_datastore *datastore;
869
870 if ((details = find_details(chan))) {
871 return details;
872 }
873 /* channel does not have one so we must create one */
874 if (!(details = session_details_new())) {
875 ast_log(LOG_WARNING, "channel '%s' can't get a FAX details structure for the datastore!\n", ast_channel_name(chan));
876 return NULL;
877 }
878 if (!(datastore = ast_datastore_alloc(&fax_datastore, NULL))) {
879 ao2_ref(details, -1);
880 ast_log(LOG_WARNING, "channel '%s' can't get a datastore!\n", ast_channel_name(chan));
881 return NULL;
882 }
883 /* add the datastore to the channel and increment the refcount */
884 datastore->data = details;
885
886 /* initialize default T.38 parameters */
889
890 ao2_ref(details, 1);
891 ast_channel_lock(chan);
892 ast_channel_datastore_add(chan, datastore);
893 ast_channel_unlock(chan);
894 return details;
895}
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition channel.c:2355
#define ast_datastore_alloc(info, uid)
Definition datastore.h:85
static struct ast_control_t38_parameters our_t38_parameters
Definition res_fax.c:834

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

738{
739 struct ast_fax_session_details *old_details = data;
740 struct ast_datastore *datastore = ast_channel_datastore_find(old_chan, &fax_datastore, NULL);
741
742 if (old_details->gateway_id >= 0) {
743 struct ast_fax_session_details *new_details = find_or_create_details(new_chan);
744
745 ast_framehook_detach(old_chan, old_details->gateway_id);
746 new_details->is_t38_negotiated = old_details->is_t38_negotiated;
747 fax_gateway_attach(new_chan, new_details);
748 ao2_cleanup(new_details);
749 }
750
751 if (old_details->faxdetect_id >= 0) {
752 ast_framehook_detach(old_chan, old_details->faxdetect_id);
753 fax_detect_attach(new_chan, old_details->faxdetect_timeout, old_details->faxdetect_flags);
754 }
755
756 if (datastore) {
757 ast_channel_datastore_remove(old_chan, datastore);
758 ast_datastore_free(datastore);
759 }
760}
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition channel.c:2364
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 1431 of file res_fax.c.

1432{
1433 RAII_VAR(struct ast_json *, json_array, ast_json_array_create(), ast_json_unref);
1434 struct ast_fax_document *doc;
1435
1436 if (!details || !json_array) {
1437 return NULL;
1438 }
1439
1440 /* don't process empty lists */
1441 if (AST_LIST_EMPTY(&details->documents)) {
1442 return NULL;
1443 }
1444
1445 AST_LIST_TRAVERSE(&details->documents, doc, next) {
1446 struct ast_json *entry = ast_json_string_create(doc->filename);
1447 if (!entry) {
1448 return NULL;
1449 }
1450 if (ast_json_array_append(json_array, entry)) {
1451 return NULL;
1452 }
1453 }
1454
1455 ast_json_ref(json_array);
1456 return json_array;
1457}
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.
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 1471 of file res_fax.c.

1472{
1473 char *filenames, *c;
1474 size_t size = 0;
1475 int first = 1;
1476 struct ast_fax_document *doc;
1477
1478 /* don't process empty lists */
1479 if (AST_LIST_EMPTY(&details->documents)) {
1480 return ast_strdup("");
1481 }
1482
1483 /* Calculate the total length of all of the file names */
1484 AST_LIST_TRAVERSE(&details->documents, doc, next) {
1485 size += strlen(separator) + strlen(prefix) + strlen(doc->filename);
1486 }
1487 size += 1; /* add space for the terminating null */
1488
1489 if (!(filenames = ast_malloc(size))) {
1490 return NULL;
1491 }
1492 c = filenames;
1493
1494 ast_build_string(&c, &size, "%s%s", prefix, AST_LIST_FIRST(&details->documents)->filename);
1495 AST_LIST_TRAVERSE(&details->documents, doc, next) {
1496 if (first) {
1497 first = 0;
1498 continue;
1499 }
1500
1501 ast_build_string(&c, &size, "%s%s%s", separator, prefix, doc->filename);
1502 }
1503
1504 return filenames;
1505}
#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 1691 of file res_fax.c.

1692{
1693 int ms;
1694 int timeout = RES_FAX_TIMEOUT;
1695 int chancount;
1696 unsigned int expected_frametype = -1;
1697 struct ast_frame_subclass expected_framesubclass = { .integer = 0, };
1698 unsigned int t38negotiated = (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED);
1699 struct ast_control_t38_parameters t38_parameters;
1700 const char *tempvar;
1701 struct ast_fax_session *fax = NULL;
1702 struct ast_frame *frame = NULL;
1703 struct ast_channel *c = chan;
1704 RAII_VAR(struct ast_format *, orig_write_format, NULL, ao2_cleanup);
1705 RAII_VAR(struct ast_format *, orig_read_format, NULL, ao2_cleanup);
1706 int remaining_time;
1707 struct timeval start;
1708
1709 chancount = 1;
1710
1711 /* Make sure one or the other is set to avoid race condition */
1712 if (t38negotiated) {
1713 details->caps |= AST_FAX_TECH_T38;
1714 } else {
1715 details->caps |= AST_FAX_TECH_AUDIO;
1716 }
1717
1718 /* create the FAX session */
1719 if (!(fax = fax_session_new(details, chan, reserved, token))) {
1720 ast_log(LOG_ERROR, "Can't create a FAX session, FAX attempt failed.\n");
1721 report_fax_status(chan, details, "No Available Resource");
1722 return -1;
1723 }
1724
1725 ast_channel_lock(chan);
1726 /* update session details */
1727 if (ast_strlen_zero(details->headerinfo) && (tempvar = pbx_builtin_getvar_helper(chan, "LOCALHEADERINFO"))) {
1728 ast_string_field_set(details, headerinfo, tempvar);
1729 }
1730 if (ast_strlen_zero(details->localstationid)) {
1731 tempvar = pbx_builtin_getvar_helper(chan, "LOCALSTATIONID");
1732 ast_string_field_set(details, localstationid, tempvar ? tempvar : "unknown");
1733 }
1734 ast_channel_unlock(chan);
1735
1736 report_fax_status(chan, details, "Allocating Resources");
1737
1738 if (details->caps & AST_FAX_TECH_AUDIO) {
1739 expected_frametype = AST_FRAME_VOICE;
1740 expected_framesubclass.format = ast_format_slin;
1741 orig_write_format = ao2_bump(ast_channel_writeformat(chan));
1742 if (ast_set_write_format(chan, ast_format_slin) < 0) {
1743 ast_log(LOG_ERROR, "channel '%s' failed to set write format to signed linear'.\n", ast_channel_name(chan));
1744 ao2_unlink(faxregistry.container, fax);
1745 ao2_ref(fax, -1);
1746 return -1;
1747 }
1748 orig_read_format = ao2_bump(ast_channel_readformat(chan));
1749 if (ast_set_read_format(chan, ast_format_slin) < 0) {
1750 ast_log(LOG_ERROR, "channel '%s' failed to set read format to signed linear.\n", ast_channel_name(chan));
1751 ao2_unlink(faxregistry.container, fax);
1752 ao2_ref(fax, -1);
1753 return -1;
1754 }
1755 if (fax->smoother) {
1757 fax->smoother = NULL;
1758 }
1759 if (!(fax->smoother = ast_smoother_new(320))) {
1760 ast_log(LOG_WARNING, "Channel '%s' FAX session '%u' failed to obtain a smoother.\n", ast_channel_name(chan), fax->id);
1761 }
1762 } else {
1763 expected_frametype = AST_FRAME_MODEM;
1764 expected_framesubclass.integer = AST_MODEM_T38;
1765 }
1766
1767 if (fax->debug_info) {
1768 fax->debug_info->base_tv = ast_tvnow();
1769 }
1770
1771 /* reset our result fields just in case the fax tech driver wants to
1772 * set custom error messages */
1773 ast_string_field_set(details, result, "");
1774 ast_string_field_set(details, resultstr, "");
1775 ast_string_field_set(details, error, "");
1776 details->is_t38_negotiated = t38negotiated;
1777 set_channel_variables(chan, details);
1778
1779 if (fax->tech->start_session(fax) < 0) {
1780 GENERIC_FAX_EXEC_ERROR(fax, chan, "INIT_ERROR", "failed to start FAX session");
1781 }
1782
1783 report_fax_status(chan, details, "FAX Transmission In Progress");
1784
1785 ast_debug(5, "channel %s will wait on FAX fd %d\n", ast_channel_name(chan), fax->fd);
1786
1787 /* handle frames for the session */
1788 remaining_time = timeout;
1789 start = ast_tvnow();
1790 while (remaining_time > 0) {
1791 struct ast_channel *ready_chan;
1792 int ofd, exception;
1793
1794 ms = 1000;
1795 errno = 0;
1796 ready_chan = ast_waitfor_nandfds(&c, chancount, &fax->fd, 1, &exception, &ofd, &ms);
1797 if (ready_chan) {
1798 if (!(frame = ast_read(chan))) {
1799 /* the channel is probably gone, so lets stop polling on it and let the
1800 * FAX session complete before we exit the application. if needed,
1801 * send the FAX stack silence so the modems can finish their session without
1802 * any problems */
1803 ast_debug(1, "Channel '%s' did not return a frame; probably hung up.\n", ast_channel_name(chan));
1804 GENERIC_FAX_EXEC_SET_VARS(fax, chan, "HANGUP", "remote channel hungup");
1805 c = NULL;
1806 chancount = 0;
1807 remaining_time = ast_remaining_ms(start, timeout);
1808 fax->tech->cancel_session(fax);
1809 if (fax->tech->generate_silence) {
1810 fax->tech->generate_silence(fax);
1811 }
1812 continue;
1813 }
1814
1815 if ((frame->frametype == AST_FRAME_CONTROL) &&
1817 (frame->datalen == sizeof(t38_parameters))) {
1818 unsigned int was_t38 = t38negotiated;
1819 struct ast_control_t38_parameters *parameters = frame->data.ptr;
1820
1821 switch (parameters->request_response) {
1823 /* the other end has requested a switch to T.38, so reply that we are willing, if we can
1824 * do T.38 as well
1825 */
1826 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
1827 if (details->caps & AST_FAX_TECH_T38) {
1828 details->is_t38_negotiated = 1;
1829 t38_parameters.request_response = AST_T38_NEGOTIATED;
1830 } else {
1831 t38_parameters.request_response = AST_T38_REFUSED;
1832 }
1833 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
1834 break;
1835 case AST_T38_NEGOTIATED:
1836 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
1837 t38negotiated = 1;
1838 details->is_t38_negotiated = 1;
1839 break;
1840 default:
1841 break;
1842 }
1843 if (t38negotiated && !was_t38) {
1844 if (fax->tech->switch_to_t38(fax)) {
1845 GENERIC_FAX_EXEC_ERROR(fax, chan, "UNKNOWN", "T.38 switch failed");
1846 break;
1847 }
1848 details->caps &= ~AST_FAX_TECH_AUDIO;
1849 expected_frametype = AST_FRAME_MODEM;
1850 expected_framesubclass.integer = AST_MODEM_T38;
1851 if (fax->smoother) {
1853 fax->smoother = NULL;
1854 }
1855
1856 report_fax_status(chan, details, "T.38 Negotiated");
1857
1858 ast_verb(3, "Channel '%s' switched to T.38 FAX session '%u'.\n", ast_channel_name(chan), fax->id);
1859 }
1860 } else if ((frame->frametype == expected_frametype) && (expected_framesubclass.integer == frame->subclass.integer) &&
1861 ((!frame->subclass.format && !expected_framesubclass.format) ||
1862 (frame->subclass.format && expected_framesubclass.format &&
1863 (ast_format_cmp(frame->subclass.format, expected_framesubclass.format) != AST_FORMAT_CMP_NOT_EQUAL)))) {
1864 struct ast_frame *f;
1865
1866 if (fax->smoother) {
1867 /* push the frame into a smoother */
1868 if (ast_smoother_feed(fax->smoother, frame) < 0) {
1869 GENERIC_FAX_EXEC_ERROR(fax, chan, "UNKNOWN", "Failed to feed the smoother");
1870 }
1871 while ((f = ast_smoother_read(fax->smoother)) && (f->data.ptr)) {
1872 if (fax->debug_info) {
1874 }
1875 /* write the frame to the FAX stack */
1876 fax->tech->write(fax, f);
1877 fax->frames_received++;
1878 if (f != frame) {
1879 ast_frfree(f);
1880 }
1881 }
1882 } else {
1883 /* write the frame to the FAX stack */
1884 fax->tech->write(fax, frame);
1885 fax->frames_received++;
1886 }
1887 start = ast_tvnow();
1888 }
1889 ast_frfree(frame);
1890 } else if (ofd == fax->fd) {
1891 /* read a frame from the FAX stack and send it out the channel.
1892 * the FAX stack will return a NULL if the FAX session has already completed */
1893 if (!(frame = fax->tech->read(fax))) {
1894 break;
1895 }
1896
1897 if (fax->debug_info && (frame->frametype == AST_FRAME_VOICE)) {
1898 debug_check_frame_for_silence(fax, 0, frame);
1899 }
1900
1901 ast_write(chan, frame);
1902 fax->frames_sent++;
1903 ast_frfree(frame);
1904 start = ast_tvnow();
1905 } else {
1906 if (ms && (ofd < 0)) {
1907 if ((errno == 0) || (errno == EINTR)) {
1908 remaining_time = ast_remaining_ms(start, timeout);
1909 if (remaining_time <= 0)
1910 GENERIC_FAX_EXEC_ERROR(fax, chan, "TIMEOUT", "fax session timed-out");
1911 continue;
1912 } else {
1913 ast_log(LOG_WARNING, "something bad happened while channel '%s' was polling.\n", ast_channel_name(chan));
1914 GENERIC_FAX_EXEC_ERROR(fax, chan, "UNKNOWN", "error polling data");
1915 break;
1916 }
1917 } else {
1918 /* nothing happened */
1919 remaining_time = ast_remaining_ms(start, timeout);
1920 if (remaining_time <= 0) {
1921 GENERIC_FAX_EXEC_ERROR(fax, chan, "TIMEOUT", "fax session timed-out");
1922 break;
1923 }
1924 }
1925 }
1926 }
1927 ast_debug(3, "channel '%s' - event loop stopped { timeout: %d, remaining_time: %d }\n", ast_channel_name(chan), timeout, remaining_time);
1928
1929 set_channel_variables(chan, details);
1930
1931 ast_atomic_fetchadd_int(&faxregistry.fax_complete, 1);
1932 if (!strcasecmp(details->result, "FAILED")) {
1933 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1934 }
1935
1936 if (fax) {
1937 ao2_unlink(faxregistry.container, fax);
1938 ao2_ref(fax, -1);
1939 }
1940
1941 /* if the channel is still alive, and we changed its read/write formats,
1942 * restore them now
1943 */
1944 if (chancount) {
1945 if (orig_read_format) {
1946 ast_set_read_format(chan, orig_read_format);
1947 }
1948 if (orig_write_format) {
1949 ast_set_write_format(chan, orig_write_format);
1950 }
1951 }
1952
1953 /* return the chancount so the calling function can determine if the channel hungup during this FAX session or not */
1954 return chancount;
1955}
#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:96
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:2958
@ 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:678
#define GENERIC_FAX_EXEC_ERROR(fax, chan, errorstr, reason)
Definition res_fax.c:1586
#define GENERIC_FAX_EXEC_SET_VARS(fax, chan, errorstr, reason)
Definition res_fax.c:1570
#define RES_FAX_TIMEOUT
Definition res_fax.c:593
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
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 4498 of file res_fax.c.

4499{
4503}
#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:649
static struct fax_options general_options
Definition res_fax.c:638

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

4890{
4891 int res;
4892
4893 /* initialize the registry */
4894 faxregistry.active_sessions = 0;
4895 faxregistry.reserved_sessions = 0;
4898 if (!faxregistry.container) {
4900 }
4901
4902 if (set_config(0) < 0) {
4903 ast_log(LOG_ERROR, "failed to load configuration file '%s'\n", config);
4904 ao2_ref(faxregistry.container, -1);
4906 }
4907
4908 /* register CLI operations and applications */
4910 ast_log(LOG_WARNING, "failed to register '%s'.\n", app_sendfax);
4911 ao2_ref(faxregistry.container, -1);
4913 }
4915 ast_log(LOG_WARNING, "failed to register '%s'.\n", app_receivefax);
4917 ao2_ref(faxregistry.container, -1);
4919 }
4920
4922 ast_log(LOG_WARNING, "failed to register 'FAXSessions' AMI command.\n");
4925 ao2_ref(faxregistry.container, -1);
4927 }
4928
4930 ast_log(LOG_WARNING, "failed to register 'FAXSession' AMI command.\n");
4931 ast_manager_unregister("FAXSession");
4934 ao2_ref(faxregistry.container, -1);
4936 }
4937
4939 ast_log(LOG_WARNING, "failed to register 'FAXStats' AMI command.\n");
4940 ast_manager_unregister("FAXSession");
4941 ast_manager_unregister("FAXSessions");
4944 ao2_ref(faxregistry.container, -1);
4946 }
4947
4951
4952 return res;
4953}
@ 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:7698
int ast_logger_register_level(const char *name)
Register a new logger level.
Definition logger.c:2821
#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:1562
static int session_cmp_cb(void *obj, void *arg, int flags)
compare callback for ao2
Definition res_fax.c:4036
static int session_hash_cb(const void *obj, const int flags)
hash callback for ao2
Definition res_fax.c:4028
static const char app_receivefax[]
Definition res_fax.c:529
static struct ast_custom_function acf_faxopt
FAXOPT dialplan function.
Definition res_fax.c:4843
static const char * config
Definition res_fax.c:654
static int sendfax_exec(struct ast_channel *chan, const char *data)
initiate a send FAX session
Definition res_fax.c:2691
#define FAX_MAXBUCKETS
maximum buckets for res_fax ao2 containers
Definition res_fax.c:591
static int receivefax_exec(struct ast_channel *chan, const char *data)
initiate a receive FAX session
Definition res_fax.c:2183
static int set_config(int reload)
configure res_fax
Definition res_fax.c:4523
static const char app_sendfax[]
Definition res_fax.c:530
static int manager_fax_session(struct mansession *s, const struct message *m)
Definition res_fax.c:4244
static int manager_fax_stats(struct mansession *s, const struct message *m)
Definition res_fax.c:4314
static struct ast_cli_entry fax_cli[]
Definition res_fax.c:4481
static int manager_fax_sessions(struct mansession *s, const struct message *m)
Definition res_fax.c:4450
#define ARRAY_LEN(a)
Definition utils.h:703

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

4245{
4246 const char *action_id = astman_get_header(m, "ActionID");
4247 const char *session_number = astman_get_header(m, "SessionNumber");
4248 char id_text[256] = "";
4249 struct ast_fax_session *session;
4251
4252 if (sscanf(session_number, "%30u", &find_session.id) != 1) {
4253 astman_send_error(s, m, "Invalid session ID");
4254 return 0;
4255 }
4256
4258 if (!session) {
4259 astman_send_error(s, m, "Session not found");
4260 return 0;
4261 }
4262
4263 if (!session->tech->manager_fax_session) {
4264 astman_send_error(s, m, "Fax technology doesn't provide a handler for FAXSession");
4265 ao2_ref(session, -1);
4266 return 0;
4267 }
4268
4269 if (!ast_strlen_zero(action_id)) {
4270 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", action_id);
4271 }
4272
4273 astman_send_ack(s, m, "FAXSession event will follow");
4274
4275 session->tech->manager_fax_session(s, id_text, session);
4276 ao2_ref(session, -1);
4277
4278 return 0;
4279}
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition manager.c:1982
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition manager.c:2014
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition manager.c:1643
static struct mansession_session * find_session(uint32_t ident, int incinuse)
Definition manager.c:7927

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

4451{
4452 const char *action_id = astman_get_header(m, "ActionID");
4453 char id_text[256];
4454 struct ast_fax_session *session;
4455 struct ao2_iterator iter;
4456 int session_count = 0;
4457
4458 id_text[0] = '\0';
4459 if (!ast_strlen_zero(action_id)) {
4460 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", action_id);
4461 }
4462
4463 astman_send_listack(s, m, "FAXSessionsEntry event list will follow", "Start");
4464
4465 iter = ao2_iterator_init(faxregistry.container, 0);
4466 while ((session = ao2_iterator_next(&iter))) {
4467 if (!manager_fax_sessions_entry(s, session, id_text)) {
4468 session_count++;
4469 }
4470 ao2_ref(session, -1);
4471 }
4472 ao2_iterator_destroy(&iter);
4473
4474 astman_send_list_complete_start(s, m, "FAXSessionsComplete", session_count);
4475 astman_append(s, "Total: %d\r\n", session_count);
4477
4478 return 0;
4479}
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:2024
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:2060
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition manager.c:2068
void astman_append(struct mansession *s, const char *fmt,...)
Definition manager.c:1903
static int manager_fax_sessions_entry(struct mansession *s, struct ast_fax_session *session, const char *id_text)
Definition res_fax.c:4418

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

4420{
4421 char *filenames;
4422
4424 filenames = generate_filenames_string(session->details, "", ",");
4425
4426 if (!filenames) {
4427 ast_log(LOG_ERROR, "Error generating Files string");
4429 return -1;
4430 }
4431
4432 astman_append(s, "Event: FAXSessionsEntry\r\n"
4433 "%s" /* ActionID if present */
4434 "Channel: %s\r\n" /* Channel name */
4435 "Technology: %s\r\n" /* Fax session technology */
4436 "SessionNumber: %u\r\n" /* Session ID */
4437 "SessionType: %s\r\n" /* G711 or T38 */
4438 "Operation: %s\r\n"
4439 "State: %s\r\n"
4440 "Files: %s\r\n"
4441 "\r\n",
4442 id_text, session->channame, session->tech->type, session->id,
4444 ast_fax_state_to_str(session->state), S_OR(filenames, ""));
4445 ast_free(filenames);
4447 return 0;
4448}

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

4315{
4316 const char *action_id = astman_get_header(m, "ActionID");
4317
4318 char id_text[256] = "";
4319
4320 astman_send_ack(s, m, "FAXStats event will follow");
4321
4322 if (!ast_strlen_zero(action_id)) {
4323 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", action_id);
4324 }
4325
4326 astman_append(s, "Event: FAXStats\r\n"
4327 "%s"
4328 "CurrentSessions: %d\r\n"
4329 "ReservedSessions: %d\r\n"
4330 "TransmitAttempts: %d\r\n"
4331 "ReceiveAttempts: %d\r\n"
4332 "CompletedFAXes: %d\r\n"
4333 "FailedFAXes: %d\r\n"
4334 "\r\n",
4335 id_text,
4336 faxregistry.active_sessions, faxregistry.reserved_sessions,
4337 faxregistry.fax_tx_attempts, faxregistry.fax_rx_attempts,
4338 faxregistry.fax_complete, faxregistry.fax_failures);
4339
4340 return 0;
4341}

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

2184{
2185 char *parse, modems[128] = "";
2186 int channel_alive;
2188 RAII_VAR(struct ast_fax_session_details *, details, NULL, ao2_cleanup);
2189 struct ast_fax_tech_token *token = NULL;
2190 struct ast_fax_document *doc;
2194 );
2195 struct ast_flags opts = { 0, };
2196 enum ast_t38_state t38state;
2197
2198 /* initialize output channel variables */
2199 pbx_builtin_setvar_helper(chan, "FAXSTATUS", "FAILED");
2200 pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", NULL);
2201 pbx_builtin_setvar_helper(chan, "FAXPAGES", "0");
2202 pbx_builtin_setvar_helper(chan, "FAXBITRATE", NULL);
2203 pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", NULL);
2204 pbx_builtin_setvar_helper(chan, "FAXMODE", NULL);
2205
2206 /* Get a FAX session details structure from the channel's FAX datastore and create one if
2207 * it does not already exist. */
2208 if (!(details = find_or_create_details(chan))) {
2209 pbx_builtin_setvar_helper(chan, "FAXERROR", "MEMORY_ERROR");
2210 pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "error allocating memory");
2211 ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
2212 return -1;
2213 }
2214
2215 ast_string_field_set(details, result, "FAILED");
2216 ast_string_field_set(details, resultstr, "error starting fax session");
2217 ast_string_field_set(details, error, "INIT_ERROR");
2218 set_channel_variables(chan, details);
2219
2220 if (details->gateway_id > 0) {
2221 ast_string_field_set(details, resultstr, "can't receive a fax on a channel with a T.38 gateway");
2222 set_channel_variables(chan, details);
2223 ast_log(LOG_ERROR, "executing ReceiveFAX on a channel with a T.38 Gateway is not supported\n");
2224 return -1;
2225 }
2226
2227 if (details->maxrate < details->minrate) {
2228 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2229 ast_string_field_set(details, resultstr, "maxrate is less than minrate");
2230 set_channel_variables(chan, details);
2231 ast_log(LOG_ERROR, "maxrate %u is less than minrate %u\n", details->maxrate, details->minrate);
2232 return -1;
2233 }
2234
2235 if (check_modem_rate(details->modems, details->minrate)) {
2236 ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
2237 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %u\n", modems, details->minrate);
2238 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2239 ast_string_field_set(details, resultstr, "incompatible 'modems' and 'minrate' settings");
2240 set_channel_variables(chan, details);
2241 return -1;
2242 }
2243
2244 if (check_modem_rate(details->modems, details->maxrate)) {
2245 ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
2246 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %u\n", modems, details->maxrate);
2247 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2248 ast_string_field_set(details, resultstr, "incompatible 'modems' and 'maxrate' settings");
2249 set_channel_variables(chan, details);
2250 return -1;
2251 }
2252
2253 if (ast_strlen_zero(data)) {
2254 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2255 ast_string_field_set(details, resultstr, "invalid arguments");
2256 set_channel_variables(chan, details);
2257 ast_log(LOG_WARNING, "%s requires an argument (filename[,options])\n", app_receivefax);
2258 return -1;
2259 }
2260 parse = ast_strdupa(data);
2262
2263 if (!ast_strlen_zero(args.options) &&
2264 ast_app_parse_options(fax_exec_options, &opts, NULL, args.options)) {
2265 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2266 ast_string_field_set(details, resultstr, "invalid arguments");
2267 set_channel_variables(chan, details);
2268 return -1;
2269 }
2270 if (ast_strlen_zero(args.filename)) {
2271 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2272 ast_string_field_set(details, resultstr, "invalid arguments");
2273 set_channel_variables(chan, details);
2274 ast_log(LOG_WARNING, "%s requires an argument (filename[,options])\n", app_receivefax);
2275 return -1;
2276 }
2277
2278 /* check for unsupported FAX application options */
2280 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2281 ast_string_field_set(details, resultstr, "invalid arguments");
2282 set_channel_variables(chan, details);
2283 ast_log(LOG_WARNING, "%s does not support polling\n", app_receivefax);
2284 return -1;
2285 }
2286
2287 ast_atomic_fetchadd_int(&faxregistry.fax_rx_attempts, 1);
2288
2289 pbx_builtin_setvar_helper(chan, "FAXERROR", "Channel Problems");
2290 pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "Error before FAX transmission started.");
2291
2292 if (!(doc = ast_calloc(1, sizeof(*doc) + strlen(args.filename) + 1))) {
2293 ast_string_field_set(details, error, "MEMORY_ERROR");
2294 ast_string_field_set(details, resultstr, "error allocating memory");
2295 set_channel_variables(chan, details);
2296 ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
2297 return -1;
2298 }
2299
2300 strcpy(doc->filename, args.filename);
2301 AST_LIST_INSERT_TAIL(&details->documents, doc, next);
2302
2303 ast_verb(3, "Channel '%s' receiving FAX '%s'\n", ast_channel_name(chan), args.filename);
2304
2305 details->caps = AST_FAX_TECH_RECEIVE;
2306 details->option.send_ced = AST_FAX_OPTFLAG_TRUE;
2307
2308 /* check for debug */
2309 if (ast_test_flag(&opts, OPT_DEBUG) || global_fax_debug) {
2310 details->option.debug = AST_FAX_OPTFLAG_TRUE;
2311 }
2312
2313 /* check for request for status events */
2314 if (ast_test_flag(&opts, OPT_STATUS)) {
2315 details->option.statusevents = AST_FAX_OPTFLAG_TRUE;
2316 }
2317
2318 t38state = ast_channel_get_t38_state(chan);
2319 if ((t38state == T38_STATE_UNAVAILABLE) || (t38state == T38_STATE_REJECTED) ||
2320 ast_test_flag(&opts, OPT_ALLOWAUDIO) ||
2322 details->option.allow_audio = AST_FAX_OPTFLAG_TRUE;
2323 }
2324
2325 if (!(s = fax_session_reserve(details, &token))) {
2326 ast_string_field_set(details, resultstr, "error reserving fax session");
2327 set_channel_variables(chan, details);
2328 ast_log(LOG_ERROR, "Unable to reserve FAX session.\n");
2329 return -1;
2330 }
2331
2332 /* make sure the channel is up */
2333 if (ast_channel_state(chan) != AST_STATE_UP) {
2334 if (ast_answer(chan)) {
2335 ast_string_field_set(details, resultstr, "error answering channel");
2336 set_channel_variables(chan, details);
2337 ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", ast_channel_name(chan));
2338 fax_session_release(s, token);
2339 return -1;
2340 }
2341 }
2342
2343 if (!ast_test_flag(&opts, OPT_FORCE_AUDIO)) {
2344 if (set_fax_t38_caps(chan, details)) {
2345 ast_string_field_set(details, error, "T38_NEG_ERROR");
2346 ast_string_field_set(details, resultstr, "error negotiating T.38");
2347 set_channel_variables(chan, details);
2348 fax_session_release(s, token);
2349 return -1;
2350 }
2351 } else {
2352 details->caps |= AST_FAX_TECH_AUDIO;
2353 }
2354
2355 if (!ast_test_flag(&opts, OPT_FORCE_AUDIO) && (details->caps & AST_FAX_TECH_T38)) {
2356 if (receivefax_t38_init(chan, details)) {
2357 ast_string_field_set(details, error, "T38_NEG_ERROR");
2358 ast_string_field_set(details, resultstr, "error negotiating T.38");
2359 set_channel_variables(chan, details);
2360 fax_session_release(s, token);
2361 ast_log(LOG_ERROR, "error initializing channel '%s' in T.38 mode\n", ast_channel_name(chan));
2362 return -1;
2363 }
2364 }
2365
2366 if ((channel_alive = generic_fax_exec(chan, details, s, token)) < 0) {
2367 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
2368 }
2369
2371 if (disable_t38(chan)) {
2372 ast_debug(1, "error disabling T.38 mode on %s\n", ast_channel_name(chan));
2373 }
2374 }
2375
2376 if (report_receive_fax_status(chan, args.filename)) {
2377 ast_log(AST_LOG_ERROR, "Error publishing ReceiveFAX status message\n");
2378 }
2379
2380 /* If the channel hungup return -1; otherwise, return 0 to continue in the dialplan */
2381 return (!channel_alive) ? -1 : 0;
2382}
#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:2776
ast_channel_state
ast_channel states
@ AST_STATE_UP
#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.
static int receivefax_t38_init(struct ast_channel *chan, struct ast_fax_session_details *details)
Definition res_fax.c:1957
static const struct ast_app_option fax_exec_options[128]
Definition res_fax.c:676
static int check_modem_rate(enum ast_fax_modems modems, unsigned int rate)
Definition res_fax.c:1039
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:1691
static int set_fax_t38_caps(struct ast_channel *chan, struct ast_fax_session_details *details)
Definition res_fax.c:1592
static int disable_t38(struct ast_channel *chan)
Definition res_fax.c:1628
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:2119
static struct @519 args
Structure used to handle boolean flags.
Definition utils.h:217

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

1958{
1959 int timeout_ms;
1960 struct ast_frame *frame = NULL;
1961 struct ast_control_t38_parameters t38_parameters;
1962 struct timeval start;
1963 int ms;
1964
1965 /* don't send any audio if we've already received a T.38 reinvite */
1967 /* generate 3 seconds of CED */
1968 if (ast_playtones_start(chan, 1024, "!2100/3000", 1)) {
1969 ast_log(LOG_ERROR, "error generating CED tone on %s\n", ast_channel_name(chan));
1970 return -1;
1971 }
1972
1973 timeout_ms = 3000;
1974 start = ast_tvnow();
1975 while ((ms = ast_remaining_ms(start, timeout_ms))) {
1976 ms = ast_waitfor(chan, ms);
1977
1978 if (ms < 0) {
1979 ast_log(LOG_ERROR, "error while generating CED tone on %s\n", ast_channel_name(chan));
1980 ast_playtones_stop(chan);
1981 return -1;
1982 }
1983
1984 if (ms == 0) { /* all done, nothing happened */
1985 break;
1986 }
1987
1988 if (!(frame = ast_read(chan))) {
1989 ast_log(LOG_ERROR, "error reading frame while generating CED tone on %s\n", ast_channel_name(chan));
1990 ast_playtones_stop(chan);
1991 return -1;
1992 }
1993
1994 if ((frame->frametype == AST_FRAME_CONTROL) &&
1996 (frame->datalen == sizeof(t38_parameters))) {
1997 struct ast_control_t38_parameters *parameters = frame->data.ptr;
1998
1999 switch (parameters->request_response) {
2001 /* the other end has requested a switch to T.38, so reply that we are willing, if we can
2002 * do T.38 as well
2003 */
2004 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
2005 t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
2006 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
2007 ast_playtones_stop(chan);
2008 break;
2009 case AST_T38_NEGOTIATED:
2010 ast_debug(1, "Negotiated T.38 for receive on %s\n", ast_channel_name(chan));
2011 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
2012 details->caps &= ~AST_FAX_TECH_AUDIO;
2013 report_fax_status(chan, details, "T.38 Negotiated");
2014 break;
2015 default:
2016 break;
2017 }
2018 }
2019 ast_frfree(frame);
2020 }
2021
2022 ast_playtones_stop(chan);
2023 }
2024
2025 /* if T.38 was negotiated, we are done initializing */
2027 return 0;
2028 }
2029
2030 /* request T.38 */
2031 ast_debug(1, "Negotiating T.38 for receive on %s\n", ast_channel_name(chan));
2032
2033 /* wait for negotiation to complete */
2034 timeout_ms = details->t38timeout;
2035
2036 /* set parameters based on the session's parameters */
2037 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
2038 t38_parameters.request_response = AST_T38_REQUEST_NEGOTIATE;
2039 if ((ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0)) {
2040 return -1;
2041 }
2042
2043 start = ast_tvnow();
2044 while ((ms = ast_remaining_ms(start, timeout_ms))) {
2045 int break_loop = 0;
2046
2047 ms = ast_waitfor(chan, ms);
2048 if (ms < 0) {
2049 ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", ast_channel_name(chan));
2050 return -1;
2051 }
2052 if (ms == 0) { /* all done, nothing happened */
2053 ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 negotiation.\n", ast_channel_name(chan));
2054 details->caps &= ~AST_FAX_TECH_T38;
2055 break;
2056 }
2057
2058 if (!(frame = ast_read(chan))) {
2059 ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", ast_channel_name(chan));
2060 return -1;
2061 }
2062
2063 if ((frame->frametype == AST_FRAME_CONTROL) &&
2065 (frame->datalen == sizeof(t38_parameters))) {
2066 struct ast_control_t38_parameters *parameters = frame->data.ptr;
2067
2068 switch (parameters->request_response) {
2070 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
2071 t38_parameters.request_response = AST_T38_NEGOTIATED;
2072 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
2073 break;
2074 case AST_T38_NEGOTIATED:
2075 ast_debug(1, "Negotiated T.38 for receive on %s\n", ast_channel_name(chan));
2076 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
2077 details->caps &= ~AST_FAX_TECH_AUDIO;
2078 report_fax_status(chan, details, "T.38 Negotiated");
2079 break_loop = 1;
2080 break;
2081 case AST_T38_REFUSED:
2082 ast_log(LOG_WARNING, "channel '%s' refused to negotiate T.38\n", ast_channel_name(chan));
2083 details->caps &= ~AST_FAX_TECH_T38;
2084 break_loop = 1;
2085 break;
2086 default:
2087 ast_log(LOG_ERROR, "channel '%s' failed to negotiate T.38\n", ast_channel_name(chan));
2088 details->caps &= ~AST_FAX_TECH_T38;
2089 break_loop = 1;
2090 break;
2091 }
2092 }
2093 ast_frfree(frame);
2094 if (break_loop) {
2095 break;
2096 }
2097 }
2098
2099 /* if T.38 was negotiated, we are done initializing */
2101 return 0;
2102 }
2103
2104 /* if we made it here, then T.38 failed, check the 'f' flag */
2105 if (details->option.allow_audio != AST_FAX_OPTFLAG_TRUE) {
2106 ast_log(LOG_WARNING, "Audio FAX not allowed on channel '%s' and T.38 negotiation failed; aborting.\n", ast_channel_name(chan));
2107 return -1;
2108 }
2109
2110 /* ok, audio fallback is allowed */
2111 details->caps |= AST_FAX_TECH_AUDIO;
2112
2113 return 0;
2114}
int ast_playtones_start(struct ast_channel *chan, int vol, const char *tonelist, int interruptible)
Start playing a list of tones on a channel.
void ast_playtones_stop(struct ast_channel *chan)
Stop playing tones on a channel.

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

4956{
4957 set_config(1);
4958 return 0;
4959}

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

1509{
1510 RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
1512 struct ast_json *json_filenames = NULL;
1513
1514 if (!details->option.statusevents) {
1515 return 0;
1516 }
1517
1518 json_filenames = generate_filenames_json(details);
1519 if (!json_filenames) {
1520 return -1;
1521 }
1522
1523 json_object = ast_json_pack("{s: s, s: s, s: s, s: s, s: o}",
1524 "type", "status",
1525 "operation", (details->caps & AST_FAX_TECH_GATEWAY)
1526 ? "gateway"
1527 : (details->caps & AST_FAX_TECH_RECEIVE) ? "receive" : "send",
1528 "status", status,
1529 "local_station_id", AST_JSON_UTF8_VALIDATE(details->localstationid),
1530 "filenames", json_filenames);
1531 if (!json_object) {
1532 return -1;
1533 }
1534
1535 {
1536 SCOPED_CHANNELLOCK(lock, chan);
1537
1539 if (!message) {
1540 return -1;
1541 }
1543 }
1544 return 0;
1545}
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:1431
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
Definition stasis.c:1578

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

2120{
2121 RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
2123 RAII_VAR(struct ast_json *, json_array, ast_json_array_create(), ast_json_unref);
2124 struct ast_json *json_filename = ast_json_string_create(filename);
2125
2126 if (!json_array || !json_filename) {
2127 ast_json_unref(json_filename);
2128 return -1;
2129 }
2130 ast_json_array_append(json_array, json_filename);
2131
2132 {
2133 const char *remote_station_id;
2134 const char *local_station_id;
2135 const char *fax_pages;
2136 const char *fax_resolution;
2137 const char *fax_bitrate;
2138 SCOPED_CHANNELLOCK(lock, chan);
2139
2140 remote_station_id = AST_JSON_UTF8_VALIDATE(pbx_builtin_getvar_helper(chan, "REMOTESTATIONID"));
2141 if (!ast_strlen_zero(remote_station_id)) {
2142 remote_station_id = ast_strdupa(remote_station_id);
2143 }
2144 local_station_id = AST_JSON_UTF8_VALIDATE(pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"));
2145 if (!ast_strlen_zero(local_station_id)) {
2146 local_station_id = ast_strdupa(local_station_id);
2147 }
2148 fax_pages = S_OR(pbx_builtin_getvar_helper(chan, "FAXPAGES"), "");
2149 if (!ast_strlen_zero(fax_pages)) {
2150 fax_pages = ast_strdupa(fax_pages);
2151 }
2152 fax_resolution = S_OR(pbx_builtin_getvar_helper(chan, "FAXRESOLUTION"), "");
2153 if (!ast_strlen_zero(fax_resolution)) {
2154 fax_resolution = ast_strdupa(fax_resolution);
2155 }
2156 fax_bitrate = S_OR(pbx_builtin_getvar_helper(chan, "FAXBITRATE"), "");
2157 if (!ast_strlen_zero(fax_bitrate)) {
2158 fax_bitrate = ast_strdupa(fax_bitrate);
2159 }
2160
2161 json_object = ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: s, s: o}",
2162 "type", "receive",
2163 "remote_station_id", S_OR(remote_station_id, ""),
2164 "local_station_id", S_OR(local_station_id, ""),
2165 "fax_pages", S_OR(fax_pages, ""),
2166 "fax_resolution", S_OR(fax_resolution, ""),
2167 "fax_bitrate", S_OR(fax_bitrate, ""),
2168 "filenames", ast_json_ref(json_array));
2169 if (!json_object) {
2170 return -1;
2171 }
2172
2174 if (!message) {
2175 return -1;
2176 }
2178 }
2179 return 0;
2180}

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

2629{
2630 RAII_VAR(struct ast_json *, json_obj, NULL, ast_json_unref);
2632 struct ast_json *json_filenames;
2633
2634 json_filenames = generate_filenames_json(details);
2635 if (!json_filenames) {
2636 return -1;
2637 }
2638
2639 {
2640 const char *remote_station_id;
2641 const char *local_station_id;
2642 const char *fax_pages;
2643 const char *fax_resolution;
2644 const char *fax_bitrate;
2645 SCOPED_CHANNELLOCK(lock, chan);
2646
2647 remote_station_id = AST_JSON_UTF8_VALIDATE(pbx_builtin_getvar_helper(chan, "REMOTESTATIONID"));
2648 if (!ast_strlen_zero(remote_station_id)) {
2649 remote_station_id = ast_strdupa(remote_station_id);
2650 }
2651 local_station_id = AST_JSON_UTF8_VALIDATE(pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"));
2652 if (!ast_strlen_zero(local_station_id)) {
2653 local_station_id = ast_strdupa(local_station_id);
2654 }
2655 fax_pages = S_OR(pbx_builtin_getvar_helper(chan, "FAXPAGES"), "");
2656 if (!ast_strlen_zero(fax_pages)) {
2657 fax_pages = ast_strdupa(fax_pages);
2658 }
2659 fax_resolution = S_OR(pbx_builtin_getvar_helper(chan, "FAXRESOLUTION"), "");
2660 if (!ast_strlen_zero(fax_resolution)) {
2661 fax_resolution = ast_strdupa(fax_resolution);
2662 }
2663 fax_bitrate = S_OR(pbx_builtin_getvar_helper(chan, "FAXBITRATE"), "");
2664 if (!ast_strlen_zero(fax_bitrate)) {
2665 fax_bitrate = ast_strdupa(fax_bitrate);
2666 }
2667 json_obj = ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: s, s: o}",
2668 "type", "send",
2669 "remote_station_id", S_OR(remote_station_id, ""),
2670 "local_station_id", S_OR(local_station_id, ""),
2671 "fax_pages", S_OR(fax_pages, ""),
2672 "fax_resolution", S_OR(fax_resolution, ""),
2673 "fax_bitrate", S_OR(fax_bitrate, ""),
2674 "filenames", json_filenames);
2675 if (!json_obj) {
2676 return -1;
2677 }
2678
2680 if (!message) {
2681 return -1;
2682 }
2684 }
2685 return 0;
2686}

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

2692{
2693 char *parse, *filenames, *c, modems[128] = "";
2694 int channel_alive, file_count;
2695 RAII_VAR(struct ast_fax_session_details *, details, NULL, ao2_cleanup);
2697 struct ast_fax_tech_token *token = NULL;
2698 struct ast_fax_document *doc;
2700 AST_APP_ARG(filenames);
2702 );
2703 struct ast_flags opts = { 0, };
2704 enum ast_t38_state t38state;
2705
2706 /* initialize output channel variables */
2707 pbx_builtin_setvar_helper(chan, "FAXSTATUS", "FAILED");
2708 pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", NULL);
2709 pbx_builtin_setvar_helper(chan, "FAXPAGES", "0");
2710 pbx_builtin_setvar_helper(chan, "FAXBITRATE", NULL);
2711 pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", NULL);
2712 pbx_builtin_setvar_helper(chan, "FAXMODE", NULL);
2713
2714 /* Get a requirement structure and set it. This structure is used
2715 * to tell the FAX technology module about the higher level FAX session */
2716 if (!(details = find_or_create_details(chan))) {
2717 pbx_builtin_setvar_helper(chan, "FAXERROR", "MEMORY_ERROR");
2718 pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "error allocating memory");
2719 ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
2720 return -1;
2721 }
2722
2723 ast_string_field_set(details, result, "FAILED");
2724 ast_string_field_set(details, resultstr, "error starting fax session");
2725 ast_string_field_set(details, error, "INIT_ERROR");
2726 set_channel_variables(chan, details);
2727
2728 if (details->gateway_id > 0) {
2729 ast_string_field_set(details, resultstr, "can't send a fax on a channel with a T.38 gateway");
2730 set_channel_variables(chan, details);
2731 ast_log(LOG_ERROR, "executing SendFAX on a channel with a T.38 Gateway is not supported\n");
2732 return -1;
2733 }
2734
2735 if (details->maxrate < details->minrate) {
2736 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2737 ast_string_field_set(details, resultstr, "maxrate is less than minrate");
2738 set_channel_variables(chan, details);
2739 ast_log(LOG_ERROR, "maxrate %u is less than minrate %u\n", details->maxrate, details->minrate);
2740 return -1;
2741 }
2742
2743 if (check_modem_rate(details->modems, details->minrate)) {
2744 ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
2745 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %u\n", modems, details->minrate);
2746 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2747 ast_string_field_set(details, resultstr, "incompatible 'modems' and 'minrate' settings");
2748 set_channel_variables(chan, details);
2749 return -1;
2750 }
2751
2752 if (check_modem_rate(details->modems, details->maxrate)) {
2753 ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
2754 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %u\n", modems, details->maxrate);
2755 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2756 ast_string_field_set(details, resultstr, "incompatible 'modems' and 'maxrate' settings");
2757 set_channel_variables(chan, details);
2758 return -1;
2759 }
2760
2761 if (ast_strlen_zero(data)) {
2762 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2763 ast_string_field_set(details, resultstr, "invalid arguments");
2764 set_channel_variables(chan, details);
2765 ast_log(LOG_WARNING, "%s requires an argument (filename[&filename[&filename]][,options])\n", app_sendfax);
2766 return -1;
2767 }
2768 parse = ast_strdupa(data);
2770
2771
2772 if (!ast_strlen_zero(args.options) &&
2773 ast_app_parse_options(fax_exec_options, &opts, NULL, args.options)) {
2774 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2775 ast_string_field_set(details, resultstr, "invalid arguments");
2776 set_channel_variables(chan, details);
2777 return -1;
2778 }
2779 if (ast_strlen_zero(args.filenames)) {
2780 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2781 ast_string_field_set(details, resultstr, "invalid arguments");
2782 set_channel_variables(chan, details);
2783 ast_log(LOG_WARNING, "%s requires an argument (filename[&filename[&filename]],options])\n", app_sendfax);
2784 return -1;
2785 }
2786
2787 /* check for unsupported FAX application options */
2789 ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2790 ast_string_field_set(details, resultstr, "invalid arguments");
2791 set_channel_variables(chan, details);
2792 ast_log(LOG_WARNING, "%s does not support polling\n", app_sendfax);
2793 return -1;
2794 }
2795
2796 ast_atomic_fetchadd_int(&faxregistry.fax_tx_attempts, 1);
2797
2798 file_count = 0;
2799 filenames = args.filenames;
2800 while ((c = strsep(&filenames, "&"))) {
2801 if (access(c, (F_OK | R_OK)) < 0) {
2802 ast_string_field_set(details, error, "FILE_ERROR");
2803 ast_string_field_set(details, resultstr, "error reading file");
2804 set_channel_variables(chan, details);
2805 ast_log(LOG_ERROR, "access failure. Verify '%s' exists and check permissions.\n", args.filenames);
2806 return -1;
2807 }
2808
2809 if (!(doc = ast_calloc(1, sizeof(*doc) + strlen(c) + 1))) {
2810 ast_string_field_set(details, error, "MEMORY_ERROR");
2811 ast_string_field_set(details, resultstr, "error allocating memory");
2812 set_channel_variables(chan, details);
2813 ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
2814 return -1;
2815 }
2816
2817 strcpy(doc->filename, c);
2818 AST_LIST_INSERT_TAIL(&details->documents, doc, next);
2819 file_count++;
2820 }
2821
2822 ast_verb(3, "Channel '%s' sending FAX:\n", ast_channel_name(chan));
2823 AST_LIST_TRAVERSE(&details->documents, doc, next) {
2824 ast_verb(3, " %s\n", doc->filename);
2825 }
2826
2827 details->caps = AST_FAX_TECH_SEND;
2828
2829 if (file_count > 1) {
2830 details->caps |= AST_FAX_TECH_MULTI_DOC;
2831 }
2832
2833 /* check for debug */
2834 if (ast_test_flag(&opts, OPT_DEBUG) || global_fax_debug) {
2835 details->option.debug = AST_FAX_OPTFLAG_TRUE;
2836 }
2837
2838 /* check for request for status events */
2839 if (ast_test_flag(&opts, OPT_STATUS)) {
2840 details->option.statusevents = AST_FAX_OPTFLAG_TRUE;
2841 }
2842
2843 t38state = ast_channel_get_t38_state(chan);
2844 if ((t38state == T38_STATE_UNAVAILABLE) || (t38state == T38_STATE_REJECTED) ||
2845 ast_test_flag(&opts, OPT_ALLOWAUDIO) ||
2847 details->option.allow_audio = AST_FAX_OPTFLAG_TRUE;
2848 }
2849
2850 if (ast_test_flag(&opts, OPT_REQUEST_T38)) {
2851 details->option.request_t38 = AST_FAX_OPTFLAG_TRUE;
2852 }
2853
2854 if (!(s = fax_session_reserve(details, &token))) {
2855 ast_string_field_set(details, resultstr, "error reserving fax session");
2856 set_channel_variables(chan, details);
2857 ast_log(LOG_ERROR, "Unable to reserve FAX session.\n");
2858 return -1;
2859 }
2860
2861 /* make sure the channel is up */
2862 if (ast_channel_state(chan) != AST_STATE_UP) {
2863 if (ast_answer(chan)) {
2864 ast_string_field_set(details, resultstr, "error answering channel");
2865 set_channel_variables(chan, details);
2866 ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", ast_channel_name(chan));
2867 fax_session_release(s, token);
2868 return -1;
2869 }
2870 }
2871
2872 if (!ast_test_flag(&opts, OPT_FORCE_AUDIO)) {
2873 if (set_fax_t38_caps(chan, details)) {
2874 ast_string_field_set(details, error, "T38_NEG_ERROR");
2875 ast_string_field_set(details, resultstr, "error negotiating T.38");
2876 set_channel_variables(chan, details);
2877 fax_session_release(s, token);
2878 return -1;
2879 }
2880 } else {
2881 details->caps |= AST_FAX_TECH_AUDIO;
2882 }
2883
2884 if (!ast_test_flag(&opts, OPT_FORCE_AUDIO) && (details->caps & AST_FAX_TECH_T38)) {
2885 if (sendfax_t38_init(chan, details)) {
2886 ast_string_field_set(details, error, "T38_NEG_ERROR");
2887 ast_string_field_set(details, resultstr, "error negotiating T.38");
2888 set_channel_variables(chan, details);
2889 fax_session_release(s, token);
2890 ast_log(LOG_ERROR, "error initializing channel '%s' in T.38 mode\n", ast_channel_name(chan));
2891 return -1;
2892 }
2893 } else {
2894 details->option.send_cng = 1;
2895 }
2896
2897 if ((channel_alive = generic_fax_exec(chan, details, s, token)) < 0) {
2898 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
2899 }
2900
2902 if (disable_t38(chan)) {
2903 ast_debug(1, "error disabling T.38 mode on %s\n", ast_channel_name(chan));
2904 }
2905 }
2906
2907 if (!(filenames = generate_filenames_string(details, "FileName: ", "\r\n"))) {
2908 ast_log(LOG_ERROR, "Error generating SendFAX manager event\n");
2909 return (!channel_alive) ? -1 : 0;
2910 }
2911
2912 /* send out the AMI completion event */
2913 if (report_send_fax_status(chan, details)) {
2914 ast_log(AST_LOG_ERROR, "Error publishing SendFAX status message\n");
2915 }
2916
2917 /* If the channel hungup return -1; otherwise, return 0 to continue in the dialplan */
2918 return (!channel_alive) ? -1 : 0;
2919}
char * strsep(char **str, const char *delims)
#define R_OK
#define F_OK
static int sendfax_t38_init(struct ast_channel *chan, struct ast_fax_session_details *details)
Definition res_fax.c:2384
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:2628

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(), F_OK, 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(), R_OK, 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 2384 of file res_fax.c.

2385{
2386 int timeout_ms;
2387 struct ast_frame *frame = NULL;
2388 struct ast_control_t38_parameters t38_parameters;
2389 struct timeval start;
2390 int ms;
2391
2392 /* send CNG tone while listening for the receiver to initiate a switch
2393 * to T.38 mode; if they do, stop sending the CNG tone and proceed with
2394 * the switch.
2395 *
2396 * 10500 is enough time for 3 CNG tones
2397 */
2398 timeout_ms = 10500;
2399
2400 /* don't send any audio if we've already received a T.38 reinvite */
2402 if (ast_playtones_start(chan, 1024, "!1100/500,!0/3000,!1100/500,!0/3000,!1100/500,!0/3000", 1)) {
2403 ast_log(LOG_ERROR, "error generating CNG tone on %s\n", ast_channel_name(chan));
2404 return -1;
2405 }
2406 }
2407
2408 start = ast_tvnow();
2409 while ((ms = ast_remaining_ms(start, timeout_ms))) {
2410 int break_loop = 0;
2411 ms = ast_waitfor(chan, ms);
2412
2413 if (ms < 0) {
2414 ast_log(LOG_ERROR, "error while generating CNG tone on %s\n", ast_channel_name(chan));
2415 ast_playtones_stop(chan);
2416 return -1;
2417 }
2418
2419 if (ms == 0) { /* all done, nothing happened */
2420 break;
2421 }
2422
2423 if (!(frame = ast_read(chan))) {
2424 ast_log(LOG_ERROR, "error reading frame while generating CNG tone on %s\n", ast_channel_name(chan));
2425 ast_playtones_stop(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 /* the other end has requested a switch to T.38, so reply that we are willing, if we can
2437 * do T.38 as well
2438 */
2439 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
2440 t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
2441 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
2442 ast_playtones_stop(chan);
2443 break;
2444 case AST_T38_NEGOTIATED:
2445 ast_debug(1, "Negotiated T.38 for send on %s\n", ast_channel_name(chan));
2446 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
2447 details->caps &= ~AST_FAX_TECH_AUDIO;
2448 report_fax_status(chan, details, "T.38 Negotiated");
2449 break_loop = 1;
2450 break;
2451 default:
2452 break;
2453 }
2454 }
2455 ast_frfree(frame);
2456 if (break_loop) {
2457 break;
2458 }
2459 }
2460
2461 ast_playtones_stop(chan);
2462
2464 return 0;
2465 }
2466
2467 /* T.38 negotiation did not happen, initiate a switch if requested */
2468 if (details->option.request_t38 == AST_FAX_OPTFLAG_TRUE) {
2469 ast_debug(1, "Negotiating T.38 for send on %s\n", ast_channel_name(chan));
2470
2471 /* wait up to five seconds for negotiation to complete */
2472 timeout_ms = 5000;
2473
2474 /* set parameters based on the session's parameters */
2475 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
2476 t38_parameters.request_response = AST_T38_REQUEST_NEGOTIATE;
2477 if ((ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0)) {
2478 return -1;
2479 }
2480
2481 start = ast_tvnow();
2482 while ((ms = ast_remaining_ms(start, timeout_ms))) {
2483 int break_loop = 0;
2484
2485 ms = ast_waitfor(chan, ms);
2486 if (ms < 0) {
2487 ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", ast_channel_name(chan));
2488 return -1;
2489 }
2490 if (ms == 0) { /* all done, nothing happened */
2491 ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 negotiation.\n", ast_channel_name(chan));
2492 details->caps &= ~AST_FAX_TECH_T38;
2493 break;
2494 }
2495
2496 if (!(frame = ast_read(chan))) {
2497 ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", ast_channel_name(chan));
2498 return -1;
2499 }
2500
2501 if ((frame->frametype == AST_FRAME_CONTROL) &&
2503 (frame->datalen == sizeof(t38_parameters))) {
2504 struct ast_control_t38_parameters *parameters = frame->data.ptr;
2505
2506 switch (parameters->request_response) {
2508 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
2509 t38_parameters.request_response = AST_T38_NEGOTIATED;
2510 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
2511 break;
2512 case AST_T38_NEGOTIATED:
2513 ast_debug(1, "Negotiated T.38 for receive on %s\n", ast_channel_name(chan));
2514 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
2515 details->caps &= ~AST_FAX_TECH_AUDIO;
2516 report_fax_status(chan, details, "T.38 Negotiated");
2517 break_loop = 1;
2518 break;
2519 case AST_T38_REFUSED:
2520 ast_log(LOG_WARNING, "channel '%s' refused to negotiate T.38\n", ast_channel_name(chan));
2521 details->caps &= ~AST_FAX_TECH_T38;
2522 break_loop = 1;
2523 break;
2524 default:
2525 ast_log(LOG_ERROR, "channel '%s' failed to negotiate T.38\n", ast_channel_name(chan));
2526 details->caps &= ~AST_FAX_TECH_T38;
2527 break_loop = 1;
2528 break;
2529 }
2530 }
2531 ast_frfree(frame);
2532 if (break_loop) {
2533 break;
2534 }
2535 }
2536
2537 /* if T.38 was negotiated, we are done initializing */
2539 return 0;
2540 }
2541
2542 /* send one more CNG tone to get audio going again for some
2543 * carriers if we are going to fall back to audio mode */
2544 if (details->option.allow_audio == AST_FAX_OPTFLAG_TRUE) {
2545 if (ast_playtones_start(chan, 1024, "!1100/500,!0/3000", 1)) {
2546 ast_log(LOG_ERROR, "error generating second CNG tone on %s\n", ast_channel_name(chan));
2547 return -1;
2548 }
2549
2550 timeout_ms = 3500;
2551 start = ast_tvnow();
2552 while ((ms = ast_remaining_ms(start, timeout_ms))) {
2553 int break_loop = 0;
2554
2555 ms = ast_waitfor(chan, ms);
2556 if (ms < 0) {
2557 ast_log(LOG_ERROR, "error while generating second CNG tone on %s\n", ast_channel_name(chan));
2558 ast_playtones_stop(chan);
2559 return -1;
2560 }
2561 if (ms == 0) { /* all done, nothing happened */
2562 break;
2563 }
2564
2565 if (!(frame = ast_read(chan))) {
2566 ast_log(LOG_ERROR, "error reading frame while generating second CNG tone on %s\n", ast_channel_name(chan));
2567 ast_playtones_stop(chan);
2568 return -1;
2569 }
2570
2571 if ((frame->frametype == AST_FRAME_CONTROL) &&
2573 (frame->datalen == sizeof(t38_parameters))) {
2574 struct ast_control_t38_parameters *parameters = frame->data.ptr;
2575
2576 switch (parameters->request_response) {
2578 /* the other end has requested a switch to T.38, so reply that we are willing, if we can
2579 * do T.38 as well
2580 */
2581 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
2582 t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
2583 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
2584 ast_playtones_stop(chan);
2585 break;
2586 case AST_T38_NEGOTIATED:
2587 ast_debug(1, "Negotiated T.38 for send on %s\n", ast_channel_name(chan));
2588 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
2589 details->caps &= ~AST_FAX_TECH_AUDIO;
2590 report_fax_status(chan, details, "T.38 Negotiated");
2591 break_loop = 1;
2592 break;
2593 default:
2594 break;
2595 }
2596 }
2597 ast_frfree(frame);
2598 if (break_loop) {
2599 break;
2600 }
2601 }
2602
2603 ast_playtones_stop(chan);
2604
2605 /* if T.38 was negotiated, we are done initializing */
2607 return 0;
2608 }
2609 }
2610 }
2611
2612 /* if we made it here, then T.38 failed, check the 'f' flag */
2613 if (details->option.allow_audio == AST_FAX_OPTFLAG_FALSE) {
2614 ast_log(LOG_WARNING, "Audio FAX not allowed on channel '%s' and T.38 negotiation failed; aborting.\n", ast_channel_name(chan));
2615 return -1;
2616 }
2617
2618 /* ok, audio fallback is allowed */
2619 details->caps |= AST_FAX_TECH_AUDIO;
2620
2621 return 0;
2622}

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

4037{
4038 struct ast_fax_session *lhs = obj, *rhs = arg;
4039
4040 return (lhs->id == rhs->id) ? CMP_MATCH | CMP_STOP : 0;
4041}
@ 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 797 of file res_fax.c.

798{
800 struct fax_options options;
801
802 if (!(d = ao2_alloc(sizeof(*d), destroy_session_details))) {
803 return NULL;
804 }
805
806 if (ast_string_field_init(d, 512)) {
807 ao2_ref(d, -1);
808 return NULL;
809 }
810
812
813 AST_LIST_HEAD_INIT_NOLOCK(&d->documents);
814
815 /* These options need to be set to the configured default and may be overridden by
816 * SendFAX, ReceiveFAX, or FAXOPT */
817 d->option.request_t38 = AST_FAX_OPTFLAG_FALSE;
818 d->option.send_cng = AST_FAX_OPTFLAG_FALSE;
819 d->option.send_ced = AST_FAX_OPTFLAG_FALSE;
820 d->option.ecm = options.ecm;
821 d->option.statusevents = options.statusevents;
822 d->modems = options.modems;
823 d->minrate = options.minrate;
824 d->maxrate = options.maxrate;
825 d->t38timeout = options.t38timeout;
826 d->gateway_id = -1;
827 d->faxdetect_id = -1;
828 d->gateway_timeout = 0;
829 d->negotiate_both = 0;
830
831 return d;
832}
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
static void destroy_session_details(void *details)
destroy a FAX session details structure
Definition res_fax.c:785
#define ast_string_field_init(x, size)
Initialize a field pool and fields.

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

4029{
4030 const struct ast_fax_session *s = obj;
4031
4032 return s->id;
4033}

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

1549{
1550 char buf[10];
1551
1552 pbx_builtin_setvar_helper(chan, "FAXSTATUS", S_OR(details->result, NULL));
1553 pbx_builtin_setvar_helper(chan, "FAXERROR", S_OR(details->error, NULL));
1554 pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", S_OR(details->resultstr, NULL));
1555 pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", AST_JSON_UTF8_VALIDATE(details->remotestationid));
1556 pbx_builtin_setvar_helper(chan, "LOCALSTATIONID", AST_JSON_UTF8_VALIDATE(details->localstationid));
1557 pbx_builtin_setvar_helper(chan, "FAXBITRATE", S_OR(details->transfer_rate, NULL));
1558 pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", S_OR(details->resolution, NULL));
1559
1560 if (details->is_t38_negotiated) {
1561 pbx_builtin_setvar_helper(chan, "FAXMODE", "T38");
1562 } else {
1563 pbx_builtin_setvar_helper(chan, "FAXMODE", "audio");
1564 }
1565
1566 snprintf(buf, sizeof(buf), "%u", details->pages_transferred);
1567 pbx_builtin_setvar_helper(chan, "FAXPAGES", buf);
1568}

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

4524{
4525 struct ast_config *cfg;
4526 struct ast_variable *v;
4527 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
4528 char modems[128] = "";
4529 struct fax_options options;
4530 int res = 0;
4531
4533
4534 /* When we're not reloading, we have to be certain to set the general options
4535 * to the defaults in case config loading goes wrong at some point. On a reload,
4536 * the general options need to stay the same as what they were prior to the
4537 * reload rather than being reset to the defaults.
4538 */
4539 if (!reload) {
4541 }
4542
4543 /* read configuration */
4544 if (!(cfg = ast_config_load2(config, "res_fax", config_flags))) {
4545 ast_log(LOG_NOTICE, "Configuration file '%s' not found, %s options.\n",
4546 config, reload ? "not changing" : "using default");
4547 return 0;
4548 }
4549
4550 if (cfg == CONFIG_STATUS_FILEINVALID) {
4551 ast_log(LOG_NOTICE, "Configuration file '%s' is invalid, %s options.\n",
4552 config, reload ? "not changing" : "using default");
4553 return 0;
4554 }
4555
4556 if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
4557 return 0;
4558 }
4559
4560 if (reload) {
4562 }
4563
4564 /* create configuration */
4565 for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
4566 int rate;
4567
4568 if (!strcasecmp(v->name, "minrate")) {
4569 ast_debug(3, "reading minrate '%s' from configuration file\n", v->value);
4570 if ((rate = fax_rate_str_to_int(v->value)) == 0) {
4571 res = -1;
4572 goto end;
4573 }
4574 options.minrate = rate;
4575 } else if (!strcasecmp(v->name, "maxrate")) {
4576 ast_debug(3, "reading maxrate '%s' from configuration file\n", v->value);
4577 if ((rate = fax_rate_str_to_int(v->value)) == 0) {
4578 res = -1;
4579 goto end;
4580 }
4581 options.maxrate = rate;
4582 } else if (!strcasecmp(v->name, "statusevents")) {
4583 ast_debug(3, "reading statusevents '%s' from configuration file\n", v->value);
4584 options.statusevents = ast_true(v->value);
4585 } else if (!strcasecmp(v->name, "ecm")) {
4586 ast_debug(3, "reading ecm '%s' from configuration file\n", v->value);
4587 options.ecm = ast_true(v->value);
4588 } else if ((!strcasecmp(v->name, "modem")) || (!strcasecmp(v->name, "modems"))) {
4589 options.modems = 0;
4590 update_modem_bits(&options.modems, v->value);
4591 } else if (!strcasecmp(v->name, "t38timeout")) {
4592 if (set_t38timeout(v->value, &options.t38timeout)) {
4593 res = -1;
4594 goto end;
4595 }
4596 }
4597 }
4598
4599 if (options.maxrate < options.minrate) {
4600 ast_log(LOG_ERROR, "maxrate %u is less than minrate %u\n", options.maxrate, options.minrate);
4601 res = -1;
4602 goto end;
4603 }
4604
4605 if (check_modem_rate(options.modems, options.minrate)) {
4606 ast_fax_modem_to_str(options.modems, modems, sizeof(modems));
4607 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %u\n", modems, options.minrate);
4608 res = -1;
4609 goto end;
4610 }
4611
4612 if (check_modem_rate(options.modems, options.maxrate)) {
4613 ast_fax_modem_to_str(options.modems, modems, sizeof(modems));
4614 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %u\n", modems, options.maxrate);
4615 res = -1;
4616 goto end;
4617 }
4618
4620
4621end:
4622 ast_config_destroy(cfg);
4623 return res;
4624}
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.
#define CONFIG_STATUS_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition extconf.c:1287
@ CONFIG_FLAG_FILEUNCHANGED
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition extconf.c:1213
static int reload(void)
static void set_general_options(const struct fax_options *options)
Definition res_fax.c:4491
static const struct fax_options default_options
Definition res_fax.c:640
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 1592 of file res_fax.c.

1593{
1594 switch (ast_channel_get_t38_state(chan)) {
1595 case T38_STATE_UNKNOWN:
1596 details->caps |= AST_FAX_TECH_T38;
1597 break;
1598 case T38_STATE_REJECTED:
1600 details->caps |= AST_FAX_TECH_AUDIO;
1601 break;
1603 /* already in T.38 mode? This should not happen. */
1604 case T38_STATE_NEGOTIATING: {
1605 /* the other end already sent us a T.38 reinvite, so we need to prod the channel
1606 * driver into resending their parameters to us if it supports doing so... if
1607 * not, we can't proceed, because we can't create a proper reply without them.
1608 * if it does work, the channel driver will send an AST_CONTROL_T38_PARAMETERS
1609 * with a request of AST_T38_REQUEST_NEGOTIATE, which will be read by the function
1610 * that gets called after this one completes
1611 */
1613 if (ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &parameters, sizeof(parameters)) != AST_T38_REQUEST_PARMS) {
1614 ast_log(LOG_ERROR, "channel '%s' is in an unsupported T.38 negotiation state, cannot continue.\n", ast_channel_name(chan));
1615 return -1;
1616 }
1617 details->caps |= AST_FAX_TECH_T38;
1618 break;
1619 }
1620 default:
1621 ast_log(LOG_ERROR, "channel '%s' is in an unsupported T.38 negotiation state, cannot continue.\n", ast_channel_name(chan));
1622 return -1;
1623 }
1624
1625 return 0;
1626}
@ 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 4491 of file res_fax.c.

4492{
4496}
#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 4505 of file res_fax.c.

4506{
4507 unsigned int timeout;
4508
4509 if (sscanf(value, "%u", &timeout) != 1) {
4510 ast_log(LOG_ERROR, "Unable to get timeout from '%s'\n", value);
4511 return -1;
4512 } else if (timeout) {
4513 *t38timeout = timeout;
4514 } else {
4515 ast_log(LOG_ERROR, "T.38 negotiation timeout must be non-zero\n");
4516 return -1;
4517 }
4518
4519 return 0;
4520}

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

842{
843 dst->version = src->version;
844 dst->max_ifp = src->max_ifp;
845 dst->rate = src->rate;
850}
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 4850 of file res_fax.c.

4851{
4853
4855 ast_log(LOG_WARNING, "failed to unregister function '%s'\n", acf_faxopt.name);
4856 }
4857
4859 ast_log(LOG_WARNING, "failed to unregister '%s'\n", app_sendfax);
4860 }
4861
4863 ast_log(LOG_WARNING, "failed to unregister '%s'\n", app_receivefax);
4864 }
4865
4866 ast_manager_unregister("FAXSessions");
4867 ast_manager_unregister("FAXSession");
4868 ast_manager_unregister("FAXStats");
4869
4870 if (fax_logger_level != -1) {
4872 }
4873
4874 ao2_ref(faxregistry.container, -1);
4875
4876 return 0;
4877}
void ast_cli_unregister_multiple(void)
Definition ael_main.c:408
void ast_logger_unregister_level(const char *name)
Unregister a previously registered logger level.
Definition logger.c:2879
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 913 of file res_fax.c.

914{
915 char *m[5], *tok, *v = (char *) value, *rest;
916 int i = 0, j;
917
918 if (!strchr(v, ',')) {
919 m[i++] = v;
920 m[i] = NULL;
921 } else {
922 tok = strtok_r(v, ", ", &rest);
923 while (tok && i < ARRAY_LEN(m) - 1) {
924 m[i++] = tok;
925 tok = strtok_r(NULL, ", ", &rest);
926 }
927 m[i] = NULL;
928 }
929
930 *bits = 0;
931 for (j = 0; j < i; j++) {
932 if (!strcasecmp(m[j], "v17")) {
933 *bits |= AST_FAX_MODEM_V17;
934 } else if (!strcasecmp(m[j], "v27")) {
935 *bits |= AST_FAX_MODEM_V27TER;
936 } else if (!strcasecmp(m[j], "v29")) {
937 *bits |= AST_FAX_MODEM_V29;
938 } else if (!strcasecmp(m[j], "v34")) {
939 *bits |= AST_FAX_MODEM_V34;
940 } else {
941 ast_log(LOG_WARNING, "ignoring invalid modem setting: '%s', valid options {v17 | v27 | v29 | v34}\n", m[j]);
942 }
943 }
944 return 0;
945}

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 = ASTERISK_GPL_KEY , .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 4968 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:4702
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:4627

FAXOPT dialplan function.

Definition at line 4843 of file res_fax.c.

4843 {
4844 .name = "FAXOPT",
4845 .read = acf_faxopt_read,
4846 .write = acf_faxopt_write,
4847};

Referenced by load_module(), and unload_module().

◆ active_sessions

int active_sessions

The number of active FAX sessions

Definition at line 599 of file res_fax.c.

◆ app_receivefax

const char app_receivefax[] = "ReceiveFAX"
static

Definition at line 529 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 530 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 4968 of file res_fax.c.

◆ config

const char* config = "res_fax.conf"
static

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

640 {
641 .minrate = RES_FAX_MINRATE,
642 .maxrate = RES_FAX_MAXRATE,
643 .statusevents = RES_FAX_STATUSEVENTS,
644 .modems = RES_FAX_MODEM,
646 .t38timeout = RES_FAX_T38TIMEOUT,
647};
#define RES_FAX_MAXRATE
Definition res_fax.c:624
#define RES_FAX_MODEM
Definition res_fax.c:626
#define RES_FAX_MINRATE
Definition res_fax.c:623
#define RES_FAX_STATUSEVENTS
Definition res_fax.c:625
#define RES_FAX_T38TIMEOUT
Definition res_fax.c:627

Referenced by set_config().

◆ fax_cli

struct ast_cli_entry fax_cli[]
static

Definition at line 4481 of file res_fax.c.

4481 {
4482 AST_CLI_DEFINE(cli_fax_show_version, "Show versions of FAX For Asterisk components"),
4483 AST_CLI_DEFINE(cli_fax_set_debug, "Enable/Disable FAX debugging on new FAX sessions"),
4484 AST_CLI_DEFINE(cli_fax_show_capabilities, "Show the capabilities of the registered FAX technology modules"),
4485 AST_CLI_DEFINE(cli_fax_show_settings, "Show the global settings and defaults of both the FAX core and technology modules"),
4486 AST_CLI_DEFINE(cli_fax_show_session, "Show the status of the named FAX sessions"),
4487 AST_CLI_DEFINE(cli_fax_show_sessions, "Show the current FAX sessions"),
4488 AST_CLI_DEFINE(cli_fax_show_stats, "Summarize FAX session history"),
4489};
#define AST_CLI_DEFINE(fn, txt,...)
Definition cli.h:197
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
Definition res_fax.c:4208
static char * cli_fax_show_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
display fax stats
Definition res_fax.c:4282
static char * cli_fax_show_capabilities(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
display registered FAX capabilities
Definition res_fax.c:4139
static char * cli_fax_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
display global defaults and settings
Definition res_fax.c:4169
static char * cli_fax_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
enable FAX debugging
Definition res_fax.c:4104
static char * cli_fax_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition res_fax.c:4072
static char * cli_fax_show_sessions(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
display fax sessions
Definition res_fax.c:4374

Referenced by load_module(), and unload_module().

◆ fax_complete

int fax_complete

Number of successful FAX transmissions

Definition at line 609 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:737
static void destroy_callback(void *data)
Definition res_fax.c:711

Definition at line 720 of file res_fax.c.

720 {
721 .type = "res_fax",
722 .destroy = destroy_callback,
723 .chan_fixup = fixup_callback,
724};

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

◆ fax_logger_level

int fax_logger_level = -1
static

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

◆ fax_tx_attempts

int fax_tx_attempts

Total number of Tx FAX attempts

Definition at line 605 of file res_fax.c.

◆ faxmodules

◆ [struct]

struct { ... } faxregistry

◆ general_options

struct fax_options general_options
static

Definition at line 638 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 656 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 613 of file res_fax.c.

◆ options_lock

ast_rwlock_t options_lock = AST_RWLOCK_INIT_VALUE
static

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

834 {
835 .version = 0,
836 .max_ifp = 400,
837 .rate = AST_T38_RATE_14400,
839};
@ AST_T38_RATE_14400
@ AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF

Referenced by find_or_create_details().

◆ reserved_sessions

int reserved_sessions

The number of reserved FAX sessions

Definition at line 601 of file res_fax.c.