Wed Jan 8 2020 09:50:18

Asterisk developer's documentation


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/manager.h"
#include "asterisk/dsp.h"
#include "asterisk/indications.h"
#include "asterisk/ast_version.h"

Go to the source code of this file.

Data Structures

struct  ast_fax_debug_info
 
struct  debug_info_history
 
struct  fax_module
 registered FAX technology modules are put into this list More...
 
struct  fax_options
 
struct  faxmodules
 
struct  manager_event_info
 

Macros

#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_V27 | AST_FAX_MODEM_V29)
 
#define RES_FAX_STATUSEVENTS   0
 
#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)
}
 

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_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...
 
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_session (void *session)
 destroy a FAX session structure More...
 
static void destroy_session_details (void *details)
 destroy a FAX session details structure More...
 
static int disable_t38 (struct ast_channel *chan)
 
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)
 
static struct ast_fax_sessionfax_session_reserve (struct ast_fax_session_details *details, struct ast_fax_tech_token **token)
 
static char * fax_session_tab_complete (struct ast_cli_args *a)
 fax session tab completion More...
 
static struct
ast_fax_session_details
find_details (struct ast_channel *chan)
 returns a reference counted pointer to a fax datastore, if it exists More...
 
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 not exist it will be created More...
 
static char * generate_filenames_string (struct ast_fax_session_details *details, char *prefix, char *separator)
 
static int generic_fax_exec (struct ast_channel *chan, struct ast_fax_session_details *details, struct ast_fax_session *reserved, struct ast_fax_tech_token *token)
 this is the generic FAX session handling function More...
 
static void get_general_options (struct fax_options *options)
 
static void get_manager_event_info (struct ast_channel *chan, struct manager_event_info *info)
 
static int load_module (void)
 load res_fax More...
 
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 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_details
session_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 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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_APP_DEPEND, }
 
struct ast_custom_function acf_faxopt
 FAXOPT dialplan function. More...
 
static const char app_receivefax [] = "ReceiveFAX"
 
static const char app_sendfax [] = "SendFAX"
 
static struct ast_module_infoast_module_info = &__mod_info
 
static const char * config = "res_fax.conf"
 
static struct fax_options default_options
 
static struct ast_cli_entry fax_cli []
 
static struct ast_datastore_info fax_datastore
 
static struct ast_app_option fax_exec_options [128] = { [ 'a' ] = { .flag = OPT_CALLEDMODE }, [ 'c' ] = { .flag = OPT_CALLERMODE }, [ 'd' ] = { .flag = OPT_DEBUG }, [ 'f' ] = { .flag = OPT_ALLOWAUDIO }, [ '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 } , }
 
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 }
 
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

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

#define FAX_MAXBUCKETS   10

maximum buckets for res_fax ao2 containers

Definition at line 216 of file res_fax.c.

Referenced by load_module().

#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", chan->name, fax->id, reason, errorstr); \
GENERIC_FAX_EXEC_ERROR_QUIET(fax, chan, errorstr, reason); \
} while (0)
#define GENERIC_FAX_EXEC_ERROR_QUIET(fax, chan, errorstr, reason)
Definition: res_fax.c:1026
#define LOG_ERROR
Definition: logger.h:155
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207

Definition at line 1031 of file res_fax.c.

Referenced by generic_fax_exec().

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

Definition at line 1026 of file res_fax.c.

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

Definition at line 1015 of file res_fax.c.

Referenced by generic_fax_exec().

#define RES_FAX_MAXRATE   14400

Definition at line 248 of file res_fax.c.

#define RES_FAX_MINRATE   4800

Definition at line 247 of file res_fax.c.

#define RES_FAX_MODEM   (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V27 | AST_FAX_MODEM_V29)

Definition at line 250 of file res_fax.c.

#define RES_FAX_STATUSEVENTS   0

Definition at line 249 of file res_fax.c.

#define RES_FAX_TIMEOUT   10000

Definition at line 218 of file res_fax.c.

Referenced by generic_fax_exec().

Enumeration Type Documentation

anonymous enum
Enumerator
OPT_CALLEDMODE 
OPT_CALLERMODE 
OPT_DEBUG 
OPT_STATUS 
OPT_ALLOWAUDIO 
OPT_REQUEST_T38 

Definition at line 279 of file res_fax.c.

279  {
280  OPT_CALLEDMODE = (1 << 0),
281  OPT_CALLERMODE = (1 << 1),
282  OPT_DEBUG = (1 << 2),
283  OPT_STATUS = (1 << 3),
284  OPT_ALLOWAUDIO = (1 << 5),
285  OPT_REQUEST_T38 = (1 << 6),
286 };

Function Documentation

static void __reg_module ( void  )
static

Definition at line 2968 of file res_fax.c.

static void __unreg_module ( void  )
static

Definition at line 2968 of file res_fax.c.

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

References ao2_ref, ast_copy_string(), ast_fax_modem_to_str(), ast_free, AST_LIST_EMPTY, AST_LIST_FIRST, ast_log(), ast_fax_session_details::documents, ast_fax_session_details::ecm, ast_fax_session_details::error, find_details(), generate_filenames_string(), ast_fax_session_details::headerinfo, ast_fax_session_details::id, ast_fax_session_details::localstationid, LOG_ERROR, LOG_WARNING, ast_fax_session_details::maxrate, ast_fax_session_details::minrate, ast_fax_session_details::modems, ast_channel::name, 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, and ast_fax_session_details::transfer_rate.

2775 {
2776  struct ast_fax_session_details *details = find_details(chan);
2777  int res = 0;
2778  char *filenames;
2779 
2780  if (!details) {
2781  ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s) because it has never been written.\n", chan->name, data);
2782  return -1;
2783  }
2784  if (!strcasecmp(data, "ecm")) {
2785  ast_copy_string(buf, details->option.ecm ? "yes" : "no", len);
2786  } else if (!strcasecmp(data, "error")) {
2787  ast_copy_string(buf, details->error, len);
2788  } else if (!strcasecmp(data, "filename")) {
2789  if (AST_LIST_EMPTY(&details->documents)) {
2790  ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s) because it has never been written.\n", chan->name, data);
2791  res = -1;
2792  } else {
2793  ast_copy_string(buf, AST_LIST_FIRST(&details->documents)->filename, len);
2794  }
2795  } else if (!strcasecmp(data, "filenames")) {
2796  if (AST_LIST_EMPTY(&details->documents)) {
2797  ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s) because it has never been written.\n", chan->name, data);
2798  res = -1;
2799  } else if ((filenames = generate_filenames_string(details, "", ","))) {
2800  ast_copy_string(buf, filenames, len);
2801  ast_free(filenames);
2802  } else {
2803  ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s), there was an error generating the filenames list.\n", chan->name, data);
2804  res = -1;
2805  }
2806  } else if (!strcasecmp(data, "headerinfo")) {
2807  ast_copy_string(buf, details->headerinfo, len);
2808  } else if (!strcasecmp(data, "localstationid")) {
2809  ast_copy_string(buf, details->localstationid, len);
2810  } else if (!strcasecmp(data, "maxrate")) {
2811  snprintf(buf, len, "%u", details->maxrate);
2812  } else if (!strcasecmp(data, "minrate")) {
2813  snprintf(buf, len, "%u", details->minrate);
2814  } else if (!strcasecmp(data, "pages")) {
2815  snprintf(buf, len, "%u", details->pages_transferred);
2816  } else if (!strcasecmp(data, "rate")) {
2817  ast_copy_string(buf, details->transfer_rate, len);
2818  } else if (!strcasecmp(data, "remotestationid")) {
2819  ast_copy_string(buf, details->remotestationid, len);
2820  } else if (!strcasecmp(data, "resolution")) {
2821  ast_copy_string(buf, details->resolution, len);
2822  } else if (!strcasecmp(data, "sessionid")) {
2823  snprintf(buf, len, "%u", details->id);
2824  } else if (!strcasecmp(data, "status")) {
2825  ast_copy_string(buf, details->result, len);
2826  } else if (!strcasecmp(data, "statusstr")) {
2827  ast_copy_string(buf, details->resultstr, len);
2828  } else if ((!strcasecmp(data, "modem")) || (!strcasecmp(data, "modems"))) {
2829  ast_fax_modem_to_str(details->modems, buf, len);
2830  } else {
2831  ast_log(LOG_WARNING, "channel '%s' can't read FAXOPT(%s) because it is unhandled!\n", chan->name, data);
2832  res = -1;
2833  }
2834  ao2_ref(details, -1);
2835 
2836  return res;
2837 }
const ast_string_field result
Definition: res_fax.h:137
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
const ast_string_field headerinfo
Definition: res_fax.h:137
#define LOG_WARNING
Definition: logger.h:144
const ast_string_field transfer_rate
Definition: res_fax.h:137
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
unsigned int id
Definition: res_fax.h:112
#define ao2_ref(o, delta)
Definition: astobj2.h:472
The data communicated between the high level applications and the generic fax function.
Definition: res_fax.h:105
const ast_string_field remotestationid
Definition: res_fax.h:137
#define LOG_ERROR
Definition: logger.h:155
union ast_fax_session_details::@203 option
unsigned int pages_transferred
Definition: res_fax.h:139
struct ast_fax_documents documents
Definition: res_fax.h:114
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
unsigned int minrate
Definition: res_fax.h:164
#define ast_free(a)
Definition: astmm.h:97
enum ast_fax_modems modems
Definition: res_fax.h:110
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
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:349
static int ast_fax_modem_to_str(enum ast_fax_modems bits, char *tbuf, size_t bufsize)
Definition: res_fax.c:539
const ast_string_field resultstr
Definition: res_fax.h:137
const ast_string_field localstationid
Definition: res_fax.h:137
unsigned int maxrate
Definition: res_fax.h:166
const ast_string_field error
Definition: res_fax.h:137
const ast_string_field resolution
Definition: res_fax.h:137
static char * generate_filenames_string(struct ast_fax_session_details *details, char *prefix, char *separator)
Definition: res_fax.c:927
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 2840 of file res_fax.c.

References ao2_ref, ast_debug, ast_false(), ast_fax_maxrate(), ast_fax_minrate(), AST_FAX_OPTFLAG_FALSE, AST_FAX_OPTFLAG_TRUE, ast_log(), ast_skip_blanks(), ast_string_field_set, ast_true(), ast_fax_session_details::ecm, fax_rate_str_to_int(), find_or_create_details(), ast_fax_session_details::headerinfo, ast_fax_session_details::localstationid, LOG_WARNING, ast_fax_session_details::maxrate, ast_fax_session_details::minrate, ast_fax_session_details::modems, ast_channel::name, ast_fax_session_details::option, and update_modem_bits().

2841 {
2842  int res = 0;
2843  struct ast_fax_session_details *details;
2844 
2845  if (!(details = find_or_create_details(chan))) {
2846  ast_log(LOG_WARNING, "channel '%s' can't set FAXOPT(%s) to '%s' because it failed to create a datastore.\n", chan->name, data, value);
2847  return -1;
2848  }
2849  ast_debug(3, "channel '%s' setting FAXOPT(%s) to '%s'\n", chan->name, data, value);
2850 
2851  if (!strcasecmp(data, "ecm")) {
2852  const char *val = ast_skip_blanks(value);
2853  if (ast_true(val)) {
2854  details->option.ecm = AST_FAX_OPTFLAG_TRUE;
2855  } else if (ast_false(val)) {
2856  details->option.ecm = AST_FAX_OPTFLAG_FALSE;
2857  } else {
2858  ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(ecm).\n", value);
2859  }
2860  } else if (!strcasecmp(data, "headerinfo")) {
2862  } else if (!strcasecmp(data, "localstationid")) {
2864  } else if (!strcasecmp(data, "maxrate")) {
2865  details->maxrate = fax_rate_str_to_int(value);
2866  if (!details->maxrate) {
2867  details->maxrate = ast_fax_maxrate();
2868  }
2869  } else if (!strcasecmp(data, "minrate")) {
2870  details->minrate = fax_rate_str_to_int(value);
2871  if (!details->minrate) {
2872  details->minrate = ast_fax_minrate();
2873  }
2874  } else if ((!strcasecmp(data, "modem")) || (!strcasecmp(data, "modems"))) {
2875  update_modem_bits(&details->modems, value);
2876  } else {
2877  ast_log(LOG_WARNING, "channel '%s' set FAXOPT(%s) to '%s' is unhandled!\n", chan->name, data, value);
2878  res = -1;
2879  }
2880 
2881  ao2_ref(details, -1);
2882 
2883  return res;
2884 }
const ast_string_field headerinfo
Definition: res_fax.h:137
Definition: ast_expr2.c:325
static unsigned int fax_rate_str_to_int(const char *ratestr)
convert a rate string to a rate
Definition: res_fax.c:690
#define LOG_WARNING
Definition: logger.h:144
int value
Definition: syslog.c:39
static int update_modem_bits(enum ast_fax_modems *bits, const char *value)
Definition: res_fax.c:460
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
#define ao2_ref(o, delta)
Definition: astobj2.h:472
The data communicated between the high level applications and the generic fax function.
Definition: res_fax.h:105
unsigned int ast_fax_minrate(void)
get the minimum supported fax rate
Definition: res_fax.c:452
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is &quot;true&quot;. This function checks to see whether a string passed to it is an indication of an &quot;true&quot; value. It checks to see if the string is &quot;yes&quot;, &quot;true&quot;, &quot;y&quot;, &quot;t&quot;, &quot;on&quot; or &quot;1&quot;.
Definition: utils.c:1533
union ast_fax_session_details::@203 option
unsigned int ast_fax_maxrate(void)
get the maxiumum supported fax rate
Definition: res_fax.c:444
const ast_string_field name
Definition: channel.h:787
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition: strings.h:97
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
unsigned int minrate
Definition: res_fax.h:164
enum ast_fax_modems modems
Definition: res_fax.h:110
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is &quot;false&quot;...
Definition: utils.c:1550
const ast_string_field localstationid
Definition: res_fax.h:137
unsigned int maxrate
Definition: res_fax.h:166
static struct ast_fax_session_details * find_or_create_details(struct ast_channel *chan)
returns a reference counted details structure from the channel&#39;s fax datastore. If the datastore does...
Definition: res_fax.c:417
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:344
static char* ast_fax_caps_to_str ( enum ast_fax_capabilities  caps,
char *  buf,
size_t  bufsize 
)
static

Definition at line 494 of file res_fax.c.

References ast_build_string(), AST_FAX_TECH_AUDIO, AST_FAX_TECH_MULTI_DOC, AST_FAX_TECH_RECEIVE, AST_FAX_TECH_SEND, AST_FAX_TECH_T38, and first.

Referenced by fax_session_new(), and fax_session_reserve().

495 {
496  char *out = buf;
497  size_t size = bufsize;
498  int first = 1;
499 
500  if (caps & AST_FAX_TECH_SEND) {
501  if (!first) {
502  ast_build_string(&buf, &size, ",");
503  }
504  ast_build_string(&buf, &size, "SEND");
505  first = 0;
506  }
507  if (caps & AST_FAX_TECH_RECEIVE) {
508  if (!first) {
509  ast_build_string(&buf, &size, ",");
510  }
511  ast_build_string(&buf, &size, "RECEIVE");
512  first = 0;
513  }
514  if (caps & AST_FAX_TECH_AUDIO) {
515  if (!first) {
516  ast_build_string(&buf, &size, ",");
517  }
518  ast_build_string(&buf, &size, "AUDIO");
519  first = 0;
520  }
521  if (caps & AST_FAX_TECH_T38) {
522  if (!first) {
523  ast_build_string(&buf, &size, ",");
524  }
525  ast_build_string(&buf, &size, "T38");
526  first = 0;
527  }
529  if (!first) {
530  ast_build_string(&buf, &size, ",");
531  }
532  ast_build_string(&buf, &size, "MULTI_DOC");
533  first = 0;
534  }
535 
536  return out;
537 }
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:1521
struct sla_ringing_trunk * first
Definition: app_meetme.c:965
enum ast_fax_capabilities caps
Definition: res_fax.h:108
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 680 of file res_fax.c.

References ast_log(), and ast_log_dynamic_level.

Referenced by spandsp_log().

681 {
682  if (fax_logger_level != -1) {
684  } else {
685  ast_log(level, file, line, function, "%s", msg);
686  }
687 }
#define ast_log_dynamic_level(level,...)
Send a log message to a dynamically registered log level.
Definition: logger.h:229
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static int fax_logger_level
Definition: res_fax.c:213
unsigned int ast_fax_maxrate ( void  )

get the maxiumum supported fax rate

Definition at line 444 of file res_fax.c.

References get_general_options(), and fax_options::maxrate.

Referenced by acf_faxopt_write().

445 {
446  struct fax_options options;
447  get_general_options(&options);
448 
449  return options.maxrate;
450 }
static void get_general_options(struct fax_options *options)
Definition: res_fax.c:2660
unsigned int ast_fax_minrate ( void  )

get the minimum supported fax rate

Definition at line 452 of file res_fax.c.

References get_general_options(), and fax_options::minrate.

Referenced by acf_faxopt_write().

453 {
454  struct fax_options options;
455  get_general_options(&options);
456 
457  return options.minrate;
458 }
static void get_general_options(struct fax_options *options)
Definition: res_fax.c:2660
static int ast_fax_modem_to_str ( enum ast_fax_modems  bits,
char *  tbuf,
size_t  bufsize 
)
static

Definition at line 539 of file res_fax.c.

References AST_FAX_MODEM_V17, AST_FAX_MODEM_V27, 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().

540 {
541  int count = 0;
542 
543  if (bits & AST_FAX_MODEM_V17) {
544  strcat(tbuf, "V17");
545  count++;
546  }
547  if (bits & AST_FAX_MODEM_V27) {
548  if (count) {
549  strcat(tbuf, ",");
550  }
551  strcat(tbuf, "V27");
552  count++;
553  }
554  if (bits & AST_FAX_MODEM_V29) {
555  if (count) {
556  strcat(tbuf, ",");
557  }
558  strcat(tbuf, "V29");
559  count++;
560  }
561  if (bits & AST_FAX_MODEM_V34) {
562  if (count) {
563  strcat(tbuf, ",");
564  }
565  strcat(tbuf, "V34");
566  count++;
567  }
568 
569  return 0;
570 }
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 657 of file res_fax.c.

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

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

658 {
659  switch (state) {
661  return "Uninitialized";
663  return "Initialized";
664  case AST_FAX_STATE_OPEN:
665  return "Open";
667  return "Active";
669  return "Complete";
671  return "Reserved";
673  return "Inactive";
674  default:
675  ast_log(LOG_WARNING, "unhandled FAX state: %u\n", state);
676  return "Unknown";
677  }
678 }
#define LOG_WARNING
Definition: logger.h:144
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int ast_fax_tech_register ( struct ast_fax_tech tech)

register a FAX technology module

register a fax technology

Definition at line 616 of file res_fax.c.

References ast_calloc, ast_module_ref(), AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, ast_fax_tech::description, ast_module_info::self, fax_module::tech, and ast_fax_tech::type.

Referenced by load_module().

617 {
618  struct fax_module *fax;
619 
620  if (!(fax = ast_calloc(1, sizeof(*fax)))) {
621  return -1;
622  }
623  fax->tech = tech;
625  AST_RWLIST_INSERT_TAIL(&faxmodules, fax, list);
628 
629  ast_verb(3, "Registered handler for '%s' (%s)\n", fax->tech->type, fax->tech->description);
630 
631  return 0;
632 }
struct ast_fax_tech * tech
Definition: res_fax.c:242
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
const char *const type
Definition: res_fax.h:210
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
const char *const description
Definition: res_fax.h:212
#define ast_verb(level,...)
Definition: logger.h:243
struct ast_module * self
Definition: module.h:227
registered FAX technology modules are put into this list
Definition: res_fax.c:241
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:726
#define ast_calloc(a, b)
Definition: astmm.h:82
struct ast_module * ast_module_ref(struct ast_module *)
Definition: loader.c:1300
void ast_fax_tech_unregister ( struct ast_fax_tech tech)

unregister a FAX technology module

unregister a fax technology

Definition at line 635 of file res_fax.c.

References ast_free, ast_module_unref(), AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, ast_module_info::self, fax_module::tech, and ast_fax_tech::type.

Referenced by unload_module().

636 {
637  struct fax_module *fax;
638 
639  ast_verb(3, "Unregistering FAX module type '%s'\n", tech->type);
640 
643  if (fax->tech != tech) {
644  continue;
645  }
648  ast_free(fax);
649  ast_verb(4, "Unregistered FAX module type '%s'\n", tech->type);
650  break;
651  }
654 }
struct ast_fax_tech * tech
Definition: res_fax.c:242
void ast_module_unref(struct ast_module *)
Definition: loader.c:1312
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
const char *const type
Definition: res_fax.h:210
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define ast_verb(level,...)
Definition: logger.h:243
struct ast_module * self
Definition: module.h:227
#define AST_RWLIST_REMOVE_CURRENT
Definition: linkedlists.h:565
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:542
#define ast_free(a)
Definition: astmm.h:97
registered FAX technology modules are put into this list
Definition: res_fax.c:241
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:602
static int check_modem_rate ( enum ast_fax_modems  modems,
unsigned int  rate 
)
static

Definition at line 572 of file res_fax.c.

References AST_FAX_MODEM_V17, AST_FAX_MODEM_V27, AST_FAX_MODEM_V29, and AST_FAX_MODEM_V34.

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

573 {
574  switch (rate) {
575  case 2400:
576  if (!(modems & (AST_FAX_MODEM_V34))) {
577  return 1;
578  }
579  break;
580  case 4800:
581  if (!(modems & (AST_FAX_MODEM_V27 | AST_FAX_MODEM_V34))) {
582  return 1;
583  }
584  break;
585  case 7200:
586  if (!(modems & (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V29 | AST_FAX_MODEM_V34))) {
587  return 1;
588  }
589  break;
590  case 9600:
592  return 1;
593  }
594  break;
595  case 12000:
596  case 14400:
597  if (!(modems & (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V34))) {
598  return 1;
599  }
600  break;
601  case 28800:
602  case 33600:
603  if (!(modems & AST_FAX_MODEM_V34)) {
604  return 1;
605  }
606  break;
607  default:
608  /* this should never happen */
609  return 1;
610  }
611 
612  return 0;
613 }
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 2421 of file res_fax.c.

References ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, global_fax_debug, and ast_cli_entry::usage.

2422 {
2423  int flag;
2424  const char *what;
2425 
2426  switch (cmd) {
2427  case CLI_INIT:
2428  e->command = "fax set debug {on|off}";
2429  e->usage =
2430  "Usage: fax set debug { on | off }\n"
2431  " Enable/Disable FAX debugging on new FAX sessions. The basic FAX debugging will result in\n"
2432  " additional events sent to manager sessions with 'call' class permissions. When\n"
2433  " verbosity is greater than '5' events will be displayed to the console and audio versus\n"
2434  " energy analysis will be performed and displayed to the console.\n";
2435  return NULL;
2436  case CLI_GENERATE:
2437  return NULL;
2438  }
2439 
2440  what = a->argv[e->args-1]; /* guaranteed to exist */
2441  if (!strcasecmp(what, "on")) {
2442  flag = 1;
2443  } else if (!strcasecmp(what, "off")) {
2444  flag = 0;
2445  } else {
2446  return CLI_SHOWUSAGE;
2447  }
2448 
2449  global_fax_debug = flag;
2450  ast_cli(a->fd, "\n\nFAX Debug %s\n\n", (flag) ? "Enabled" : "Disabled");
2451 
2452  return CLI_SUCCESS;
2453 }
Definition: cli.h:146
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
int args
This gets set in ast_cli_register()
Definition: cli.h:179
const int fd
Definition: cli.h:153
const char *const * argv
Definition: cli.h:155
#define CLI_SHOWUSAGE
Definition: cli.h:44
char * command
Definition: cli.h:180
static int global_fax_debug
Definition: res_fax.c:277
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
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 2456 of file res_fax.c.

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

2457 {
2458  struct fax_module *fax;
2459  unsigned int num_modules = 0;
2460 
2461  switch (cmd) {
2462  case CLI_INIT:
2463  e->command = "fax show capabilities";
2464  e->usage =
2465  "Usage: fax show capabilities\n"
2466  " Shows the capabilities of the registered FAX technology modules\n";
2467  return NULL;
2468  case CLI_GENERATE:
2469  return NULL;
2470  }
2471 
2472  ast_cli(a->fd, "\n\nRegistered FAX Technology Modules:\n\n");
2474  AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
2475  ast_cli(a->fd, "%-15s : %s\n%-15s : %s\n%-15s : ", "Type", fax->tech->type, "Description", fax->tech->description, "Capabilities");
2476  fax->tech->cli_show_capabilities(a->fd);
2477  num_modules++;
2478  }
2480  ast_cli(a->fd, "%u registered modules\n\n", num_modules);
2481 
2482  return CLI_SUCCESS;
2483 }
struct ast_fax_tech * tech
Definition: res_fax.c:242
const char *const type
Definition: res_fax.h:210
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
Definition: cli.h:146
const char *const description
Definition: res_fax.h:212
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
const int fd
Definition: cli.h:153
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
char * command
Definition: cli.h:180
char *(*const cli_show_capabilities)(int)
Definition: res_fax.h:240
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
registered FAX technology modules are put into this list
Definition: res_fax.c:241
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 2524 of file res_fax.c.

References ao2_find, ao2_ref, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_log(), CLI_GENERATE, CLI_INIT, ast_fax_tech::cli_show_session, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, fax_session_tab_complete(), faxregistry, ast_cli_args::fd, ast_fax_session::id, LOG_ERROR, OBJ_POINTER, RESULT_SUCCESS, ast_fax_session::tech, and ast_cli_entry::usage.

2525 {
2526  struct ast_fax_session *s, tmp;
2527 
2528  switch (cmd) {
2529  case CLI_INIT:
2530  e->command = "fax show session";
2531  e->usage =
2532  "Usage: fax show session <session number>\n"
2533  " Shows status of the named FAX session\n";
2534  return NULL;
2535  case CLI_GENERATE:
2536  return fax_session_tab_complete(a);
2537  }
2538 
2539  if (a->argc != 4) {
2540  return CLI_SHOWUSAGE;
2541  }
2542 
2543  if (sscanf(a->argv[3], "%u", &tmp.id) != 1) {
2544  ast_log(LOG_ERROR, "invalid session id: '%s'\n", a->argv[3]);
2545  return RESULT_SUCCESS;
2546  }
2547 
2548  ast_cli(a->fd, "\nFAX Session Details:\n--------------------\n\n");
2549  s = ao2_find(faxregistry.container, &tmp, OBJ_POINTER);
2550  if (s) {
2551  s->tech->cli_show_session(s, a->fd);
2552  ao2_ref(s, -1);
2553  }
2554  ast_cli(a->fd, "\n\n");
2555 
2556  return CLI_SUCCESS;
2557 }
unsigned int id
Definition: res_fax.h:180
const int argc
Definition: cli.h:154
Definition: cli.h:146
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
static struct @331 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.
char *(*const cli_show_session)(struct ast_fax_session *, int)
Definition: res_fax.h:242
const int fd
Definition: cli.h:153
#define ao2_ref(o, delta)
Definition: astobj2.h:472
const char *const * argv
Definition: cli.h:155
#define LOG_ERROR
Definition: logger.h:155
#define CLI_SHOWUSAGE
Definition: cli.h:44
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
struct ast_fax_tech * tech
Definition: res_fax.h:190
#define ao2_find(arg1, arg2, arg3)
Definition: astobj2.h:964
char * command
Definition: cli.h:180
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
The data required to handle a fax session.
Definition: res_fax.h:178
static char * fax_session_tab_complete(struct ast_cli_args *a)
fax session tab completion
Definition: res_fax.c:2361
#define RESULT_SUCCESS
Definition: cli.h:39
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 2593 of file res_fax.c.

References ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_cli(), ast_fax_state_to_str(), AST_FAX_TECH_AUDIO, AST_FAX_TECH_SEND, ast_free, ast_log(), ast_fax_session_details::caps, ast_fax_session::channame, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_fax_session::details, faxregistry, ast_cli_args::fd, generate_filenames_string(), ast_fax_session::id, LOG_ERROR, session_count, ast_fax_session::state, ast_fax_session::tech, ast_fax_tech::type, and ast_cli_entry::usage.

2594 {
2595  struct ast_fax_session *s;
2596  struct ao2_iterator i;
2597  int session_count;
2598  char *filenames;
2599 
2600  switch (cmd) {
2601  case CLI_INIT:
2602  e->command = "fax show sessions";
2603  e->usage =
2604  "Usage: fax show sessions\n"
2605  " Shows the current FAX sessions\n";
2606  return NULL;
2607  case CLI_GENERATE:
2608  return NULL;
2609  }
2610 
2611  ast_cli(a->fd, "\nCurrent FAX Sessions:\n\n");
2612  ast_cli(a->fd, "%-20.20s %-10.10s %-10.10s %-5.5s %-10.10s %-15.15s %-30.30s\n",
2613  "Channel", "Tech", "FAXID", "Type", "Operation", "State", "File(s)");
2614  i = ao2_iterator_init(faxregistry.container, 0);
2615  while ((s = ao2_iterator_next(&i))) {
2616  ao2_lock(s);
2617 
2618  if (!(filenames = generate_filenames_string(s->details, "", ", "))) {
2619  ast_log(LOG_ERROR, "Error printing filenames for 'fax show sessions' command\n");
2620  ao2_unlock(s);
2621  ao2_ref(s, -1);
2623  return CLI_FAILURE;
2624  }
2625 
2626  ast_cli(a->fd, "%-20.20s %-10.10s %-10u %-5.5s %-10.10s %-15.15s %-30s\n",
2627  s->channame, s->tech->type, s->id,
2628  (s->details->caps & AST_FAX_TECH_AUDIO) ? "G.711" : "T.38",
2629  (s->details->caps & AST_FAX_TECH_SEND) ? "send" : "receive",
2630  ast_fax_state_to_str(s->state), filenames);
2631 
2632  ast_free(filenames);
2633  ao2_unlock(s);
2634  ao2_ref(s, -1);
2635  }
2637  session_count = ao2_container_count(faxregistry.container);
2638  ast_cli(a->fd, "\n%d FAX sessions\n\n", session_count);
2639 
2640  return CLI_SUCCESS;
2641 }
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
Definition: astobj2.c:470
unsigned int id
Definition: res_fax.h:180
#define ao2_iterator_next(arg1)
Definition: astobj2.h:1126
const char *const type
Definition: res_fax.h:210
Definition: cli.h:146
#define ao2_unlock(a)
Definition: astobj2.h:497
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
static struct @331 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.
const int fd
Definition: cli.h:153
#define ao2_ref(o, delta)
Definition: astobj2.h:472
struct ast_fax_session_details * details
Definition: res_fax.h:184
#define ao2_lock(a)
Definition: astobj2.h:488
char * channame
Definition: res_fax.h:196
#define LOG_ERROR
Definition: logger.h:155
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
struct ast_fax_tech * tech
Definition: res_fax.h:190
#define CLI_FAILURE
Definition: cli.h:45
#define ast_free(a)
Definition: astmm.h:97
char * command
Definition: cli.h:180
enum ast_fax_state state
Definition: res_fax.h:194
static int session_count
Definition: http.c:75
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
The data required to handle a fax session.
Definition: res_fax.h:178
const char * ast_fax_state_to_str(enum ast_fax_state state)
convert an ast_fax_state to a string
Definition: res_fax.c:657
enum ast_fax_capabilities caps
Definition: res_fax.h:108
static char * generate_filenames_string(struct ast_fax_session_details *details, char *prefix, char *separator)
Definition: res_fax.c:927
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 2486 of file res_fax.c.

References ast_cli(), ast_fax_modem_to_str(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, ast_fax_tech::cli_show_settings, CLI_SUCCESS, ast_cli_entry::command, ast_fax_tech::description, fax_options::ecm, ast_cli_args::fd, get_general_options(), fax_options::maxrate, fax_options::minrate, fax_options::modems, fax_options::statusevents, fax_module::tech, ast_fax_tech::type, and ast_cli_entry::usage.

2487 {
2488  struct fax_module *fax;
2489  char modems[128] = "";
2490  struct fax_options options;
2491 
2492  switch (cmd) {
2493  case CLI_INIT:
2494  e->command = "fax show settings";
2495  e->usage =
2496  "Usage: fax show settings\n"
2497  " Show the global settings and defaults of both the FAX core and technology modules\n";
2498  return NULL;
2499  case CLI_GENERATE:
2500  return NULL;
2501  }
2502 
2503  get_general_options(&options);
2504 
2505  ast_cli(a->fd, "FAX For Asterisk Settings:\n");
2506  ast_cli(a->fd, "\tECM: %s\n", options.ecm ? "Enabled" : "Disabled");
2507  ast_cli(a->fd, "\tStatus Events: %s\n", options.statusevents ? "On" : "Off");
2508  ast_cli(a->fd, "\tMinimum Bit Rate: %u\n", options.minrate);
2509  ast_cli(a->fd, "\tMaximum Bit Rate: %u\n", options.maxrate);
2510  ast_fax_modem_to_str(options.modems, modems, sizeof(modems));
2511  ast_cli(a->fd, "\tModem Modulations Allowed: %s\n", modems);
2512  ast_cli(a->fd, "\n\nFAX Technology Modules:\n\n");
2514  AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
2515  ast_cli(a->fd, "%s (%s) Settings:\n", fax->tech->type, fax->tech->description);
2516  fax->tech->cli_show_settings(a->fd);
2517  }
2519 
2520  return CLI_SUCCESS;
2521 }
struct ast_fax_tech * tech
Definition: res_fax.c:242
const char *const type
Definition: res_fax.h:210
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
Definition: cli.h:146
const char *const description
Definition: res_fax.h:212
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
const int fd
Definition: cli.h:153
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
char *(*const cli_show_settings)(int)
Definition: res_fax.h:246
char * command
Definition: cli.h:180
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
registered FAX technology modules are put into this list
Definition: res_fax.c:241
static int ast_fax_modem_to_str(enum ast_fax_modems bits, char *tbuf, size_t bufsize)
Definition: res_fax.c:539
static void get_general_options(struct fax_options *options)
Definition: res_fax.c:2660
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 2560 of file res_fax.c.

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

2561 {
2562  struct fax_module *fax;
2563 
2564  switch (cmd) {
2565  case CLI_INIT:
2566  e->command = "fax show stats";
2567  e->usage =
2568  "Usage: fax show stats\n"
2569  " Shows a statistical summary of FAX transmissions\n";
2570  return NULL;
2571  case CLI_GENERATE:
2572  return NULL;
2573  }
2574 
2575  ast_cli(a->fd, "\nFAX Statistics:\n---------------\n\n");
2576  ast_cli(a->fd, "%-20.20s : %d\n", "Current Sessions", faxregistry.active_sessions);
2577  ast_cli(a->fd, "%-20.20s : %d\n", "Reserved Sessions", faxregistry.reserved_sessions);
2578  ast_cli(a->fd, "%-20.20s : %d\n", "Transmit Attempts", faxregistry.fax_tx_attempts);
2579  ast_cli(a->fd, "%-20.20s : %d\n", "Receive Attempts", faxregistry.fax_rx_attempts);
2580  ast_cli(a->fd, "%-20.20s : %d\n", "Completed FAXes", faxregistry.fax_complete);
2581  ast_cli(a->fd, "%-20.20s : %d\n", "Failed FAXes", faxregistry.fax_failures);
2583  AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
2584  fax->tech->cli_show_stats(a->fd);
2585  }
2587  ast_cli(a->fd, "\n\n");
2588 
2589  return CLI_SUCCESS;
2590 }
struct ast_fax_tech * tech
Definition: res_fax.c:242
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
Definition: cli.h:146
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
static struct @331 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
const int fd
Definition: cli.h:153
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
char * command
Definition: cli.h:180
const char * usage
Definition: cli.h:171
char *(*const cli_show_stats)(int)
Definition: res_fax.h:244
#define CLI_SUCCESS
Definition: cli.h:43
registered FAX technology modules are put into this list
Definition: res_fax.c:241
static char* cli_fax_show_version ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 2389 of file res_fax.c.

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

2390 {
2391  struct fax_module *fax;
2392 
2393  switch(cmd) {
2394  case CLI_INIT:
2395  e->command = "fax show version";
2396  e->usage =
2397  "Usage: fax show version\n"
2398  " Show versions of FAX For Asterisk components.\n";
2399  return NULL;
2400  case CLI_GENERATE:
2401  return NULL;
2402  }
2403 
2404  if (a->argc != 3) {
2405  return CLI_SHOWUSAGE;
2406  }
2407 
2408  ast_cli(a->fd, "FAX For Asterisk Components:\n");
2409  ast_cli(a->fd, "\tApplications: %s\n", ast_get_version());
2411  AST_RWLIST_TRAVERSE(&faxmodules, fax, list) {
2412  ast_cli(a->fd, "\t%s: %s\n", fax->tech->description, fax->tech->version);
2413  }
2415  ast_cli(a->fd, "\n");
2416 
2417  return CLI_SUCCESS;
2418 }
struct ast_fax_tech * tech
Definition: res_fax.c:242
const char * ast_get_version(void)
Retrieve the Asterisk version string.
Definition: version.c:14
const int argc
Definition: cli.h:154
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
Definition: cli.h:146
const char *const description
Definition: res_fax.h:212
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
const int fd
Definition: cli.h:153
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
#define CLI_SHOWUSAGE
Definition: cli.h:44
char * command
Definition: cli.h:180
const char *const version
Definition: res_fax.h:214
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
registered FAX technology modules are put into this list
Definition: res_fax.c:241
static void debug_check_frame_for_silence ( struct ast_fax_session s,
unsigned int  c2s,
struct ast_frame frame 
)
static

Definition at line 303 of file res_fax.c.

References ast_dsp_reset(), ast_dsp_silence(), ast_tvnow(), ast_tvsub(), ast_verb, ast_fax_debug_info::base_tv, ast_fax_session::channame, debug_info_history::consec_frames, debug_info_history::consec_ms, ast_fax_session::debug_info, ast_fax_debug_info::dsp, ast_fax_session::id, ast_fax_debug_info::s2c, ast_frame::samples, and debug_info_history::silence.

Referenced by generic_fax_exec().

304 {
305  struct debug_info_history *history = c2s ? &s->debug_info->c2s : &s->debug_info->s2c;
306  int dspsilence;
307  unsigned int last_consec_frames, last_consec_ms;
308  unsigned char wassil;
309  struct timeval diff;
310 
311  diff = ast_tvsub(ast_tvnow(), s->debug_info->base_tv);
312 
314  ast_dsp_silence(s->debug_info->dsp, frame, &dspsilence);
315 
316  wassil = history->silence;
317  history->silence = (dspsilence != 0) ? 1 : 0;
318  if (history->silence != wassil) {
319  last_consec_frames = history->consec_frames;
320  last_consec_ms = history->consec_ms;
321  history->consec_frames = 0;
322  history->consec_ms = 0;
323 
324  if ((last_consec_frames != 0)) {
325  ast_verb(6, "Channel '%s' fax session '%u', [ %.3ld.%.6ld ], %s sent %u frames (%u ms) of %s.\n",
326  s->channame, s->id, (long) diff.tv_sec, (long int) diff.tv_usec,
327  (c2s) ? "channel" : "stack", last_consec_frames, last_consec_ms,
328  (wassil) ? "silence" : "energy");
329  }
330  }
331 
332  history->consec_frames++;
333  history->consec_ms += (frame->samples / 8);
334 }
unsigned int consec_frames
Definition: res_fax.c:202
unsigned int id
Definition: res_fax.h:180
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
#define ast_verb(level,...)
Definition: logger.h:243
struct ast_fax_debug_info * debug_info
Definition: res_fax.h:202
char * channame
Definition: res_fax.h:196
void ast_dsp_reset(struct ast_dsp *dsp)
Reset total silence count.
Definition: dsp.c:1725
unsigned int consec_ms
Definition: res_fax.c:203
struct ast_dsp * dsp
Definition: res_fax.c:210
int ast_dsp_silence(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
Return non-zero if this is silence. Updates &quot;totalsilence&quot; with the total number of seconds of silenc...
Definition: dsp.c:1355
struct timeval base_tv
Definition: res_fax.c:208
struct timeval ast_tvsub(struct timeval a, struct timeval b)
Returns the difference of two timevals a - b.
Definition: utils.c:1601
unsigned char silence
Definition: res_fax.c:204
struct debug_info_history c2s s2c
Definition: res_fax.c:209
int samples
Definition: frame.h:150
static void destroy_callback ( void *  data)
static

Definition at line 336 of file res_fax.c.

References ao2_ref.

337 {
338  if (data) {
339  ao2_ref(data, -1);
340  }
341 }
#define ao2_ref(o, delta)
Definition: astobj2.h:472
static void destroy_session ( void *  session)
static

destroy a FAX session structure

Definition at line 727 of file res_fax.c.

References ao2_ref, ast_atomic_fetchadd_int(), ast_dsp_free(), AST_FAX_STATE_INACTIVE, ast_free, ast_module_unref(), ast_smoother_free(), 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, 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().

728 {
729  struct ast_fax_session *s = session;
730 
731  if (s->tech) {
732  fax_session_release(s, NULL);
733  if (s->tech_pvt) {
734  s->tech->destroy_session(s);
735  }
737  }
738 
739  if (s->details) {
740  ao2_ref(s->details, -1);
741  }
742 
743  if (s->debug_info) {
745  ast_free(s->debug_info);
746  }
747 
748  if (s->smoother) {
750  }
751 
752  if (s->state != AST_FAX_STATE_INACTIVE) {
753  ast_atomic_fetchadd_int(&faxregistry.active_sessions, -1);
754  }
755 
756  ast_free(s->channame);
758 }
void ast_smoother_free(struct ast_smoother *s)
Definition: frame.c:294
void ast_module_unref(struct ast_module *)
Definition: loader.c:1312
void ast_dsp_free(struct ast_dsp *dsp)
Definition: dsp.c:1650
struct ast_smoother * smoother
Definition: res_fax.h:204
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return * the previous value of *p. This can be used to handle reference co...
Definition: lock.h:603
static struct @331 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.
struct ast_fax_debug_info * debug_info
Definition: res_fax.h:202
#define ao2_ref(o, delta)
Definition: astobj2.h:472
struct ast_fax_session_details * details
Definition: res_fax.h:184
char * channame
Definition: res_fax.h:196
struct ast_module * module
Definition: res_fax.h:218
void(*const destroy_session)(struct ast_fax_session *)
Definition: res_fax.h:226
static void fax_session_release(struct ast_fax_session *s, struct ast_fax_tech_token *token)
Definition: res_fax.c:714
struct ast_fax_tech * tech
Definition: res_fax.h:190
#define ast_free(a)
Definition: astmm.h:97
enum ast_fax_state state
Definition: res_fax.h:194
struct ast_dsp * dsp
Definition: res_fax.c:210
The data required to handle a fax session.
Definition: res_fax.h:178
char * chan_uniqueid
Definition: res_fax.h:198
void * tech_pvt
Definition: res_fax.h:192
static void destroy_session_details ( void *  details)
static

destroy a FAX session details structure

Definition at line 371 of file res_fax.c.

References ast_free, AST_LIST_REMOVE_HEAD, ast_string_field_free_memory, ast_fax_session_details::documents, and ast_fax_document::next.

Referenced by session_details_new().

372 {
373  struct ast_fax_session_details *d = details;
374  struct ast_fax_document *doc;
375 
376  while ((doc = AST_LIST_REMOVE_HEAD(&d->documents, next))) {
377  ast_free(doc);
378  }
380 }
The data communicated between the high level applications and the generic fax function.
Definition: res_fax.h:105
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:818
struct ast_fax_documents documents
Definition: res_fax.h:114
#define ast_free(a)
Definition: astmm.h:97
struct ast_fax_document * next
Definition: res_fax.h:98
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:253
static int disable_t38 ( struct ast_channel chan)
static

Definition at line 1092 of file res_fax.c.

References 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, ast_channel::name, ast_frame::ptr, ast_control_t38_parameters::request_response, and ast_frame::subclass.

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

1093 {
1094  int timeout_ms;
1095  struct ast_frame *frame = NULL;
1097  struct timeval start;
1098  int ms;
1099 
1100  ast_debug(1, "Shutting down T.38 on %s\n", chan->name);
1101  if (ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0) {
1102  ast_debug(1, "error while disabling T.38 on channel '%s'\n", chan->name);
1103  return -1;
1104  }
1105 
1106  /* wait up to five seconds for negotiation to complete */
1107  timeout_ms = 5000;
1108  start = ast_tvnow();
1109  while ((ms = ast_remaining_ms(start, timeout_ms))) {
1110  ms = ast_waitfor(chan, ms);
1111 
1112  if (ms == 0) {
1113  break;
1114  }
1115  if (ms < 0) {
1116  ast_debug(1, "error while disabling T.38 on channel '%s'\n", chan->name);
1117  return -1;
1118  }
1119 
1120  if (!(frame = ast_read(chan))) {
1121  return -1;
1122  }
1123  if ((frame->frametype == AST_FRAME_CONTROL) &&
1125  (frame->datalen == sizeof(t38_parameters))) {
1126  struct ast_control_t38_parameters *parameters = frame->data.ptr;
1127 
1128  switch (parameters->request_response) {
1129  case AST_T38_TERMINATED:
1130  ast_debug(1, "Shut down T.38 on %s\n", chan->name);
1131  break;
1132  case AST_T38_REFUSED:
1133  ast_log(LOG_WARNING, "channel '%s' refused to disable T.38\n", chan->name);
1134  ast_frfree(frame);
1135  return -1;
1136  default:
1137  ast_log(LOG_ERROR, "channel '%s' failed to disable T.38\n", chan->name);
1138  ast_frfree(frame);
1139  return -1;
1140  }
1141  ast_frfree(frame);
1142  break;
1143  }
1144  ast_frfree(frame);
1145  }
1146 
1147  if (ms == 0) { /* all done, nothing happened */
1148  ast_debug(1, "channel '%s' timed-out during T.38 shutdown\n", chan->name);
1149  }
1150 
1151  return 0;
1152 }
union ast_frame_subclass subclass
Definition: frame.h:146
void * ptr
Definition: frame.h:160
#define LOG_WARNING
Definition: logger.h:144
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4383
enum ast_control_t38 request_response
Definition: frame.h:412
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:4447
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
int datalen
Definition: frame.h:148
#define LOG_ERROR
Definition: logger.h:155
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
Definition: utils.c:1615
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3539
Data structure associated with a single frame of data.
Definition: frame.h:142
enum ast_frame_type frametype
Definition: frame.h:144
#define ast_frfree(fr)
Definition: frame.h:583
union ast_frame::@172 data
static unsigned int fax_rate_str_to_int ( const char *  ratestr)
static

convert a rate string to a rate

Definition at line 690 of file res_fax.c.

References ast_log(), LOG_ERROR, and LOG_WARNING.

Referenced by acf_faxopt_write(), and set_config().

691 {
692  int rate;
693 
694  if (sscanf(ratestr, "%d", &rate) != 1) {
695  ast_log(LOG_ERROR, "failed to sscanf '%s' to rate\n", ratestr);
696  return 0;
697  }
698  switch (rate) {
699  case 2400:
700  case 4800:
701  case 7200:
702  case 9600:
703  case 12000:
704  case 14400:
705  case 28800:
706  case 33600:
707  return rate;
708  default:
709  ast_log(LOG_WARNING, "ignoring invalid rate '%s'. Valid options are {2400 | 4800 | 7200 | 9600 | 12000 | 14400 | 28800 | 33600}\n", ratestr);
710  return 0;
711  }
712 }
#define LOG_WARNING
Definition: logger.h:144
enum ast_control_t38_rate rate
Definition: frame.h:415
#define LOG_ERROR
Definition: logger.h:155
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
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

Definition at line 810 of file res_fax.c.

References ao2_alloc, ao2_link, ao2_ref, ast_atomic_fetchadd_int(), ast_calloc, 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_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_channel::name, ast_fax_tech::new_session, ast_fax_session_details::option, ast_fax_session::state, ast_fax_session::tech, fax_module::tech, ast_fax_session::tech_pvt, and ast_channel::uniqueid.

Referenced by generic_fax_exec().

811 {
812  struct ast_fax_session *s = NULL;
813  struct fax_module *faxmod;
814  char caps[128] = "";
815 
816  if (reserved) {
817  s = reserved;
818  ao2_ref(reserved, +1);
819 
820  if (s->state == AST_FAX_STATE_RESERVED) {
821  ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, -1);
823  }
824  }
825 
826  if (!s && !(s = ao2_alloc(sizeof(*s), destroy_session))) {
827  return NULL;
828  }
829 
830  ast_atomic_fetchadd_int(&faxregistry.active_sessions, 1);
832 
833  if (details->option.debug && (details->caps & AST_FAX_TECH_AUDIO)) {
834  if (!(s->debug_info = ast_calloc(1, sizeof(*(s->debug_info))))) {
835  fax_session_release(s, token);
836  ao2_ref(s, -1);
837  return NULL;
838  }
839  if (!(s->debug_info->dsp = ast_dsp_new())) {
840  ast_free(s->debug_info);
841  s->debug_info = NULL;
842  fax_session_release(s, token);
843  ao2_ref(s, -1);
844  return NULL;
845  }
847  }
848 
849  if (!(s->channame = ast_strdup(chan->name))) {
850  fax_session_release(s, token);
851  ao2_ref(s, -1);
852  return NULL;
853  }
854 
855  if (!(s->chan_uniqueid = ast_strdup(chan->uniqueid))) {
856  fax_session_release(s, token);
857  ao2_ref(s, -1);
858  return NULL;
859  }
860 
861  s->chan = chan;
862  s->details = details;
863  ao2_ref(s->details, 1);
864 
865  details->id = s->id = ast_atomic_fetchadd_int(&faxregistry.nextsessionname, 1);
866 
867  if (!token) {
868  /* locate a FAX technology module that can handle said requirements */
870  AST_RWLIST_TRAVERSE(&faxmodules, faxmod, list) {
871  if ((faxmod->tech->caps & details->caps) != details->caps) {
872  continue;
873  }
874  ast_debug(4, "Requesting a new FAX session from '%s'.\n", faxmod->tech->description);
875  ast_module_ref(faxmod->tech->module);
876  if (reserved) {
877  /* Balance module ref from reserved session */
878  ast_module_unref(reserved->tech->module);
879  }
880  s->tech = faxmod->tech;
881  break;
882  }
884 
885  if (!faxmod) {
886  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)));
887  ao2_ref(s, -1);
888  return NULL;
889  }
890  }
891 
892  if (!(s->tech_pvt = s->tech->new_session(s, token))) {
893  ast_log(LOG_ERROR, "FAX session failed to initialize.\n");
894  ao2_ref(s, -1);
895  return NULL;
896  }
897  /* link the session to the session container */
898  if (!(ao2_link(faxregistry.container, s))) {
899  ast_log(LOG_ERROR, "failed to add FAX session '%u' to container.\n", s->id);
900  ao2_ref(s, -1);
901  return NULL;
902  }
903  ast_debug(4, "channel '%s' using FAX session '%u'\n", s->channame, s->id);
904 
905  return s;
906 }
struct ast_fax_tech * tech
Definition: res_fax.c:242
#define ao2_link(arg1, arg2)
Definition: astobj2.h:785
void ast_module_unref(struct ast_module *)
Definition: loader.c:1312
const ast_string_field uniqueid
Definition: channel.h:787
#define ast_strdup(a)
Definition: astmm.h:109
unsigned int id
Definition: res_fax.h:180
static char * ast_fax_caps_to_str(enum ast_fax_capabilities caps, char *buf, size_t bufsize)
Definition: res_fax.c:494
struct ast_dsp * ast_dsp_new(void)
Definition: dsp.c:1607
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
static void destroy_session(void *session)
destroy a FAX session structure
Definition: res_fax.c:727
const char *const description
Definition: res_fax.h:212
struct ast_channel * chan
Definition: res_fax.h:200
void *(*const new_session)(struct ast_fax_session *, struct ast_fax_tech_token *)
Definition: res_fax.h:224
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return * the previous value of *p. This can be used to handle reference co...
Definition: lock.h:603
unsigned int id
Definition: res_fax.h:112
static struct @331 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
struct ast_fax_debug_info * debug_info
Definition: res_fax.h:202
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
enum ast_fax_capabilities caps
Definition: res_fax.h:216
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
#define ao2_ref(o, delta)
Definition: astobj2.h:472
struct ast_fax_session_details * details
Definition: res_fax.h:184
char * channame
Definition: res_fax.h:196
struct ast_module * module
Definition: res_fax.h:218
void ast_dsp_set_threshold(struct ast_dsp *dsp, int threshold)
Set threshold value for silence.
Definition: dsp.c:1655
#define LOG_ERROR
Definition: logger.h:155
union ast_fax_session_details::@203 option
static void fax_session_release(struct ast_fax_session *s, struct ast_fax_tech_token *token)
Definition: res_fax.c:714
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:430
struct ast_fax_tech * tech
Definition: res_fax.h:190
#define ast_free(a)
Definition: astmm.h:97
enum ast_fax_state state
Definition: res_fax.h:194
struct ast_dsp * dsp
Definition: res_fax.c:210
registered FAX technology modules are put into this list
Definition: res_fax.c:241
#define ast_calloc(a, b)
Definition: astmm.h:82
The data required to handle a fax session.
Definition: res_fax.h:178
enum ast_fax_capabilities caps
Definition: res_fax.h:108
char * chan_uniqueid
Definition: res_fax.h:198
void * tech_pvt
Definition: res_fax.h:192
struct ast_module * ast_module_ref(struct ast_module *)
Definition: loader.c:1300
static void fax_session_release ( struct ast_fax_session s,
struct ast_fax_tech_token *  token 
)
static

Definition at line 714 of file res_fax.c.

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

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

715 {
716  if (token) {
717  s->tech->release_token(token);
718  }
719 
720  if (s->state == AST_FAX_STATE_RESERVED) {
721  ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, -1);
723  }
724 }
void(*const release_token)(struct ast_fax_tech_token *)
Definition: res_fax.h:222
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return * the previous value of *p. This can be used to handle reference co...
Definition: lock.h:603
static struct @331 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.
struct ast_fax_tech * tech
Definition: res_fax.h:190
enum ast_fax_state state
Definition: res_fax.h:194
static struct ast_fax_session* fax_session_reserve ( struct ast_fax_session_details details,
struct ast_fax_tech_token **  token 
)
static

Definition at line 760 of file res_fax.c.

References ao2_alloc, ao2_ref, ast_atomic_fetchadd_int(), ast_debug, ast_fax_caps_to_str(), AST_FAX_STATE_INACTIVE, AST_FAX_STATE_RESERVED, ast_log(), ast_module_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(), faxregistry, LOG_ERROR, ast_fax_tech::module, ast_fax_tech::reserve_session, ast_fax_session::state, ast_fax_session::tech, and fax_module::tech.

Referenced by receivefax_exec(), and sendfax_exec().

761 {
762  struct ast_fax_session *s;
763  struct fax_module *faxmod;
764  char caps[128] = "";
765 
766  if (!(s = ao2_alloc(sizeof(*s), destroy_session))) {
767  return NULL;
768  }
769 
771 
772  /* locate a FAX technology module that can handle said requirements
773  * Note: the requirements have not yet been finalized as T.38
774  * negotiation has not yet occured. */
776  AST_RWLIST_TRAVERSE(&faxmodules, faxmod, list) {
777  if ((faxmod->tech->caps & details->caps) != details->caps) {
778  continue;
779  }
780  ast_debug(4, "Reserving a FAX session from '%s'.\n", faxmod->tech->description);
781  ast_module_ref(faxmod->tech->module);
782  s->tech = faxmod->tech;
783  break;
784  }
786 
787  if (!faxmod) {
788  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)));
789  ao2_ref(s, -1);
790  return NULL;
791  }
792 
793  if (!s->tech->reserve_session) {
794  ast_debug(1, "Selected FAX technology module (%s) does not support reserving sessions.\n", s->tech->description);
795  return s;
796  }
797 
798  if (!(*token = s->tech->reserve_session(s))) {
799  ao2_ref(s, -1);
800  return NULL;
801  }
802 
804  ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, 1);
805 
806  return s;
807 }
struct ast_fax_tech * tech
Definition: res_fax.c:242
static char * ast_fax_caps_to_str(enum ast_fax_capabilities caps, char *buf, size_t bufsize)
Definition: res_fax.c:494
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
static void destroy_session(void *session)
destroy a FAX session structure
Definition: res_fax.c:727
const char *const description
Definition: res_fax.h:212
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return * the previous value of *p. This can be used to handle reference co...
Definition: lock.h:603
static struct @331 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
struct ast_fax_tech_token *(*const reserve_session)(struct ast_fax_session *)
Definition: res_fax.h:220
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
enum ast_fax_capabilities caps
Definition: res_fax.h:216
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
#define ao2_ref(o, delta)
Definition: astobj2.h:472
struct ast_module * module
Definition: res_fax.h:218
#define LOG_ERROR
Definition: logger.h:155
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:430
struct ast_fax_tech * tech
Definition: res_fax.h:190
enum ast_fax_state state
Definition: res_fax.h:194
registered FAX technology modules are put into this list
Definition: res_fax.c:241
The data required to handle a fax session.
Definition: res_fax.h:178
enum ast_fax_capabilities caps
Definition: res_fax.h:108
struct ast_module * ast_module_ref(struct ast_module *)
Definition: loader.c:1300
static char* fax_session_tab_complete ( struct ast_cli_args a)
static

fax session tab completion

Definition at line 2361 of file res_fax.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_strdup, faxregistry, ast_fax_session::id, ast_cli_args::n, name, ast_cli_args::pos, and ast_cli_args::word.

Referenced by cli_fax_show_session().

2362 {
2363  int tklen;
2364  int wordnum = 0;
2365  char *name = NULL;
2366  struct ao2_iterator i;
2367  struct ast_fax_session *s;
2368  char tbuf[5];
2369 
2370  if (a->pos != 3) {
2371  return NULL;
2372  }
2373 
2374  tklen = strlen(a->word);
2375  i = ao2_iterator_init(faxregistry.container, 0);
2376  while ((s = ao2_iterator_next(&i))) {
2377  snprintf(tbuf, sizeof(tbuf), "%u", s->id);
2378  if (!strncasecmp(a->word, tbuf, tklen) && ++wordnum > a->n) {
2379  name = ast_strdup(tbuf);
2380  ao2_ref(s, -1);
2381  break;
2382  }
2383  ao2_ref(s, -1);
2384  }
2386  return name;
2387 }
#define ast_strdup(a)
Definition: astmm.h:109
unsigned int id
Definition: res_fax.h:180
#define ao2_iterator_next(arg1)
Definition: astobj2.h:1126
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
static struct @331 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.
const int n
Definition: cli.h:159
#define ao2_ref(o, delta)
Definition: astobj2.h:472
static const char name[]
const char * word
Definition: cli.h:157
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
const int pos
Definition: cli.h:158
The data required to handle a fax session.
Definition: res_fax.h:178
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 349 of file res_fax.c.

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

Referenced by acf_faxopt_read(), and find_or_create_details().

350 {
351  struct ast_fax_session_details *details;
352  struct ast_datastore *datastore;
353 
354  ast_channel_lock(chan);
355  if (!(datastore = ast_channel_datastore_find(chan, &fax_datastore, NULL))) {
356  ast_channel_unlock(chan);
357  return NULL;
358  }
359  if (!(details = datastore->data)) {
360  ast_log(LOG_WARNING, "Huh? channel '%s' has a FAX datastore without data!\n", chan->name);
361  ast_channel_unlock(chan);
362  return NULL;
363  }
364  ao2_ref(details, 1);
365  ast_channel_unlock(chan);
366 
367  return details;
368 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
#define LOG_WARNING
Definition: logger.h:144
Structure for a data store object.
Definition: datastore.h:54
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:2604
#define ao2_ref(o, delta)
Definition: astobj2.h:472
The data communicated between the high level applications and the generic fax function.
Definition: res_fax.h:105
static struct ast_datastore_info fax_datastore
Definition: res_fax.c:343
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ast_channel_unlock(chan)
Definition: channel.h:2467
void * data
Definition: datastore.h:56
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 417 of file res_fax.c.

References ao2_ref, ast_channel_datastore_add(), ast_channel_lock, ast_channel_unlock, ast_datastore_alloc(), ast_log(), ast_datastore::data, fax_datastore, find_details(), LOG_WARNING, ast_channel::name, and session_details_new().

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

418 {
419  struct ast_fax_session_details *details;
420  struct ast_datastore *datastore;
421 
422  if ((details = find_details(chan))) {
423  return details;
424  }
425  /* channel does not have one so we must create one */
426  if (!(details = session_details_new())) {
427  ast_log(LOG_WARNING, "channel '%s' can't get a FAX details structure for the datastore!\n", chan->name);
428  return NULL;
429  }
430  if (!(datastore = ast_datastore_alloc(&fax_datastore, NULL))) {
431  ao2_ref(details, -1);
432  ast_log(LOG_WARNING, "channel '%s' can't get a datastore!\n", chan->name);
433  return NULL;
434  }
435  /* add the datastore to the channel and increment the refcount */
436  datastore->data = details;
437  ao2_ref(details, 1);
438  ast_channel_lock(chan);
439  ast_channel_datastore_add(chan, datastore);
440  ast_channel_unlock(chan);
441  return details;
442 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
#define LOG_WARNING
Definition: logger.h:144
Structure for a data store object.
Definition: datastore.h:54
static struct ast_fax_session_details * session_details_new(void)
create a FAX session details structure
Definition: res_fax.c:383
#define ao2_ref(o, delta)
Definition: astobj2.h:472
The data communicated between the high level applications and the generic fax function.
Definition: res_fax.h:105
static struct ast_datastore_info fax_datastore
Definition: res_fax.c:343
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
struct ast_datastore * ast_datastore_alloc(const struct ast_datastore_info *info, const char *uid)
Definition: datastore.c:98
#define ast_channel_unlock(chan)
Definition: channel.h:2467
void * data
Definition: datastore.h:56
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:349
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2590
static char* generate_filenames_string ( struct ast_fax_session_details details,
char *  prefix,
char *  separator 
)
static

Definition at line 927 of file res_fax.c.

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

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

928 {
929  char *filenames, *c;
930  size_t size = 0;
931  int first = 1;
932  struct ast_fax_document *doc;
933 
934  /* don't process empty lists */
935  if (AST_LIST_EMPTY(&details->documents)) {
936  return NULL;
937  }
938 
939  /* Calculate the total length of all of the file names */
940  AST_LIST_TRAVERSE(&details->documents, doc, next) {
941  size += strlen(separator) + strlen(prefix) + strlen(doc->filename);
942  }
943  size += 1; /* add space for the terminating null */
944 
945  if (!(filenames = ast_malloc(size))) {
946  return NULL;
947  }
948  c = filenames;
949 
950  ast_build_string(&c, &size, "%s%s", prefix, AST_LIST_FIRST(&details->documents)->filename);
951  AST_LIST_TRAVERSE(&details->documents, doc, next) {
952  if (first) {
953  first = 0;
954  continue;
955  }
956 
957  ast_build_string(&c, &size, "%s%s%s", separator, prefix, doc->filename);
958  }
959 
960  return filenames;
961 }
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
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:1521
char filename[0]
Definition: res_fax.h:99
struct ast_fax_documents documents
Definition: res_fax.h:114
struct sla_ringing_trunk * first
Definition: app_meetme.c:965
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct ast_fax_document * next
Definition: res_fax.h:98
#define ast_malloc(a)
Definition: astmm.h:91
static char prefix[MAX_PREFIX]
Definition: http.c:107
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 1162 of file res_fax.c.

References ao2_lock, ao2_ref, ao2_unlink, ao2_unlock, ast_atomic_fetchadd_int(), ast_channel_get_t38_state(), ast_channel_lock, ast_channel_unlock, AST_CONTROL_T38_PARAMETERS, ast_debug, AST_FAX_TECH_AUDIO, AST_FAX_TECH_T38, AST_FORMAT_SLINEAR, 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, ast_fax_tech::cancel_session, ast_fax_session_details::caps, chancount, ast_frame_subclass::codec, ast_frame::data, ast_frame::datalen, debug_check_frame_for_silence(), ast_fax_session::debug_info, errno, f, fax_session_new(), faxregistry, ast_fax_session::fd, 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::localstationid, LOG_ERROR, LOG_WARNING, ast_channel::name, ast_fax_session_details::our_t38_parameters, pbx_builtin_getvar_helper(), ast_frame::ptr, ast_fax_tech::read, ast_channel::readformat, report_fax_status(), ast_control_t38_parameters::request_response, RES_FAX_TIMEOUT, 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, ast_fax_tech::write, and ast_channel::writeformat.

Referenced by receivefax_exec(), and sendfax_exec().

1163 {
1164  int ms;
1165  int timeout = RES_FAX_TIMEOUT;
1166  int chancount;
1167  unsigned int expected_frametype = -1;
1168  union ast_frame_subclass expected_framesubclass = { .integer = -1 };
1169  unsigned int t38negotiated = (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED);
1170  struct ast_control_t38_parameters t38_parameters;
1171  const char *tempvar;
1172  struct ast_fax_session *fax = NULL;
1173  struct ast_frame *frame = NULL;
1174  struct ast_channel *c = chan;
1175  unsigned int orig_write_format = 0, orig_read_format = 0;
1176  int remaining_time;
1177  struct timeval start;
1178 
1179  chancount = 1;
1180 
1181  /* create the FAX session */
1182  if (!(fax = fax_session_new(details, chan, reserved, token))) {
1183  ast_log(LOG_ERROR, "Can't create a FAX session, FAX attempt failed.\n");
1184  report_fax_status(chan, details, "No Available Resource");
1185  return -1;
1186  }
1187 
1188  ast_channel_lock(chan);
1189  /* update session details */
1190  if (ast_strlen_zero(details->headerinfo) && (tempvar = pbx_builtin_getvar_helper(chan, "LOCALHEADERINFO"))) {
1191  ast_string_field_set(details, headerinfo, tempvar);
1192  }
1193  if (ast_strlen_zero(details->localstationid)) {
1194  tempvar = pbx_builtin_getvar_helper(chan, "LOCALSTATIONID");
1195  ast_string_field_set(details, localstationid, tempvar ? tempvar : "unknown");
1196  }
1197  ast_channel_unlock(chan);
1198 
1199  report_fax_status(chan, details, "Allocating Resources");
1200 
1201  if (details->caps & AST_FAX_TECH_AUDIO) {
1202  expected_frametype = AST_FRAME_VOICE;;
1203  expected_framesubclass.codec = AST_FORMAT_SLINEAR;
1204  orig_write_format = chan->writeformat;
1205  if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
1206  ast_log(LOG_ERROR, "channel '%s' failed to set write format to signed linear'.\n", chan->name);
1207  ao2_lock(faxregistry.container);
1208  ao2_unlink(faxregistry.container, fax);
1209  ao2_unlock(faxregistry.container);
1210  ao2_ref(fax, -1);
1211  ast_channel_unlock(chan);
1212  return -1;
1213  }
1214  orig_read_format = chan->readformat;
1215  if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0) {
1216  ast_log(LOG_ERROR, "channel '%s' failed to set read format to signed linear.\n", chan->name);
1217  ao2_lock(faxregistry.container);
1218  ao2_unlink(faxregistry.container, fax);
1219  ao2_unlock(faxregistry.container);
1220  ao2_ref(fax, -1);
1221  ast_channel_unlock(chan);
1222  return -1;
1223  }
1224  if (fax->smoother) {
1226  fax->smoother = NULL;
1227  }
1228  if (!(fax->smoother = ast_smoother_new(320))) {
1229  ast_log(LOG_WARNING, "Channel '%s' FAX session '%u' failed to obtain a smoother.\n", chan->name, fax->id);
1230  }
1231  } else {
1232  expected_frametype = AST_FRAME_MODEM;
1233  expected_framesubclass.codec = AST_MODEM_T38;
1234  }
1235 
1236  if (fax->debug_info) {
1237  fax->debug_info->base_tv = ast_tvnow();
1238  }
1239 
1240  /* reset our result fields just in case the fax tech driver wants to
1241  * set custom error messages */
1242  ast_string_field_set(details, result, "");
1243  ast_string_field_set(details, resultstr, "");
1244  ast_string_field_set(details, error, "");
1245  set_channel_variables(chan, details);
1246 
1247  if (fax->tech->start_session(fax) < 0) {
1248  GENERIC_FAX_EXEC_ERROR(fax, chan, "INIT_ERROR", "failed to start FAX session");
1249  }
1250 
1251  report_fax_status(chan, details, "FAX Transmission In Progress");
1252 
1253  ast_debug(5, "channel %s will wait on FAX fd %d\n", chan->name, fax->fd);
1254 
1255  /* handle frames for the session */
1256  remaining_time = timeout;
1257  start = ast_tvnow();
1258  while (remaining_time > 0) {
1259  struct ast_channel *ready_chan;
1260  int ofd, exception;
1261 
1262  ms = 1000;
1263  errno = 0;
1264  ready_chan = ast_waitfor_nandfds(&c, chancount, &fax->fd, 1, &exception, &ofd, &ms);
1265  if (ready_chan) {
1266  if (!(frame = ast_read(chan))) {
1267  /* the channel is probably gone, so lets stop polling on it and let the
1268  * FAX session complete before we exit the application. if needed,
1269  * send the FAX stack silence so the modems can finish their session without
1270  * any problems */
1271  ast_debug(1, "Channel '%s' did not return a frame; probably hung up.\n", chan->name);
1272  GENERIC_FAX_EXEC_SET_VARS(fax, chan, "HANGUP", "remote channel hungup");
1273  c = NULL;
1274  chancount = 0;
1275  remaining_time = ast_remaining_ms(start, timeout);
1276  fax->tech->cancel_session(fax);
1277  if (fax->tech->generate_silence) {
1278  fax->tech->generate_silence(fax);
1279  }
1280  continue;
1281  }
1282 
1283  if ((frame->frametype == AST_FRAME_CONTROL) &&
1285  (frame->datalen == sizeof(t38_parameters))) {
1286  unsigned int was_t38 = t38negotiated;
1287  struct ast_control_t38_parameters *parameters = frame->data.ptr;
1288 
1289  switch (parameters->request_response) {
1291  /* the other end has requested a switch to T.38, so reply that we are willing, if we can
1292  * do T.38 as well
1293  */
1294  t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
1295  t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
1296  ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
1297  break;
1298  case AST_T38_NEGOTIATED:
1299  t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
1300  t38negotiated = 1;
1301  break;
1302  default:
1303  break;
1304  }
1305  if (t38negotiated && !was_t38) {
1306  fax->tech->switch_to_t38(fax);
1307  details->caps &= ~AST_FAX_TECH_AUDIO;
1308  expected_frametype = AST_FRAME_MODEM;
1309  expected_framesubclass.codec = AST_MODEM_T38;
1310  if (fax->smoother) {
1312  fax->smoother = NULL;
1313  }
1314 
1315  report_fax_status(chan, details, "T.38 Negotiated");
1316 
1317  ast_verb(3, "Channel '%s' switched to T.38 FAX session '%u'.\n", chan->name, fax->id);
1318  }
1319  } else if ((frame->frametype == expected_frametype) &&
1320  (!memcmp(&frame->subclass, &expected_framesubclass, sizeof(frame->subclass)))) {
1321  struct ast_frame *f;
1322 
1323  if (fax->smoother) {
1324  /* push the frame into a smoother */
1325  if (ast_smoother_feed(fax->smoother, frame) < 0) {
1326  GENERIC_FAX_EXEC_ERROR(fax, chan, "UNKNOWN", "Failed to feed the smoother");
1327  }
1328  while ((f = ast_smoother_read(fax->smoother)) && (f->data.ptr)) {
1329  if (fax->debug_info) {
1330  debug_check_frame_for_silence(fax, 1, f);
1331  }
1332  /* write the frame to the FAX stack */
1333  fax->tech->write(fax, f);
1334  fax->frames_received++;
1335  if (f != frame) {
1336  ast_frfree(f);
1337  }
1338  }
1339  } else {
1340  /* write the frame to the FAX stack */
1341  fax->tech->write(fax, frame);
1342  fax->frames_received++;
1343  }
1344  start = ast_tvnow();
1345  }
1346  ast_frfree(frame);
1347  } else if (ofd == fax->fd) {
1348  /* read a frame from the FAX stack and send it out the channel.
1349  * the FAX stack will return a NULL if the FAX session has already completed */
1350  if (!(frame = fax->tech->read(fax))) {
1351  break;
1352  }
1353 
1354  if (fax->debug_info && (frame->frametype == AST_FRAME_VOICE)) {
1355  debug_check_frame_for_silence(fax, 0, frame);
1356  }
1357 
1358  ast_write(chan, frame);
1359  fax->frames_sent++;
1360  ast_frfree(frame);
1361  start = ast_tvnow();
1362  } else {
1363  if (ms && (ofd < 0)) {
1364  if ((errno == 0) || (errno == EINTR)) {
1365  remaining_time = ast_remaining_ms(start, timeout);
1366  if (remaining_time <= 0)
1367  GENERIC_FAX_EXEC_ERROR(fax, chan, "TIMEOUT", "fax session timed-out");
1368  continue;
1369  } else {
1370  ast_log(LOG_WARNING, "something bad happened while channel '%s' was polling.\n", chan->name);
1371  GENERIC_FAX_EXEC_ERROR(fax, chan, "UNKNOWN", "error polling data");
1372  break;
1373  }
1374  } else {
1375  /* nothing happened */
1376  remaining_time = ast_remaining_ms(start, timeout);
1377  if (remaining_time <= 0) {
1378  GENERIC_FAX_EXEC_ERROR(fax, chan, "TIMEOUT", "fax session timed-out");
1379  break;
1380  }
1381  }
1382  }
1383  }
1384  ast_debug(3, "channel '%s' - event loop stopped { timeout: %d, remaining_time: %d }\n", chan->name, timeout, remaining_time);
1385 
1386  set_channel_variables(chan, details);
1387 
1388  if (!strcasecmp(details->result, "FAILED")) {
1389  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1390  } else {
1391  ast_atomic_fetchadd_int(&faxregistry.fax_complete, 1);
1392  }
1393 
1394  if (fax) {
1395  ao2_lock(faxregistry.container);
1396  ao2_unlink(faxregistry.container, fax);
1397  ao2_unlock(faxregistry.container);
1398  ao2_ref(fax, -1);
1399  }
1400 
1401  /* if the channel is still alive, and we changed its read/write formats,
1402  * restore them now
1403  */
1404  if (chancount) {
1405  if (orig_read_format) {
1406  ast_set_read_format(chan, orig_read_format);
1407  }
1408  if (orig_write_format) {
1409  ast_set_write_format(chan, orig_write_format);
1410  }
1411  }
1412 
1413  /* return the chancount so the calling function can determine if the channel hungup during this FAX session or not */
1414  return chancount;
1415 }
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:2417
const ast_string_field result
Definition: res_fax.h:137
union ast_frame_subclass subclass
Definition: frame.h:146
#define GENERIC_FAX_EXEC_ERROR(fax, chan, errorstr, reason)
Definition: res_fax.c:1031
struct ast_smoother * ast_smoother_new(int bytes)
Definition: frame.c:183
#define ast_channel_lock(chan)
Definition: channel.h:2466
Main Channel structure associated with a channel.
Definition: channel.h:742
void ast_smoother_free(struct ast_smoother *s)
Definition: frame.c:294
int(*const start_session)(struct ast_fax_session *)
Definition: res_fax.h:232
int(*const switch_to_t38)(struct ast_fax_session *)
Definition: res_fax.h:238
unsigned long frames_sent
Definition: res_fax.h:188
const ast_string_field headerinfo
Definition: res_fax.h:137
format_t writeformat
Definition: channel.h:854
unsigned long frames_received
Definition: res_fax.h:186
unsigned int id
Definition: res_fax.h:180
struct ast_frame * ast_smoother_read(struct ast_smoother *s)
Definition: frame.c:244
void * ptr
Definition: frame.h:160
int(*const cancel_session)(struct ast_fax_session *)
Definition: res_fax.h:234
#define LOG_WARNING
Definition: logger.h:144
static void t38_parameters_ast_to_fax(struct ast_fax_t38_parameters *dst, const struct ast_control_t38_parameters *src)
Definition: res_fax.c:1037
static void t38_parameters_fax_to_ast(struct ast_control_t38_parameters *dst, const struct ast_fax_t38_parameters *src)
Definition: res_fax.c:1048
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4383
struct ast_smoother * smoother
Definition: res_fax.h:204
enum ast_control_t38 request_response
Definition: frame.h:412
#define AST_MODEM_T38
Definition: frame.h:216
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:4447
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
#define ao2_unlock(a)
Definition: astobj2.h:497
format_t codec
Definition: frame.h:137
struct ast_channel * ast_waitfor_nandfds(struct ast_channel **chan, int n, int *fds, int nfds, int *exception, int *outfd, int *ms)
Waits for activity on a group of channels.
Definition: channel.c:3188
#define ast_verb(level,...)
Definition: logger.h:243
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return * the previous value of *p. This can be used to handle reference co...
Definition: lock.h:603
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
Definition: pbx.c:10475
static struct @331 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.
int ast_set_write_format(struct ast_channel *chan, format_t format)
Sets write format on channel chan Set write format for channel to whichever component of &quot;format&quot; is ...
Definition: channel.c:5307
struct ast_fax_debug_info * debug_info
Definition: res_fax.h:202
int ast_set_read_format(struct ast_channel *chan, format_t format)
Sets read format on channel chan Set read format for channel to whichever component of &quot;format&quot; is be...
Definition: channel.c:5301
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
#define GENERIC_FAX_EXEC_SET_VARS(fax, chan, errorstr, reason)
Definition: res_fax.c:1015
struct ast_fax_t38_parameters our_t38_parameters
Definition: res_fax.h:168
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
int datalen
Definition: frame.h:148
#define ao2_ref(o, delta)
Definition: astobj2.h:472
#define ao2_lock(a)
Definition: astobj2.h:488
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:810
#define LOG_ERROR
Definition: logger.h:155
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
Definition: utils.c:1615
static void set_channel_variables(struct ast_channel *chan, struct ast_fax_session_details *details)
Set fax related channel variables.
Definition: res_fax.c:1000
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
struct ast_fax_tech * tech
Definition: res_fax.h:190
#define ast_channel_unlock(chan)
Definition: channel.h:2467
int errno
static struct ast_format f[]
Definition: format_g726.c:181
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:4916
int(*const write)(struct ast_fax_session *, const struct ast_frame *)
Definition: res_fax.h:230
#define AST_FORMAT_SLINEAR
Definition: frame.h:254
static int chancount
Definition: channel.c:102
format_t readformat
Definition: channel.h:853
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:964
The data required to handle a fax session.
Definition: res_fax.h:178
struct timeval base_tv
Definition: res_fax.c:208
static void debug_check_frame_for_silence(struct ast_fax_session *s, unsigned int c2s, struct ast_frame *frame)
Definition: res_fax.c:303
Data structure associated with a single frame of data.
Definition: frame.h:142
enum ast_fax_capabilities caps
Definition: res_fax.h:108
#define RES_FAX_TIMEOUT
Definition: res_fax.c:218
enum ast_frame_type frametype
Definition: frame.h:144
struct ast_frame *(*const read)(struct ast_fax_session *)
Definition: res_fax.h:228
const ast_string_field localstationid
Definition: res_fax.h:137
#define ast_frfree(fr)
Definition: frame.h:583
struct ast_fax_t38_parameters their_t38_parameters
Definition: res_fax.h:170
union ast_frame::@172 data
#define ao2_unlink(arg1, arg2)
Definition: astobj2.h:817
int(*const generate_silence)(struct ast_fax_session *)
Definition: res_fax.h:236
#define ast_smoother_feed(s, f)
Definition: frame.h:686
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:344
static void get_general_options ( struct fax_options options)
static

Definition at line 2660 of file res_fax.c.

References ast_rwlock_rdlock, ast_rwlock_unlock, general_options, and options_lock.

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

2661 {
2663  *options = general_options;
2665 }
#define ast_rwlock_rdlock(a)
Definition: lock.h:201
static ast_rwlock_t options_lock
Definition: res_fax.c:270
#define ast_rwlock_unlock(a)
Definition: lock.h:200
static struct fax_options general_options
Definition: res_fax.c:260
static void get_manager_event_info ( struct ast_channel chan,
struct manager_event_info info 
)
static

Definition at line 908 of file res_fax.c.

References manager_event_info::cid, manager_event_info::context, manager_event_info::exten, and pbx_substitute_variables_helper().

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

909 {
910  pbx_substitute_variables_helper(chan, "${CONTEXT}", info->context, sizeof(info->context));
911  pbx_substitute_variables_helper(chan, "${EXTEN}", info->exten, sizeof(info->exten));
912  pbx_substitute_variables_helper(chan, "${CALLERID(num)}", info->cid, sizeof(info->cid));
913 }
void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
Definition: pbx.c:4676
char cid[128]
Definition: res_fax.c:300
char context[AST_MAX_CONTEXT]
Definition: res_fax.c:298
char exten[AST_MAX_EXTENSION]
Definition: res_fax.c:299
static int load_module ( void  )
static

load res_fax

Definition at line 2920 of file res_fax.c.

References acf_faxopt, ao2_container_alloc, ao2_ref, ARRAY_LEN, ast_cli_register_multiple(), ast_custom_function_register, ast_log(), ast_logger_register_level(), AST_MODULE_LOAD_DECLINE, ast_register_application_xml, ast_unregister_application(), config, fax_cli, FAX_MAXBUCKETS, faxregistry, LOG_ERROR, LOG_WARNING, receivefax_exec(), sendfax_exec(), session_cmp_cb(), session_hash_cb(), and set_config().

2921 {
2922  int res;
2923 
2924  /* initialize the registry */
2925  faxregistry.active_sessions = 0;
2926  faxregistry.reserved_sessions = 0;
2928  return AST_MODULE_LOAD_DECLINE;
2929  }
2930 
2931  if (set_config(0) < 0) {
2932  ast_log(LOG_ERROR, "failed to load configuration file '%s'\n", config);
2933  ao2_ref(faxregistry.container, -1);
2934  return AST_MODULE_LOAD_DECLINE;
2935  }
2936 
2937  /* register CLI operations and applications */
2939  ast_log(LOG_WARNING, "failed to register '%s'.\n", app_sendfax);
2940  ao2_ref(faxregistry.container, -1);
2941  return AST_MODULE_LOAD_DECLINE;
2942  }
2944  ast_log(LOG_WARNING, "failed to register '%s'.\n", app_receivefax);
2946  ao2_ref(faxregistry.container, -1);
2947  return AST_MODULE_LOAD_DECLINE;
2948  }
2952 
2953  return res;
2954 }
static int receivefax_exec(struct ast_channel *chan, const char *data)
initiate a receive FAX session
Definition: res_fax.c:1579
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static const char app_sendfax[]
Definition: res_fax.c:199
#define LOG_WARNING
Definition: logger.h:144
static int session_hash_cb(const void *obj, const int flags)
hash callback for ao2
Definition: res_fax.c:2345
static int session_cmp_cb(void *obj, void *arg, int flags)
compare callback for ao2
Definition: res_fax.c:2353
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx.c:7705
static struct @331 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.
static const char app_receivefax[]
Definition: res_fax.c:198
#define ao2_ref(o, delta)
Definition: astobj2.h:472
static int sendfax_exec(struct ast_channel *chan, const char *data)
initiate a send FAX session
Definition: res_fax.c:2067
int ast_logger_register_level(const char *name)
Register a new logger level.
Definition: logger.c:1627
#define LOG_ERROR
Definition: logger.h:155
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define FAX_MAXBUCKETS
maximum buckets for res_fax ao2 containers
Definition: res_fax.c:216
static int fax_logger_level
Definition: res_fax.c:213
static const char * config
Definition: res_fax.c:275
static int set_config(int reload)
configure res_fax
Definition: res_fax.c:2668
#define ao2_container_alloc(arg1, arg2, arg3)
Definition: astobj2.h:734
int ast_cli_register_multiple(struct ast_cli_entry *e, int len)
Register multiple commands.
Definition: cli.c:2167
static struct ast_cli_entry fax_cli[]
Definition: res_fax.c:2643
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1164
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:437
struct ast_custom_function acf_faxopt
FAXOPT dialplan function.
Definition: res_fax.c:2887
static int receivefax_exec ( struct ast_channel chan,
const char *  data 
)
static

initiate a receive FAX session

Definition at line 1579 of file res_fax.c.

References ast_channel::_state, ast_fax_session_details::allow_audio, ao2_ref, args, ast_answer(), AST_APP_ARG, ast_app_parse_options(), ast_atomic_fetchadd_int(), ast_calloc, ast_channel_get_t38_state(), ast_channel_lock, ast_channel_unlock, ast_debug, AST_DECLARE_APP_ARGS, ast_fax_modem_to_str(), AST_FAX_OPTFLAG_TRUE, AST_FAX_TECH_RECEIVE, AST_FAX_TECH_T38, AST_LIST_INSERT_TAIL, ast_log(), AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_verb, ast_fax_session_details::caps, check_modem_rate(), manager_event_info::cid, manager_event_info::context, ast_fax_session_details::debug, disable_t38(), ast_fax_session_details::documents, EVENT_FLAG_CALL, manager_event_info::exten, fax_exec_options, fax_session_release(), fax_session_reserve(), faxregistry, ast_fax_document::filename, find_or_create_details(), generic_fax_exec(), get_manager_event_info(), global_fax_debug, LOG_ERROR, LOG_WARNING, manager_event, ast_fax_session_details::maxrate, ast_fax_session_details::minrate, ast_fax_session_details::modems, ast_channel::name, OPT_ALLOWAUDIO, OPT_CALLEDMODE, OPT_CALLERMODE, OPT_DEBUG, OPT_STATUS, ast_fax_session_details::option, parse(), pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), receivefax_t38_init(), S_OR, ast_fax_session_details::send_ced, set_channel_variables(), set_fax_t38_caps(), ast_fax_session_details::statusevents, T38_STATE_NEGOTIATED, and T38_STATE_UNAVAILABLE.

Referenced by load_module().

1580 {
1581  char *parse, modems[128] = "";
1582  int channel_alive;
1583  struct ast_fax_session_details *details;
1584  struct ast_fax_session *s;
1585  struct ast_fax_tech_token *token = NULL;
1586  struct ast_fax_document *doc;
1589  AST_APP_ARG(options);
1590  );
1591  struct ast_flags opts = { 0, };
1592  struct manager_event_info info;
1593 
1594  /* initialize output channel variables */
1595  pbx_builtin_setvar_helper(chan, "FAXSTATUS", "FAILED");
1596  pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", NULL);
1597  pbx_builtin_setvar_helper(chan, "FAXPAGES", "0");
1598  pbx_builtin_setvar_helper(chan, "FAXBITRATE", NULL);
1599  pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", NULL);
1600 
1601  /* if we ran receivefax then we attempted to receive a fax, even if we
1602  * never start a fax session */
1603  ast_atomic_fetchadd_int(&faxregistry.fax_rx_attempts, 1);
1604 
1605  /* Get a FAX session details structure from the channel's FAX datastore and create one if
1606  * it does not already exist. */
1607  if (!(details = find_or_create_details(chan))) {
1608  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1609  pbx_builtin_setvar_helper(chan, "FAXERROR", "MEMORY_ERROR");
1610  pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "error allocating memory");
1611  ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
1612  return -1;
1613  }
1614 
1615  ast_string_field_set(details, result, "FAILED");
1616  ast_string_field_set(details, resultstr, "error starting fax session");
1617  ast_string_field_set(details, error, "INIT_ERROR");
1618  set_channel_variables(chan, details);
1619 
1620  if (details->maxrate < details->minrate) {
1621  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1622  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
1623  ast_string_field_set(details, resultstr, "maxrate is less than minrate");
1624  set_channel_variables(chan, details);
1625  ast_log(LOG_ERROR, "maxrate %u is less than minrate %u\n", details->maxrate, details->minrate);
1626  ao2_ref(details, -1);
1627  return -1;
1628  }
1629 
1630  if (check_modem_rate(details->modems, details->minrate)) {
1631  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1632  ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
1633  ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %u\n", modems, details->minrate);
1634  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
1635  ast_string_field_set(details, resultstr, "incompatible 'modems' and 'minrate' settings");
1636  set_channel_variables(chan, details);
1637  ao2_ref(details, -1);
1638  return -1;
1639  }
1640 
1641  if (check_modem_rate(details->modems, details->maxrate)) {
1642  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1643  ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
1644  ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %u\n", modems, details->maxrate);
1645  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
1646  ast_string_field_set(details, resultstr, "incompatible 'modems' and 'maxrate' settings");
1647  set_channel_variables(chan, details);
1648  ao2_ref(details, -1);
1649  return -1;
1650  }
1651 
1652  if (ast_strlen_zero(data)) {
1653  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1654  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
1655  ast_string_field_set(details, resultstr, "invalid arguments");
1656  set_channel_variables(chan, details);
1657  ast_log(LOG_WARNING, "%s requires an argument (filename[,options])\n", app_receivefax);
1658  ao2_ref(details, -1);
1659  return -1;
1660  }
1661  parse = ast_strdupa(data);
1662  AST_STANDARD_APP_ARGS(args, parse);
1663 
1664  if (!ast_strlen_zero(args.options) &&
1665  ast_app_parse_options(fax_exec_options, &opts, NULL, args.options)) {
1666  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1667  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
1668  ast_string_field_set(details, resultstr, "invalid arguments");
1669  set_channel_variables(chan, details);
1670  ao2_ref(details, -1);
1671  return -1;
1672  }
1673  if (ast_strlen_zero(args.filename)) {
1674  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1675  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
1676  ast_string_field_set(details, resultstr, "invalid arguments");
1677  set_channel_variables(chan, details);
1678  ast_log(LOG_WARNING, "%s requires an argument (filename[,options])\n", app_receivefax);
1679  ao2_ref(details, -1);
1680  return -1;
1681  }
1682 
1683  /* check for unsupported FAX application options */
1684  if (ast_test_flag(&opts, OPT_CALLERMODE) || ast_test_flag(&opts, OPT_CALLEDMODE)) {
1685  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1686  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
1687  ast_string_field_set(details, resultstr, "invalid arguments");
1688  set_channel_variables(chan, details);
1689  ast_log(LOG_WARNING, "%s does not support polling\n", app_receivefax);
1690  ao2_ref(details, -1);
1691  return -1;
1692  }
1693 
1694  pbx_builtin_setvar_helper(chan, "FAXERROR", "Channel Problems");
1695  pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "Error before FAX transmission started.");
1696 
1697  if (!(doc = ast_calloc(1, sizeof(*doc) + strlen(args.filename) + 1))) {
1698  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1699  ast_string_field_set(details, error, "MEMORY_ERROR");
1700  ast_string_field_set(details, resultstr, "error allocating memory");
1701  set_channel_variables(chan, details);
1702  ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
1703  ao2_ref(details, -1);
1704  return -1;
1705  }
1706 
1707  strcpy(doc->filename, args.filename);
1708  AST_LIST_INSERT_TAIL(&details->documents, doc, next);
1709 
1710  ast_verb(3, "Channel '%s' receiving FAX '%s'\n", chan->name, args.filename);
1711 
1712  details->caps = AST_FAX_TECH_RECEIVE;
1714 
1715  /* check for debug */
1716  if (ast_test_flag(&opts, OPT_DEBUG) || global_fax_debug) {
1717  details->option.debug = AST_FAX_OPTFLAG_TRUE;
1718  }
1719 
1720  /* check for request for status events */
1721  if (ast_test_flag(&opts, OPT_STATUS)) {
1723  }
1724 
1726  ast_test_flag(&opts, OPT_ALLOWAUDIO)) {
1728  }
1729 
1730  if (!(s = fax_session_reserve(details, &token))) {
1731  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1732  ast_string_field_set(details, resultstr, "error reserving fax session");
1733  set_channel_variables(chan, details);
1734  ast_log(LOG_ERROR, "Unable to reserve FAX session.\n");
1735  ao2_ref(details, -1);
1736  return -1;
1737  }
1738 
1739  /* make sure the channel is up */
1740  if (chan->_state != AST_STATE_UP) {
1741  if (ast_answer(chan)) {
1742  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1743  ast_string_field_set(details, resultstr, "error answering channel");
1744  set_channel_variables(chan, details);
1745  ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", chan->name);
1746  fax_session_release(s, token);
1747  ao2_ref(s, -1);
1748  ao2_ref(details, -1);
1749  return -1;
1750  }
1751  }
1752 
1753  if (set_fax_t38_caps(chan, details)) {
1754  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1755  ast_string_field_set(details, error, "T38_NEG_ERROR");
1756  ast_string_field_set(details, resultstr, "error negotiating T.38");
1757  set_channel_variables(chan, details);
1758  fax_session_release(s, token);
1759  ao2_ref(s, -1);
1760  ao2_ref(details, -1);
1761  return -1;
1762  }
1763 
1764  if (details->caps & AST_FAX_TECH_T38) {
1765  if (receivefax_t38_init(chan, details)) {
1766  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1767  ast_string_field_set(details, error, "T38_NEG_ERROR");
1768  ast_string_field_set(details, resultstr, "error negotiating T.38");
1769  set_channel_variables(chan, details);
1770  fax_session_release(s, token);
1771  ao2_ref(s, -1);
1772  ao2_ref(details, -1);
1773  ast_log(LOG_ERROR, "error initializing channel '%s' in T.38 mode\n", chan->name);
1774  return -1;
1775  }
1776  }
1777 
1778  if ((channel_alive = generic_fax_exec(chan, details, s, token)) < 0) {
1779  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
1780  }
1781 
1783  if (disable_t38(chan)) {
1784  ast_debug(1, "error disabling T.38 mode on %s\n", chan->name);
1785  }
1786  }
1787 
1788  /* send out the AMI completion event */
1789  ast_channel_lock(chan);
1790 
1791  get_manager_event_info(chan, &info);
1793  "ReceiveFAX",
1794  "Channel: %s\r\n"
1795  "Context: %s\r\n"
1796  "Exten: %s\r\n"
1797  "CallerID: %s\r\n"
1798  "RemoteStationID: %s\r\n"
1799  "LocalStationID: %s\r\n"
1800  "PagesTransferred: %s\r\n"
1801  "Resolution: %s\r\n"
1802  "TransferRate: %s\r\n"
1803  "FileName: %s\r\n",
1804  chan->name,
1805  info.context,
1806  info.exten,
1807  info.cid,
1808  S_OR(pbx_builtin_getvar_helper(chan, "REMOTESTATIONID"), ""),
1809  S_OR(pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"), ""),
1810  S_OR(pbx_builtin_getvar_helper(chan, "FAXPAGES"), ""),
1811  S_OR(pbx_builtin_getvar_helper(chan, "FAXRESOLUTION"), ""),
1812  S_OR(pbx_builtin_getvar_helper(chan, "FAXBITRATE"), ""),
1813  args.filename);
1814  ast_channel_unlock(chan);
1815 
1816  ao2_ref(s, -1);
1817  ao2_ref(details, -1);
1818 
1819  /* If the channel hungup return -1; otherwise, return 0 to continue in the dialplan */
1820  return (!channel_alive) ? -1 : 0;
1821 }
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:2417
#define ast_channel_lock(chan)
Definition: channel.h:2466
static int receivefax_t38_init(struct ast_channel *chan, struct ast_fax_session_details *details)
Definition: res_fax.c:1417
#define ast_test_flag(p, flag)
Definition: utils.h:63
static void get_manager_event_info(struct ast_channel *chan, struct manager_event_info *info)
Definition: res_fax.c:908
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:1162
#define LOG_WARNING
Definition: logger.h:144
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: app.c:2101
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
#define EVENT_FLAG_CALL
Definition: manager.h:72
#define ast_verb(level,...)
Definition: logger.h:243
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return * the previous value of *p. This can be used to handle reference co...
Definition: lock.h:603
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
Definition: pbx.c:10475
static struct @331 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static int disable_t38(struct ast_channel *chan)
Definition: res_fax.c:1092
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
static int check_modem_rate(enum ast_fax_modems modems, unsigned int rate)
Definition: res_fax.c:572
static const char app_receivefax[]
Definition: res_fax.c:198
#define ao2_ref(o, delta)
Definition: astobj2.h:472
char filename[0]
Definition: res_fax.h:99
The data communicated between the high level applications and the generic fax function.
Definition: res_fax.h:105
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
static int set_fax_t38_caps(struct ast_channel *chan, struct ast_fax_session_details *details)
Definition: res_fax.c:1059
#define LOG_ERROR
Definition: logger.h:155
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:716
union ast_fax_session_details::@203 option
static void fax_session_release(struct ast_fax_session *s, struct ast_fax_tech_token *token)
Definition: res_fax.c:714
static struct @350 args
static void set_channel_variables(struct ast_channel *chan, struct ast_fax_session_details *details)
Set fax related channel variables.
Definition: res_fax.c:1000
struct ast_fax_documents documents
Definition: res_fax.h:114
enum ast_channel_state _state
Definition: channel.h:839
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
unsigned int minrate
Definition: res_fax.h:164
#define ast_channel_unlock(chan)
Definition: channel.h:2467
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1858
enum ast_fax_modems modems
Definition: res_fax.h:110
static int global_fax_debug
Definition: res_fax.c:277
Structure used to handle boolean flags.
Definition: utils.h:200
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...
Definition: pbx.c:10546
static struct ast_app_option fax_exec_options[128]
Definition: res_fax.c:295
static struct ast_fax_session * fax_session_reserve(struct ast_fax_session_details *details, struct ast_fax_tech_token **token)
Definition: res_fax.c:760
#define ast_calloc(a, b)
Definition: astmm.h:82
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:3086
The data required to handle a fax session.
Definition: res_fax.h:178
enum ast_fax_capabilities caps
Definition: res_fax.h:108
static int ast_fax_modem_to_str(enum ast_fax_modems bits, char *tbuf, size_t bufsize)
Definition: res_fax.c:539
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
unsigned int maxrate
Definition: res_fax.h:166
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:219
static struct ast_fax_session_details * find_or_create_details(struct ast_channel *chan)
returns a reference counted details structure from the channel&#39;s fax datastore. If the datastore does...
Definition: res_fax.c:417
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:344
static int receivefax_t38_init ( struct ast_channel chan,
struct ast_fax_session_details details 
)
static

Definition at line 1417 of file res_fax.c.

References ast_fax_session_details::allow_audio, ast_channel_get_t38_state(), 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, ast_channel::name, ast_fax_session_details::option, ast_fax_session_details::our_t38_parameters, 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, and ast_fax_session_details::their_t38_parameters.

Referenced by receivefax_exec().

1418 {
1419  int timeout_ms;
1420  struct ast_frame *frame = NULL;
1421  struct ast_control_t38_parameters t38_parameters;
1422  struct timeval start;
1423  int ms;
1424 
1426 
1427  /* don't send any audio if we've already received a T.38 reinvite */
1429  /* generate 3 seconds of CED */
1430  if (ast_playtones_start(chan, 1024, "!2100/3000", 1)) {
1431  ast_log(LOG_ERROR, "error generating CED tone on %s\n", chan->name);
1432  return -1;
1433  }
1434 
1435  timeout_ms = 3000;
1436  start = ast_tvnow();
1437  while ((ms = ast_remaining_ms(start, timeout_ms))) {
1438  ms = ast_waitfor(chan, ms);
1439 
1440  if (ms < 0) {
1441  ast_log(LOG_ERROR, "error while generating CED tone on %s\n", chan->name);
1442  ast_playtones_stop(chan);
1443  return -1;
1444  }
1445 
1446  if (ms == 0) { /* all done, nothing happened */
1447  break;
1448  }
1449 
1450  if (!(frame = ast_read(chan))) {
1451  ast_log(LOG_ERROR, "error reading frame while generating CED tone on %s\n", chan->name);
1452  ast_playtones_stop(chan);
1453  return -1;
1454  }
1455 
1456  if ((frame->frametype == AST_FRAME_CONTROL) &&
1458  (frame->datalen == sizeof(t38_parameters))) {
1459  struct ast_control_t38_parameters *parameters = frame->data.ptr;
1460 
1461  switch (parameters->request_response) {
1463  /* the other end has requested a switch to T.38, so reply that we are willing, if we can
1464  * do T.38 as well
1465  */
1466  t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
1467  t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
1468  ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
1469  ast_playtones_stop(chan);
1470  break;
1471  case AST_T38_NEGOTIATED:
1472  ast_debug(1, "Negotiated T.38 for receive on %s\n", chan->name);
1473  t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
1474  details->caps &= ~AST_FAX_TECH_AUDIO;
1475  report_fax_status(chan, details, "T.38 Negotiated");
1476  break;
1477  default:
1478  break;
1479  }
1480  }
1481  ast_frfree(frame);
1482  }
1483 
1484  ast_playtones_stop(chan);
1485  }
1486 
1487  /* if T.38 was negotiated, we are done initializing */
1489  return 0;
1490  }
1491 
1492  /* request T.38 */
1493  ast_debug(1, "Negotiating T.38 for receive on %s\n", chan->name);
1494 
1495  /* wait up to five seconds for negotiation to complete */
1496  timeout_ms = 5000;
1497 
1498  /* set parameters based on the session's parameters */
1499  t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
1500  t38_parameters.request_response = AST_T38_REQUEST_NEGOTIATE;
1501  if ((ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0)) {
1502  return -1;
1503  }
1504 
1505  start = ast_tvnow();
1506  while ((ms = ast_remaining_ms(start, timeout_ms))) {
1507  int break_loop = 0;
1508 
1509  ms = ast_waitfor(chan, ms);
1510  if (ms < 0) {
1511  ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", chan->name);
1512  return -1;
1513  }
1514  if (ms == 0) { /* all done, nothing happened */
1515  ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 negotiation.\n", chan->name);
1516  details->caps &= ~AST_FAX_TECH_T38;
1517  break;
1518  }
1519 
1520  if (!(frame = ast_read(chan))) {
1521  ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", chan->name);
1522  return -1;
1523  }
1524 
1525  if ((frame->frametype == AST_FRAME_CONTROL) &&
1527  (frame->datalen == sizeof(t38_parameters))) {
1528  struct ast_control_t38_parameters *parameters = frame->data.ptr;
1529 
1530  switch (parameters->request_response) {
1532  t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
1533  t38_parameters.request_response = AST_T38_NEGOTIATED;
1534  ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
1535  break;
1536  case AST_T38_NEGOTIATED:
1537  ast_debug(1, "Negotiated T.38 for receive on %s\n", chan->name);
1538  t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
1539  details->caps &= ~AST_FAX_TECH_AUDIO;
1540  report_fax_status(chan, details, "T.38 Negotiated");
1541  break_loop = 1;
1542  break;
1543  case AST_T38_REFUSED:
1544  ast_log(LOG_WARNING, "channel '%s' refused to negotiate T.38\n", chan->name);
1545  details->caps &= ~AST_FAX_TECH_T38;
1546  break_loop = 1;
1547  break;
1548  default:
1549  ast_log(LOG_ERROR, "channel '%s' failed to negotiate T.38\n", chan->name);
1550  details->caps &= ~AST_FAX_TECH_T38;
1551  break_loop = 1;
1552  break;
1553  }
1554  }
1555  ast_frfree(frame);
1556  if (break_loop) {
1557  break;
1558  }
1559  }
1560 
1561  /* if T.38 was negotiated, we are done initializing */
1563  return 0;
1564  }
1565 
1566  /* if we made it here, then T.38 failed, check the 'f' flag */
1567  if (details->option.allow_audio != AST_FAX_OPTFLAG_TRUE) {
1568  ast_log(LOG_WARNING, "Audio FAX not allowed on channel '%s' and T.38 negotiation failed; aborting.\n", chan->name);
1569  return -1;
1570  }
1571 
1572  /* ok, audio fallback is allowed */
1573  details->caps |= AST_FAX_TECH_AUDIO;
1574 
1575  return 0;
1576 }
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:2417
union ast_frame_subclass subclass
Definition: frame.h:146
static struct ast_control_t38_parameters our_t38_parameters
Definition: res_fax.c:1154
void * ptr
Definition: frame.h:160
#define LOG_WARNING
Definition: logger.h:144
static void t38_parameters_ast_to_fax(struct ast_fax_t38_parameters *dst, const struct ast_control_t38_parameters *src)
Definition: res_fax.c:1037
static void t38_parameters_fax_to_ast(struct ast_control_t38_parameters *dst, const struct ast_fax_t38_parameters *src)
Definition: res_fax.c:1048
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4383
enum ast_control_t38 request_response
Definition: frame.h:412
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:4447
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
void ast_playtones_stop(struct ast_channel *chan)
Stop playing tones on a channel.
Definition: indications.c:411
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
struct ast_fax_t38_parameters our_t38_parameters
Definition: res_fax.h:168
int datalen
Definition: frame.h:148
#define LOG_ERROR
Definition: logger.h:155
union ast_fax_session_details::@203 option
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
Definition: utils.c:1615
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3539
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:964
Data structure associated with a single frame of data.
Definition: frame.h:142
enum ast_fax_capabilities caps
Definition: res_fax.h:108
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:319
enum ast_frame_type frametype
Definition: frame.h:144
#define ast_frfree(fr)
Definition: frame.h:583
struct ast_fax_t38_parameters their_t38_parameters
Definition: res_fax.h:170
union ast_frame::@172 data
static int reload_module ( void  )
static

Definition at line 2956 of file res_fax.c.

References set_config().

2957 {
2958  set_config(1);
2959  return 0;
2960 }
static int set_config(int reload)
configure res_fax
Definition: res_fax.c:2668
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 964 of file res_fax.c.

References ast_channel_lock, ast_channel_unlock, AST_FAX_TECH_RECEIVE, ast_free, ast_fax_session_details::caps, manager_event_info::cid, manager_event_info::context, EVENT_FLAG_CALL, manager_event_info::exten, generate_filenames_string(), get_manager_event_info(), ast_fax_session_details::localstationid, manager_event, ast_channel::name, ast_fax_session_details::option, and ast_fax_session_details::statusevents.

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

965 {
966  char *filenames = generate_filenames_string(details, "FileName: ", "\r\n");
967  if (!filenames) {
968  return 1;
969  }
970 
971  ast_channel_lock(chan);
972  if (details->option.statusevents) {
973  struct manager_event_info info;
974 
975  get_manager_event_info(chan, &info);
977  (details->caps & AST_FAX_TECH_RECEIVE) ? "ReceiveFAXStatus" : "SendFAXStatus",
978  "Status: %s\r\n"
979  "Channel: %s\r\n"
980  "Context: %s\r\n"
981  "Exten: %s\r\n"
982  "CallerID: %s\r\n"
983  "LocalStationID: %s\r\n"
984  "%s\r\n",
985  status,
986  chan->name,
987  info.context,
988  info.exten,
989  info.cid,
990  details->localstationid,
991  filenames);
992  }
993  ast_channel_unlock(chan);
994  ast_free(filenames);
995 
996  return 0;
997 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
static void get_manager_event_info(struct ast_channel *chan, struct manager_event_info *info)
Definition: res_fax.c:908
#define EVENT_FLAG_CALL
Definition: manager.h:72
union ast_fax_session_details::@203 option
const ast_string_field name
Definition: channel.h:787
#define ast_channel_unlock(chan)
Definition: channel.h:2467
#define ast_free(a)
Definition: astmm.h:97
enum ast_fax_capabilities caps
Definition: res_fax.h:108
const ast_string_field localstationid
Definition: res_fax.h:137
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:219
jack_status_t status
Definition: app_jack.c:143
static char * generate_filenames_string(struct ast_fax_session_details *details, char *prefix, char *separator)
Definition: res_fax.c:927
static int sendfax_exec ( struct ast_channel chan,
const char *  data 
)
static

initiate a send FAX session

Definition at line 2067 of file res_fax.c.

References ast_channel::_state, ast_fax_session_details::allow_audio, ao2_ref, args, ast_answer(), AST_APP_ARG, ast_app_parse_options(), ast_atomic_fetchadd_int(), ast_calloc, ast_channel_get_t38_state(), ast_channel_lock, ast_channel_unlock, ast_debug, AST_DECLARE_APP_ARGS, ast_fax_modem_to_str(), AST_FAX_OPTFLAG_TRUE, AST_FAX_TECH_MULTI_DOC, AST_FAX_TECH_SEND, AST_FAX_TECH_T38, ast_free, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_log(), AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_verb, ast_fax_session_details::caps, check_modem_rate(), manager_event_info::cid, manager_event_info::context, ast_fax_session_details::debug, disable_t38(), ast_fax_session_details::documents, EVENT_FLAG_CALL, manager_event_info::exten, fax_exec_options, fax_session_release(), fax_session_reserve(), faxregistry, ast_fax_document::filename, find_or_create_details(), generate_filenames_string(), generic_fax_exec(), get_manager_event_info(), global_fax_debug, LOG_ERROR, LOG_WARNING, manager_event, ast_fax_session_details::maxrate, ast_fax_session_details::minrate, ast_fax_session_details::modems, ast_channel::name, OPT_ALLOWAUDIO, OPT_CALLEDMODE, OPT_CALLERMODE, OPT_DEBUG, OPT_REQUEST_T38, OPT_STATUS, ast_fax_session_details::option, parse(), pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), ast_fax_session_details::request_t38, S_OR, ast_fax_session_details::send_cng, sendfax_t38_init(), set_channel_variables(), set_fax_t38_caps(), ast_fax_session_details::statusevents, strsep(), T38_STATE_NEGOTIATED, and T38_STATE_UNAVAILABLE.

Referenced by load_module().

2068 {
2069  char *parse, *filenames, *c, modems[128] = "";
2070  int channel_alive, file_count;
2071  struct ast_fax_session_details *details;
2072  struct ast_fax_session *s;
2073  struct ast_fax_tech_token *token = NULL;
2074  struct ast_fax_document *doc;
2076  AST_APP_ARG(filenames);
2077  AST_APP_ARG(options);
2078  );
2079  struct ast_flags opts = { 0, };
2080  struct manager_event_info info;
2081 
2082  /* initialize output channel variables */
2083  pbx_builtin_setvar_helper(chan, "FAXSTATUS", "FAILED");
2084  pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", NULL);
2085  pbx_builtin_setvar_helper(chan, "FAXPAGES", "0");
2086  pbx_builtin_setvar_helper(chan, "FAXBITRATE", NULL);
2087  pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", NULL);
2088 
2089  /* if we ran sendfax then we attempted to send a fax, even if we never
2090  * start a fax session */
2091  ast_atomic_fetchadd_int(&faxregistry.fax_tx_attempts, 1);
2092 
2093  /* Get a requirement structure and set it. This structure is used
2094  * to tell the FAX technology module about the higher level FAX session */
2095  if (!(details = find_or_create_details(chan))) {
2096  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
2097  pbx_builtin_setvar_helper(chan, "FAXERROR", "MEMORY_ERROR");
2098  pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "error allocating memory");
2099  ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
2100  return -1;
2101  }
2102 
2103  ast_string_field_set(details, result, "FAILED");
2104  ast_string_field_set(details, resultstr, "error starting fax session");
2105  ast_string_field_set(details, error, "INIT_ERROR");
2106  set_channel_variables(chan, details);
2107 
2108  if (details->maxrate < details->minrate) {
2109  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
2110  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2111  ast_string_field_set(details, resultstr, "maxrate is less than minrate");
2112  set_channel_variables(chan, details);
2113  ast_log(LOG_ERROR, "maxrate %u is less than minrate %u\n", details->maxrate, details->minrate);
2114  ao2_ref(details, -1);
2115  return -1;
2116  }
2117 
2118  if (check_modem_rate(details->modems, details->minrate)) {
2119  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
2120  ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
2121  ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %u\n", modems, details->minrate);
2122  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2123  ast_string_field_set(details, resultstr, "incompatible 'modems' and 'minrate' settings");
2124  set_channel_variables(chan, details);
2125  ao2_ref(details, -1);
2126  return -1;
2127  }
2128 
2129  if (check_modem_rate(details->modems, details->maxrate)) {
2130  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
2131  ast_fax_modem_to_str(details->modems, modems, sizeof(modems));
2132  ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %u\n", modems, details->maxrate);
2133  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2134  ast_string_field_set(details, resultstr, "incompatible 'modems' and 'maxrate' settings");
2135  set_channel_variables(chan, details);
2136  ao2_ref(details, -1);
2137  return -1;
2138  }
2139 
2140  if (ast_strlen_zero(data)) {
2141  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
2142  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2143  ast_string_field_set(details, resultstr, "invalid arguments");
2144  set_channel_variables(chan, details);
2145  ast_log(LOG_WARNING, "%s requires an argument (filename[&filename[&filename]][,options])\n", app_sendfax);
2146  ao2_ref(details, -1);
2147  return -1;
2148  }
2149  parse = ast_strdupa(data);
2150  AST_STANDARD_APP_ARGS(args, parse);
2151 
2152 
2153  if (!ast_strlen_zero(args.options) &&
2154  ast_app_parse_options(fax_exec_options, &opts, NULL, args.options)) {
2155  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
2156  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2157  ast_string_field_set(details, resultstr, "invalid arguments");
2158  set_channel_variables(chan, details);
2159  ao2_ref(details, -1);
2160  return -1;
2161  }
2162  if (ast_strlen_zero(args.filenames)) {
2163  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
2164  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2165  ast_string_field_set(details, resultstr, "invalid arguments");
2166  set_channel_variables(chan, details);
2167  ast_log(LOG_WARNING, "%s requires an argument (filename[&filename[&filename]],options])\n", app_sendfax);
2168  ao2_ref(details, -1);
2169  return -1;
2170  }
2171 
2172  /* check for unsupported FAX application options */
2173  if (ast_test_flag(&opts, OPT_CALLERMODE) || ast_test_flag(&opts, OPT_CALLEDMODE)) {
2174  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
2175  ast_string_field_set(details, error, "INVALID_ARGUMENTS");
2176  ast_string_field_set(details, resultstr, "invalid arguments");
2177  set_channel_variables(chan, details);
2178  ast_log(LOG_WARNING, "%s does not support polling\n", app_sendfax);
2179  ao2_ref(details, -1);
2180  return -1;
2181  }
2182 
2183  file_count = 0;
2184  filenames = args.filenames;
2185  while ((c = strsep(&filenames, "&"))) {
2186  if (access(c, (F_OK | R_OK)) < 0) {
2187  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
2188  ast_string_field_set(details, error, "FILE_ERROR");
2189  ast_string_field_set(details, resultstr, "error reading file");
2190  set_channel_variables(chan, details);
2191  ast_log(LOG_ERROR, "access failure. Verify '%s' exists and check permissions.\n", args.filenames);
2192  ao2_ref(details, -1);
2193  return -1;
2194  }
2195 
2196  if (!(doc = ast_calloc(1, sizeof(*doc) + strlen(c) + 1))) {
2197  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
2198  ast_string_field_set(details, error, "MEMORY_ERROR");
2199  ast_string_field_set(details, resultstr, "error allocating memory");
2200  set_channel_variables(chan, details);
2201  ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
2202  ao2_ref(details, -1);
2203  return -1;
2204  }
2205 
2206  strcpy(doc->filename, c);
2207  AST_LIST_INSERT_TAIL(&details->documents, doc, next);
2208  file_count++;
2209  }
2210 
2211  if (file_count > 1) {
2212  details->caps |= AST_FAX_TECH_MULTI_DOC;
2213  }
2214 
2215  ast_verb(3, "Channel '%s' sending FAX:\n", chan->name);
2216  AST_LIST_TRAVERSE(&details->documents, doc, next) {
2217  ast_verb(3, " %s\n", doc->filename);
2218  }
2219 
2220  details->caps = AST_FAX_TECH_SEND;
2221 
2222  /* check for debug */
2223  if (ast_test_flag(&opts, OPT_DEBUG) || global_fax_debug) {
2224  details->option.debug = AST_FAX_OPTFLAG_TRUE;
2225  }
2226 
2227  /* check for request for status events */
2228  if (ast_test_flag(&opts, OPT_STATUS)) {
2230  }
2231 
2233  ast_test_flag(&opts, OPT_ALLOWAUDIO)) {
2235  }
2236 
2237  if (ast_test_flag(&opts, OPT_REQUEST_T38)) {
2239  }
2240 
2241  if (!(s = fax_session_reserve(details, &token))) {
2242  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
2243  ast_string_field_set(details, resultstr, "error reserving fax session");
2244  set_channel_variables(chan, details);
2245  ast_log(LOG_ERROR, "Unable to reserve FAX session.\n");
2246  ao2_ref(details, -1);
2247  return -1;
2248  }
2249 
2250  /* make sure the channel is up */
2251  if (chan->_state != AST_STATE_UP) {
2252  if (ast_answer(chan)) {
2253  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
2254  ast_string_field_set(details, resultstr, "error answering channel");
2255  set_channel_variables(chan, details);
2256  ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", chan->name);
2257  fax_session_release(s, token);
2258  ao2_ref(s, -1);
2259  ao2_ref(details, -1);
2260  return -1;
2261  }
2262  }
2263 
2264  if (set_fax_t38_caps(chan, details)) {
2265  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
2266  ast_string_field_set(details, error, "T38_NEG_ERROR");
2267  ast_string_field_set(details, resultstr, "error negotiating T.38");
2268  set_channel_variables(chan, details);
2269  fax_session_release(s, token);
2270  ao2_ref(s, -1);
2271  ao2_ref(details, -1);
2272  return -1;
2273  }
2274 
2275  if (details->caps & AST_FAX_TECH_T38) {
2276  if (sendfax_t38_init(chan, details)) {
2277  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
2278  ast_string_field_set(details, error, "T38_NEG_ERROR");
2279  ast_string_field_set(details, resultstr, "error negotiating T.38");
2280  set_channel_variables(chan, details);
2281  fax_session_release(s, token);
2282  ao2_ref(s, -1);
2283  ao2_ref(details, -1);
2284  ast_log(LOG_ERROR, "error initializing channel '%s' in T.38 mode\n", chan->name);
2285  return -1;
2286  }
2287  } else {
2288  details->option.send_cng = 1;
2289  }
2290 
2291  if ((channel_alive = generic_fax_exec(chan, details, s, token)) < 0) {
2292  ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
2293  }
2294 
2296  if (disable_t38(chan)) {
2297  ast_debug(1, "error disabling T.38 mode on %s\n", chan->name);
2298  }
2299  }
2300 
2301  if (!(filenames = generate_filenames_string(details, "FileName: ", "\r\n"))) {
2302  ast_log(LOG_ERROR, "Error generating SendFAX manager event\n");
2303  ao2_ref(s, -1);
2304  ao2_ref(details, -1);
2305  return (!channel_alive) ? -1 : 0;
2306  }
2307 
2308  /* send out the AMI completion event */
2309  ast_channel_lock(chan);
2310  get_manager_event_info(chan, &info);
2312  "SendFAX",
2313  "Channel: %s\r\n"
2314  "Context: %s\r\n"
2315  "Exten: %s\r\n"
2316  "CallerID: %s\r\n"
2317  "RemoteStationID: %s\r\n"
2318  "LocalStationID: %s\r\n"
2319  "PagesTransferred: %s\r\n"
2320  "Resolution: %s\r\n"
2321  "TransferRate: %s\r\n"
2322  "%s\r\n",
2323  chan->name,
2324  info.context,
2325  info.exten,
2326  info.cid,
2327  S_OR(pbx_builtin_getvar_helper(chan, "REMOTESTATIONID"), ""),
2328  S_OR(pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"), ""),
2329  S_OR(pbx_builtin_getvar_helper(chan, "FAXPAGES"), ""),
2330  S_OR(pbx_builtin_getvar_helper(chan, "FAXRESOLUTION"), ""),
2331  S_OR(pbx_builtin_getvar_helper(chan, "FAXBITRATE"), ""),
2332  filenames);
2333  ast_channel_unlock(chan);
2334 
2335  ast_free(filenames);
2336 
2337  ao2_ref(s, -1);
2338  ao2_ref(details, -1);
2339 
2340  /* If the channel hungup return -1; otherwise, return 0 to continue in the dialplan */
2341  return (!channel_alive) ? -1 : 0;
2342 }
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:2417
#define ast_channel_lock(chan)
Definition: channel.h:2466
char * strsep(char **str, const char *delims)
#define ast_test_flag(p, flag)
Definition: utils.h:63
static void get_manager_event_info(struct ast_channel *chan, struct manager_event_info *info)
Definition: res_fax.c:908
static const char app_sendfax[]
Definition: res_fax.c:199
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:1162
#define LOG_WARNING
Definition: logger.h:144
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: app.c:2101
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
#define EVENT_FLAG_CALL
Definition: manager.h:72
#define ast_verb(level,...)
Definition: logger.h:243
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return * the previous value of *p. This can be used to handle reference co...
Definition: lock.h:603
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
Definition: pbx.c:10475
static struct @331 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static int disable_t38(struct ast_channel *chan)
Definition: res_fax.c:1092
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
static int check_modem_rate(enum ast_fax_modems modems, unsigned int rate)
Definition: res_fax.c:572
#define ao2_ref(o, delta)
Definition: astobj2.h:472
char filename[0]
Definition: res_fax.h:99
The data communicated between the high level applications and the generic fax function.
Definition: res_fax.h:105
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
static int set_fax_t38_caps(struct ast_channel *chan, struct ast_fax_session_details *details)
Definition: res_fax.c:1059
#define LOG_ERROR
Definition: logger.h:155
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:716
union ast_fax_session_details::@203 option
static void fax_session_release(struct ast_fax_session *s, struct ast_fax_tech_token *token)
Definition: res_fax.c:714
static struct @350 args
static void set_channel_variables(struct ast_channel *chan, struct ast_fax_session_details *details)
Set fax related channel variables.
Definition: res_fax.c:1000
struct ast_fax_documents documents
Definition: res_fax.h:114
enum ast_channel_state _state
Definition: channel.h:839
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
unsigned int minrate
Definition: res_fax.h:164
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define ast_channel_unlock(chan)
Definition: channel.h:2467
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1858
#define ast_free(a)
Definition: astmm.h:97
enum ast_fax_modems modems
Definition: res_fax.h:110
static int global_fax_debug
Definition: res_fax.c:277
Structure used to handle boolean flags.
Definition: utils.h:200
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...
Definition: pbx.c:10546
static struct ast_app_option fax_exec_options[128]
Definition: res_fax.c:295
static struct ast_fax_session * fax_session_reserve(struct ast_fax_session_details *details, struct ast_fax_tech_token **token)
Definition: res_fax.c:760
#define ast_calloc(a, b)
Definition: astmm.h:82
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:3086
The data required to handle a fax session.
Definition: res_fax.h:178
enum ast_fax_capabilities caps
Definition: res_fax.h:108
static int ast_fax_modem_to_str(enum ast_fax_modems bits, char *tbuf, size_t bufsize)
Definition: res_fax.c:539
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
unsigned int maxrate
Definition: res_fax.h:166
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:219
static struct ast_fax_session_details * find_or_create_details(struct ast_channel *chan)
returns a reference counted details structure from the channel&#39;s fax datastore. If the datastore does...
Definition: res_fax.c:417
static int sendfax_t38_init(struct ast_channel *chan, struct ast_fax_session_details *details)
Definition: res_fax.c:1823
static char * generate_filenames_string(struct ast_fax_session_details *details, char *prefix, char *separator)
Definition: res_fax.c:927
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:344
static int sendfax_t38_init ( struct ast_channel chan,
struct ast_fax_session_details details 
)
static

Definition at line 1823 of file res_fax.c.

References ast_fax_session_details::allow_audio, ast_channel_get_t38_state(), 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, ast_channel::name, ast_fax_session_details::option, ast_fax_session_details::our_t38_parameters, 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().

1824 {
1825  int timeout_ms;
1826  struct ast_frame *frame = NULL;
1827  struct ast_control_t38_parameters t38_parameters;
1828  struct timeval start;
1829  int ms;
1830 
1832 
1833  /* send CNG tone while listening for the receiver to initiate a switch
1834  * to T.38 mode; if they do, stop sending the CNG tone and proceed with
1835  * the switch.
1836  *
1837  * 10500 is enough time for 3 CNG tones
1838  */
1839  timeout_ms = 10500;
1840 
1841  /* don't send any audio if we've already received a T.38 reinvite */
1843  if (ast_playtones_start(chan, 1024, "!1100/500,!0/3000,!1100/500,!0/3000,!1100/500,!0/3000", 1)) {
1844  ast_log(LOG_ERROR, "error generating CNG tone on %s\n", chan->name);
1845  return -1;
1846  }
1847  }
1848 
1849  start = ast_tvnow();
1850  while ((ms = ast_remaining_ms(start, timeout_ms))) {
1851  int break_loop = 0;
1852  ms = ast_waitfor(chan, ms);
1853 
1854  if (ms < 0) {
1855  ast_log(LOG_ERROR, "error while generating CNG tone on %s\n", chan->name);
1856  ast_playtones_stop(chan);
1857  return -1;
1858  }
1859 
1860  if (ms == 0) { /* all done, nothing happened */
1861  break;
1862  }
1863 
1864  if (!(frame = ast_read(chan))) {
1865  ast_log(LOG_ERROR, "error reading frame while generating CNG tone on %s\n", chan->name);
1866  ast_playtones_stop(chan);
1867  return -1;
1868  }
1869 
1870  if ((frame->frametype == AST_FRAME_CONTROL) &&
1872  (frame->datalen == sizeof(t38_parameters))) {
1873  struct ast_control_t38_parameters *parameters = frame->data.ptr;
1874 
1875  switch (parameters->request_response) {
1877  /* the other end has requested a switch to T.38, so reply that we are willing, if we can
1878  * do T.38 as well
1879  */
1880  t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
1881  t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
1882  ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
1883  ast_playtones_stop(chan);
1884  break;
1885  case AST_T38_NEGOTIATED:
1886  ast_debug(1, "Negotiated T.38 for send on %s\n", chan->name);
1887  t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
1888  details->caps &= ~AST_FAX_TECH_AUDIO;
1889  report_fax_status(chan, details, "T.38 Negotiated");
1890  break_loop = 1;
1891  break;
1892  default:
1893  break;
1894  }
1895  }
1896  ast_frfree(frame);
1897  if (break_loop) {
1898  break;
1899  }
1900  }
1901 
1902  ast_playtones_stop(chan);
1903 
1905  return 0;
1906  }
1907 
1908  /* T.38 negotiation did not happen, initiate a switch if requested */
1909  if (details->option.request_t38 == AST_FAX_OPTFLAG_TRUE) {
1910  ast_debug(1, "Negotiating T.38 for send on %s\n", chan->name);
1911 
1912  /* wait up to five seconds for negotiation to complete */
1913  timeout_ms = 5000;
1914 
1915  /* set parameters based on the session's parameters */
1916  t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
1917  t38_parameters.request_response = AST_T38_REQUEST_NEGOTIATE;
1918  if ((ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0)) {
1919  return -1;
1920  }
1921 
1922  start = ast_tvnow();
1923  while ((ms = ast_remaining_ms(start, timeout_ms))) {
1924  int break_loop = 0;
1925 
1926  ms = ast_waitfor(chan, ms);
1927  if (ms < 0) {
1928  ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", chan->name);
1929  return -1;
1930  }
1931  if (ms == 0) { /* all done, nothing happened */
1932  ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 negotiation.\n", chan->name);
1933  details->caps &= ~AST_FAX_TECH_T38;
1934  break;
1935  }
1936 
1937  if (!(frame = ast_read(chan))) {
1938  ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", chan->name);
1939  return -1;
1940  }
1941 
1942  if ((frame->frametype == AST_FRAME_CONTROL) &&
1944  (frame->datalen == sizeof(t38_parameters))) {
1945  struct ast_control_t38_parameters *parameters = frame->data.ptr;
1946 
1947  switch (parameters->request_response) {
1949  t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
1950  t38_parameters.request_response = AST_T38_NEGOTIATED;
1951  ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
1952  break;
1953  case AST_T38_NEGOTIATED:
1954  ast_debug(1, "Negotiated T.38 for receive on %s\n", chan->name);
1955  t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
1956  details->caps &= ~AST_FAX_TECH_AUDIO;
1957  report_fax_status(chan, details, "T.38 Negotiated");
1958  break_loop = 1;
1959  break;
1960  case AST_T38_REFUSED:
1961  ast_log(LOG_WARNING, "channel '%s' refused to negotiate T.38\n", chan->name);
1962  details->caps &= ~AST_FAX_TECH_T38;
1963  break_loop = 1;
1964  break;
1965  default:
1966  ast_log(LOG_ERROR, "channel '%s' failed to negotiate T.38\n", chan->name);
1967  details->caps &= ~AST_FAX_TECH_T38;
1968  break_loop = 1;
1969  break;
1970  }
1971  }
1972  ast_frfree(frame);
1973  if (break_loop) {
1974  break;
1975  }
1976  }
1977 
1978  /* if T.38 was negotiated, we are done initializing */
1980  return 0;
1981  }
1982 
1983  /* send one more CNG tone to get audio going again for some
1984  * carriers if we are going to fall back to audio mode */
1985  if (details->option.allow_audio == AST_FAX_OPTFLAG_TRUE) {
1986  if (ast_playtones_start(chan, 1024, "!1100/500,!0/3000", 1)) {
1987  ast_log(LOG_ERROR, "error generating second CNG tone on %s\n", chan->name);
1988  return -1;
1989  }
1990 
1991  timeout_ms = 3500;
1992  start = ast_tvnow();
1993  while ((ms = ast_remaining_ms(start, timeout_ms))) {
1994  int break_loop = 0;
1995 
1996  ms = ast_waitfor(chan, ms);
1997  if (ms < 0) {
1998  ast_log(LOG_ERROR, "error while generating second CNG tone on %s\n", chan->name);
1999  ast_playtones_stop(chan);
2000  return -1;
2001  }
2002  if (ms == 0) { /* all done, nothing happened */
2003  break;
2004  }
2005 
2006  if (!(frame = ast_read(chan))) {
2007  ast_log(LOG_ERROR, "error reading frame while generating second CNG tone on %s\n", chan->name);
2008  ast_playtones_stop(chan);
2009  return -1;
2010  }
2011 
2012  if ((frame->frametype == AST_FRAME_CONTROL) &&
2014  (frame->datalen == sizeof(t38_parameters))) {
2015  struct ast_control_t38_parameters *parameters = frame->data.ptr;
2016 
2017  switch (parameters->request_response) {
2019  /* the other end has requested a switch to T.38, so reply that we are willing, if we can
2020  * do T.38 as well
2021  */
2022  t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
2023  t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
2024  ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
2025  ast_playtones_stop(chan);
2026  break;
2027  case AST_T38_NEGOTIATED:
2028  ast_debug(1, "Negotiated T.38 for send on %s\n", chan->name);
2029  t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
2030  details->caps &= ~AST_FAX_TECH_AUDIO;
2031  report_fax_status(chan, details, "T.38 Negotiated");
2032  break_loop = 1;
2033  break;
2034  default:
2035  break;
2036  }
2037  }
2038  ast_frfree(frame);
2039  if (break_loop) {
2040  break;
2041  }
2042  }
2043 
2044  ast_playtones_stop(chan);
2045 
2046  /* if T.38 was negotiated, we are done initializing */
2048  return 0;
2049  }
2050  }
2051  }
2052 
2053  /* if we made it here, then T.38 failed, check the 'f' flag */
2054  if (details->option.allow_audio == AST_FAX_OPTFLAG_FALSE) {
2055  ast_log(LOG_WARNING, "Audio FAX not allowed on channel '%s' and T.38 negotiation failed; aborting.\n", chan->name);
2056  return -1;
2057  }
2058 
2059  /* ok, audio fallback is allowed */
2060  details->caps |= AST_FAX_TECH_AUDIO;
2061 
2062  return 0;
2063 }
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:2417
union ast_frame_subclass subclass
Definition: frame.h:146
static struct ast_control_t38_parameters our_t38_parameters
Definition: res_fax.c:1154
void * ptr
Definition: frame.h:160
#define LOG_WARNING
Definition: logger.h:144
static void t38_parameters_ast_to_fax(struct ast_fax_t38_parameters *dst, const struct ast_control_t38_parameters *src)
Definition: res_fax.c:1037
static void t38_parameters_fax_to_ast(struct ast_control_t38_parameters *dst, const struct ast_fax_t38_parameters *src)
Definition: res_fax.c:1048
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4383
enum ast_control_t38 request_response
Definition: frame.h:412
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:4447
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
void ast_playtones_stop(struct ast_channel *chan)
Stop playing tones on a channel.
Definition: indications.c:411
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
struct ast_fax_t38_parameters our_t38_parameters
Definition: res_fax.h:168
int datalen
Definition: frame.h:148
#define LOG_ERROR
Definition: logger.h:155
union ast_fax_session_details::@203 option
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
Definition: utils.c:1615
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3539
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:964
Data structure associated with a single frame of data.
Definition: frame.h:142
enum ast_fax_capabilities caps
Definition: res_fax.h:108
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:319
enum ast_frame_type frametype
Definition: frame.h:144
#define ast_frfree(fr)
Definition: frame.h:583
struct ast_fax_t38_parameters their_t38_parameters
Definition: res_fax.h:170
union ast_frame::@172 data
static int session_cmp_cb ( void *  obj,
void *  arg,
int  flags 
)
static

compare callback for ao2

Definition at line 2353 of file res_fax.c.

References CMP_MATCH, CMP_STOP, and ast_fax_session::id.

Referenced by load_module().

2354 {
2355  struct ast_fax_session *lhs = obj, *rhs = arg;
2356 
2357  return (lhs->id == rhs->id) ? CMP_MATCH | CMP_STOP : 0;
2358 }
unsigned int id
Definition: res_fax.h:180
The data required to handle a fax session.
Definition: res_fax.h:178
static struct ast_fax_session_details* session_details_new ( void  )
static

create a FAX session details structure

Definition at line 383 of file res_fax.c.

References ao2_alloc, ao2_ref, AST_FAX_OPTFLAG_FALSE, AST_LIST_HEAD_INIT_NOLOCK, ast_string_field_init, destroy_session_details(), ast_fax_session_details::documents, ast_fax_session_details::ecm, fax_options::ecm, get_general_options(), ast_fax_session_details::maxrate, fax_options::maxrate, ast_fax_session_details::minrate, fax_options::minrate, ast_fax_session_details::modems, fax_options::modems, ast_fax_session_details::option, ast_fax_session_details::request_t38, ast_fax_session_details::send_ced, ast_fax_session_details::send_cng, ast_fax_session_details::statusevents, and fax_options::statusevents.

Referenced by find_or_create_details().

384 {
385  struct ast_fax_session_details *d;
386  struct fax_options options;
387 
388  if (!(d = ao2_alloc(sizeof(*d), destroy_session_details))) {
389  return NULL;
390  }
391 
392  if (ast_string_field_init(d, 512)) {
393  ao2_ref(d, -1);
394  return NULL;
395  }
396 
397  get_general_options(&options);
398 
400 
401  /* These options need to be set to the configured default and may be overridden by
402  * SendFAX, ReceiveFAX, or FAXOPT */
406  d->option.ecm = options.ecm;
407  d->option.statusevents = options.statusevents;
408  d->modems = options.modems;
409  d->minrate = options.minrate;
410  d->maxrate = options.maxrate;
411 
412  return d;
413 }
static void destroy_session_details(void *details)
destroy a FAX session details structure
Definition: res_fax.c:371
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:249
#define ao2_ref(o, delta)
Definition: astobj2.h:472
The data communicated between the high level applications and the generic fax function.
Definition: res_fax.h:105
union ast_fax_session_details::@203 option
struct ast_fax_documents documents
Definition: res_fax.h:114
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:430
unsigned int minrate
Definition: res_fax.h:164
enum ast_fax_modems modems
Definition: res_fax.h:110
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:666
unsigned int maxrate
Definition: res_fax.h:166
static void get_general_options(struct fax_options *options)
Definition: res_fax.c:2660
static int session_hash_cb ( const void *  obj,
const int  flags 
)
static

hash callback for ao2

Definition at line 2345 of file res_fax.c.

References ast_fax_session::id.

Referenced by load_module().

2346 {
2347  const struct ast_fax_session *s = obj;
2348 
2349  return s->id;
2350 }
unsigned int id
Definition: res_fax.h:180
The data required to handle a fax session.
Definition: res_fax.h:178
static void set_channel_variables ( struct ast_channel chan,
struct ast_fax_session_details details 
)
static

Set fax related channel variables.

Definition at line 1000 of file res_fax.c.

References ast_fax_session_details::error, ast_fax_session_details::localstationid, 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 generic_fax_exec(), receivefax_exec(), and sendfax_exec().

1001 {
1002  char buf[10];
1003  pbx_builtin_setvar_helper(chan, "FAXSTATUS", S_OR(details->result, NULL));
1004  pbx_builtin_setvar_helper(chan, "FAXERROR", S_OR(details->error, NULL));
1005  pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", S_OR(details->resultstr, NULL));
1006  pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", S_OR(details->remotestationid, NULL));
1007  pbx_builtin_setvar_helper(chan, "LOCALSTATIONID", S_OR(details->localstationid, NULL));
1008  pbx_builtin_setvar_helper(chan, "FAXBITRATE", S_OR(details->transfer_rate, NULL));
1009  pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", S_OR(details->resolution, NULL));
1010 
1011  snprintf(buf, sizeof(buf), "%u", details->pages_transferred);
1012  pbx_builtin_setvar_helper(chan, "FAXPAGES", buf);
1013 }
const ast_string_field result
Definition: res_fax.h:137
const ast_string_field transfer_rate
Definition: res_fax.h:137
const ast_string_field remotestationid
Definition: res_fax.h:137
unsigned int pages_transferred
Definition: res_fax.h:139
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...
Definition: pbx.c:10546
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
const ast_string_field resultstr
Definition: res_fax.h:137
const ast_string_field localstationid
Definition: res_fax.h:137
const ast_string_field error
Definition: res_fax.h:137
const ast_string_field resolution
Definition: res_fax.h:137
static int set_config ( int  reload)
static

configure res_fax

Definition at line 2668 of file res_fax.c.

References ast_config_destroy(), ast_config_load2(), ast_debug, ast_fax_modem_to_str(), AST_FAX_MODEM_V27, AST_FAX_MODEM_V34, ast_log(), ast_true(), ast_variable_browse(), check_modem_rate(), config, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, default_options, fax_options::ecm, fax_rate_str_to_int(), LOG_ERROR, LOG_NOTICE, LOG_WARNING, fax_options::maxrate, fax_options::minrate, fax_options::modems, ast_variable::name, ast_variable::next, set_general_options(), fax_options::statusevents, update_modem_bits(), and ast_variable::value.

Referenced by load_module(), and reload_module().

2669 {
2670  struct ast_config *cfg;
2671  struct ast_variable *v;
2672  struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
2673  char modems[128] = "";
2674  struct fax_options options;
2675  int res = 0;
2676 
2677  options = default_options;
2678 
2679  /* When we're not reloading, we have to be certain to set the general options
2680  * to the defaults in case config loading goes wrong at some point. On a reload,
2681  * the general options need to stay the same as what they were prior to the
2682  * reload rather than being reset to the defaults.
2683  */
2684  if (!reload) {
2685  set_general_options(&options);
2686  }
2687 
2688  /* read configuration */
2689  if (!(cfg = ast_config_load2(config, "res_fax", config_flags))) {
2690  ast_log(LOG_NOTICE, "Configuration file '%s' not found, %s options.\n",
2691  config, reload ? "not changing" : "using default");
2692  return 0;
2693  }
2694 
2695  if (cfg == CONFIG_STATUS_FILEINVALID) {
2696  ast_log(LOG_NOTICE, "Configuration file '%s' is invalid, %s options.\n",
2697  config, reload ? "not changing" : "using default");
2698  return 0;
2699  }
2700 
2701  if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
2702  return 0;
2703  }
2704 
2705  if (reload) {
2706  options = default_options;
2707  }
2708 
2709  /* create configuration */
2710  for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
2711  int rate;
2712 
2713  if (!strcasecmp(v->name, "minrate")) {
2714  ast_debug(3, "reading minrate '%s' from configuration file\n", v->value);
2715  if ((rate = fax_rate_str_to_int(v->value)) == 0) {
2716  res = -1;
2717  goto end;
2718  }
2719  options.minrate = rate;
2720  } else if (!strcasecmp(v->name, "maxrate")) {
2721  ast_debug(3, "reading maxrate '%s' from configuration file\n", v->value);
2722  if ((rate = fax_rate_str_to_int(v->value)) == 0) {
2723  res = -1;
2724  goto end;
2725  }
2726  options.maxrate = rate;
2727  } else if (!strcasecmp(v->name, "statusevents")) {
2728  ast_debug(3, "reading statusevents '%s' from configuration file\n", v->value);
2729  options.statusevents = ast_true(v->value);
2730  } else if (!strcasecmp(v->name, "ecm")) {
2731  ast_debug(3, "reading ecm '%s' from configuration file\n", v->value);
2732  options.ecm = ast_true(v->value);
2733  } else if ((!strcasecmp(v->name, "modem")) || (!strcasecmp(v->name, "modems"))) {
2734  options.modems = 0;
2735  update_modem_bits(&options.modems, v->value);
2736  }
2737  }
2738 
2739  if (options.maxrate < options.minrate) {
2740  ast_log(LOG_ERROR, "maxrate %u is less than minrate %u\n", options.maxrate, options.minrate);
2741  res = -1;
2742  goto end;
2743  }
2744 
2745  if (options.minrate == 2400 && (options.modems & AST_FAX_MODEM_V27) && !(options.modems & (AST_FAX_MODEM_V34))) {
2746  ast_fax_modem_to_str(options.modems, modems, sizeof(modems));
2747  ast_log(LOG_WARNING, "'modems' setting '%s' is no longer accepted with 'minrate' setting %u\n", modems, options.minrate);
2748  ast_log(LOG_WARNING, "'minrate' has been reset to 4800, please update res_fax.conf.\n");
2749  options.minrate = 4800;
2750  }
2751 
2752  if (check_modem_rate(options.modems, options.minrate)) {
2753  ast_fax_modem_to_str(options.modems, modems, sizeof(modems));
2754  ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %u\n", modems, options.minrate);
2755  res = -1;
2756  goto end;
2757  }
2758 
2759  if (check_modem_rate(options.modems, options.maxrate)) {
2760  ast_fax_modem_to_str(options.modems, modems, sizeof(modems));
2761  ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %u\n", modems, options.maxrate);
2762  res = -1;
2763  goto end;
2764  }
2765 
2766  set_general_options(&options);
2767 
2768 end:
2769  ast_config_destroy(cfg);
2770  return res;
2771 }
static unsigned int fax_rate_str_to_int(const char *ratestr)
convert a rate string to a rate
Definition: res_fax.c:690
static struct fax_options default_options
Definition: res_fax.c:262
#define LOG_WARNING
Definition: logger.h:144
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category)
Goes through variables.
Definition: config.c:597
Structure for variables, used for configurations and for channel variables.
Definition: config.h:75
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
Definition: config.c:2499
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
static int update_modem_bits(enum ast_fax_modems *bits, const char *value)
Definition: res_fax.c:460
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
const char * value
Definition: config.h:79
static int check_modem_rate(enum ast_fax_modems modems, unsigned int rate)
Definition: res_fax.c:572
const char * name
Definition: config.h:77
static int reload(void)
Definition: app_amd.c:497
#define LOG_ERROR
Definition: logger.h:155
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is &quot;true&quot;. This function checks to see whether a string passed to it is an indication of an &quot;true&quot; value. It checks to see if the string is &quot;yes&quot;, &quot;true&quot;, &quot;y&quot;, &quot;t&quot;, &quot;on&quot; or &quot;1&quot;.
Definition: utils.c:1533
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
Structure used to handle boolean flags.
Definition: utils.h:200
static const char * config
Definition: res_fax.c:275
static void set_general_options(const struct fax_options *options)
Definition: res_fax.c:2653
static int ast_fax_modem_to_str(enum ast_fax_modems bits, char *tbuf, size_t bufsize)
Definition: res_fax.c:539
struct ast_variable * next
Definition: config.h:82
#define CONFIG_STATUS_FILEINVALID
Definition: config.h:52
#define CONFIG_STATUS_FILEUNCHANGED
Definition: config.h:51
static int set_fax_t38_caps ( struct ast_channel chan,
struct ast_fax_session_details details 
)
static

Definition at line 1059 of file res_fax.c.

References ast_channel_get_t38_state(), 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_channel::name, ast_control_t38_parameters::request_response, T38_STATE_NEGOTIATING, T38_STATE_UNAVAILABLE, and T38_STATE_UNKNOWN.

Referenced by receivefax_exec(), and sendfax_exec().

1060 {
1061  switch (ast_channel_get_t38_state(chan)) {
1062  case T38_STATE_UNKNOWN:
1063  details->caps |= AST_FAX_TECH_T38;
1064  break;
1065  case T38_STATE_UNAVAILABLE:
1066  details->caps |= AST_FAX_TECH_AUDIO;
1067  break;
1068  case T38_STATE_NEGOTIATING: {
1069  /* the other end already sent us a T.38 reinvite, so we need to prod the channel
1070  * driver into resending their parameters to us if it supports doing so... if
1071  * not, we can't proceed, because we can't create a proper reply without them.
1072  * if it does work, the channel driver will send an AST_CONTROL_T38_PARAMETERS
1073  * with a request of AST_T38_REQUEST_NEGOTIATE, which will be read by the function
1074  * that gets called after this one completes
1075  */
1077  if (ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &parameters, sizeof(parameters)) != AST_T38_REQUEST_PARMS) {
1078  ast_log(LOG_ERROR, "channel '%s' is in an unsupported T.38 negotiation state, cannot continue.\n", chan->name);
1079  return -1;
1080  }
1081  details->caps |= AST_FAX_TECH_T38;
1082  break;
1083  }
1084  default:
1085  ast_log(LOG_ERROR, "channel '%s' is in an unsupported T.38 negotiation state, cannot continue.\n", chan->name);
1086  return -1;
1087  }
1088 
1089  return 0;
1090 }
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:2417
enum ast_control_t38 request_response
Definition: frame.h:412
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:4447
#define LOG_ERROR
Definition: logger.h:155
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
enum ast_fax_capabilities caps
Definition: res_fax.h:108
static void set_general_options ( const struct fax_options options)
static

Definition at line 2653 of file res_fax.c.

References ast_rwlock_unlock, ast_rwlock_wrlock, general_options, and options_lock.

Referenced by set_config().

2654 {
2656  general_options = *options;
2658 }
static ast_rwlock_t options_lock
Definition: res_fax.c:270
#define ast_rwlock_unlock(a)
Definition: lock.h:200
#define ast_rwlock_wrlock(a)
Definition: lock.h:202
static struct fax_options general_options
Definition: res_fax.c:260
static void t38_parameters_ast_to_fax ( struct ast_fax_t38_parameters dst,
const struct ast_control_t38_parameters src 
)
static

Definition at line 1037 of file res_fax.c.

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

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

1038 {
1039  dst->version = src->version;
1040  dst->max_ifp = src->max_ifp;
1041  dst->rate = src->rate;
1042  dst->rate_management = src->rate_management;
1043  dst->fill_bit_removal = src->fill_bit_removal;
1044  dst->transcoding_mmr = src->transcoding_mmr;
1045  dst->transcoding_jbig = src->transcoding_jbig;
1046 }
unsigned int version
Definition: frame.h:413
enum ast_control_t38_rate rate
Definition: res_fax.h:90
unsigned int transcoding_mmr
Definition: frame.h:418
enum ast_control_t38_rate rate
Definition: frame.h:415
unsigned int max_ifp
Definition: frame.h:414
unsigned int transcoding_mmr
Definition: res_fax.h:93
unsigned int transcoding_jbig
Definition: res_fax.h:94
unsigned int fill_bit_removal
Definition: frame.h:417
unsigned int max_ifp
Definition: res_fax.h:89
unsigned int transcoding_jbig
Definition: frame.h:419
unsigned int version
Definition: res_fax.h:88
enum ast_control_t38_rate_management rate_management
Definition: frame.h:416
enum ast_control_t38_rate_management rate_management
Definition: res_fax.h:91
unsigned int fill_bit_removal
Definition: res_fax.h:92
static void t38_parameters_fax_to_ast ( struct ast_control_t38_parameters dst,
const struct ast_fax_t38_parameters src 
)
static

Definition at line 1048 of file res_fax.c.

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

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

1049 {
1050  dst->version = src->version;
1051  dst->max_ifp = src->max_ifp;
1052  dst->rate = src->rate;
1053  dst->rate_management = src->rate_management;
1054  dst->fill_bit_removal = src->fill_bit_removal;
1055  dst->transcoding_mmr = src->transcoding_mmr;
1056  dst->transcoding_jbig = src->transcoding_jbig;
1057 }
unsigned int version
Definition: frame.h:413
enum ast_control_t38_rate rate
Definition: res_fax.h:90
unsigned int transcoding_mmr
Definition: frame.h:418
enum ast_control_t38_rate rate
Definition: frame.h:415
unsigned int max_ifp
Definition: frame.h:414
unsigned int transcoding_mmr
Definition: res_fax.h:93
unsigned int transcoding_jbig
Definition: res_fax.h:94
unsigned int fill_bit_removal
Definition: frame.h:417
unsigned int max_ifp
Definition: res_fax.h:89
unsigned int transcoding_jbig
Definition: frame.h:419
unsigned int version
Definition: res_fax.h:88
enum ast_control_t38_rate_management rate_management
Definition: frame.h:416
enum ast_control_t38_rate_management rate_management
Definition: res_fax.h:91
unsigned int fill_bit_removal
Definition: res_fax.h:92
static int unload_module ( void  )
static

unload res_fax

Definition at line 2894 of file res_fax.c.

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

2895 {
2897 
2899  ast_log(LOG_WARNING, "failed to unregister function '%s'\n", acf_faxopt.name);
2900  }
2901 
2903  ast_log(LOG_WARNING, "failed to unregister '%s'\n", app_sendfax);
2904  }
2905 
2907  ast_log(LOG_WARNING, "failed to unregister '%s'\n", app_receivefax);
2908  }
2909 
2910  if (fax_logger_level != -1) {
2912  }
2913 
2914  ao2_ref(faxregistry.container, -1);
2915 
2916  return 0;
2917 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: cli.c:2177
static const char app_sendfax[]
Definition: res_fax.c:199
#define LOG_WARNING
Definition: logger.h:144
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx.c:7705
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
Definition: pbx.c:3814
static struct @331 faxregistry
The faxregistry is used to manage information and statistics for all FAX sessions.
void ast_logger_unregister_level(const char *name)
Unregister a previously registered logger level.
Definition: logger.c:1670
static const char app_receivefax[]
Definition: res_fax.c:198
#define ao2_ref(o, delta)
Definition: astobj2.h:472
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static int fax_logger_level
Definition: res_fax.c:213
const char * name
Definition: pbx.h:96
static struct ast_cli_entry fax_cli[]
Definition: res_fax.c:2643
struct ast_custom_function acf_faxopt
FAXOPT dialplan function.
Definition: res_fax.c:2887
static int update_modem_bits ( enum ast_fax_modems bits,
const char *  value 
)
static

Definition at line 460 of file res_fax.c.

References ARRAY_LEN, AST_FAX_MODEM_V17, AST_FAX_MODEM_V27, AST_FAX_MODEM_V29, AST_FAX_MODEM_V34, ast_log(), and LOG_WARNING.

Referenced by acf_faxopt_write(), and set_config().

461 {
462  char *m[5], *tok, *v = (char *)value;
463  int i = 0, j;
464 
465  if (!strchr(v, ',')) {
466  m[i++] = v;
467  m[i] = NULL;
468  } else {
469  tok = strtok(v, ", ");
470  while (tok && i < ARRAY_LEN(m) - 1) {
471  m[i++] = tok;
472  tok = strtok(NULL, ", ");
473  }
474  m[i] = NULL;
475  }
476 
477  *bits = 0;
478  for (j = 0; j < i; j++) {
479  if (!strcasecmp(m[j], "v17")) {
480  *bits |= AST_FAX_MODEM_V17;
481  } else if (!strcasecmp(m[j], "v27")) {
482  *bits |= AST_FAX_MODEM_V27;
483  } else if (!strcasecmp(m[j], "v29")) {
484  *bits |= AST_FAX_MODEM_V29;
485  } else if (!strcasecmp(m[j], "v34")) {
486  *bits |= AST_FAX_MODEM_V34;
487  } else {
488  ast_log(LOG_WARNING, "ignoring invalid modem setting: '%s', valid options {v17 | v27 | v29 | v34}\n", m[j]);
489  }
490  }
491  return 0;
492 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
#define LOG_WARNING
Definition: logger.h:144
int value
Definition: syslog.c:39
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207

Variable Documentation

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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_APP_DEPEND, }
static

Definition at line 2968 of file res_fax.c.

struct ast_custom_function acf_faxopt
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:2840
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:2774

FAXOPT dialplan function.

Definition at line 2887 of file res_fax.c.

Referenced by load_module(), and unload_module().

int active_sessions

The number of active FAX sessions

Definition at line 223 of file res_fax.c.

const char app_receivefax[] = "ReceiveFAX"
static

Definition at line 198 of file res_fax.c.

const char app_sendfax[] = "SendFAX"
static

Definition at line 199 of file res_fax.c.

Definition at line 2968 of file res_fax.c.

const char* config = "res_fax.conf"
static

Definition at line 275 of file res_fax.c.

Referenced by load_module(), and set_config().

struct ao2_container* container

active sessions are astobj2 objects

Definition at line 227 of file res_fax.c.

struct fax_options default_options
static

Definition at line 262 of file res_fax.c.

Referenced by set_config().

struct ast_cli_entry fax_cli[]
static

Definition at line 2643 of file res_fax.c.

Referenced by load_module(), and unload_module().

int fax_complete

Number of successful FAX transmissions

Definition at line 233 of file res_fax.c.

struct ast_datastore_info fax_datastore
static
Initial value:
= {
.type = "res_fax",
.destroy = destroy_callback,
}
static void destroy_callback(void *data)
Definition: res_fax.c:336

Definition at line 343 of file res_fax.c.

Referenced by find_details(), and find_or_create_details().

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

Definition at line 295 of file res_fax.c.

Referenced by receivefax_exec(), and sendfax_exec().

int fax_failures

Number of failed FAX transmissions

Definition at line 235 of file res_fax.c.

int fax_logger_level = -1
static

Definition at line 213 of file res_fax.c.

int fax_rx_attempts

Total number of Rx FAX attempts

Definition at line 231 of file res_fax.c.

int fax_tx_attempts

Total number of Tx FAX attempts

Definition at line 229 of file res_fax.c.

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

Definition at line 260 of file res_fax.c.

Referenced by get_general_options(), and set_general_options().

int global_fax_debug = 0
static

Definition at line 277 of file res_fax.c.

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

int nextsessionname

the next unique session name

Definition at line 237 of file res_fax.c.

ast_rwlock_t options_lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, 1 }
static

Definition at line 270 of file res_fax.c.

Referenced by get_general_options(), and set_general_options().

struct ast_control_t38_parameters our_t38_parameters
static

Definition at line 1154 of file res_fax.c.

Referenced by receivefax_t38_init(), and sendfax_t38_init().

int reserved_sessions

The number of reserved FAX sessions

Definition at line 225 of file res_fax.c.