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

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

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

Go to the source code of this file.

Data Structures

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

Macros

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

Enumerations

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

Functions

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

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "Generic FAX Applications" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_APP_DEPEND, }
 
static struct ast_custom_function acf_faxopt
 FAXOPT dialplan function. More...
 
static const char app_receivefax [] = "ReceiveFAX"
 
static const char app_sendfax [] = "SendFAX"
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static const char * config = "res_fax.conf"
 
static const struct fax_options default_options
 
static struct ast_cli_entry fax_cli []
 
static const struct ast_datastore_info fax_datastore
 
static const struct ast_app_option fax_exec_options [128] = { [ 'a' ] = { .flag = OPT_CALLEDMODE }, [ 'c' ] = { .flag = OPT_CALLERMODE }, [ 'd' ] = { .flag = OPT_DEBUG }, [ 'f' ] = { .flag = OPT_ALLOWAUDIO }, [ 'F' ] = { .flag = OPT_FORCE_AUDIO }, [ 's' ] = { .flag = OPT_STATUS }, [ 'z' ] = { .flag = OPT_REQUEST_T38 }, }
 
static int fax_logger_level = -1
 
static struct faxmodules faxmodules = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
 
struct {
   int   active_sessions
 
   struct ao2_container *   container
 
   int   fax_complete
 
   int   fax_failures
 
   int   fax_rx_attempts
 
   int   fax_tx_attempts
 
   int   nextsessionname
 
   int   reserved_sessions
 
faxregistry
 The faxregistry is used to manage information and statistics for all FAX sessions. More...
 
static struct fax_options general_options
 
static int global_fax_debug = 0
 
static ast_rwlock_t options_lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} }
 
static struct ast_control_t38_parameters our_t38_parameters
 

Detailed Description

Generic FAX Resource for FAX technology resource modules.

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

A generic FAX resource module that provides SendFAX and ReceiveFAX applications. This module requires FAX technology modules, like res_fax_spandsp, to register with it so it can use the technology modules to perform the actual FAX transmissions.

Definition in file res_fax.c.

Macro Definition Documentation

◆ FAX_DETECT_MODE_BOTH

#define FAX_DETECT_MODE_BOTH   (FAX_DETECT_MODE_CNG | FAX_DETECT_MODE_T38)

Definition at line 484 of file res_fax.c.

◆ FAX_DETECT_MODE_CNG

#define FAX_DETECT_MODE_CNG   (1 << 0)

FAX Detect flags.

Definition at line 482 of file res_fax.c.

◆ FAX_DETECT_MODE_T38

#define FAX_DETECT_MODE_T38   (1 << 1)

Definition at line 483 of file res_fax.c.

◆ FAX_GATEWAY_TIMEOUT

#define FAX_GATEWAY_TIMEOUT   RES_FAX_TIMEOUT

Definition at line 492 of file res_fax.c.

◆ FAX_MAXBUCKETS

#define FAX_MAXBUCKETS   10

maximum buckets for res_fax ao2 containers

Definition at line 489 of file res_fax.c.

◆ GENERIC_FAX_EXEC_ERROR

#define GENERIC_FAX_EXEC_ERROR (   fax,
  chan,
  errorstr,
  reason 
)
Value:
do { \
ast_log(LOG_ERROR, "channel '%s' FAX session '%u' failure, reason: '%s' (%s)\n", ast_channel_name(chan), fax->id, reason, errorstr); \
GENERIC_FAX_EXEC_ERROR_QUIET(fax, chan, errorstr, reason); \
} while (0)
const char * ast_channel_name(const struct ast_channel *chan)
#define LOG_ERROR

Definition at line 1484 of file res_fax.c.

◆ GENERIC_FAX_EXEC_ERROR_QUIET

#define GENERIC_FAX_EXEC_ERROR_QUIET (   fax,
  chan,
  errorstr,
  reason 
)
Value:
do { \
GENERIC_FAX_EXEC_SET_VARS(fax, chan, errorstr, reason); \
} while (0)

Definition at line 1479 of file res_fax.c.

◆ GENERIC_FAX_EXEC_SET_VARS

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

Definition at line 1468 of file res_fax.c.

◆ RES_FAX_MAXRATE

#define RES_FAX_MAXRATE   14400

Definition at line 522 of file res_fax.c.

◆ RES_FAX_MINRATE

#define RES_FAX_MINRATE   4800

Definition at line 521 of file res_fax.c.

◆ RES_FAX_MODEM

#define RES_FAX_MODEM   (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V27TER | AST_FAX_MODEM_V29)

Definition at line 524 of file res_fax.c.

◆ RES_FAX_STATUSEVENTS

#define RES_FAX_STATUSEVENTS   0

Definition at line 523 of file res_fax.c.

◆ RES_FAX_T38TIMEOUT

#define RES_FAX_T38TIMEOUT   5000

Definition at line 525 of file res_fax.c.

◆ RES_FAX_TIMEOUT

#define RES_FAX_TIMEOUT   10000

Definition at line 491 of file res_fax.c.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
OPT_CALLEDMODE 
OPT_CALLERMODE 
OPT_DEBUG 
OPT_STATUS 
OPT_ALLOWAUDIO 
OPT_REQUEST_T38 
OPT_FORCE_AUDIO 

Definition at line 556 of file res_fax.c.

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

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 4866 of file res_fax.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 4866 of file res_fax.c.

◆ acf_faxopt_read()

static int acf_faxopt_read ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
)
static

FAXOPT read function returns the contents of a FAX option.

Definition at line 4525 of file res_fax.c.

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

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

◆ acf_faxopt_write()

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

FAXOPT write function modifies the contents of a FAX option.

Definition at line 4600 of file res_fax.c.

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

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

◆ ast_fax_caps_to_str()

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

Definition at line 845 of file res_fax.c.

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

References ast_build_string(), AST_FAX_TECH_AUDIO, AST_FAX_TECH_GATEWAY, AST_FAX_TECH_MULTI_DOC, AST_FAX_TECH_RECEIVE, AST_FAX_TECH_SEND, AST_FAX_TECH_T38, AST_FAX_TECH_V21_DETECT, buf, first, and out.

Referenced by fax_session_new(), and fax_session_reserve().

◆ ast_fax_log()

void ast_fax_log ( int  level,
const char *  file,
const int  line,
const char *  function,
const char *  msg 
)

Log message at FAX or recommended level.

The first four parameters can be represented with Asterisk's LOG_* levels. In other words, this function may be called like

ast_fax_log(LOG_DEBUG, msg);

Definition at line 1035 of file res_fax.c.

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

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

Referenced by spandsp_log().

◆ ast_fax_maxrate()

unsigned int ast_fax_maxrate ( void  )

get the maxiumum supported fax rate

Definition at line 795 of file res_fax.c.

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

References get_general_options(), and options.

Referenced by acf_faxopt_write().

◆ ast_fax_minrate()

unsigned int ast_fax_minrate ( void  )

get the minimum supported fax rate

Definition at line 803 of file res_fax.c.

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

References get_general_options(), and options.

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

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

References AST_FAX_MODEM_V17, AST_FAX_MODEM_V27TER, AST_FAX_MODEM_V29, and AST_FAX_MODEM_V34.

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

◆ ast_fax_session_operation_str()

const char * ast_fax_session_operation_str ( struct ast_fax_session s)

get string representation of a FAX session's operation

Definition at line 4253 of file res_fax.c.

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

References AST_FAX_TECH_GATEWAY, AST_FAX_TECH_RECEIVE, AST_FAX_TECH_SEND, AST_FAX_TECH_V21_DETECT, ast_fax_session_details::caps, and ast_fax_session::details.

Referenced by cli_fax_show_sessions(), manager_fax_sessions_entry(), and spandsp_manager_fax_session().

◆ ast_fax_state_to_str()

const char * ast_fax_state_to_str ( enum ast_fax_state  state)

convert a ast_fax_state to a string

convert an ast_fax_state to a string

Definition at line 1012 of file res_fax.c.

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

References AST_FAX_STATE_ACTIVE, AST_FAX_STATE_COMPLETE, AST_FAX_STATE_INACTIVE, AST_FAX_STATE_INITIALIZED, AST_FAX_STATE_OPEN, AST_FAX_STATE_RESERVED, AST_FAX_STATE_UNINITIALIZED, ast_log, and LOG_WARNING.

Referenced by cli_fax_show_sessions(), manager_fax_sessions_entry(), spandsp_fax_cli_show_session(), spandsp_fax_write(), and spandsp_manager_fax_session().

◆ ast_fax_tech_register()

int ast_fax_tech_register ( struct ast_fax_tech tech)

register a FAX technology module

register a fax technology

Definition at line 973 of file res_fax.c.

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

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

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

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

References ast_free, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, fax_module::tech, and ast_fax_tech::type.

Referenced by unload_module().

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 4866 of file res_fax.c.

◆ check_modem_rate()

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

Definition at line 937 of file res_fax.c.

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

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

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

◆ cli_fax_set_debug()

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

enable FAX debugging

Definition at line 4002 of file res_fax.c.

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

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

◆ cli_fax_show_capabilities()

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

display registered FAX capabilities

Definition at line 4037 of file res_fax.c.

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

References a, ast_cli(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, ast_fax_tech::cli_show_capabilities, CLI_SUCCESS, ast_cli_entry::command, ast_fax_tech::description, NULL, fax_module::tech, ast_fax_tech::type, and ast_cli_entry::usage.

◆ cli_fax_show_session()

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

display details of a specified fax session

Definition at line 4106 of file res_fax.c.

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

References a, ao2_find, ao2_ref, ast_cli(), ast_log, ast_fax_session::channame, CLI_GENERATE, CLI_INIT, ast_fax_tech::cli_show_session, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, fax_session_tab_complete(), faxregistry, LOG_ERROR, NULL, OBJ_POINTER, RESULT_SUCCESS, ast_fax_session::tech, tmp(), and ast_cli_entry::usage.

◆ cli_fax_show_sessions()

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

display fax sessions

Definition at line 4272 of file res_fax.c.

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

References a, ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_cli(), ast_fax_session_operation_str(), ast_fax_state_to_str(), ast_free, ast_fax_session::channame, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_fax_session::details, fax_session_type(), faxregistry, generate_filenames_string(), ast_fax_session::id, NULL, S_OR, session_count, ast_fax_session::state, ast_fax_session::tech, ast_fax_tech::type, and ast_cli_entry::usage.

◆ cli_fax_show_settings()

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

display global defaults and settings

Definition at line 4067 of file res_fax.c.

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

References a, ast_cli(), ast_fax_modem_to_str(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, ast_fax_tech::cli_show_settings, CLI_SUCCESS, ast_cli_entry::command, ast_fax_tech::description, get_general_options(), fax_options::modems, NULL, options, fax_module::tech, ast_fax_tech::type, and ast_cli_entry::usage.

◆ cli_fax_show_stats()

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

display fax stats

Definition at line 4180 of file res_fax.c.

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

References a, ast_cli(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, ast_fax_tech::cli_show_stats, CLI_SUCCESS, ast_cli_entry::command, faxregistry, NULL, fax_module::tech, and ast_cli_entry::usage.

◆ cli_fax_show_version()

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

Definition at line 3970 of file res_fax.c.

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

References a, ast_cli(), ast_get_version(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_fax_tech::description, NULL, fax_module::tech, ast_cli_entry::usage, and ast_fax_tech::version.

◆ debug_check_frame_for_silence()

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

Definition at line 576 of file res_fax.c.

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

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

References ao2_ref.

◆ destroy_faxdetect()

static void destroy_faxdetect ( void *  data)
static

destroy a FAX detect structure

Definition at line 3675 of file res_fax.c.

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

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

Referenced by fax_detect_new().

◆ destroy_gateway()

static void destroy_gateway ( void *  data)
static

destroy a FAX gateway session structure

Definition at line 2838 of file res_fax.c.

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

References ao2_cleanup, ao2_ref, ao2_unlink, fax_gateway::chan_read_format, fax_gateway::chan_write_format, destroy_v21_sessions(), fax_session_release(), faxregistry, NULL, fax_gateway::peer_read_format, fax_gateway::peer_write_format, fax_gateway::s, and fax_gateway::token.

Referenced by fax_gateway_new().

◆ destroy_session()

static void destroy_session ( void *  session)
static

destroy a FAX session structure

Definition at line 1095 of file res_fax.c.

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

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

Referenced by fax_session_new(), and fax_session_reserve().

◆ destroy_session_details()

static void destroy_session_details ( void *  details)
static

destroy a FAX session details structure

Definition at line 683 of file res_fax.c.

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

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

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

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

References ao2_ref, ao2_unlink, fax_gateway::chan_v21_session, faxregistry, NULL, and fax_gateway::peer_v21_session.

Referenced by destroy_gateway(), fax_gateway_detect_v21(), and fax_gateway_start().

◆ disable_t38()

static int disable_t38 ( struct ast_channel chan)
static

Definition at line 1526 of file res_fax.c.

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

References ast_channel_name(), AST_CONTROL_T38_PARAMETERS, ast_debug, AST_FRAME_CONTROL, ast_frfree, ast_indicate_data(), ast_log, ast_read(), ast_remaining_ms(), AST_T38_REFUSED, AST_T38_REQUEST_TERMINATE, AST_T38_TERMINATED, ast_tvnow(), ast_waitfor(), ast_frame::data, ast_frame::datalen, ast_frame::frametype, ast_frame_subclass::integer, LOG_ERROR, LOG_WARNING, NULL, ast_frame::ptr, ast_control_t38_parameters::request_response, and ast_frame::subclass.

Referenced by receivefax_exec(), and sendfax_exec().

◆ fax_detect_attach()

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

Attach a faxdetect framehook object to a channel.

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

Definition at line 3888 of file res_fax.c.

3889{
3890 struct fax_detect *faxdetect;
3891 struct ast_fax_session_details *details;
3892 struct ast_framehook_interface fr_hook = {
3894 .event_cb = fax_detect_framehook,
3895 .destroy_cb = fax_detect_framehook_destroy,
3896 };
3897
3898 if (!(details = find_or_create_details(chan))) {
3899 ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
3900 return -1;
3901 }
3902
3903 /* set up the frame hook*/
3904 faxdetect = fax_detect_new(chan, timeout, flags);
3905 if (!faxdetect) {
3906 ao2_ref(details, -1);
3907 return -1;
3908 }
3909
3910 fr_hook.data = faxdetect;
3911 faxdetect->details = details;
3912 ast_channel_lock(chan);
3913 details->faxdetect_id = ast_framehook_attach(chan, &fr_hook);
3914 details->faxdetect_timeout = timeout;
3915 details->faxdetect_flags = flags;
3916 ast_channel_unlock(chan);
3917
3918 if (details->faxdetect_id < 0) {
3919 ao2_ref(faxdetect, -1);
3920 }
3921
3922 return details->faxdetect_id;
3923}
int ast_framehook_attach(struct ast_channel *chan, struct ast_framehook_interface *i)
Attach an framehook onto a channel for frame interception.
Definition: framehook.c:132
#define AST_FRAMEHOOK_INTERFACE_VERSION
Definition: framehook.h:227
static void fax_detect_framehook_destroy(void *data)
Deref the faxdetect data structure when the faxdetect framehook is detached.
Definition: res_fax.c:3726
static struct fax_detect * fax_detect_new(struct ast_channel *chan, int timeout, int flags)
Create a new fax detect object.
Definition: res_fax.c:3693
static struct ast_frame * fax_detect_framehook(struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data)
Fax Detect Framehook.
Definition: res_fax.c:3744

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

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

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

References ao2_cleanup, ao2_ref, ao2_replace, ast_async_goto(), ast_channel_bridge_peer(), ast_channel_caller(), ast_channel_context(), ast_channel_exten(), ast_channel_lock, ast_channel_make_compatible(), ast_channel_name(), ast_channel_readformat(), ast_channel_unlock, AST_CONTROL_T38_PARAMETERS, ast_debug, ast_dsp_process(), ast_exists_extension(), ast_format_alaw, ast_format_cmp(), AST_FORMAT_CMP_EQUAL, ast_format_slin, ast_format_ulaw, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_framehook_detach(), AST_FRAMEHOOK_EVENT_ATTACHED, AST_FRAMEHOOK_EVENT_DETACHED, AST_FRAMEHOOK_EVENT_READ, ast_frfree, ast_log, ast_null_frame, ast_set_read_format(), AST_T38_NEGOTIATED, AST_T38_REQUEST_NEGOTIATE, ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), ast_verb, ast_frame::data, ast_frame::datalen, fax_detect::details, fax_detect::dsp, FAX_DETECT_MODE_T38, ast_fax_session_details::faxdetect_id, ast_fax_session_details::faxdetect_timeout, fax_detect::flags, ast_frame_subclass::format, ast_frame::frametype, ast_frame_subclass::integer, LOG_NOTICE, NULL, fax_detect::orig_format, pbx_builtin_setvar_helper(), ast_frame::ptr, RAII_VAR, ast_control_t38_parameters::request_response, result, S_COR, ast_frame::subclass, and fax_detect::timeout_start.

Referenced by fax_detect_attach().

◆ fax_detect_framehook_destroy()

static void fax_detect_framehook_destroy ( void *  data)
static

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

Parameters
dataframehook data (faxdetect data)

Definition at line 3726 of file res_fax.c.

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

References ao2_ref.

Referenced by fax_detect_attach().

◆ fax_detect_new()

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

Create a new fax detect object.

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

Definition at line 3693 of file res_fax.c.

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

References ao2_alloc, ao2_ref, ast_dsp_new(), ast_dsp_set_faxmode(), ast_dsp_set_features(), ast_tvnow(), destroy_faxdetect(), fax_detect::dsp, DSP_FAXMODE_DETECT_CNG, DSP_FAXMODE_DETECT_SQUELCH, DSP_FEATURE_FAX_DETECT, FAX_DETECT_MODE_CNG, fax_detect::flags, NULL, and fax_detect::timeout_start.

Referenced by fax_detect_attach().

◆ fax_gateway_attach()

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

Attach a gateway framehook object to a channel.

Parameters
chanthe channel to attach to
detailsfax session details
Returns
the framehook id of the attached framehook or -1 on error
Return values
-1error

Definition at line 3625 of file res_fax.c.

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

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

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

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

References ao2_ref, ast_channel_get_t38_state(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_debug, ast_framehook_detach(), ast_log, ast_null_frame, ast_string_field_set, AST_T38_NEGOTIATED, AST_T38_REFUSED, AST_T38_REQUEST_NEGOTIATE, AST_T38_REQUEST_TERMINATE, AST_T38_TERMINATED, ast_tvnow(), ast_frame::data, ast_frame::datalen, error(), fax_gateway_indicate_t38(), fax_gateway_start(), FAX_GATEWAY_TIMEOUT, find_details(), fax_gateway::framehook, ast_fax_session_details::gateway_id, ast_fax_session_details::gateway_timeout, ast_fax_session_details::is_t38_negotiated, LOG_ERROR, LOG_WARNING, ast_fax_session_details::our_t38_parameters, ast_frame::ptr, report_fax_status(), ast_control_t38_parameters::request_response, result, ast_fax_session_details::resultstr, set_channel_variables(), t38_parameters_ast_to_fax(), t38_parameters_fax_to_ast(), fax_gateway::t38_state, T38_STATE_NEGOTIATED, T38_STATE_NEGOTIATING, T38_STATE_REJECTED, T38_STATE_UNAVAILABLE, T38_STATE_UNKNOWN, ast_fax_session_details::their_t38_parameters, and fax_gateway::timeout_start.

Referenced by fax_gateway_framehook().

◆ fax_gateway_detect_v21()

static struct ast_frame * fax_gateway_detect_v21 ( struct fax_gateway gateway,
struct ast_channel chan,
struct ast_channel peer,
struct ast_channel active,
struct ast_frame f 
)
static
Precondition
chan is locked on entry

Definition at line 3011 of file res_fax.c.

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

References ao2_ref, ast_channel_get_t38_state(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_debug, ast_log, ast_write(), ast_fax_session::chan, fax_gateway::chan_v21_session, destroy_v21_sessions(), ast_fax_session::details, fax_gateway::detected_v21, fax_gateway_request_t38(), find_or_create_details(), if(), LOG_WARNING, ast_fax_session_details::negotiate_both, ast_fax_session_details::option, fax_gateway::peer_v21_session, T38_STATE_UNKNOWN, ast_fax_session::tech, ast_fax_session_details::v21_detected, and ast_fax_tech::write.

Referenced by fax_gateway_framehook().

◆ fax_gateway_framehook()

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

T.30<->T.38 gateway framehook.

Intercept packets on bridged channels and determine if a T.38 gateway is required. If a gateway is required, start a gateway and handle T.38 negotiation if necessary.

Parameters
chanchannel running the gateway
fframe to handle may be NULL
eventframehook event
dataframehook data (struct fax_gateway *)
Precondition
chan is locked on entry
Returns
processed frame or NULL when f is NULL or a null frame

Definition at line 3382 of file res_fax.c.

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

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

References ao2_ref, AST_FAX_STATE_ACTIVE, AST_FAX_STATE_COMPLETE, AST_FAX_STATE_INITIALIZED, AST_FAX_STATE_OPEN, ast_fax_tech::cancel_session, fax_gateway::s, ast_fax_session::state, and ast_fax_session::tech.

Referenced by fax_gateway_attach().

◆ fax_gateway_indicate_t38()

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

Definition at line 3084 of file res_fax.c.

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

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

Referenced by fax_gateway_detect_t38().

◆ fax_gateway_new()

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

Create a new fax gateway object.

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

Definition at line 2879 of file res_fax.c.

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

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

Referenced by fax_gateway_attach().

◆ fax_gateway_request_t38()

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

Definition at line 2971 of file res_fax.c.

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

References ao2_ref, ast_channel_name(), AST_CONTROL_T38_PARAMETERS, ast_debug, AST_FRAME_CONTROL, ast_framehook_detach(), ast_frisolate, ast_log, AST_T38_REQUEST_NEGOTIATE, ast_tvnow(), FAX_GATEWAY_TIMEOUT, find_details(), fax_gateway::framehook, ast_fax_session_details::gateway_timeout, ast_frame_subclass::integer, ast_fax_session_details::is_t38_negotiated, LOG_ERROR, NULL, ast_fax_session_details::our_t38_parameters, ast_control_t38_parameters::request_response, ast_frame::src, ast_frame::subclass, t38_parameters_fax_to_ast(), fax_gateway::t38_state, T38_STATE_NEGOTIATING, and fax_gateway::timeout_start.

Referenced by fax_gateway_detect_v21().

◆ fax_gateway_start()

static int fax_gateway_start ( struct fax_gateway gateway,
struct ast_fax_session_details details,
struct ast_channel chan 
)
static

Create a fax session and start T.30<->T.38 gateway mode.

Parameters
gatewaya fax gateway object
detailsfax session details
chanactive channel
Precondition
chan is locked on entry
Returns
0 on error 1 on success

Definition at line 2916 of file res_fax.c.

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

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

Referenced by fax_gateway_detect_t38().

◆ fax_rate_str_to_int()

static unsigned int fax_rate_str_to_int ( const char *  ratestr)
static

convert a rate string to a rate

Definition at line 1045 of file res_fax.c.

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

References ast_log, LOG_ERROR, and LOG_WARNING.

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

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

References ao2_alloc, ao2_link, ao2_ref, ao2_unlink, ast_atomic_fetchadd_int(), ast_calloc, ast_channel_name(), ast_channel_uniqueid(), ast_debug, ast_dsp_new(), ast_dsp_set_threshold(), ast_fax_caps_to_str(), AST_FAX_STATE_RESERVED, AST_FAX_STATE_UNINITIALIZED, AST_FAX_TECH_AUDIO, ast_free, ast_log, ast_module_running_ref, ast_module_unref, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdup, ast_fax_session_details::caps, ast_fax_tech::caps, ast_fax_session::chan, ast_fax_session::chan_uniqueid, ast_fax_session::channame, ast_fax_session_details::debug, ast_fax_session::debug_info, ast_fax_tech::description, destroy_session(), ast_fax_session::details, ast_fax_debug_info::dsp, fax_session_release(), faxregistry, ast_fax_session_details::id, ast_fax_session::id, LOG_ERROR, ast_fax_tech::module, ast_fax_tech::new_session, NULL, ast_fax_session_details::option, ast_fax_session::state, ast_fax_session::tech, fax_module::tech, and ast_fax_session::tech_pvt.

Referenced by fax_gateway_start(), fax_v21_session_new(), and generic_fax_exec().

◆ fax_session_release()

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

Release a session token.

Parameters
sa session returned from fax_session_reserve()
tokena token generated from fax_session_reserve()

This function releases the given token and marks the given session as no longer reserved. It is safe to call on a session that is not actually reserved and with a NULL token. This is so that sessions returned by technologies that do not support reserved sessions don't require extra logic to handle.

Note
This function DOES NOT release the given fax session, only the given token.

Definition at line 1082 of file res_fax.c.

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

References ast_atomic_fetchadd_int(), AST_FAX_STATE_INACTIVE, AST_FAX_STATE_RESERVED, faxregistry, ast_fax_tech::release_token, ast_fax_session::state, and ast_fax_session::tech.

Referenced by destroy_gateway(), destroy_session(), fax_session_new(), receivefax_exec(), and sendfax_exec().

◆ fax_session_reserve()

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

Reserve a fax session.

Parameters
detailsthe fax session details
tokena pointer to a place to store a token to be passed to fax_session_new() later

This function reserves a fax session for use later. If the selected fax technology does not support reserving sessions a session will still be returned but token will not be set.

Note
The reference returned by this function does not get consumed by fax_session_new() and must always be dereferenced separately.
Returns
NULL or an uninitialized and possibly reserved session

Definition at line 1145 of file res_fax.c.

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

References ao2_alloc, ao2_ref, ast_atomic_fetchadd_int(), ast_debug, ast_fax_caps_to_str(), AST_FAX_STATE_INACTIVE, AST_FAX_STATE_RESERVED, ast_log, ast_module_running_ref, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_fax_session_details::caps, ast_fax_tech::caps, ast_fax_tech::description, destroy_session(), ast_fax_session::details, faxregistry, LOG_ERROR, ast_fax_tech::module, NULL, ast_fax_tech::reserve_session, ast_fax_session::state, ast_fax_session::tech, and fax_module::tech.

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

◆ fax_session_tab_complete()

static char * fax_session_tab_complete ( struct ast_cli_args a)
static

fax session tab completion

Definition at line 3942 of file res_fax.c.

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

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

Referenced by cli_fax_show_session().

◆ fax_session_type()

static const char * fax_session_type ( struct ast_fax_session s)
static

Definition at line 4241 of file res_fax.c.

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

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

Referenced by cli_fax_show_sessions(), and manager_fax_sessions_entry().

◆ fax_v21_session_new()

static struct ast_fax_session * fax_v21_session_new ( struct ast_channel chan)
static

Definition at line 2860 of file res_fax.c.

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

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

Referenced by fax_gateway_framehook(), and fax_gateway_new().

◆ find_details()

static struct ast_fax_session_details * find_details ( struct ast_channel chan)
static

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

Definition at line 661 of file res_fax.c.

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

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

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

◆ find_or_create_details()

static struct ast_fax_session_details * find_or_create_details ( struct ast_channel chan)
static

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

Definition at line 763 of file res_fax.c.

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

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

Referenced by 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 635 of file res_fax.c.

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

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

◆ generate_filenames_json()

static struct ast_json * generate_filenames_json ( struct ast_fax_session_details details)
static

Definition at line 1329 of file res_fax.c.

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

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

Referenced by report_fax_status(), and report_send_fax_status().

◆ generate_filenames_string()

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

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

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

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

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

Definition at line 1369 of file res_fax.c.

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

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

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

◆ generic_fax_exec()

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

this is the generic FAX session handling function

Definition at line 1589 of file res_fax.c.

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

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

Referenced by receivefax_exec(), and sendfax_exec().

◆ get_general_options()

static void get_general_options ( struct fax_options options)
static

Definition at line 4396 of file res_fax.c.

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

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

Referenced by ast_fax_maxrate(), ast_fax_minrate(), 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 4787 of file res_fax.c.

4788{
4789 int res;
4790
4791 /* initialize the registry */
4792 faxregistry.active_sessions = 0;
4793 faxregistry.reserved_sessions = 0;
4796 if (!faxregistry.container) {
4798 }
4799
4800 if (set_config(0) < 0) {
4801 ast_log(LOG_ERROR, "failed to load configuration file '%s'\n", config);
4802 ao2_ref(faxregistry.container, -1);
4804 }
4805
4806 /* register CLI operations and applications */
4808 ast_log(LOG_WARNING, "failed to register '%s'.\n", app_sendfax);
4809 ao2_ref(faxregistry.container, -1);
4811 }
4813 ast_log(LOG_WARNING, "failed to register '%s'.\n", app_receivefax);
4815 ao2_ref(faxregistry.container, -1);
4817 }
4818
4820 ast_log(LOG_WARNING, "failed to register 'FAXSessions' AMI command.\n");
4823 ao2_ref(faxregistry.container, -1);
4825 }
4826
4828 ast_log(LOG_WARNING, "failed to register 'FAXSession' AMI command.\n");
4829 ast_manager_unregister("FAXSession");
4832 ao2_ref(faxregistry.container, -1);
4834 }
4835
4837 ast_log(LOG_WARNING, "failed to register 'FAXStats' AMI command.\n");
4838 ast_manager_unregister("FAXSession");
4839 ast_manager_unregister("FAXSessions");
4842 ao2_ref(faxregistry.container, -1);
4844 }
4845
4849
4850 return res;
4851}
@ AO2_ALLOC_OPT_LOCK_MUTEX
Definition: astobj2.h:363
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
Definition: astobj2.h:1303
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7934
int ast_logger_register_level(const char *name)
Register a new logger level.
Definition: logger.c:2839
#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:191
#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:626
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1558
static int session_cmp_cb(void *obj, void *arg, int flags)
compare callback for ao2
Definition: res_fax.c:3934
static int session_hash_cb(const void *obj, const int flags)
hash callback for ao2
Definition: res_fax.c:3926
static const char app_receivefax[]
Definition: res_fax.c:427
static struct ast_custom_function acf_faxopt
FAXOPT dialplan function.
Definition: res_fax.c:4741
static const char * config
Definition: res_fax.c:552
static int sendfax_exec(struct ast_channel *chan, const char *data)
initiate a send FAX session
Definition: res_fax.c:2589
#define FAX_MAXBUCKETS
maximum buckets for res_fax ao2 containers
Definition: res_fax.c:489
static int receivefax_exec(struct ast_channel *chan, const char *data)
initiate a receive FAX session
Definition: res_fax.c:2081
static int set_config(int reload)
configure res_fax
Definition: res_fax.c:4421
static const char app_sendfax[]
Definition: res_fax.c:428
static int manager_fax_session(struct mansession *s, const struct message *m)
Definition: res_fax.c:4142
static int manager_fax_stats(struct mansession *s, const struct message *m)
Definition: res_fax.c:4212
static struct ast_cli_entry fax_cli[]
Definition: res_fax.c:4379
static int manager_fax_sessions(struct mansession *s, const struct message *m)
Definition: res_fax.c:4348
#define ARRAY_LEN(a)
Definition: utils.h:666

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

◆ manager_fax_session()

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

Definition at line 4142 of file res_fax.c.

4143{
4144 const char *action_id = astman_get_header(m, "ActionID");
4145 const char *session_number = astman_get_header(m, "SessionNumber");
4146 char id_text[256] = "";
4147 struct ast_fax_session *session;
4149
4150 if (sscanf(session_number, "%30u", &find_session.id) != 1) {
4151 astman_send_error(s, m, "Invalid session ID");
4152 return 0;
4153 }
4154
4156 if (!session) {
4157 astman_send_error(s, m, "Session not found");
4158 return 0;
4159 }
4160
4161 if (!session->tech->manager_fax_session) {
4162 astman_send_error(s, m, "Fax technology doesn't provide a handler for FAXSession");
4163 ao2_ref(session, -1);
4164 return 0;
4165 }
4166
4167 if (!ast_strlen_zero(action_id)) {
4168 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", action_id);
4169 }
4170
4171 astman_send_ack(s, m, "FAXSession event will follow");
4172
4173 session->tech->manager_fax_session(s, id_text, session);
4174 ao2_ref(session, -1);
4175
4176 return 0;
4177}
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3280
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3312
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:2941
static struct mansession_session * find_session(uint32_t ident, int incinuse)
Definition: manager.c:8154

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

4349{
4350 const char *action_id = astman_get_header(m, "ActionID");
4351 char id_text[256];
4352 struct ast_fax_session *session;
4353 struct ao2_iterator iter;
4354 int session_count = 0;
4355
4356 id_text[0] = '\0';
4357 if (!ast_strlen_zero(action_id)) {
4358 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", action_id);
4359 }
4360
4361 astman_send_listack(s, m, "FAXSessionsEntry event list will follow", "Start");
4362
4363 iter = ao2_iterator_init(faxregistry.container, 0);
4364 while ((session = ao2_iterator_next(&iter))) {
4365 if (!manager_fax_sessions_entry(s, session, id_text)) {
4366 session_count++;
4367 }
4368 ao2_ref(session, -1);
4369 }
4370 ao2_iterator_destroy(&iter);
4371
4372 astman_send_list_complete_start(s, m, "FAXSessionsComplete", session_count);
4373 astman_append(s, "Total: %d\r\n", session_count);
4375
4376 return 0;
4377}
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:3322
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:3358
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:3366
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3201
static int manager_fax_sessions_entry(struct mansession *s, struct ast_fax_session *session, const char *id_text)
Definition: res_fax.c:4316

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

4318{
4319 char *filenames;
4320
4322 filenames = generate_filenames_string(session->details, "", ",");
4323
4324 if (!filenames) {
4325 ast_log(LOG_ERROR, "Error generating Files string");
4327 return -1;
4328 }
4329
4330 astman_append(s, "Event: FAXSessionsEntry\r\n"
4331 "%s" /* ActionID if present */
4332 "Channel: %s\r\n" /* Channel name */
4333 "Technology: %s\r\n" /* Fax session technology */
4334 "SessionNumber: %u\r\n" /* Session ID */
4335 "SessionType: %s\r\n" /* G711 or T38 */
4336 "Operation: %s\r\n"
4337 "State: %s\r\n"
4338 "Files: %s\r\n"
4339 "\r\n",
4340 id_text, session->channame, session->tech->type, session->id,
4342 ast_fax_state_to_str(session->state), S_OR(filenames, ""));
4343 ast_free(filenames);
4345 return 0;
4346}

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

4213{
4214 const char *action_id = astman_get_header(m, "ActionID");
4215
4216 char id_text[256] = "";
4217
4218 astman_send_ack(s, m, "FAXStats event will follow");
4219
4220 if (!ast_strlen_zero(action_id)) {
4221 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", action_id);
4222 }
4223
4224 astman_append(s, "Event: FAXStats\r\n"
4225 "%s"
4226 "CurrentSessions: %d\r\n"
4227 "ReservedSessions: %d\r\n"
4228 "TransmitAttempts: %d\r\n"
4229 "ReceiveAttempts: %d\r\n"
4230 "CompletedFAXes: %d\r\n"
4231 "FailedFAXes: %d\r\n"
4232 "\r\n",
4233 id_text,
4234 faxregistry.active_sessions, faxregistry.reserved_sessions,
4235 faxregistry.fax_tx_attempts, faxregistry.fax_rx_attempts,
4236 faxregistry.fax_complete, faxregistry.fax_failures);
4237
4238 return 0;
4239}

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

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

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

Referenced by load_module().

◆ receivefax_t38_init()

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

Definition at line 1855 of file res_fax.c.

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

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

Referenced by receivefax_exec().

◆ reload_module()

static int reload_module ( void  )
static

Definition at line 4853 of file res_fax.c.

4854{
4855 set_config(1);
4856 return 0;
4857}

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

1407{
1408 RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
1410 struct ast_json *json_filenames = NULL;
1411
1412 if (!details->option.statusevents) {
1413 return 0;
1414 }
1415
1416 json_filenames = generate_filenames_json(details);
1417 if (!json_filenames) {
1418 return -1;
1419 }
1420
1421 json_object = ast_json_pack("{s: s, s: s, s: s, s: s, s: o}",
1422 "type", "status",
1423 "operation", (details->caps & AST_FAX_TECH_GATEWAY)
1424 ? "gateway"
1425 : (details->caps & AST_FAX_TECH_RECEIVE) ? "receive" : "send",
1426 "status", status,
1427 "local_station_id", AST_JSON_UTF8_VALIDATE(details->localstationid),
1428 "filenames", json_filenames);
1429 if (!json_object) {
1430 return -1;
1431 }
1432
1433 {
1434 SCOPED_CHANNELLOCK(lock, chan);
1435
1437 if (!message) {
1438 return -1;
1439 }
1441 }
1442 return 0;
1443}
jack_status_t status
Definition: app_jack.c:146
ast_mutex_t lock
Definition: app_sla.c:331
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:619
static struct ast_json * generate_filenames_json(struct ast_fax_session_details *details)
Definition: res_fax.c:1329
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
Definition: stasis.c:1511

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

2018{
2019 RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
2021 RAII_VAR(struct ast_json *, json_array, ast_json_array_create(), ast_json_unref);
2022 struct ast_json *json_filename = ast_json_string_create(filename);
2023
2024 if (!json_array || !json_filename) {
2025 ast_json_unref(json_filename);
2026 return -1;
2027 }
2028 ast_json_array_append(json_array, json_filename);
2029
2030 {
2031 const char *remote_station_id;
2032 const char *local_station_id;
2033 const char *fax_pages;
2034 const char *fax_resolution;
2035 const char *fax_bitrate;
2036 SCOPED_CHANNELLOCK(lock, chan);
2037
2038 remote_station_id = AST_JSON_UTF8_VALIDATE(pbx_builtin_getvar_helper(chan, "REMOTESTATIONID"));
2039 if (!ast_strlen_zero(remote_station_id)) {
2040 remote_station_id = ast_strdupa(remote_station_id);
2041 }
2042 local_station_id = AST_JSON_UTF8_VALIDATE(pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"));
2043 if (!ast_strlen_zero(local_station_id)) {
2044 local_station_id = ast_strdupa(local_station_id);
2045 }
2046 fax_pages = S_OR(pbx_builtin_getvar_helper(chan, "FAXPAGES"), "");
2047 if (!ast_strlen_zero(fax_pages)) {
2048 fax_pages = ast_strdupa(fax_pages);
2049 }
2050 fax_resolution = S_OR(pbx_builtin_getvar_helper(chan, "FAXRESOLUTION"), "");
2051 if (!ast_strlen_zero(fax_resolution)) {
2052 fax_resolution = ast_strdupa(fax_resolution);
2053 }
2054 fax_bitrate = S_OR(pbx_builtin_getvar_helper(chan, "FAXBITRATE"), "");
2055 if (!ast_strlen_zero(fax_bitrate)) {
2056 fax_bitrate = ast_strdupa(fax_bitrate);
2057 }
2058
2059 json_object = ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: s, s: o}",
2060 "type", "receive",
2061 "remote_station_id", S_OR(remote_station_id, ""),
2062 "local_station_id", S_OR(local_station_id, ""),
2063 "fax_pages", S_OR(fax_pages, ""),
2064 "fax_resolution", S_OR(fax_resolution, ""),
2065 "fax_bitrate", S_OR(fax_bitrate, ""),
2066 "filenames", ast_json_ref(json_array));
2067 if (!json_object) {
2068 return -1;
2069 }
2070
2072 if (!message) {
2073 return -1;
2074 }
2076 }
2077 return 0;
2078}

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

2527{
2528 RAII_VAR(struct ast_json *, json_obj, NULL, ast_json_unref);
2530 struct ast_json *json_filenames;
2531
2532 json_filenames = generate_filenames_json(details);
2533 if (!json_filenames) {
2534 return -1;
2535 }
2536
2537 {
2538 const char *remote_station_id;
2539 const char *local_station_id;
2540 const char *fax_pages;
2541 const char *fax_resolution;
2542 const char *fax_bitrate;
2543 SCOPED_CHANNELLOCK(lock, chan);
2544
2545 remote_station_id = AST_JSON_UTF8_VALIDATE(pbx_builtin_getvar_helper(chan, "REMOTESTATIONID"));
2546 if (!ast_strlen_zero(remote_station_id)) {
2547 remote_station_id = ast_strdupa(remote_station_id);
2548 }
2549 local_station_id = AST_JSON_UTF8_VALIDATE(pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"));
2550 if (!ast_strlen_zero(local_station_id)) {
2551 local_station_id = ast_strdupa(local_station_id);
2552 }
2553 fax_pages = S_OR(pbx_builtin_getvar_helper(chan, "FAXPAGES"), "");
2554 if (!ast_strlen_zero(fax_pages)) {
2555 fax_pages = ast_strdupa(fax_pages);
2556 }
2557 fax_resolution = S_OR(pbx_builtin_getvar_helper(chan, "FAXRESOLUTION"), "");
2558 if (!ast_strlen_zero(fax_resolution)) {
2559 fax_resolution = ast_strdupa(fax_resolution);
2560 }
2561 fax_bitrate = S_OR(pbx_builtin_getvar_helper(chan, "FAXBITRATE"), "");
2562 if (!ast_strlen_zero(fax_bitrate)) {
2563 fax_bitrate = ast_strdupa(fax_bitrate);
2564 }
2565 json_obj = ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: s, s: o}",
2566 "type", "send",
2567 "remote_station_id", S_OR(remote_station_id, ""),
2568 "local_station_id", S_OR(local_station_id, ""),
2569 "fax_pages", S_OR(fax_pages, ""),
2570 "fax_resolution", S_OR(fax_resolution, ""),
2571 "fax_bitrate", S_OR(fax_bitrate, ""),
2572 "filenames", json_filenames);
2573 if (!json_obj) {
2574 return -1;
2575 }
2576
2578 if (!message) {
2579 return -1;
2580 }
2582 }
2583 return 0;
2584}

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

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

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

Referenced by load_module().

◆ sendfax_t38_init()

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

Definition at line 2282 of file res_fax.c.

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

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

3935{
3936 struct ast_fax_session *lhs = obj, *rhs = arg;
3937
3938 return (lhs->id == rhs->id) ? CMP_MATCH | CMP_STOP : 0;
3939}
@ 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 695 of file res_fax.c.

696{
698 struct fax_options options;
699
700 if (!(d = ao2_alloc(sizeof(*d), destroy_session_details))) {
701 return NULL;
702 }
703
704 if (ast_string_field_init(d, 512)) {
705 ao2_ref(d, -1);
706 return NULL;
707 }
708
710
711 AST_LIST_HEAD_INIT_NOLOCK(&d->documents);
712
713 /* These options need to be set to the configured default and may be overridden by
714 * SendFAX, ReceiveFAX, or FAXOPT */
715 d->option.request_t38 = AST_FAX_OPTFLAG_FALSE;
716 d->option.send_cng = AST_FAX_OPTFLAG_FALSE;
717 d->option.send_ced = AST_FAX_OPTFLAG_FALSE;
718 d->option.ecm = options.ecm;
719 d->option.statusevents = options.statusevents;
720 d->modems = options.modems;
721 d->minrate = options.minrate;
722 d->maxrate = options.maxrate;
723 d->t38timeout = options.t38timeout;
724 d->gateway_id = -1;
725 d->faxdetect_id = -1;
726 d->gateway_timeout = 0;
727 d->negotiate_both = 0;
728
729 return d;
730}
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:681
static void destroy_session_details(void *details)
destroy a FAX session details structure
Definition: res_fax.c:683
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:359

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

Referenced by fax_v21_session_new(), and find_or_create_details().

◆ session_hash_cb()

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

hash callback for ao2

Definition at line 3926 of file res_fax.c.

3927{
3928 const struct ast_fax_session *s = obj;
3929
3930 return s->id;
3931}

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

1447{
1448 char buf[10];
1449
1450 pbx_builtin_setvar_helper(chan, "FAXSTATUS", S_OR(details->result, NULL));
1451 pbx_builtin_setvar_helper(chan, "FAXERROR", S_OR(details->error, NULL));
1452 pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", S_OR(details->resultstr, NULL));
1453 pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", AST_JSON_UTF8_VALIDATE(details->remotestationid));
1454 pbx_builtin_setvar_helper(chan, "LOCALSTATIONID", AST_JSON_UTF8_VALIDATE(details->localstationid));
1455 pbx_builtin_setvar_helper(chan, "FAXBITRATE", S_OR(details->transfer_rate, NULL));
1456 pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", S_OR(details->resolution, NULL));
1457
1458 if (details->is_t38_negotiated) {
1459 pbx_builtin_setvar_helper(chan, "FAXMODE", "T38");
1460 } else {
1461 pbx_builtin_setvar_helper(chan, "FAXMODE", "audio");
1462 }
1463
1464 snprintf(buf, sizeof(buf), "%u", details->pages_transferred);
1465 pbx_builtin_setvar_helper(chan, "FAXPAGES", buf);
1466}

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

4422{
4423 struct ast_config *cfg;
4424 struct ast_variable *v;
4425 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
4426 char modems[128] = "";
4427 struct fax_options options;
4428 int res = 0;
4429
4431
4432 /* When we're not reloading, we have to be certain to set the general options
4433 * to the defaults in case config loading goes wrong at some point. On a reload,
4434 * the general options need to stay the same as what they were prior to the
4435 * reload rather than being reset to the defaults.
4436 */
4437 if (!reload) {
4439 }
4440
4441 /* read configuration */
4442 if (!(cfg = ast_config_load2(config, "res_fax", config_flags))) {
4443 ast_log(LOG_NOTICE, "Configuration file '%s' not found, %s options.\n",
4444 config, reload ? "not changing" : "using default");
4445 return 0;
4446 }
4447
4448 if (cfg == CONFIG_STATUS_FILEINVALID) {
4449 ast_log(LOG_NOTICE, "Configuration file '%s' is invalid, %s options.\n",
4450 config, reload ? "not changing" : "using default");
4451 return 0;
4452 }
4453
4454 if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
4455 return 0;
4456 }
4457
4458 if (reload) {
4460 }
4461
4462 /* create configuration */
4463 for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
4464 int rate;
4465
4466 if (!strcasecmp(v->name, "minrate")) {
4467 ast_debug(3, "reading minrate '%s' from configuration file\n", v->value);
4468 if ((rate = fax_rate_str_to_int(v->value)) == 0) {
4469 res = -1;
4470 goto end;
4471 }
4472 options.minrate = rate;
4473 } else if (!strcasecmp(v->name, "maxrate")) {
4474 ast_debug(3, "reading maxrate '%s' from configuration file\n", v->value);
4475 if ((rate = fax_rate_str_to_int(v->value)) == 0) {
4476 res = -1;
4477 goto end;
4478 }
4479 options.maxrate = rate;
4480 } else if (!strcasecmp(v->name, "statusevents")) {
4481 ast_debug(3, "reading statusevents '%s' from configuration file\n", v->value);
4482 options.statusevents = ast_true(v->value);
4483 } else if (!strcasecmp(v->name, "ecm")) {
4484 ast_debug(3, "reading ecm '%s' from configuration file\n", v->value);
4485 options.ecm = ast_true(v->value);
4486 } else if ((!strcasecmp(v->name, "modem")) || (!strcasecmp(v->name, "modems"))) {
4487 options.modems = 0;
4488 update_modem_bits(&options.modems, v->value);
4489 } else if (!strcasecmp(v->name, "t38timeout")) {
4490 if (set_t38timeout(v->value, &options.t38timeout)) {
4491 res = -1;
4492 goto end;
4493 }
4494 }
4495 }
4496
4497 if (options.maxrate < options.minrate) {
4498 ast_log(LOG_ERROR, "maxrate %u is less than minrate %u\n", options.maxrate, options.minrate);
4499 res = -1;
4500 goto end;
4501 }
4502
4503 if (check_modem_rate(options.modems, options.minrate)) {
4504 ast_fax_modem_to_str(options.modems, modems, sizeof(modems));
4505 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %u\n", modems, options.minrate);
4506 res = -1;
4507 goto end;
4508 }
4509
4510 if (check_modem_rate(options.modems, options.maxrate)) {
4511 ast_fax_modem_to_str(options.modems, modems, sizeof(modems));
4512 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %u\n", modems, options.maxrate);
4513 res = -1;
4514 goto end;
4515 }
4516
4518
4519end:
4520 ast_config_destroy(cfg);
4521 return res;
4522}
char * end
Definition: eagi_proxy.c:73
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
Definition: main/config.c:3321
#define CONFIG_STATUS_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1289
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1215
@ CONFIG_FLAG_FILEUNCHANGED
static int reload(void)
static void set_general_options(const struct fax_options *options)
Definition: res_fax.c:4389
static const struct fax_options default_options
Definition: res_fax.c:538
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 1490 of file res_fax.c.

1491{
1492 switch (ast_channel_get_t38_state(chan)) {
1493 case T38_STATE_UNKNOWN:
1494 details->caps |= AST_FAX_TECH_T38;
1495 break;
1496 case T38_STATE_REJECTED:
1498 details->caps |= AST_FAX_TECH_AUDIO;
1499 break;
1501 /* already in T.38 mode? This should not happen. */
1502 case T38_STATE_NEGOTIATING: {
1503 /* the other end already sent us a T.38 reinvite, so we need to prod the channel
1504 * driver into resending their parameters to us if it supports doing so... if
1505 * not, we can't proceed, because we can't create a proper reply without them.
1506 * if it does work, the channel driver will send an AST_CONTROL_T38_PARAMETERS
1507 * with a request of AST_T38_REQUEST_NEGOTIATE, which will be read by the function
1508 * that gets called after this one completes
1509 */
1511 if (ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &parameters, sizeof(parameters)) != AST_T38_REQUEST_PARMS) {
1512 ast_log(LOG_ERROR, "channel '%s' is in an unsupported T.38 negotiation state, cannot continue.\n", ast_channel_name(chan));
1513 return -1;
1514 }
1515 details->caps |= AST_FAX_TECH_T38;
1516 break;
1517 }
1518 default:
1519 ast_log(LOG_ERROR, "channel '%s' is in an unsupported T.38 negotiation state, cannot continue.\n", ast_channel_name(chan));
1520 return -1;
1521 }
1522
1523 return 0;
1524}
@ 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 4389 of file res_fax.c.

4390{
4394}
#define ast_rwlock_wrlock(a)
Definition: lock.h:236

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

4404{
4405 unsigned int timeout;
4406
4407 if (sscanf(value, "%u", &timeout) != 1) {
4408 ast_log(LOG_ERROR, "Unable to get timeout from '%s'\n", value);
4409 return -1;
4410 } else if (timeout) {
4411 *t38timeout = timeout;
4412 } else {
4413 ast_log(LOG_ERROR, "T.38 negotiation timeout must be non-zero\n");
4414 return -1;
4415 }
4416
4417 return 0;
4418}

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

740{
741 dst->version = src->version;
742 dst->max_ifp = src->max_ifp;
743 dst->rate = src->rate;
748}
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 4748 of file res_fax.c.

4749{
4751
4753 ast_log(LOG_WARNING, "failed to unregister function '%s'\n", acf_faxopt.name);
4754 }
4755
4757 ast_log(LOG_WARNING, "failed to unregister '%s'\n", app_sendfax);
4758 }
4759
4761 ast_log(LOG_WARNING, "failed to unregister '%s'\n", app_receivefax);
4762 }
4763
4764 ast_manager_unregister("FAXSessions");
4765 ast_manager_unregister("FAXSession");
4766 ast_manager_unregister("FAXStats");
4767
4768 if (fax_logger_level != -1) {
4770 }
4771
4772 ao2_ref(faxregistry.container, -1);
4773
4774 return 0;
4775}
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
void ast_logger_unregister_level(const char *name)
Unregister a previously registered logger level.
Definition: logger.c:2897
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 811 of file res_fax.c.

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

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

Referenced by acf_faxopt_write(), and set_config().

Variable Documentation

◆ __mod_info

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

Definition at line 4866 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:4600
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:4525

FAXOPT dialplan function.

Definition at line 4741 of file res_fax.c.

Referenced by load_module(), and unload_module().

◆ active_sessions

int active_sessions

The number of active FAX sessions

Definition at line 497 of file res_fax.c.

◆ app_receivefax

const char app_receivefax[] = "ReceiveFAX"
static

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

◆ config

const char* config = "res_fax.conf"
static

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

Referenced by set_config().

◆ fax_cli

struct ast_cli_entry fax_cli[]
static

Definition at line 4379 of file res_fax.c.

Referenced by load_module(), and unload_module().

◆ fax_complete

int fax_complete

Number of successful FAX transmissions

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

Definition at line 618 of file res_fax.c.

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

◆ fax_exec_options

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

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

◆ fax_logger_level

int fax_logger_level = -1
static

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

◆ fax_tx_attempts

int fax_tx_attempts

Total number of Tx FAX attempts

Definition at line 503 of file res_fax.c.

◆ faxmodules

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

◆ 

struct { ... } faxregistry

◆ general_options

struct fax_options general_options
static

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

◆ options_lock

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

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

Referenced by find_or_create_details().

◆ reserved_sessions

int reserved_sessions

The number of reserved FAX sessions

Definition at line 499 of file res_fax.c.