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 |
Defines | |
#define | FAX_MAXBUCKETS 10 |
maximum buckets for res_fax ao2 containers | |
#define | GENERIC_FAX_EXEC_ERROR(fax, chan, errorstr, reason) |
#define | GENERIC_FAX_EXEC_ERROR_QUIET(fax, chan, errorstr, reason) |
#define | GENERIC_FAX_EXEC_SET_VARS(fax, chan, errorstr, reason) |
#define | RES_FAX_MAXRATE 14400 |
#define | RES_FAX_MINRATE 4800 |
#define | RES_FAX_MODEM (AST_FAX_MODEM_V17 | AST_FAX_MODEM_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. | |
static int | acf_faxopt_write (struct ast_channel *chan, const char *cmd, char *data, const char *value) |
FAXOPT write function modifies the contents of a FAX option. | |
static char * | ast_fax_caps_to_str (enum ast_fax_capabilities caps, char *buf, size_t bufsize) |
void | ast_fax_log (int level, const char *file, const int line, const char *function, const char *msg) |
Log message at FAX or recommended level. | |
unsigned int | ast_fax_maxrate (void) |
get the maxiumum supported fax rate | |
unsigned int | ast_fax_minrate (void) |
get the minimum supported fax rate | |
static int | ast_fax_modem_to_str (enum ast_fax_modems bits, char *tbuf, size_t bufsize) |
const char * | ast_fax_state_to_str (enum ast_fax_state state) |
convert a ast_fax_state to a string | |
int | ast_fax_tech_register (struct ast_fax_tech *tech) |
register a FAX technology module | |
void | ast_fax_tech_unregister (struct ast_fax_tech *tech) |
unregister a FAX technology module | |
static int | check_modem_rate (enum ast_fax_modems modems, unsigned int rate) |
static char * | cli_fax_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
enable FAX debugging | |
static char * | cli_fax_show_capabilities (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
display registered FAX capabilities | |
static char * | cli_fax_show_session (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
display details of a specified fax session | |
static char * | cli_fax_show_sessions (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
display fax sessions | |
static char * | cli_fax_show_settings (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
display global defaults and settings | |
static char * | cli_fax_show_stats (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
display fax stats | |
static char * | cli_fax_show_version (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static void | debug_check_frame_for_silence (struct ast_fax_session *s, unsigned int c2s, struct ast_frame *frame) |
static void | destroy_callback (void *data) |
static void | destroy_session (void *session) |
destroy a FAX session structure | |
static void | destroy_session_details (void *details) |
destroy a FAX session details structure | |
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 | |
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 | |
static void | fax_session_release (struct ast_fax_session *s, struct ast_fax_tech_token *token) |
static struct ast_fax_session * | fax_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 | |
static struct ast_fax_session_details * | find_details (struct ast_channel *chan) |
returns a reference counted pointer to a fax datastore, if it exists | |
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 | |
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 | |
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 | |
static int | receivefax_exec (struct ast_channel *chan, const char *data) |
initiate a receive FAX session | |
static int | receivefax_t38_init (struct ast_channel *chan, struct ast_fax_session_details *details) |
static int | reload_module (void) |
static int | report_fax_status (struct ast_channel *chan, struct ast_fax_session_details *details, const char *status) |
send a FAX status manager event | |
static int | sendfax_exec (struct ast_channel *chan, const char *data) |
initiate a send FAX session | |
static int | sendfax_t38_init (struct ast_channel *chan, struct ast_fax_session_details *details) |
static int | session_cmp_cb (void *obj, void *arg, int flags) |
compare callback for ao2 | |
static struct ast_fax_session_details * | session_details_new (void) |
create a FAX session details structure | |
static int | session_hash_cb (const void *obj, const int flags) |
hash callback for ao2 | |
static void | set_channel_variables (struct ast_channel *chan, struct ast_fax_session_details *details) |
Set fax related channel variables. | |
static int | set_config (int reload) |
configure res_fax | |
static int | set_fax_t38_caps (struct ast_channel *chan, struct ast_fax_session_details *details) |
static void | set_general_options (const struct fax_options *options) |
static void | t38_parameters_ast_to_fax (struct ast_fax_t38_parameters *dst, const struct ast_control_t38_parameters *src) |
static void | t38_parameters_fax_to_ast (struct ast_control_t38_parameters *dst, const struct ast_fax_t38_parameters *src) |
static int | unload_module (void) |
unload res_fax | |
static int | update_modem_bits (enum ast_fax_modems *bits, const char *value) |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "Generic FAX Applications" , .key = "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. | |
static const char | app_receivefax [] = "ReceiveFAX" |
static const char | app_sendfax [] = "SendFAX" |
static struct ast_module_info * | ast_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 |
struct { | |
int active_sessions | |
struct ao2_container * container | |
int fax_complete | |
int fax_failures | |
int fax_rx_attempts | |
int fax_tx_attempts | |
int nextsessionname | |
int reserved_sessions | |
} | faxregistry |
The faxregistry is used to manage information and statistics for all FAX sessions. | |
static struct fax_options | general_options |
static int | global_fax_debug = 0 |
static ast_rwlock_t | options_lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, 1 } |
static struct ast_control_t38_parameters | our_t38_parameters |
Generic FAX Resource for FAX technology resource modules.
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.
#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 | ) |
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)
Definition at line 1031 of file res_fax.c.
Referenced by generic_fax_exec().
#define GENERIC_FAX_EXEC_ERROR_QUIET | ( | fax, | |||
chan, | |||||
errorstr, | |||||
reason | ) |
do { \ GENERIC_FAX_EXEC_SET_VARS(fax, chan, errorstr, reason); \ } while (0)
#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_MODEM (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V27 | AST_FAX_MODEM_V29) |
#define RES_FAX_TIMEOUT 10000 |
Definition at line 218 of file res_fax.c.
Referenced by generic_fax_exec().
anonymous enum |
Definition at line 279 of file res_fax.c.
00279 { 00280 OPT_CALLEDMODE = (1 << 0), 00281 OPT_CALLERMODE = (1 << 1), 00282 OPT_DEBUG = (1 << 2), 00283 OPT_STATUS = (1 << 3), 00284 OPT_ALLOWAUDIO = (1 << 5), 00285 OPT_REQUEST_T38 = (1 << 6), 00286 };
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, find_details(), generate_filenames_string(), ast_fax_session_details::id, LOG_ERROR, LOG_WARNING, ast_fax_session_details::maxrate, ast_fax_session_details::minrate, ast_fax_session_details::modems, ast_fax_session_details::option, and ast_fax_session_details::pages_transferred.
02775 { 02776 struct ast_fax_session_details *details = find_details(chan); 02777 int res = 0; 02778 char *filenames; 02779 02780 if (!details) { 02781 ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s) because it has never been written.\n", chan->name, data); 02782 return -1; 02783 } 02784 if (!strcasecmp(data, "ecm")) { 02785 ast_copy_string(buf, details->option.ecm ? "yes" : "no", len); 02786 } else if (!strcasecmp(data, "error")) { 02787 ast_copy_string(buf, details->error, len); 02788 } else if (!strcasecmp(data, "filename")) { 02789 if (AST_LIST_EMPTY(&details->documents)) { 02790 ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s) because it has never been written.\n", chan->name, data); 02791 res = -1; 02792 } else { 02793 ast_copy_string(buf, AST_LIST_FIRST(&details->documents)->filename, len); 02794 } 02795 } else if (!strcasecmp(data, "filenames")) { 02796 if (AST_LIST_EMPTY(&details->documents)) { 02797 ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s) because it has never been written.\n", chan->name, data); 02798 res = -1; 02799 } else if ((filenames = generate_filenames_string(details, "", ","))) { 02800 ast_copy_string(buf, filenames, len); 02801 ast_free(filenames); 02802 } else { 02803 ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s), there was an error generating the filenames list.\n", chan->name, data); 02804 res = -1; 02805 } 02806 } else if (!strcasecmp(data, "headerinfo")) { 02807 ast_copy_string(buf, details->headerinfo, len); 02808 } else if (!strcasecmp(data, "localstationid")) { 02809 ast_copy_string(buf, details->localstationid, len); 02810 } else if (!strcasecmp(data, "maxrate")) { 02811 snprintf(buf, len, "%u", details->maxrate); 02812 } else if (!strcasecmp(data, "minrate")) { 02813 snprintf(buf, len, "%u", details->minrate); 02814 } else if (!strcasecmp(data, "pages")) { 02815 snprintf(buf, len, "%u", details->pages_transferred); 02816 } else if (!strcasecmp(data, "rate")) { 02817 ast_copy_string(buf, details->transfer_rate, len); 02818 } else if (!strcasecmp(data, "remotestationid")) { 02819 ast_copy_string(buf, details->remotestationid, len); 02820 } else if (!strcasecmp(data, "resolution")) { 02821 ast_copy_string(buf, details->resolution, len); 02822 } else if (!strcasecmp(data, "sessionid")) { 02823 snprintf(buf, len, "%u", details->id); 02824 } else if (!strcasecmp(data, "status")) { 02825 ast_copy_string(buf, details->result, len); 02826 } else if (!strcasecmp(data, "statusstr")) { 02827 ast_copy_string(buf, details->resultstr, len); 02828 } else if ((!strcasecmp(data, "modem")) || (!strcasecmp(data, "modems"))) { 02829 ast_fax_modem_to_str(details->modems, buf, len); 02830 } else { 02831 ast_log(LOG_WARNING, "channel '%s' can't read FAXOPT(%s) because it is unhandled!\n", chan->name, data); 02832 res = -1; 02833 } 02834 ao2_ref(details, -1); 02835 02836 return res; 02837 }
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(), LOG_WARNING, ast_fax_session_details::maxrate, ast_fax_session_details::minrate, ast_fax_session_details::modems, ast_fax_session_details::option, and update_modem_bits().
02841 { 02842 int res = 0; 02843 struct ast_fax_session_details *details; 02844 02845 if (!(details = find_or_create_details(chan))) { 02846 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); 02847 return -1; 02848 } 02849 ast_debug(3, "channel '%s' setting FAXOPT(%s) to '%s'\n", chan->name, data, value); 02850 02851 if (!strcasecmp(data, "ecm")) { 02852 const char *val = ast_skip_blanks(value); 02853 if (ast_true(val)) { 02854 details->option.ecm = AST_FAX_OPTFLAG_TRUE; 02855 } else if (ast_false(val)) { 02856 details->option.ecm = AST_FAX_OPTFLAG_FALSE; 02857 } else { 02858 ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(ecm).\n", value); 02859 } 02860 } else if (!strcasecmp(data, "headerinfo")) { 02861 ast_string_field_set(details, headerinfo, value); 02862 } else if (!strcasecmp(data, "localstationid")) { 02863 ast_string_field_set(details, localstationid, value); 02864 } else if (!strcasecmp(data, "maxrate")) { 02865 details->maxrate = fax_rate_str_to_int(value); 02866 if (!details->maxrate) { 02867 details->maxrate = ast_fax_maxrate(); 02868 } 02869 } else if (!strcasecmp(data, "minrate")) { 02870 details->minrate = fax_rate_str_to_int(value); 02871 if (!details->minrate) { 02872 details->minrate = ast_fax_minrate(); 02873 } 02874 } else if ((!strcasecmp(data, "modem")) || (!strcasecmp(data, "modems"))) { 02875 update_modem_bits(&details->modems, value); 02876 } else { 02877 ast_log(LOG_WARNING, "channel '%s' set FAXOPT(%s) to '%s' is unhandled!\n", chan->name, data, value); 02878 res = -1; 02879 } 02880 02881 ao2_ref(details, -1); 02882 02883 return res; 02884 }
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().
00495 { 00496 char *out = buf; 00497 size_t size = bufsize; 00498 int first = 1; 00499 00500 if (caps & AST_FAX_TECH_SEND) { 00501 if (!first) { 00502 ast_build_string(&buf, &size, ","); 00503 } 00504 ast_build_string(&buf, &size, "SEND"); 00505 first = 0; 00506 } 00507 if (caps & AST_FAX_TECH_RECEIVE) { 00508 if (!first) { 00509 ast_build_string(&buf, &size, ","); 00510 } 00511 ast_build_string(&buf, &size, "RECEIVE"); 00512 first = 0; 00513 } 00514 if (caps & AST_FAX_TECH_AUDIO) { 00515 if (!first) { 00516 ast_build_string(&buf, &size, ","); 00517 } 00518 ast_build_string(&buf, &size, "AUDIO"); 00519 first = 0; 00520 } 00521 if (caps & AST_FAX_TECH_T38) { 00522 if (!first) { 00523 ast_build_string(&buf, &size, ","); 00524 } 00525 ast_build_string(&buf, &size, "T38"); 00526 first = 0; 00527 } 00528 if (caps & AST_FAX_TECH_MULTI_DOC) { 00529 if (!first) { 00530 ast_build_string(&buf, &size, ","); 00531 } 00532 ast_build_string(&buf, &size, "MULTI_DOC"); 00533 first = 0; 00534 } 00535 00536 return out; 00537 }
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().
00681 { 00682 if (fax_logger_level != -1) { 00683 ast_log_dynamic_level(fax_logger_level, "%s", msg); 00684 } else { 00685 ast_log(level, file, line, function, "%s", msg); 00686 } 00687 }
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().
00445 { 00446 struct fax_options options; 00447 get_general_options(&options); 00448 00449 return options.maxrate; 00450 }
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().
00453 { 00454 struct fax_options options; 00455 get_general_options(&options); 00456 00457 return options.minrate; 00458 }
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().
00540 { 00541 int count = 0; 00542 00543 if (bits & AST_FAX_MODEM_V17) { 00544 strcat(tbuf, "V17"); 00545 count++; 00546 } 00547 if (bits & AST_FAX_MODEM_V27) { 00548 if (count) { 00549 strcat(tbuf, ","); 00550 } 00551 strcat(tbuf, "V27"); 00552 count++; 00553 } 00554 if (bits & AST_FAX_MODEM_V29) { 00555 if (count) { 00556 strcat(tbuf, ","); 00557 } 00558 strcat(tbuf, "V29"); 00559 count++; 00560 } 00561 if (bits & AST_FAX_MODEM_V34) { 00562 if (count) { 00563 strcat(tbuf, ","); 00564 } 00565 strcat(tbuf, "V34"); 00566 count++; 00567 } 00568 00569 return 0; 00570 }
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().
00658 { 00659 switch (state) { 00660 case AST_FAX_STATE_UNINITIALIZED: 00661 return "Uninitialized"; 00662 case AST_FAX_STATE_INITIALIZED: 00663 return "Initialized"; 00664 case AST_FAX_STATE_OPEN: 00665 return "Open"; 00666 case AST_FAX_STATE_ACTIVE: 00667 return "Active"; 00668 case AST_FAX_STATE_COMPLETE: 00669 return "Complete"; 00670 case AST_FAX_STATE_RESERVED: 00671 return "Reserved"; 00672 case AST_FAX_STATE_INACTIVE: 00673 return "Inactive"; 00674 default: 00675 ast_log(LOG_WARNING, "unhandled FAX state: %u\n", state); 00676 return "Unknown"; 00677 } 00678 }
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, fax_module::tech, and ast_fax_tech::type.
Referenced by load_module().
00617 { 00618 struct fax_module *fax; 00619 00620 if (!(fax = ast_calloc(1, sizeof(*fax)))) { 00621 return -1; 00622 } 00623 fax->tech = tech; 00624 AST_RWLIST_WRLOCK(&faxmodules); 00625 AST_RWLIST_INSERT_TAIL(&faxmodules, fax, list); 00626 AST_RWLIST_UNLOCK(&faxmodules); 00627 ast_module_ref(ast_module_info->self); 00628 00629 ast_verb(3, "Registered handler for '%s' (%s)\n", fax->tech->type, fax->tech->description); 00630 00631 return 0; 00632 }
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, fax_module::tech, and ast_fax_tech::type.
Referenced by unload_module().
00636 { 00637 struct fax_module *fax; 00638 00639 ast_verb(3, "Unregistering FAX module type '%s'\n", tech->type); 00640 00641 AST_RWLIST_WRLOCK(&faxmodules); 00642 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&faxmodules, fax, list) { 00643 if (fax->tech != tech) { 00644 continue; 00645 } 00646 AST_RWLIST_REMOVE_CURRENT(list); 00647 ast_module_unref(ast_module_info->self); 00648 ast_free(fax); 00649 ast_verb(4, "Unregistered FAX module type '%s'\n", tech->type); 00650 break; 00651 } 00652 AST_RWLIST_TRAVERSE_SAFE_END; 00653 AST_RWLIST_UNLOCK(&faxmodules); 00654 }
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().
00573 { 00574 switch (rate) { 00575 case 2400: 00576 if (!(modems & (AST_FAX_MODEM_V34))) { 00577 return 1; 00578 } 00579 break; 00580 case 4800: 00581 if (!(modems & (AST_FAX_MODEM_V27 | AST_FAX_MODEM_V34))) { 00582 return 1; 00583 } 00584 break; 00585 case 7200: 00586 if (!(modems & (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V29 | AST_FAX_MODEM_V34))) { 00587 return 1; 00588 } 00589 break; 00590 case 9600: 00591 if (!(modems & (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V27 | AST_FAX_MODEM_V29 | AST_FAX_MODEM_V34))) { 00592 return 1; 00593 } 00594 break; 00595 case 12000: 00596 case 14400: 00597 if (!(modems & (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V34))) { 00598 return 1; 00599 } 00600 break; 00601 case 28800: 00602 case 33600: 00603 if (!(modems & AST_FAX_MODEM_V34)) { 00604 return 1; 00605 } 00606 break; 00607 default: 00608 /* this should never happen */ 00609 return 1; 00610 } 00611 00612 return 0; 00613 }
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.
02422 { 02423 int flag; 02424 const char *what; 02425 02426 switch (cmd) { 02427 case CLI_INIT: 02428 e->command = "fax set debug {on|off}"; 02429 e->usage = 02430 "Usage: fax set debug { on | off }\n" 02431 " Enable/Disable FAX debugging on new FAX sessions. The basic FAX debugging will result in\n" 02432 " additional events sent to manager sessions with 'call' class permissions. When\n" 02433 " verbosity is greater than '5' events will be displayed to the console and audio versus\n" 02434 " energy analysis will be performed and displayed to the console.\n"; 02435 return NULL; 02436 case CLI_GENERATE: 02437 return NULL; 02438 } 02439 02440 what = a->argv[e->args-1]; /* guaranteed to exist */ 02441 if (!strcasecmp(what, "on")) { 02442 flag = 1; 02443 } else if (!strcasecmp(what, "off")) { 02444 flag = 0; 02445 } else { 02446 return CLI_SHOWUSAGE; 02447 } 02448 02449 global_fax_debug = flag; 02450 ast_cli(a->fd, "\n\nFAX Debug %s\n\n", (flag) ? "Enabled" : "Disabled"); 02451 02452 return CLI_SUCCESS; 02453 }
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.
02457 { 02458 struct fax_module *fax; 02459 unsigned int num_modules = 0; 02460 02461 switch (cmd) { 02462 case CLI_INIT: 02463 e->command = "fax show capabilities"; 02464 e->usage = 02465 "Usage: fax show capabilities\n" 02466 " Shows the capabilities of the registered FAX technology modules\n"; 02467 return NULL; 02468 case CLI_GENERATE: 02469 return NULL; 02470 } 02471 02472 ast_cli(a->fd, "\n\nRegistered FAX Technology Modules:\n\n"); 02473 AST_RWLIST_RDLOCK(&faxmodules); 02474 AST_RWLIST_TRAVERSE(&faxmodules, fax, list) { 02475 ast_cli(a->fd, "%-15s : %s\n%-15s : %s\n%-15s : ", "Type", fax->tech->type, "Description", fax->tech->description, "Capabilities"); 02476 fax->tech->cli_show_capabilities(a->fd); 02477 num_modules++; 02478 } 02479 AST_RWLIST_UNLOCK(&faxmodules); 02480 ast_cli(a->fd, "%u registered modules\n\n", num_modules); 02481 02482 return CLI_SUCCESS; 02483 }
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.
02525 { 02526 struct ast_fax_session *s, tmp; 02527 02528 switch (cmd) { 02529 case CLI_INIT: 02530 e->command = "fax show session"; 02531 e->usage = 02532 "Usage: fax show session <session number>\n" 02533 " Shows status of the named FAX session\n"; 02534 return NULL; 02535 case CLI_GENERATE: 02536 return fax_session_tab_complete(a); 02537 } 02538 02539 if (a->argc != 4) { 02540 return CLI_SHOWUSAGE; 02541 } 02542 02543 if (sscanf(a->argv[3], "%u", &tmp.id) != 1) { 02544 ast_log(LOG_ERROR, "invalid session id: '%s'\n", a->argv[3]); 02545 return RESULT_SUCCESS; 02546 } 02547 02548 ast_cli(a->fd, "\nFAX Session Details:\n--------------------\n\n"); 02549 s = ao2_find(faxregistry.container, &tmp, OBJ_POINTER); 02550 if (s) { 02551 s->tech->cli_show_session(s, a->fd); 02552 ao2_ref(s, -1); 02553 } 02554 ast_cli(a->fd, "\n\n"); 02555 02556 return CLI_SUCCESS; 02557 }
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.
02594 { 02595 struct ast_fax_session *s; 02596 struct ao2_iterator i; 02597 int session_count; 02598 char *filenames; 02599 02600 switch (cmd) { 02601 case CLI_INIT: 02602 e->command = "fax show sessions"; 02603 e->usage = 02604 "Usage: fax show sessions\n" 02605 " Shows the current FAX sessions\n"; 02606 return NULL; 02607 case CLI_GENERATE: 02608 return NULL; 02609 } 02610 02611 ast_cli(a->fd, "\nCurrent FAX Sessions:\n\n"); 02612 ast_cli(a->fd, "%-20.20s %-10.10s %-10.10s %-5.5s %-10.10s %-15.15s %-30.30s\n", 02613 "Channel", "Tech", "FAXID", "Type", "Operation", "State", "File(s)"); 02614 i = ao2_iterator_init(faxregistry.container, 0); 02615 while ((s = ao2_iterator_next(&i))) { 02616 ao2_lock(s); 02617 02618 if (!(filenames = generate_filenames_string(s->details, "", ", "))) { 02619 ast_log(LOG_ERROR, "Error printing filenames for 'fax show sessions' command\n"); 02620 ao2_unlock(s); 02621 ao2_ref(s, -1); 02622 ao2_iterator_destroy(&i); 02623 return CLI_FAILURE; 02624 } 02625 02626 ast_cli(a->fd, "%-20.20s %-10.10s %-10u %-5.5s %-10.10s %-15.15s %-30s\n", 02627 s->channame, s->tech->type, s->id, 02628 (s->details->caps & AST_FAX_TECH_AUDIO) ? "G.711" : "T.38", 02629 (s->details->caps & AST_FAX_TECH_SEND) ? "send" : "receive", 02630 ast_fax_state_to_str(s->state), filenames); 02631 02632 ast_free(filenames); 02633 ao2_unlock(s); 02634 ao2_ref(s, -1); 02635 } 02636 ao2_iterator_destroy(&i); 02637 session_count = ao2_container_count(faxregistry.container); 02638 ast_cli(a->fd, "\n%d FAX sessions\n\n", session_count); 02639 02640 return CLI_SUCCESS; 02641 }
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.
02487 { 02488 struct fax_module *fax; 02489 char modems[128] = ""; 02490 struct fax_options options; 02491 02492 switch (cmd) { 02493 case CLI_INIT: 02494 e->command = "fax show settings"; 02495 e->usage = 02496 "Usage: fax show settings\n" 02497 " Show the global settings and defaults of both the FAX core and technology modules\n"; 02498 return NULL; 02499 case CLI_GENERATE: 02500 return NULL; 02501 } 02502 02503 get_general_options(&options); 02504 02505 ast_cli(a->fd, "FAX For Asterisk Settings:\n"); 02506 ast_cli(a->fd, "\tECM: %s\n", options.ecm ? "Enabled" : "Disabled"); 02507 ast_cli(a->fd, "\tStatus Events: %s\n", options.statusevents ? "On" : "Off"); 02508 ast_cli(a->fd, "\tMinimum Bit Rate: %u\n", options.minrate); 02509 ast_cli(a->fd, "\tMaximum Bit Rate: %u\n", options.maxrate); 02510 ast_fax_modem_to_str(options.modems, modems, sizeof(modems)); 02511 ast_cli(a->fd, "\tModem Modulations Allowed: %s\n", modems); 02512 ast_cli(a->fd, "\n\nFAX Technology Modules:\n\n"); 02513 AST_RWLIST_RDLOCK(&faxmodules); 02514 AST_RWLIST_TRAVERSE(&faxmodules, fax, list) { 02515 ast_cli(a->fd, "%s (%s) Settings:\n", fax->tech->type, fax->tech->description); 02516 fax->tech->cli_show_settings(a->fd); 02517 } 02518 AST_RWLIST_UNLOCK(&faxmodules); 02519 02520 return CLI_SUCCESS; 02521 }
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.
02561 { 02562 struct fax_module *fax; 02563 02564 switch (cmd) { 02565 case CLI_INIT: 02566 e->command = "fax show stats"; 02567 e->usage = 02568 "Usage: fax show stats\n" 02569 " Shows a statistical summary of FAX transmissions\n"; 02570 return NULL; 02571 case CLI_GENERATE: 02572 return NULL; 02573 } 02574 02575 ast_cli(a->fd, "\nFAX Statistics:\n---------------\n\n"); 02576 ast_cli(a->fd, "%-20.20s : %d\n", "Current Sessions", faxregistry.active_sessions); 02577 ast_cli(a->fd, "%-20.20s : %d\n", "Reserved Sessions", faxregistry.reserved_sessions); 02578 ast_cli(a->fd, "%-20.20s : %d\n", "Transmit Attempts", faxregistry.fax_tx_attempts); 02579 ast_cli(a->fd, "%-20.20s : %d\n", "Receive Attempts", faxregistry.fax_rx_attempts); 02580 ast_cli(a->fd, "%-20.20s : %d\n", "Completed FAXes", faxregistry.fax_complete); 02581 ast_cli(a->fd, "%-20.20s : %d\n", "Failed FAXes", faxregistry.fax_failures); 02582 AST_RWLIST_RDLOCK(&faxmodules); 02583 AST_RWLIST_TRAVERSE(&faxmodules, fax, list) { 02584 fax->tech->cli_show_stats(a->fd); 02585 } 02586 AST_RWLIST_UNLOCK(&faxmodules); 02587 ast_cli(a->fd, "\n\n"); 02588 02589 return CLI_SUCCESS; 02590 }
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.
02390 { 02391 struct fax_module *fax; 02392 02393 switch(cmd) { 02394 case CLI_INIT: 02395 e->command = "fax show version"; 02396 e->usage = 02397 "Usage: fax show version\n" 02398 " Show versions of FAX For Asterisk components.\n"; 02399 return NULL; 02400 case CLI_GENERATE: 02401 return NULL; 02402 } 02403 02404 if (a->argc != 3) { 02405 return CLI_SHOWUSAGE; 02406 } 02407 02408 ast_cli(a->fd, "FAX For Asterisk Components:\n"); 02409 ast_cli(a->fd, "\tApplications: %s\n", ast_get_version()); 02410 AST_RWLIST_RDLOCK(&faxmodules); 02411 AST_RWLIST_TRAVERSE(&faxmodules, fax, list) { 02412 ast_cli(a->fd, "\t%s: %s\n", fax->tech->description, fax->tech->version); 02413 } 02414 AST_RWLIST_UNLOCK(&faxmodules); 02415 ast_cli(a->fd, "\n"); 02416 02417 return CLI_SUCCESS; 02418 }
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().
00304 { 00305 struct debug_info_history *history = c2s ? &s->debug_info->c2s : &s->debug_info->s2c; 00306 int dspsilence; 00307 unsigned int last_consec_frames, last_consec_ms; 00308 unsigned char wassil; 00309 struct timeval diff; 00310 00311 diff = ast_tvsub(ast_tvnow(), s->debug_info->base_tv); 00312 00313 ast_dsp_reset(s->debug_info->dsp); 00314 ast_dsp_silence(s->debug_info->dsp, frame, &dspsilence); 00315 00316 wassil = history->silence; 00317 history->silence = (dspsilence != 0) ? 1 : 0; 00318 if (history->silence != wassil) { 00319 last_consec_frames = history->consec_frames; 00320 last_consec_ms = history->consec_ms; 00321 history->consec_frames = 0; 00322 history->consec_ms = 0; 00323 00324 if ((last_consec_frames != 0)) { 00325 ast_verb(6, "Channel '%s' fax session '%u', [ %.3ld.%.6ld ], %s sent %u frames (%u ms) of %s.\n", 00326 s->channame, s->id, (long) diff.tv_sec, (long int) diff.tv_usec, 00327 (c2s) ? "channel" : "stack", last_consec_frames, last_consec_ms, 00328 (wassil) ? "silence" : "energy"); 00329 } 00330 } 00331 00332 history->consec_frames++; 00333 history->consec_ms += (frame->samples / 8); 00334 }
static void destroy_callback | ( | void * | data | ) | [static] |
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().
00728 { 00729 struct ast_fax_session *s = session; 00730 00731 if (s->tech) { 00732 fax_session_release(s, NULL); 00733 if (s->tech_pvt) { 00734 s->tech->destroy_session(s); 00735 } 00736 ast_module_unref(s->tech->module); 00737 } 00738 00739 if (s->details) { 00740 ao2_ref(s->details, -1); 00741 } 00742 00743 if (s->debug_info) { 00744 ast_dsp_free(s->debug_info->dsp); 00745 ast_free(s->debug_info); 00746 } 00747 00748 if (s->smoother) { 00749 ast_smoother_free(s->smoother); 00750 } 00751 00752 if (s->state != AST_FAX_STATE_INACTIVE) { 00753 ast_atomic_fetchadd_int(&faxregistry.active_sessions, -1); 00754 } 00755 00756 ast_free(s->channame); 00757 ast_free(s->chan_uniqueid); 00758 }
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 fax_module::next.
Referenced by session_details_new().
00372 { 00373 struct ast_fax_session_details *d = details; 00374 struct ast_fax_document *doc; 00375 00376 while ((doc = AST_LIST_REMOVE_HEAD(&d->documents, next))) { 00377 ast_free(doc); 00378 } 00379 ast_string_field_free_memory(d); 00380 }
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_frame::ptr, ast_control_t38_parameters::request_response, and ast_frame::subclass.
Referenced by receivefax_exec(), sendfax_exec(), and transmit_t38().
01093 { 01094 int timeout_ms; 01095 struct ast_frame *frame = NULL; 01096 struct ast_control_t38_parameters t38_parameters = { .request_response = AST_T38_REQUEST_TERMINATE, }; 01097 struct timeval start; 01098 int ms; 01099 01100 ast_debug(1, "Shutting down T.38 on %s\n", chan->name); 01101 if (ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0) { 01102 ast_debug(1, "error while disabling T.38 on channel '%s'\n", chan->name); 01103 return -1; 01104 } 01105 01106 /* wait up to five seconds for negotiation to complete */ 01107 timeout_ms = 5000; 01108 start = ast_tvnow(); 01109 while ((ms = ast_remaining_ms(start, timeout_ms))) { 01110 ms = ast_waitfor(chan, ms); 01111 01112 if (ms == 0) { 01113 break; 01114 } 01115 if (ms < 0) { 01116 ast_debug(1, "error while disabling T.38 on channel '%s'\n", chan->name); 01117 return -1; 01118 } 01119 01120 if (!(frame = ast_read(chan))) { 01121 return -1; 01122 } 01123 if ((frame->frametype == AST_FRAME_CONTROL) && 01124 (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) && 01125 (frame->datalen == sizeof(t38_parameters))) { 01126 struct ast_control_t38_parameters *parameters = frame->data.ptr; 01127 01128 switch (parameters->request_response) { 01129 case AST_T38_TERMINATED: 01130 ast_debug(1, "Shut down T.38 on %s\n", chan->name); 01131 break; 01132 case AST_T38_REFUSED: 01133 ast_log(LOG_WARNING, "channel '%s' refused to disable T.38\n", chan->name); 01134 ast_frfree(frame); 01135 return -1; 01136 default: 01137 ast_log(LOG_ERROR, "channel '%s' failed to disable T.38\n", chan->name); 01138 ast_frfree(frame); 01139 return -1; 01140 } 01141 ast_frfree(frame); 01142 break; 01143 } 01144 ast_frfree(frame); 01145 } 01146 01147 if (ms == 0) { /* all done, nothing happened */ 01148 ast_debug(1, "channel '%s' timed-out during T.38 shutdown\n", chan->name); 01149 } 01150 01151 return 0; 01152 }
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().
00691 { 00692 int rate; 00693 00694 if (sscanf(ratestr, "%d", &rate) != 1) { 00695 ast_log(LOG_ERROR, "failed to sscanf '%s' to rate\n", ratestr); 00696 return 0; 00697 } 00698 switch (rate) { 00699 case 2400: 00700 case 4800: 00701 case 7200: 00702 case 9600: 00703 case 12000: 00704 case 14400: 00705 case 28800: 00706 case 33600: 00707 return rate; 00708 default: 00709 ast_log(LOG_WARNING, "ignoring invalid rate '%s'. Valid options are {2400 | 4800 | 7200 | 9600 | 12000 | 14400 | 28800 | 33600}\n", ratestr); 00710 return 0; 00711 } 00712 }
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, read] |
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_tech::caps, ast_fax_session_details::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::id, ast_fax_session_details::id, LOG_ERROR, ast_fax_tech::module, ast_fax_tech::new_session, ast_fax_session_details::option, ast_fax_session::state, ast_fax_session::tech, fax_module::tech, and ast_fax_session::tech_pvt.
Referenced by generic_fax_exec().
00811 { 00812 struct ast_fax_session *s = NULL; 00813 struct fax_module *faxmod; 00814 char caps[128] = ""; 00815 00816 if (reserved) { 00817 s = reserved; 00818 ao2_ref(reserved, +1); 00819 00820 if (s->state == AST_FAX_STATE_RESERVED) { 00821 ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, -1); 00822 s->state = AST_FAX_STATE_UNINITIALIZED; 00823 } 00824 } 00825 00826 if (!s && !(s = ao2_alloc(sizeof(*s), destroy_session))) { 00827 return NULL; 00828 } 00829 00830 ast_atomic_fetchadd_int(&faxregistry.active_sessions, 1); 00831 s->state = AST_FAX_STATE_UNINITIALIZED; 00832 00833 if (details->option.debug && (details->caps & AST_FAX_TECH_AUDIO)) { 00834 if (!(s->debug_info = ast_calloc(1, sizeof(*(s->debug_info))))) { 00835 fax_session_release(s, token); 00836 ao2_ref(s, -1); 00837 return NULL; 00838 } 00839 if (!(s->debug_info->dsp = ast_dsp_new())) { 00840 ast_free(s->debug_info); 00841 s->debug_info = NULL; 00842 fax_session_release(s, token); 00843 ao2_ref(s, -1); 00844 return NULL; 00845 } 00846 ast_dsp_set_threshold(s->debug_info->dsp, 128); 00847 } 00848 00849 if (!(s->channame = ast_strdup(chan->name))) { 00850 fax_session_release(s, token); 00851 ao2_ref(s, -1); 00852 return NULL; 00853 } 00854 00855 if (!(s->chan_uniqueid = ast_strdup(chan->uniqueid))) { 00856 fax_session_release(s, token); 00857 ao2_ref(s, -1); 00858 return NULL; 00859 } 00860 00861 s->chan = chan; 00862 s->details = details; 00863 ao2_ref(s->details, 1); 00864 00865 details->id = s->id = ast_atomic_fetchadd_int(&faxregistry.nextsessionname, 1); 00866 00867 if (!token) { 00868 /* locate a FAX technology module that can handle said requirements */ 00869 AST_RWLIST_RDLOCK(&faxmodules); 00870 AST_RWLIST_TRAVERSE(&faxmodules, faxmod, list) { 00871 if ((faxmod->tech->caps & details->caps) != details->caps) { 00872 continue; 00873 } 00874 ast_debug(4, "Requesting a new FAX session from '%s'.\n", faxmod->tech->description); 00875 ast_module_ref(faxmod->tech->module); 00876 if (reserved) { 00877 /* Balance module ref from reserved session */ 00878 ast_module_unref(reserved->tech->module); 00879 } 00880 s->tech = faxmod->tech; 00881 break; 00882 } 00883 AST_RWLIST_UNLOCK(&faxmodules); 00884 00885 if (!faxmod) { 00886 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))); 00887 ao2_ref(s, -1); 00888 return NULL; 00889 } 00890 } 00891 00892 if (!(s->tech_pvt = s->tech->new_session(s, token))) { 00893 ast_log(LOG_ERROR, "FAX session failed to initialize.\n"); 00894 ao2_ref(s, -1); 00895 return NULL; 00896 } 00897 /* link the session to the session container */ 00898 if (!(ao2_link(faxregistry.container, s))) { 00899 ast_log(LOG_ERROR, "failed to add FAX session '%u' to container.\n", s->id); 00900 ao2_ref(s, -1); 00901 return NULL; 00902 } 00903 ast_debug(4, "channel '%s' using FAX session '%u'\n", s->channame, s->id); 00904 00905 return s; 00906 }
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().
00715 { 00716 if (token) { 00717 s->tech->release_token(token); 00718 } 00719 00720 if (s->state == AST_FAX_STATE_RESERVED) { 00721 ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, -1); 00722 s->state = AST_FAX_STATE_INACTIVE; 00723 } 00724 }
static struct ast_fax_session* fax_session_reserve | ( | struct ast_fax_session_details * | details, | |
struct ast_fax_tech_token ** | token | |||
) | [static, read] |
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().
00761 { 00762 struct ast_fax_session *s; 00763 struct fax_module *faxmod; 00764 char caps[128] = ""; 00765 00766 if (!(s = ao2_alloc(sizeof(*s), destroy_session))) { 00767 return NULL; 00768 } 00769 00770 s->state = AST_FAX_STATE_INACTIVE; 00771 00772 /* locate a FAX technology module that can handle said requirements 00773 * Note: the requirements have not yet been finalized as T.38 00774 * negotiation has not yet occured. */ 00775 AST_RWLIST_RDLOCK(&faxmodules); 00776 AST_RWLIST_TRAVERSE(&faxmodules, faxmod, list) { 00777 if ((faxmod->tech->caps & details->caps) != details->caps) { 00778 continue; 00779 } 00780 ast_debug(4, "Reserving a FAX session from '%s'.\n", faxmod->tech->description); 00781 ast_module_ref(faxmod->tech->module); 00782 s->tech = faxmod->tech; 00783 break; 00784 } 00785 AST_RWLIST_UNLOCK(&faxmodules); 00786 00787 if (!faxmod) { 00788 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))); 00789 ao2_ref(s, -1); 00790 return NULL; 00791 } 00792 00793 if (!s->tech->reserve_session) { 00794 ast_debug(1, "Selected FAX technology module (%s) does not support reserving sessions.\n", s->tech->description); 00795 return s; 00796 } 00797 00798 if (!(*token = s->tech->reserve_session(s))) { 00799 ao2_ref(s, -1); 00800 return NULL; 00801 } 00802 00803 s->state = AST_FAX_STATE_RESERVED; 00804 ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, 1); 00805 00806 return s; 00807 }
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().
02362 { 02363 int tklen; 02364 int wordnum = 0; 02365 char *name = NULL; 02366 struct ao2_iterator i; 02367 struct ast_fax_session *s; 02368 char tbuf[5]; 02369 02370 if (a->pos != 3) { 02371 return NULL; 02372 } 02373 02374 tklen = strlen(a->word); 02375 i = ao2_iterator_init(faxregistry.container, 0); 02376 while ((s = ao2_iterator_next(&i))) { 02377 snprintf(tbuf, sizeof(tbuf), "%u", s->id); 02378 if (!strncasecmp(a->word, tbuf, tklen) && ++wordnum > a->n) { 02379 name = ast_strdup(tbuf); 02380 ao2_ref(s, -1); 02381 break; 02382 } 02383 ao2_ref(s, -1); 02384 } 02385 ao2_iterator_destroy(&i); 02386 return name; 02387 }
static struct ast_fax_session_details* find_details | ( | struct ast_channel * | chan | ) | [static, read] |
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, and LOG_WARNING.
Referenced by acf_faxopt_read(), and find_or_create_details().
00350 { 00351 struct ast_fax_session_details *details; 00352 struct ast_datastore *datastore; 00353 00354 ast_channel_lock(chan); 00355 if (!(datastore = ast_channel_datastore_find(chan, &fax_datastore, NULL))) { 00356 ast_channel_unlock(chan); 00357 return NULL; 00358 } 00359 if (!(details = datastore->data)) { 00360 ast_log(LOG_WARNING, "Huh? channel '%s' has a FAX datastore without data!\n", chan->name); 00361 ast_channel_unlock(chan); 00362 return NULL; 00363 } 00364 ao2_ref(details, 1); 00365 ast_channel_unlock(chan); 00366 00367 return details; 00368 }
static struct ast_fax_session_details* find_or_create_details | ( | struct ast_channel * | chan | ) | [static, read] |
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, and session_details_new().
Referenced by acf_faxopt_write(), receivefax_exec(), and sendfax_exec().
00418 { 00419 struct ast_fax_session_details *details; 00420 struct ast_datastore *datastore; 00421 00422 if ((details = find_details(chan))) { 00423 return details; 00424 } 00425 /* channel does not have one so we must create one */ 00426 if (!(details = session_details_new())) { 00427 ast_log(LOG_WARNING, "channel '%s' can't get a FAX details structure for the datastore!\n", chan->name); 00428 return NULL; 00429 } 00430 if (!(datastore = ast_datastore_alloc(&fax_datastore, NULL))) { 00431 ao2_ref(details, -1); 00432 ast_log(LOG_WARNING, "channel '%s' can't get a datastore!\n", chan->name); 00433 return NULL; 00434 } 00435 /* add the datastore to the channel and increment the refcount */ 00436 datastore->data = details; 00437 ao2_ref(details, 1); 00438 ast_channel_lock(chan); 00439 ast_channel_datastore_add(chan, datastore); 00440 ast_channel_unlock(chan); 00441 return details; 00442 }
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 fax_module::next.
Referenced by acf_faxopt_read(), cli_fax_show_sessions(), report_fax_status(), and sendfax_exec().
00928 { 00929 char *filenames, *c; 00930 size_t size = 0; 00931 int first = 1; 00932 struct ast_fax_document *doc; 00933 00934 /* don't process empty lists */ 00935 if (AST_LIST_EMPTY(&details->documents)) { 00936 return NULL; 00937 } 00938 00939 /* Calculate the total length of all of the file names */ 00940 AST_LIST_TRAVERSE(&details->documents, doc, next) { 00941 size += strlen(separator) + strlen(prefix) + strlen(doc->filename); 00942 } 00943 size += 1; /* add space for the terminating null */ 00944 00945 if (!(filenames = ast_malloc(size))) { 00946 return NULL; 00947 } 00948 c = filenames; 00949 00950 ast_build_string(&c, &size, "%s%s", prefix, AST_LIST_FIRST(&details->documents)->filename); 00951 AST_LIST_TRAVERSE(&details->documents, doc, next) { 00952 if (first) { 00953 first = 0; 00954 continue; 00955 } 00956 00957 ast_build_string(&c, &size, "%s%s%s", separator, prefix, doc->filename); 00958 } 00959 00960 return filenames; 00961 }
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::id, ast_frame_subclass::integer, LOG_ERROR, LOG_WARNING, 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, 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().
01163 { 01164 int ms; 01165 int timeout = RES_FAX_TIMEOUT; 01166 int chancount; 01167 unsigned int expected_frametype = -1; 01168 union ast_frame_subclass expected_framesubclass = { .integer = -1 }; 01169 unsigned int t38negotiated = (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED); 01170 struct ast_control_t38_parameters t38_parameters; 01171 const char *tempvar; 01172 struct ast_fax_session *fax = NULL; 01173 struct ast_frame *frame = NULL; 01174 struct ast_channel *c = chan; 01175 unsigned int orig_write_format = 0, orig_read_format = 0; 01176 int remaining_time; 01177 struct timeval start; 01178 01179 chancount = 1; 01180 01181 /* create the FAX session */ 01182 if (!(fax = fax_session_new(details, chan, reserved, token))) { 01183 ast_log(LOG_ERROR, "Can't create a FAX session, FAX attempt failed.\n"); 01184 report_fax_status(chan, details, "No Available Resource"); 01185 return -1; 01186 } 01187 01188 ast_channel_lock(chan); 01189 /* update session details */ 01190 if (ast_strlen_zero(details->headerinfo) && (tempvar = pbx_builtin_getvar_helper(chan, "LOCALHEADERINFO"))) { 01191 ast_string_field_set(details, headerinfo, tempvar); 01192 } 01193 if (ast_strlen_zero(details->localstationid)) { 01194 tempvar = pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"); 01195 ast_string_field_set(details, localstationid, tempvar ? tempvar : "unknown"); 01196 } 01197 ast_channel_unlock(chan); 01198 01199 report_fax_status(chan, details, "Allocating Resources"); 01200 01201 if (details->caps & AST_FAX_TECH_AUDIO) { 01202 expected_frametype = AST_FRAME_VOICE;; 01203 expected_framesubclass.codec = AST_FORMAT_SLINEAR; 01204 orig_write_format = chan->writeformat; 01205 if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) { 01206 ast_log(LOG_ERROR, "channel '%s' failed to set write format to signed linear'.\n", chan->name); 01207 ao2_lock(faxregistry.container); 01208 ao2_unlink(faxregistry.container, fax); 01209 ao2_unlock(faxregistry.container); 01210 ao2_ref(fax, -1); 01211 ast_channel_unlock(chan); 01212 return -1; 01213 } 01214 orig_read_format = chan->readformat; 01215 if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0) { 01216 ast_log(LOG_ERROR, "channel '%s' failed to set read format to signed linear.\n", chan->name); 01217 ao2_lock(faxregistry.container); 01218 ao2_unlink(faxregistry.container, fax); 01219 ao2_unlock(faxregistry.container); 01220 ao2_ref(fax, -1); 01221 ast_channel_unlock(chan); 01222 return -1; 01223 } 01224 if (fax->smoother) { 01225 ast_smoother_free(fax->smoother); 01226 fax->smoother = NULL; 01227 } 01228 if (!(fax->smoother = ast_smoother_new(320))) { 01229 ast_log(LOG_WARNING, "Channel '%s' FAX session '%u' failed to obtain a smoother.\n", chan->name, fax->id); 01230 } 01231 } else { 01232 expected_frametype = AST_FRAME_MODEM; 01233 expected_framesubclass.codec = AST_MODEM_T38; 01234 } 01235 01236 if (fax->debug_info) { 01237 fax->debug_info->base_tv = ast_tvnow(); 01238 } 01239 01240 /* reset our result fields just in case the fax tech driver wants to 01241 * set custom error messages */ 01242 ast_string_field_set(details, result, ""); 01243 ast_string_field_set(details, resultstr, ""); 01244 ast_string_field_set(details, error, ""); 01245 set_channel_variables(chan, details); 01246 01247 if (fax->tech->start_session(fax) < 0) { 01248 GENERIC_FAX_EXEC_ERROR(fax, chan, "INIT_ERROR", "failed to start FAX session"); 01249 } 01250 01251 report_fax_status(chan, details, "FAX Transmission In Progress"); 01252 01253 ast_debug(5, "channel %s will wait on FAX fd %d\n", chan->name, fax->fd); 01254 01255 /* handle frames for the session */ 01256 remaining_time = timeout; 01257 start = ast_tvnow(); 01258 while (remaining_time > 0) { 01259 struct ast_channel *ready_chan; 01260 int ofd, exception; 01261 01262 ms = 1000; 01263 errno = 0; 01264 ready_chan = ast_waitfor_nandfds(&c, chancount, &fax->fd, 1, &exception, &ofd, &ms); 01265 if (ready_chan) { 01266 if (!(frame = ast_read(chan))) { 01267 /* the channel is probably gone, so lets stop polling on it and let the 01268 * FAX session complete before we exit the application. if needed, 01269 * send the FAX stack silence so the modems can finish their session without 01270 * any problems */ 01271 ast_debug(1, "Channel '%s' did not return a frame; probably hung up.\n", chan->name); 01272 GENERIC_FAX_EXEC_SET_VARS(fax, chan, "HANGUP", "remote channel hungup"); 01273 c = NULL; 01274 chancount = 0; 01275 remaining_time = ast_remaining_ms(start, timeout); 01276 fax->tech->cancel_session(fax); 01277 if (fax->tech->generate_silence) { 01278 fax->tech->generate_silence(fax); 01279 } 01280 continue; 01281 } 01282 01283 if ((frame->frametype == AST_FRAME_CONTROL) && 01284 (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) && 01285 (frame->datalen == sizeof(t38_parameters))) { 01286 unsigned int was_t38 = t38negotiated; 01287 struct ast_control_t38_parameters *parameters = frame->data.ptr; 01288 01289 switch (parameters->request_response) { 01290 case AST_T38_REQUEST_NEGOTIATE: 01291 /* the other end has requested a switch to T.38, so reply that we are willing, if we can 01292 * do T.38 as well 01293 */ 01294 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters); 01295 t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED; 01296 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)); 01297 break; 01298 case AST_T38_NEGOTIATED: 01299 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters); 01300 t38negotiated = 1; 01301 break; 01302 default: 01303 break; 01304 } 01305 if (t38negotiated && !was_t38) { 01306 fax->tech->switch_to_t38(fax); 01307 details->caps &= ~AST_FAX_TECH_AUDIO; 01308 expected_frametype = AST_FRAME_MODEM; 01309 expected_framesubclass.codec = AST_MODEM_T38; 01310 if (fax->smoother) { 01311 ast_smoother_free(fax->smoother); 01312 fax->smoother = NULL; 01313 } 01314 01315 report_fax_status(chan, details, "T.38 Negotiated"); 01316 01317 ast_verb(3, "Channel '%s' switched to T.38 FAX session '%u'.\n", chan->name, fax->id); 01318 } 01319 } else if ((frame->frametype == expected_frametype) && 01320 (!memcmp(&frame->subclass, &expected_framesubclass, sizeof(frame->subclass)))) { 01321 struct ast_frame *f; 01322 01323 if (fax->smoother) { 01324 /* push the frame into a smoother */ 01325 if (ast_smoother_feed(fax->smoother, frame) < 0) { 01326 GENERIC_FAX_EXEC_ERROR(fax, chan, "UNKNOWN", "Failed to feed the smoother"); 01327 } 01328 while ((f = ast_smoother_read(fax->smoother)) && (f->data.ptr)) { 01329 if (fax->debug_info) { 01330 debug_check_frame_for_silence(fax, 1, f); 01331 } 01332 /* write the frame to the FAX stack */ 01333 fax->tech->write(fax, f); 01334 fax->frames_received++; 01335 if (f != frame) { 01336 ast_frfree(f); 01337 } 01338 } 01339 } else { 01340 /* write the frame to the FAX stack */ 01341 fax->tech->write(fax, frame); 01342 fax->frames_received++; 01343 } 01344 start = ast_tvnow(); 01345 } 01346 ast_frfree(frame); 01347 } else if (ofd == fax->fd) { 01348 /* read a frame from the FAX stack and send it out the channel. 01349 * the FAX stack will return a NULL if the FAX session has already completed */ 01350 if (!(frame = fax->tech->read(fax))) { 01351 break; 01352 } 01353 01354 if (fax->debug_info && (frame->frametype == AST_FRAME_VOICE)) { 01355 debug_check_frame_for_silence(fax, 0, frame); 01356 } 01357 01358 ast_write(chan, frame); 01359 fax->frames_sent++; 01360 ast_frfree(frame); 01361 start = ast_tvnow(); 01362 } else { 01363 if (ms && (ofd < 0)) { 01364 if ((errno == 0) || (errno == EINTR)) { 01365 remaining_time = ast_remaining_ms(start, timeout); 01366 if (remaining_time <= 0) 01367 GENERIC_FAX_EXEC_ERROR(fax, chan, "TIMEOUT", "fax session timed-out"); 01368 continue; 01369 } else { 01370 ast_log(LOG_WARNING, "something bad happened while channel '%s' was polling.\n", chan->name); 01371 GENERIC_FAX_EXEC_ERROR(fax, chan, "UNKNOWN", "error polling data"); 01372 break; 01373 } 01374 } else { 01375 /* nothing happened */ 01376 remaining_time = ast_remaining_ms(start, timeout); 01377 if (remaining_time <= 0) { 01378 GENERIC_FAX_EXEC_ERROR(fax, chan, "TIMEOUT", "fax session timed-out"); 01379 break; 01380 } 01381 } 01382 } 01383 } 01384 ast_debug(3, "channel '%s' - event loop stopped { timeout: %d, remaining_time: %d }\n", chan->name, timeout, remaining_time); 01385 01386 set_channel_variables(chan, details); 01387 01388 if (!strcasecmp(details->result, "FAILED")) { 01389 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 01390 } else { 01391 ast_atomic_fetchadd_int(&faxregistry.fax_complete, 1); 01392 } 01393 01394 if (fax) { 01395 ao2_lock(faxregistry.container); 01396 ao2_unlink(faxregistry.container, fax); 01397 ao2_unlock(faxregistry.container); 01398 ao2_ref(fax, -1); 01399 } 01400 01401 /* if the channel is still alive, and we changed its read/write formats, 01402 * restore them now 01403 */ 01404 if (chancount) { 01405 if (orig_read_format) { 01406 ast_set_read_format(chan, orig_read_format); 01407 } 01408 if (orig_write_format) { 01409 ast_set_write_format(chan, orig_write_format); 01410 } 01411 } 01412 01413 /* return the chancount so the calling function can determine if the channel hungup during this FAX session or not */ 01414 return chancount; 01415 }
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().
02661 { 02662 ast_rwlock_rdlock(&options_lock); 02663 *options = general_options; 02664 ast_rwlock_unlock(&options_lock); 02665 }
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().
00909 { 00910 pbx_substitute_variables_helper(chan, "${CONTEXT}", info->context, sizeof(info->context)); 00911 pbx_substitute_variables_helper(chan, "${EXTEN}", info->exten, sizeof(info->exten)); 00912 pbx_substitute_variables_helper(chan, "${CALLERID(num)}", info->cid, sizeof(info->cid)); 00913 }
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().
02921 { 02922 int res; 02923 02924 /* initialize the registry */ 02925 faxregistry.active_sessions = 0; 02926 faxregistry.reserved_sessions = 0; 02927 if (!(faxregistry.container = ao2_container_alloc(FAX_MAXBUCKETS, session_hash_cb, session_cmp_cb))) { 02928 return AST_MODULE_LOAD_DECLINE; 02929 } 02930 02931 if (set_config(0) < 0) { 02932 ast_log(LOG_ERROR, "failed to load configuration file '%s'\n", config); 02933 ao2_ref(faxregistry.container, -1); 02934 return AST_MODULE_LOAD_DECLINE; 02935 } 02936 02937 /* register CLI operations and applications */ 02938 if (ast_register_application_xml(app_sendfax, sendfax_exec) < 0) { 02939 ast_log(LOG_WARNING, "failed to register '%s'.\n", app_sendfax); 02940 ao2_ref(faxregistry.container, -1); 02941 return AST_MODULE_LOAD_DECLINE; 02942 } 02943 if (ast_register_application_xml(app_receivefax, receivefax_exec) < 0) { 02944 ast_log(LOG_WARNING, "failed to register '%s'.\n", app_receivefax); 02945 ast_unregister_application(app_sendfax); 02946 ao2_ref(faxregistry.container, -1); 02947 return AST_MODULE_LOAD_DECLINE; 02948 } 02949 ast_cli_register_multiple(fax_cli, ARRAY_LEN(fax_cli)); 02950 res = ast_custom_function_register(&acf_faxopt); 02951 fax_logger_level = ast_logger_register_level("FAX"); 02952 02953 return res; 02954 }
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, fax_module::next, 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().
01580 { 01581 char *parse, modems[128] = ""; 01582 int channel_alive; 01583 struct ast_fax_session_details *details; 01584 struct ast_fax_session *s; 01585 struct ast_fax_tech_token *token = NULL; 01586 struct ast_fax_document *doc; 01587 AST_DECLARE_APP_ARGS(args, 01588 AST_APP_ARG(filename); 01589 AST_APP_ARG(options); 01590 ); 01591 struct ast_flags opts = { 0, }; 01592 struct manager_event_info info; 01593 01594 /* initialize output channel variables */ 01595 pbx_builtin_setvar_helper(chan, "FAXSTATUS", "FAILED"); 01596 pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", NULL); 01597 pbx_builtin_setvar_helper(chan, "FAXPAGES", "0"); 01598 pbx_builtin_setvar_helper(chan, "FAXBITRATE", NULL); 01599 pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", NULL); 01600 01601 /* if we ran receivefax then we attempted to receive a fax, even if we 01602 * never start a fax session */ 01603 ast_atomic_fetchadd_int(&faxregistry.fax_rx_attempts, 1); 01604 01605 /* Get a FAX session details structure from the channel's FAX datastore and create one if 01606 * it does not already exist. */ 01607 if (!(details = find_or_create_details(chan))) { 01608 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 01609 pbx_builtin_setvar_helper(chan, "FAXERROR", "MEMORY_ERROR"); 01610 pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "error allocating memory"); 01611 ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n"); 01612 return -1; 01613 } 01614 01615 ast_string_field_set(details, result, "FAILED"); 01616 ast_string_field_set(details, resultstr, "error starting fax session"); 01617 ast_string_field_set(details, error, "INIT_ERROR"); 01618 set_channel_variables(chan, details); 01619 01620 if (details->maxrate < details->minrate) { 01621 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 01622 ast_string_field_set(details, error, "INVALID_ARGUMENTS"); 01623 ast_string_field_set(details, resultstr, "maxrate is less than minrate"); 01624 set_channel_variables(chan, details); 01625 ast_log(LOG_ERROR, "maxrate %u is less than minrate %u\n", details->maxrate, details->minrate); 01626 ao2_ref(details, -1); 01627 return -1; 01628 } 01629 01630 if (check_modem_rate(details->modems, details->minrate)) { 01631 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 01632 ast_fax_modem_to_str(details->modems, modems, sizeof(modems)); 01633 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %u\n", modems, details->minrate); 01634 ast_string_field_set(details, error, "INVALID_ARGUMENTS"); 01635 ast_string_field_set(details, resultstr, "incompatible 'modems' and 'minrate' settings"); 01636 set_channel_variables(chan, details); 01637 ao2_ref(details, -1); 01638 return -1; 01639 } 01640 01641 if (check_modem_rate(details->modems, details->maxrate)) { 01642 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 01643 ast_fax_modem_to_str(details->modems, modems, sizeof(modems)); 01644 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %u\n", modems, details->maxrate); 01645 ast_string_field_set(details, error, "INVALID_ARGUMENTS"); 01646 ast_string_field_set(details, resultstr, "incompatible 'modems' and 'maxrate' settings"); 01647 set_channel_variables(chan, details); 01648 ao2_ref(details, -1); 01649 return -1; 01650 } 01651 01652 if (ast_strlen_zero(data)) { 01653 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 01654 ast_string_field_set(details, error, "INVALID_ARGUMENTS"); 01655 ast_string_field_set(details, resultstr, "invalid arguments"); 01656 set_channel_variables(chan, details); 01657 ast_log(LOG_WARNING, "%s requires an argument (filename[,options])\n", app_receivefax); 01658 ao2_ref(details, -1); 01659 return -1; 01660 } 01661 parse = ast_strdupa(data); 01662 AST_STANDARD_APP_ARGS(args, parse); 01663 01664 if (!ast_strlen_zero(args.options) && 01665 ast_app_parse_options(fax_exec_options, &opts, NULL, args.options)) { 01666 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 01667 ast_string_field_set(details, error, "INVALID_ARGUMENTS"); 01668 ast_string_field_set(details, resultstr, "invalid arguments"); 01669 set_channel_variables(chan, details); 01670 ao2_ref(details, -1); 01671 return -1; 01672 } 01673 if (ast_strlen_zero(args.filename)) { 01674 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 01675 ast_string_field_set(details, error, "INVALID_ARGUMENTS"); 01676 ast_string_field_set(details, resultstr, "invalid arguments"); 01677 set_channel_variables(chan, details); 01678 ast_log(LOG_WARNING, "%s requires an argument (filename[,options])\n", app_receivefax); 01679 ao2_ref(details, -1); 01680 return -1; 01681 } 01682 01683 /* check for unsupported FAX application options */ 01684 if (ast_test_flag(&opts, OPT_CALLERMODE) || ast_test_flag(&opts, OPT_CALLEDMODE)) { 01685 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 01686 ast_string_field_set(details, error, "INVALID_ARGUMENTS"); 01687 ast_string_field_set(details, resultstr, "invalid arguments"); 01688 set_channel_variables(chan, details); 01689 ast_log(LOG_WARNING, "%s does not support polling\n", app_receivefax); 01690 ao2_ref(details, -1); 01691 return -1; 01692 } 01693 01694 pbx_builtin_setvar_helper(chan, "FAXERROR", "Channel Problems"); 01695 pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "Error before FAX transmission started."); 01696 01697 if (!(doc = ast_calloc(1, sizeof(*doc) + strlen(args.filename) + 1))) { 01698 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 01699 ast_string_field_set(details, error, "MEMORY_ERROR"); 01700 ast_string_field_set(details, resultstr, "error allocating memory"); 01701 set_channel_variables(chan, details); 01702 ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n"); 01703 ao2_ref(details, -1); 01704 return -1; 01705 } 01706 01707 strcpy(doc->filename, args.filename); 01708 AST_LIST_INSERT_TAIL(&details->documents, doc, next); 01709 01710 ast_verb(3, "Channel '%s' receiving FAX '%s'\n", chan->name, args.filename); 01711 01712 details->caps = AST_FAX_TECH_RECEIVE; 01713 details->option.send_ced = AST_FAX_OPTFLAG_TRUE; 01714 01715 /* check for debug */ 01716 if (ast_test_flag(&opts, OPT_DEBUG) || global_fax_debug) { 01717 details->option.debug = AST_FAX_OPTFLAG_TRUE; 01718 } 01719 01720 /* check for request for status events */ 01721 if (ast_test_flag(&opts, OPT_STATUS)) { 01722 details->option.statusevents = AST_FAX_OPTFLAG_TRUE; 01723 } 01724 01725 if ((ast_channel_get_t38_state(chan) == T38_STATE_UNAVAILABLE) || 01726 ast_test_flag(&opts, OPT_ALLOWAUDIO)) { 01727 details->option.allow_audio = AST_FAX_OPTFLAG_TRUE; 01728 } 01729 01730 if (!(s = fax_session_reserve(details, &token))) { 01731 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 01732 ast_string_field_set(details, resultstr, "error reserving fax session"); 01733 set_channel_variables(chan, details); 01734 ast_log(LOG_ERROR, "Unable to reserve FAX session.\n"); 01735 ao2_ref(details, -1); 01736 return -1; 01737 } 01738 01739 /* make sure the channel is up */ 01740 if (chan->_state != AST_STATE_UP) { 01741 if (ast_answer(chan)) { 01742 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 01743 ast_string_field_set(details, resultstr, "error answering channel"); 01744 set_channel_variables(chan, details); 01745 ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", chan->name); 01746 fax_session_release(s, token); 01747 ao2_ref(s, -1); 01748 ao2_ref(details, -1); 01749 return -1; 01750 } 01751 } 01752 01753 if (set_fax_t38_caps(chan, details)) { 01754 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 01755 ast_string_field_set(details, error, "T38_NEG_ERROR"); 01756 ast_string_field_set(details, resultstr, "error negotiating T.38"); 01757 set_channel_variables(chan, details); 01758 fax_session_release(s, token); 01759 ao2_ref(s, -1); 01760 ao2_ref(details, -1); 01761 return -1; 01762 } 01763 01764 if (details->caps & AST_FAX_TECH_T38) { 01765 if (receivefax_t38_init(chan, details)) { 01766 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 01767 ast_string_field_set(details, error, "T38_NEG_ERROR"); 01768 ast_string_field_set(details, resultstr, "error negotiating T.38"); 01769 set_channel_variables(chan, details); 01770 fax_session_release(s, token); 01771 ao2_ref(s, -1); 01772 ao2_ref(details, -1); 01773 ast_log(LOG_ERROR, "error initializing channel '%s' in T.38 mode\n", chan->name); 01774 return -1; 01775 } 01776 } 01777 01778 if ((channel_alive = generic_fax_exec(chan, details, s, token)) < 0) { 01779 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 01780 } 01781 01782 if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) { 01783 if (disable_t38(chan)) { 01784 ast_debug(1, "error disabling T.38 mode on %s\n", chan->name); 01785 } 01786 } 01787 01788 /* send out the AMI completion event */ 01789 ast_channel_lock(chan); 01790 01791 get_manager_event_info(chan, &info); 01792 manager_event(EVENT_FLAG_CALL, 01793 "ReceiveFAX", 01794 "Channel: %s\r\n" 01795 "Context: %s\r\n" 01796 "Exten: %s\r\n" 01797 "CallerID: %s\r\n" 01798 "RemoteStationID: %s\r\n" 01799 "LocalStationID: %s\r\n" 01800 "PagesTransferred: %s\r\n" 01801 "Resolution: %s\r\n" 01802 "TransferRate: %s\r\n" 01803 "FileName: %s\r\n", 01804 chan->name, 01805 info.context, 01806 info.exten, 01807 info.cid, 01808 S_OR(pbx_builtin_getvar_helper(chan, "REMOTESTATIONID"), ""), 01809 S_OR(pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"), ""), 01810 S_OR(pbx_builtin_getvar_helper(chan, "FAXPAGES"), ""), 01811 S_OR(pbx_builtin_getvar_helper(chan, "FAXRESOLUTION"), ""), 01812 S_OR(pbx_builtin_getvar_helper(chan, "FAXBITRATE"), ""), 01813 args.filename); 01814 ast_channel_unlock(chan); 01815 01816 ao2_ref(s, -1); 01817 ao2_ref(details, -1); 01818 01819 /* If the channel hungup return -1; otherwise, return 0 to continue in the dialplan */ 01820 return (!channel_alive) ? -1 : 0; 01821 }
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_fax_session_details::option, our_t38_parameters, ast_fax_session_details::our_t38_parameters, ast_frame::ptr, report_fax_status(), ast_control_t38_parameters::request_response, ast_frame::subclass, t38_parameters_ast_to_fax(), t38_parameters_fax_to_ast(), T38_STATE_NEGOTIATED, T38_STATE_NEGOTIATING, and ast_fax_session_details::their_t38_parameters.
Referenced by receivefax_exec().
01418 { 01419 int timeout_ms; 01420 struct ast_frame *frame = NULL; 01421 struct ast_control_t38_parameters t38_parameters; 01422 struct timeval start; 01423 int ms; 01424 01425 t38_parameters_ast_to_fax(&details->our_t38_parameters, &our_t38_parameters); 01426 01427 /* don't send any audio if we've already received a T.38 reinvite */ 01428 if (ast_channel_get_t38_state(chan) != T38_STATE_NEGOTIATING) { 01429 /* generate 3 seconds of CED */ 01430 if (ast_playtones_start(chan, 1024, "!2100/3000", 1)) { 01431 ast_log(LOG_ERROR, "error generating CED tone on %s\n", chan->name); 01432 return -1; 01433 } 01434 01435 timeout_ms = 3000; 01436 start = ast_tvnow(); 01437 while ((ms = ast_remaining_ms(start, timeout_ms))) { 01438 ms = ast_waitfor(chan, ms); 01439 01440 if (ms < 0) { 01441 ast_log(LOG_ERROR, "error while generating CED tone on %s\n", chan->name); 01442 ast_playtones_stop(chan); 01443 return -1; 01444 } 01445 01446 if (ms == 0) { /* all done, nothing happened */ 01447 break; 01448 } 01449 01450 if (!(frame = ast_read(chan))) { 01451 ast_log(LOG_ERROR, "error reading frame while generating CED tone on %s\n", chan->name); 01452 ast_playtones_stop(chan); 01453 return -1; 01454 } 01455 01456 if ((frame->frametype == AST_FRAME_CONTROL) && 01457 (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) && 01458 (frame->datalen == sizeof(t38_parameters))) { 01459 struct ast_control_t38_parameters *parameters = frame->data.ptr; 01460 01461 switch (parameters->request_response) { 01462 case AST_T38_REQUEST_NEGOTIATE: 01463 /* the other end has requested a switch to T.38, so reply that we are willing, if we can 01464 * do T.38 as well 01465 */ 01466 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters); 01467 t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED; 01468 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)); 01469 ast_playtones_stop(chan); 01470 break; 01471 case AST_T38_NEGOTIATED: 01472 ast_debug(1, "Negotiated T.38 for receive on %s\n", chan->name); 01473 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters); 01474 details->caps &= ~AST_FAX_TECH_AUDIO; 01475 report_fax_status(chan, details, "T.38 Negotiated"); 01476 break; 01477 default: 01478 break; 01479 } 01480 } 01481 ast_frfree(frame); 01482 } 01483 01484 ast_playtones_stop(chan); 01485 } 01486 01487 /* if T.38 was negotiated, we are done initializing */ 01488 if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) { 01489 return 0; 01490 } 01491 01492 /* request T.38 */ 01493 ast_debug(1, "Negotiating T.38 for receive on %s\n", chan->name); 01494 01495 /* wait up to five seconds for negotiation to complete */ 01496 timeout_ms = 5000; 01497 01498 /* set parameters based on the session's parameters */ 01499 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters); 01500 t38_parameters.request_response = AST_T38_REQUEST_NEGOTIATE; 01501 if ((ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0)) { 01502 return -1; 01503 } 01504 01505 start = ast_tvnow(); 01506 while ((ms = ast_remaining_ms(start, timeout_ms))) { 01507 int break_loop = 0; 01508 01509 ms = ast_waitfor(chan, ms); 01510 if (ms < 0) { 01511 ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", chan->name); 01512 return -1; 01513 } 01514 if (ms == 0) { /* all done, nothing happened */ 01515 ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 negotiation.\n", chan->name); 01516 details->caps &= ~AST_FAX_TECH_T38; 01517 break; 01518 } 01519 01520 if (!(frame = ast_read(chan))) { 01521 ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", chan->name); 01522 return -1; 01523 } 01524 01525 if ((frame->frametype == AST_FRAME_CONTROL) && 01526 (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) && 01527 (frame->datalen == sizeof(t38_parameters))) { 01528 struct ast_control_t38_parameters *parameters = frame->data.ptr; 01529 01530 switch (parameters->request_response) { 01531 case AST_T38_REQUEST_NEGOTIATE: 01532 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters); 01533 t38_parameters.request_response = AST_T38_NEGOTIATED; 01534 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)); 01535 break; 01536 case AST_T38_NEGOTIATED: 01537 ast_debug(1, "Negotiated T.38 for receive on %s\n", chan->name); 01538 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters); 01539 details->caps &= ~AST_FAX_TECH_AUDIO; 01540 report_fax_status(chan, details, "T.38 Negotiated"); 01541 break_loop = 1; 01542 break; 01543 case AST_T38_REFUSED: 01544 ast_log(LOG_WARNING, "channel '%s' refused to negotiate T.38\n", chan->name); 01545 details->caps &= ~AST_FAX_TECH_T38; 01546 break_loop = 1; 01547 break; 01548 default: 01549 ast_log(LOG_ERROR, "channel '%s' failed to negotiate T.38\n", chan->name); 01550 details->caps &= ~AST_FAX_TECH_T38; 01551 break_loop = 1; 01552 break; 01553 } 01554 } 01555 ast_frfree(frame); 01556 if (break_loop) { 01557 break; 01558 } 01559 } 01560 01561 /* if T.38 was negotiated, we are done initializing */ 01562 if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) { 01563 return 0; 01564 } 01565 01566 /* if we made it here, then T.38 failed, check the 'f' flag */ 01567 if (details->option.allow_audio != AST_FAX_OPTFLAG_TRUE) { 01568 ast_log(LOG_WARNING, "Audio FAX not allowed on channel '%s' and T.38 negotiation failed; aborting.\n", chan->name); 01569 return -1; 01570 } 01571 01572 /* ok, audio fallback is allowed */ 01573 details->caps |= AST_FAX_TECH_AUDIO; 01574 01575 return 0; 01576 }
static int reload_module | ( | void | ) | [static] |
Definition at line 2956 of file res_fax.c.
References set_config().
02957 { 02958 set_config(1); 02959 return 0; 02960 }
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(), manager_event, ast_fax_session_details::option, and ast_fax_session_details::statusevents.
Referenced by generic_fax_exec(), receivefax_t38_init(), and sendfax_t38_init().
00965 { 00966 char *filenames = generate_filenames_string(details, "FileName: ", "\r\n"); 00967 if (!filenames) { 00968 return 1; 00969 } 00970 00971 ast_channel_lock(chan); 00972 if (details->option.statusevents) { 00973 struct manager_event_info info; 00974 00975 get_manager_event_info(chan, &info); 00976 manager_event(EVENT_FLAG_CALL, 00977 (details->caps & AST_FAX_TECH_RECEIVE) ? "ReceiveFAXStatus" : "SendFAXStatus", 00978 "Status: %s\r\n" 00979 "Channel: %s\r\n" 00980 "Context: %s\r\n" 00981 "Exten: %s\r\n" 00982 "CallerID: %s\r\n" 00983 "LocalStationID: %s\r\n" 00984 "%s\r\n", 00985 status, 00986 chan->name, 00987 info.context, 00988 info.exten, 00989 info.cid, 00990 details->localstationid, 00991 filenames); 00992 } 00993 ast_channel_unlock(chan); 00994 ast_free(filenames); 00995 00996 return 0; 00997 }
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, fax_module::next, 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, T38_STATE_NEGOTIATED, and T38_STATE_UNAVAILABLE.
Referenced by load_module().
02068 { 02069 char *parse, *filenames, *c, modems[128] = ""; 02070 int channel_alive, file_count; 02071 struct ast_fax_session_details *details; 02072 struct ast_fax_session *s; 02073 struct ast_fax_tech_token *token = NULL; 02074 struct ast_fax_document *doc; 02075 AST_DECLARE_APP_ARGS(args, 02076 AST_APP_ARG(filenames); 02077 AST_APP_ARG(options); 02078 ); 02079 struct ast_flags opts = { 0, }; 02080 struct manager_event_info info; 02081 02082 /* initialize output channel variables */ 02083 pbx_builtin_setvar_helper(chan, "FAXSTATUS", "FAILED"); 02084 pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", NULL); 02085 pbx_builtin_setvar_helper(chan, "FAXPAGES", "0"); 02086 pbx_builtin_setvar_helper(chan, "FAXBITRATE", NULL); 02087 pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", NULL); 02088 02089 /* if we ran sendfax then we attempted to send a fax, even if we never 02090 * start a fax session */ 02091 ast_atomic_fetchadd_int(&faxregistry.fax_tx_attempts, 1); 02092 02093 /* Get a requirement structure and set it. This structure is used 02094 * to tell the FAX technology module about the higher level FAX session */ 02095 if (!(details = find_or_create_details(chan))) { 02096 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 02097 pbx_builtin_setvar_helper(chan, "FAXERROR", "MEMORY_ERROR"); 02098 pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "error allocating memory"); 02099 ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n"); 02100 return -1; 02101 } 02102 02103 ast_string_field_set(details, result, "FAILED"); 02104 ast_string_field_set(details, resultstr, "error starting fax session"); 02105 ast_string_field_set(details, error, "INIT_ERROR"); 02106 set_channel_variables(chan, details); 02107 02108 if (details->maxrate < details->minrate) { 02109 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 02110 ast_string_field_set(details, error, "INVALID_ARGUMENTS"); 02111 ast_string_field_set(details, resultstr, "maxrate is less than minrate"); 02112 set_channel_variables(chan, details); 02113 ast_log(LOG_ERROR, "maxrate %u is less than minrate %u\n", details->maxrate, details->minrate); 02114 ao2_ref(details, -1); 02115 return -1; 02116 } 02117 02118 if (check_modem_rate(details->modems, details->minrate)) { 02119 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 02120 ast_fax_modem_to_str(details->modems, modems, sizeof(modems)); 02121 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %u\n", modems, details->minrate); 02122 ast_string_field_set(details, error, "INVALID_ARGUMENTS"); 02123 ast_string_field_set(details, resultstr, "incompatible 'modems' and 'minrate' settings"); 02124 set_channel_variables(chan, details); 02125 ao2_ref(details, -1); 02126 return -1; 02127 } 02128 02129 if (check_modem_rate(details->modems, details->maxrate)) { 02130 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 02131 ast_fax_modem_to_str(details->modems, modems, sizeof(modems)); 02132 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %u\n", modems, details->maxrate); 02133 ast_string_field_set(details, error, "INVALID_ARGUMENTS"); 02134 ast_string_field_set(details, resultstr, "incompatible 'modems' and 'maxrate' settings"); 02135 set_channel_variables(chan, details); 02136 ao2_ref(details, -1); 02137 return -1; 02138 } 02139 02140 if (ast_strlen_zero(data)) { 02141 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 02142 ast_string_field_set(details, error, "INVALID_ARGUMENTS"); 02143 ast_string_field_set(details, resultstr, "invalid arguments"); 02144 set_channel_variables(chan, details); 02145 ast_log(LOG_WARNING, "%s requires an argument (filename[&filename[&filename]][,options])\n", app_sendfax); 02146 ao2_ref(details, -1); 02147 return -1; 02148 } 02149 parse = ast_strdupa(data); 02150 AST_STANDARD_APP_ARGS(args, parse); 02151 02152 02153 if (!ast_strlen_zero(args.options) && 02154 ast_app_parse_options(fax_exec_options, &opts, NULL, args.options)) { 02155 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 02156 ast_string_field_set(details, error, "INVALID_ARGUMENTS"); 02157 ast_string_field_set(details, resultstr, "invalid arguments"); 02158 set_channel_variables(chan, details); 02159 ao2_ref(details, -1); 02160 return -1; 02161 } 02162 if (ast_strlen_zero(args.filenames)) { 02163 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 02164 ast_string_field_set(details, error, "INVALID_ARGUMENTS"); 02165 ast_string_field_set(details, resultstr, "invalid arguments"); 02166 set_channel_variables(chan, details); 02167 ast_log(LOG_WARNING, "%s requires an argument (filename[&filename[&filename]],options])\n", app_sendfax); 02168 ao2_ref(details, -1); 02169 return -1; 02170 } 02171 02172 /* check for unsupported FAX application options */ 02173 if (ast_test_flag(&opts, OPT_CALLERMODE) || ast_test_flag(&opts, OPT_CALLEDMODE)) { 02174 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 02175 ast_string_field_set(details, error, "INVALID_ARGUMENTS"); 02176 ast_string_field_set(details, resultstr, "invalid arguments"); 02177 set_channel_variables(chan, details); 02178 ast_log(LOG_WARNING, "%s does not support polling\n", app_sendfax); 02179 ao2_ref(details, -1); 02180 return -1; 02181 } 02182 02183 file_count = 0; 02184 filenames = args.filenames; 02185 while ((c = strsep(&filenames, "&"))) { 02186 if (access(c, (F_OK | R_OK)) < 0) { 02187 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 02188 ast_string_field_set(details, error, "FILE_ERROR"); 02189 ast_string_field_set(details, resultstr, "error reading file"); 02190 set_channel_variables(chan, details); 02191 ast_log(LOG_ERROR, "access failure. Verify '%s' exists and check permissions.\n", args.filenames); 02192 ao2_ref(details, -1); 02193 return -1; 02194 } 02195 02196 if (!(doc = ast_calloc(1, sizeof(*doc) + strlen(c) + 1))) { 02197 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 02198 ast_string_field_set(details, error, "MEMORY_ERROR"); 02199 ast_string_field_set(details, resultstr, "error allocating memory"); 02200 set_channel_variables(chan, details); 02201 ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n"); 02202 ao2_ref(details, -1); 02203 return -1; 02204 } 02205 02206 strcpy(doc->filename, c); 02207 AST_LIST_INSERT_TAIL(&details->documents, doc, next); 02208 file_count++; 02209 } 02210 02211 if (file_count > 1) { 02212 details->caps |= AST_FAX_TECH_MULTI_DOC; 02213 } 02214 02215 ast_verb(3, "Channel '%s' sending FAX:\n", chan->name); 02216 AST_LIST_TRAVERSE(&details->documents, doc, next) { 02217 ast_verb(3, " %s\n", doc->filename); 02218 } 02219 02220 details->caps = AST_FAX_TECH_SEND; 02221 02222 /* check for debug */ 02223 if (ast_test_flag(&opts, OPT_DEBUG) || global_fax_debug) { 02224 details->option.debug = AST_FAX_OPTFLAG_TRUE; 02225 } 02226 02227 /* check for request for status events */ 02228 if (ast_test_flag(&opts, OPT_STATUS)) { 02229 details->option.statusevents = AST_FAX_OPTFLAG_TRUE; 02230 } 02231 02232 if ((ast_channel_get_t38_state(chan) == T38_STATE_UNAVAILABLE) || 02233 ast_test_flag(&opts, OPT_ALLOWAUDIO)) { 02234 details->option.allow_audio = AST_FAX_OPTFLAG_TRUE; 02235 } 02236 02237 if (ast_test_flag(&opts, OPT_REQUEST_T38)) { 02238 details->option.request_t38 = AST_FAX_OPTFLAG_TRUE; 02239 } 02240 02241 if (!(s = fax_session_reserve(details, &token))) { 02242 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 02243 ast_string_field_set(details, resultstr, "error reserving fax session"); 02244 set_channel_variables(chan, details); 02245 ast_log(LOG_ERROR, "Unable to reserve FAX session.\n"); 02246 ao2_ref(details, -1); 02247 return -1; 02248 } 02249 02250 /* make sure the channel is up */ 02251 if (chan->_state != AST_STATE_UP) { 02252 if (ast_answer(chan)) { 02253 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 02254 ast_string_field_set(details, resultstr, "error answering channel"); 02255 set_channel_variables(chan, details); 02256 ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", chan->name); 02257 fax_session_release(s, token); 02258 ao2_ref(s, -1); 02259 ao2_ref(details, -1); 02260 return -1; 02261 } 02262 } 02263 02264 if (set_fax_t38_caps(chan, details)) { 02265 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 02266 ast_string_field_set(details, error, "T38_NEG_ERROR"); 02267 ast_string_field_set(details, resultstr, "error negotiating T.38"); 02268 set_channel_variables(chan, details); 02269 fax_session_release(s, token); 02270 ao2_ref(s, -1); 02271 ao2_ref(details, -1); 02272 return -1; 02273 } 02274 02275 if (details->caps & AST_FAX_TECH_T38) { 02276 if (sendfax_t38_init(chan, details)) { 02277 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 02278 ast_string_field_set(details, error, "T38_NEG_ERROR"); 02279 ast_string_field_set(details, resultstr, "error negotiating T.38"); 02280 set_channel_variables(chan, details); 02281 fax_session_release(s, token); 02282 ao2_ref(s, -1); 02283 ao2_ref(details, -1); 02284 ast_log(LOG_ERROR, "error initializing channel '%s' in T.38 mode\n", chan->name); 02285 return -1; 02286 } 02287 } else { 02288 details->option.send_cng = 1; 02289 } 02290 02291 if ((channel_alive = generic_fax_exec(chan, details, s, token)) < 0) { 02292 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 02293 } 02294 02295 if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) { 02296 if (disable_t38(chan)) { 02297 ast_debug(1, "error disabling T.38 mode on %s\n", chan->name); 02298 } 02299 } 02300 02301 if (!(filenames = generate_filenames_string(details, "FileName: ", "\r\n"))) { 02302 ast_log(LOG_ERROR, "Error generating SendFAX manager event\n"); 02303 ao2_ref(s, -1); 02304 ao2_ref(details, -1); 02305 return (!channel_alive) ? -1 : 0; 02306 } 02307 02308 /* send out the AMI completion event */ 02309 ast_channel_lock(chan); 02310 get_manager_event_info(chan, &info); 02311 manager_event(EVENT_FLAG_CALL, 02312 "SendFAX", 02313 "Channel: %s\r\n" 02314 "Context: %s\r\n" 02315 "Exten: %s\r\n" 02316 "CallerID: %s\r\n" 02317 "RemoteStationID: %s\r\n" 02318 "LocalStationID: %s\r\n" 02319 "PagesTransferred: %s\r\n" 02320 "Resolution: %s\r\n" 02321 "TransferRate: %s\r\n" 02322 "%s\r\n", 02323 chan->name, 02324 info.context, 02325 info.exten, 02326 info.cid, 02327 S_OR(pbx_builtin_getvar_helper(chan, "REMOTESTATIONID"), ""), 02328 S_OR(pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"), ""), 02329 S_OR(pbx_builtin_getvar_helper(chan, "FAXPAGES"), ""), 02330 S_OR(pbx_builtin_getvar_helper(chan, "FAXRESOLUTION"), ""), 02331 S_OR(pbx_builtin_getvar_helper(chan, "FAXBITRATE"), ""), 02332 filenames); 02333 ast_channel_unlock(chan); 02334 02335 ast_free(filenames); 02336 02337 ao2_ref(s, -1); 02338 ao2_ref(details, -1); 02339 02340 /* If the channel hungup return -1; otherwise, return 0 to continue in the dialplan */ 02341 return (!channel_alive) ? -1 : 0; 02342 }
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_fax_session_details::option, our_t38_parameters, ast_fax_session_details::our_t38_parameters, ast_frame::ptr, report_fax_status(), ast_control_t38_parameters::request_response, ast_fax_session_details::request_t38, ast_frame::subclass, t38_parameters_ast_to_fax(), t38_parameters_fax_to_ast(), T38_STATE_NEGOTIATED, T38_STATE_NEGOTIATING, and ast_fax_session_details::their_t38_parameters.
Referenced by sendfax_exec().
01824 { 01825 int timeout_ms; 01826 struct ast_frame *frame = NULL; 01827 struct ast_control_t38_parameters t38_parameters; 01828 struct timeval start; 01829 int ms; 01830 01831 t38_parameters_ast_to_fax(&details->our_t38_parameters, &our_t38_parameters); 01832 01833 /* send CNG tone while listening for the receiver to initiate a switch 01834 * to T.38 mode; if they do, stop sending the CNG tone and proceed with 01835 * the switch. 01836 * 01837 * 10500 is enough time for 3 CNG tones 01838 */ 01839 timeout_ms = 10500; 01840 01841 /* don't send any audio if we've already received a T.38 reinvite */ 01842 if (ast_channel_get_t38_state(chan) != T38_STATE_NEGOTIATING) { 01843 if (ast_playtones_start(chan, 1024, "!1100/500,!0/3000,!1100/500,!0/3000,!1100/500,!0/3000", 1)) { 01844 ast_log(LOG_ERROR, "error generating CNG tone on %s\n", chan->name); 01845 return -1; 01846 } 01847 } 01848 01849 start = ast_tvnow(); 01850 while ((ms = ast_remaining_ms(start, timeout_ms))) { 01851 int break_loop = 0; 01852 ms = ast_waitfor(chan, ms); 01853 01854 if (ms < 0) { 01855 ast_log(LOG_ERROR, "error while generating CNG tone on %s\n", chan->name); 01856 ast_playtones_stop(chan); 01857 return -1; 01858 } 01859 01860 if (ms == 0) { /* all done, nothing happened */ 01861 break; 01862 } 01863 01864 if (!(frame = ast_read(chan))) { 01865 ast_log(LOG_ERROR, "error reading frame while generating CNG tone on %s\n", chan->name); 01866 ast_playtones_stop(chan); 01867 return -1; 01868 } 01869 01870 if ((frame->frametype == AST_FRAME_CONTROL) && 01871 (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) && 01872 (frame->datalen == sizeof(t38_parameters))) { 01873 struct ast_control_t38_parameters *parameters = frame->data.ptr; 01874 01875 switch (parameters->request_response) { 01876 case AST_T38_REQUEST_NEGOTIATE: 01877 /* the other end has requested a switch to T.38, so reply that we are willing, if we can 01878 * do T.38 as well 01879 */ 01880 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters); 01881 t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED; 01882 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)); 01883 ast_playtones_stop(chan); 01884 break; 01885 case AST_T38_NEGOTIATED: 01886 ast_debug(1, "Negotiated T.38 for send on %s\n", chan->name); 01887 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters); 01888 details->caps &= ~AST_FAX_TECH_AUDIO; 01889 report_fax_status(chan, details, "T.38 Negotiated"); 01890 break_loop = 1; 01891 break; 01892 default: 01893 break; 01894 } 01895 } 01896 ast_frfree(frame); 01897 if (break_loop) { 01898 break; 01899 } 01900 } 01901 01902 ast_playtones_stop(chan); 01903 01904 if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) { 01905 return 0; 01906 } 01907 01908 /* T.38 negotiation did not happen, initiate a switch if requested */ 01909 if (details->option.request_t38 == AST_FAX_OPTFLAG_TRUE) { 01910 ast_debug(1, "Negotiating T.38 for send on %s\n", chan->name); 01911 01912 /* wait up to five seconds for negotiation to complete */ 01913 timeout_ms = 5000; 01914 01915 /* set parameters based on the session's parameters */ 01916 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters); 01917 t38_parameters.request_response = AST_T38_REQUEST_NEGOTIATE; 01918 if ((ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0)) { 01919 return -1; 01920 } 01921 01922 start = ast_tvnow(); 01923 while ((ms = ast_remaining_ms(start, timeout_ms))) { 01924 int break_loop = 0; 01925 01926 ms = ast_waitfor(chan, ms); 01927 if (ms < 0) { 01928 ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", chan->name); 01929 return -1; 01930 } 01931 if (ms == 0) { /* all done, nothing happened */ 01932 ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 negotiation.\n", chan->name); 01933 details->caps &= ~AST_FAX_TECH_T38; 01934 break; 01935 } 01936 01937 if (!(frame = ast_read(chan))) { 01938 ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", chan->name); 01939 return -1; 01940 } 01941 01942 if ((frame->frametype == AST_FRAME_CONTROL) && 01943 (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) && 01944 (frame->datalen == sizeof(t38_parameters))) { 01945 struct ast_control_t38_parameters *parameters = frame->data.ptr; 01946 01947 switch (parameters->request_response) { 01948 case AST_T38_REQUEST_NEGOTIATE: 01949 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters); 01950 t38_parameters.request_response = AST_T38_NEGOTIATED; 01951 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)); 01952 break; 01953 case AST_T38_NEGOTIATED: 01954 ast_debug(1, "Negotiated T.38 for receive on %s\n", chan->name); 01955 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters); 01956 details->caps &= ~AST_FAX_TECH_AUDIO; 01957 report_fax_status(chan, details, "T.38 Negotiated"); 01958 break_loop = 1; 01959 break; 01960 case AST_T38_REFUSED: 01961 ast_log(LOG_WARNING, "channel '%s' refused to negotiate T.38\n", chan->name); 01962 details->caps &= ~AST_FAX_TECH_T38; 01963 break_loop = 1; 01964 break; 01965 default: 01966 ast_log(LOG_ERROR, "channel '%s' failed to negotiate T.38\n", chan->name); 01967 details->caps &= ~AST_FAX_TECH_T38; 01968 break_loop = 1; 01969 break; 01970 } 01971 } 01972 ast_frfree(frame); 01973 if (break_loop) { 01974 break; 01975 } 01976 } 01977 01978 /* if T.38 was negotiated, we are done initializing */ 01979 if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) { 01980 return 0; 01981 } 01982 01983 /* send one more CNG tone to get audio going again for some 01984 * carriers if we are going to fall back to audio mode */ 01985 if (details->option.allow_audio == AST_FAX_OPTFLAG_TRUE) { 01986 if (ast_playtones_start(chan, 1024, "!1100/500,!0/3000", 1)) { 01987 ast_log(LOG_ERROR, "error generating second CNG tone on %s\n", chan->name); 01988 return -1; 01989 } 01990 01991 timeout_ms = 3500; 01992 start = ast_tvnow(); 01993 while ((ms = ast_remaining_ms(start, timeout_ms))) { 01994 int break_loop = 0; 01995 01996 ms = ast_waitfor(chan, ms); 01997 if (ms < 0) { 01998 ast_log(LOG_ERROR, "error while generating second CNG tone on %s\n", chan->name); 01999 ast_playtones_stop(chan); 02000 return -1; 02001 } 02002 if (ms == 0) { /* all done, nothing happened */ 02003 break; 02004 } 02005 02006 if (!(frame = ast_read(chan))) { 02007 ast_log(LOG_ERROR, "error reading frame while generating second CNG tone on %s\n", chan->name); 02008 ast_playtones_stop(chan); 02009 return -1; 02010 } 02011 02012 if ((frame->frametype == AST_FRAME_CONTROL) && 02013 (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) && 02014 (frame->datalen == sizeof(t38_parameters))) { 02015 struct ast_control_t38_parameters *parameters = frame->data.ptr; 02016 02017 switch (parameters->request_response) { 02018 case AST_T38_REQUEST_NEGOTIATE: 02019 /* the other end has requested a switch to T.38, so reply that we are willing, if we can 02020 * do T.38 as well 02021 */ 02022 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters); 02023 t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED; 02024 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)); 02025 ast_playtones_stop(chan); 02026 break; 02027 case AST_T38_NEGOTIATED: 02028 ast_debug(1, "Negotiated T.38 for send on %s\n", chan->name); 02029 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters); 02030 details->caps &= ~AST_FAX_TECH_AUDIO; 02031 report_fax_status(chan, details, "T.38 Negotiated"); 02032 break_loop = 1; 02033 break; 02034 default: 02035 break; 02036 } 02037 } 02038 ast_frfree(frame); 02039 if (break_loop) { 02040 break; 02041 } 02042 } 02043 02044 ast_playtones_stop(chan); 02045 02046 /* if T.38 was negotiated, we are done initializing */ 02047 if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) { 02048 return 0; 02049 } 02050 } 02051 } 02052 02053 /* if we made it here, then T.38 failed, check the 'f' flag */ 02054 if (details->option.allow_audio == AST_FAX_OPTFLAG_FALSE) { 02055 ast_log(LOG_WARNING, "Audio FAX not allowed on channel '%s' and T.38 negotiation failed; aborting.\n", chan->name); 02056 return -1; 02057 } 02058 02059 /* ok, audio fallback is allowed */ 02060 details->caps |= AST_FAX_TECH_AUDIO; 02061 02062 return 0; 02063 }
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().
02354 { 02355 struct ast_fax_session *lhs = obj, *rhs = arg; 02356 02357 return (lhs->id == rhs->id) ? CMP_MATCH | CMP_STOP : 0; 02358 }
static struct ast_fax_session_details* session_details_new | ( | void | ) | [static, read] |
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, fax_options::ecm, ast_fax_session_details::ecm, get_general_options(), fax_options::maxrate, ast_fax_session_details::maxrate, fax_options::minrate, ast_fax_session_details::minrate, fax_options::modems, ast_fax_session_details::modems, ast_fax_session_details::option, ast_fax_session_details::request_t38, ast_fax_session_details::send_ced, ast_fax_session_details::send_cng, fax_options::statusevents, and ast_fax_session_details::statusevents.
Referenced by find_or_create_details().
00384 { 00385 struct ast_fax_session_details *d; 00386 struct fax_options options; 00387 00388 if (!(d = ao2_alloc(sizeof(*d), destroy_session_details))) { 00389 return NULL; 00390 } 00391 00392 if (ast_string_field_init(d, 512)) { 00393 ao2_ref(d, -1); 00394 return NULL; 00395 } 00396 00397 get_general_options(&options); 00398 00399 AST_LIST_HEAD_INIT_NOLOCK(&d->documents); 00400 00401 /* These options need to be set to the configured default and may be overridden by 00402 * SendFAX, ReceiveFAX, or FAXOPT */ 00403 d->option.request_t38 = AST_FAX_OPTFLAG_FALSE; 00404 d->option.send_cng = AST_FAX_OPTFLAG_FALSE; 00405 d->option.send_ced = AST_FAX_OPTFLAG_FALSE; 00406 d->option.ecm = options.ecm; 00407 d->option.statusevents = options.statusevents; 00408 d->modems = options.modems; 00409 d->minrate = options.minrate; 00410 d->maxrate = options.maxrate; 00411 00412 return d; 00413 }
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().
02346 { 02347 const struct ast_fax_session *s = obj; 02348 02349 return s->id; 02350 }
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::pages_transferred, pbx_builtin_setvar_helper(), and S_OR.
Referenced by generic_fax_exec(), receivefax_exec(), and sendfax_exec().
01001 { 01002 char buf[10]; 01003 pbx_builtin_setvar_helper(chan, "FAXSTATUS", S_OR(details->result, NULL)); 01004 pbx_builtin_setvar_helper(chan, "FAXERROR", S_OR(details->error, NULL)); 01005 pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", S_OR(details->resultstr, NULL)); 01006 pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", S_OR(details->remotestationid, NULL)); 01007 pbx_builtin_setvar_helper(chan, "LOCALSTATIONID", S_OR(details->localstationid, NULL)); 01008 pbx_builtin_setvar_helper(chan, "FAXBITRATE", S_OR(details->transfer_rate, NULL)); 01009 pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", S_OR(details->resolution, NULL)); 01010 01011 snprintf(buf, sizeof(buf), "%u", details->pages_transferred); 01012 pbx_builtin_setvar_helper(chan, "FAXPAGES", buf); 01013 }
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().
02669 { 02670 struct ast_config *cfg; 02671 struct ast_variable *v; 02672 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 02673 char modems[128] = ""; 02674 struct fax_options options; 02675 int res = 0; 02676 02677 options = default_options; 02678 02679 /* When we're not reloading, we have to be certain to set the general options 02680 * to the defaults in case config loading goes wrong at some point. On a reload, 02681 * the general options need to stay the same as what they were prior to the 02682 * reload rather than being reset to the defaults. 02683 */ 02684 if (!reload) { 02685 set_general_options(&options); 02686 } 02687 02688 /* read configuration */ 02689 if (!(cfg = ast_config_load2(config, "res_fax", config_flags))) { 02690 ast_log(LOG_NOTICE, "Configuration file '%s' not found, %s options.\n", 02691 config, reload ? "not changing" : "using default"); 02692 return 0; 02693 } 02694 02695 if (cfg == CONFIG_STATUS_FILEINVALID) { 02696 ast_log(LOG_NOTICE, "Configuration file '%s' is invalid, %s options.\n", 02697 config, reload ? "not changing" : "using default"); 02698 return 0; 02699 } 02700 02701 if (cfg == CONFIG_STATUS_FILEUNCHANGED) { 02702 return 0; 02703 } 02704 02705 if (reload) { 02706 options = default_options; 02707 } 02708 02709 /* create configuration */ 02710 for (v = ast_variable_browse(cfg, "general"); v; v = v->next) { 02711 int rate; 02712 02713 if (!strcasecmp(v->name, "minrate")) { 02714 ast_debug(3, "reading minrate '%s' from configuration file\n", v->value); 02715 if ((rate = fax_rate_str_to_int(v->value)) == 0) { 02716 res = -1; 02717 goto end; 02718 } 02719 options.minrate = rate; 02720 } else if (!strcasecmp(v->name, "maxrate")) { 02721 ast_debug(3, "reading maxrate '%s' from configuration file\n", v->value); 02722 if ((rate = fax_rate_str_to_int(v->value)) == 0) { 02723 res = -1; 02724 goto end; 02725 } 02726 options.maxrate = rate; 02727 } else if (!strcasecmp(v->name, "statusevents")) { 02728 ast_debug(3, "reading statusevents '%s' from configuration file\n", v->value); 02729 options.statusevents = ast_true(v->value); 02730 } else if (!strcasecmp(v->name, "ecm")) { 02731 ast_debug(3, "reading ecm '%s' from configuration file\n", v->value); 02732 options.ecm = ast_true(v->value); 02733 } else if ((!strcasecmp(v->name, "modem")) || (!strcasecmp(v->name, "modems"))) { 02734 options.modems = 0; 02735 update_modem_bits(&options.modems, v->value); 02736 } 02737 } 02738 02739 if (options.maxrate < options.minrate) { 02740 ast_log(LOG_ERROR, "maxrate %u is less than minrate %u\n", options.maxrate, options.minrate); 02741 res = -1; 02742 goto end; 02743 } 02744 02745 if (options.minrate == 2400 && (options.modems & AST_FAX_MODEM_V27) && !(options.modems & (AST_FAX_MODEM_V34))) { 02746 ast_fax_modem_to_str(options.modems, modems, sizeof(modems)); 02747 ast_log(LOG_WARNING, "'modems' setting '%s' is no longer accepted with 'minrate' setting %u\n", modems, options.minrate); 02748 ast_log(LOG_WARNING, "'minrate' has been reset to 4800, please update res_fax.conf.\n"); 02749 options.minrate = 4800; 02750 } 02751 02752 if (check_modem_rate(options.modems, options.minrate)) { 02753 ast_fax_modem_to_str(options.modems, modems, sizeof(modems)); 02754 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %u\n", modems, options.minrate); 02755 res = -1; 02756 goto end; 02757 } 02758 02759 if (check_modem_rate(options.modems, options.maxrate)) { 02760 ast_fax_modem_to_str(options.modems, modems, sizeof(modems)); 02761 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %u\n", modems, options.maxrate); 02762 res = -1; 02763 goto end; 02764 } 02765 02766 set_general_options(&options); 02767 02768 end: 02769 ast_config_destroy(cfg); 02770 return res; 02771 }
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_control_t38_parameters::request_response, T38_STATE_NEGOTIATING, T38_STATE_UNAVAILABLE, and T38_STATE_UNKNOWN.
Referenced by receivefax_exec(), and sendfax_exec().
01060 { 01061 switch (ast_channel_get_t38_state(chan)) { 01062 case T38_STATE_UNKNOWN: 01063 details->caps |= AST_FAX_TECH_T38; 01064 break; 01065 case T38_STATE_UNAVAILABLE: 01066 details->caps |= AST_FAX_TECH_AUDIO; 01067 break; 01068 case T38_STATE_NEGOTIATING: { 01069 /* the other end already sent us a T.38 reinvite, so we need to prod the channel 01070 * driver into resending their parameters to us if it supports doing so... if 01071 * not, we can't proceed, because we can't create a proper reply without them. 01072 * if it does work, the channel driver will send an AST_CONTROL_T38_PARAMETERS 01073 * with a request of AST_T38_REQUEST_NEGOTIATE, which will be read by the function 01074 * that gets called after this one completes 01075 */ 01076 struct ast_control_t38_parameters parameters = { .request_response = AST_T38_REQUEST_PARMS, }; 01077 if (ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, ¶meters, sizeof(parameters)) != AST_T38_REQUEST_PARMS) { 01078 ast_log(LOG_ERROR, "channel '%s' is in an unsupported T.38 negotiation state, cannot continue.\n", chan->name); 01079 return -1; 01080 } 01081 details->caps |= AST_FAX_TECH_T38; 01082 break; 01083 } 01084 default: 01085 ast_log(LOG_ERROR, "channel '%s' is in an unsupported T.38 negotiation state, cannot continue.\n", chan->name); 01086 return -1; 01087 } 01088 01089 return 0; 01090 }
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().
02654 { 02655 ast_rwlock_wrlock(&options_lock); 02656 general_options = *options; 02657 ast_rwlock_unlock(&options_lock); 02658 }
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_control_t38_parameters::fill_bit_removal, ast_fax_t38_parameters::fill_bit_removal, ast_control_t38_parameters::max_ifp, ast_fax_t38_parameters::max_ifp, ast_control_t38_parameters::rate, ast_fax_t38_parameters::rate, ast_control_t38_parameters::rate_management, ast_fax_t38_parameters::rate_management, ast_control_t38_parameters::transcoding_jbig, ast_fax_t38_parameters::transcoding_jbig, ast_control_t38_parameters::transcoding_mmr, ast_fax_t38_parameters::transcoding_mmr, ast_control_t38_parameters::version, and ast_fax_t38_parameters::version.
Referenced by generic_fax_exec(), receivefax_t38_init(), and sendfax_t38_init().
01038 { 01039 dst->version = src->version; 01040 dst->max_ifp = src->max_ifp; 01041 dst->rate = src->rate; 01042 dst->rate_management = src->rate_management; 01043 dst->fill_bit_removal = src->fill_bit_removal; 01044 dst->transcoding_mmr = src->transcoding_mmr; 01045 dst->transcoding_jbig = src->transcoding_jbig; 01046 }
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().
01049 { 01050 dst->version = src->version; 01051 dst->max_ifp = src->max_ifp; 01052 dst->rate = src->rate; 01053 dst->rate_management = src->rate_management; 01054 dst->fill_bit_removal = src->fill_bit_removal; 01055 dst->transcoding_mmr = src->transcoding_mmr; 01056 dst->transcoding_jbig = src->transcoding_jbig; 01057 }
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.
02895 { 02896 ast_cli_unregister_multiple(fax_cli, ARRAY_LEN(fax_cli)); 02897 02898 if (ast_custom_function_unregister(&acf_faxopt) < 0) { 02899 ast_log(LOG_WARNING, "failed to unregister function '%s'\n", acf_faxopt.name); 02900 } 02901 02902 if (ast_unregister_application(app_sendfax) < 0) { 02903 ast_log(LOG_WARNING, "failed to unregister '%s'\n", app_sendfax); 02904 } 02905 02906 if (ast_unregister_application(app_receivefax) < 0) { 02907 ast_log(LOG_WARNING, "failed to unregister '%s'\n", app_receivefax); 02908 } 02909 02910 if (fax_logger_level != -1) { 02911 ast_logger_unregister_level("FAX"); 02912 } 02913 02914 ao2_ref(faxregistry.container, -1); 02915 02916 return 0; 02917 }
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().
00461 { 00462 char *m[5], *tok, *v = (char *)value; 00463 int i = 0, j; 00464 00465 if (!strchr(v, ',')) { 00466 m[i++] = v; 00467 m[i] = NULL; 00468 } else { 00469 tok = strtok(v, ", "); 00470 while (tok && i < ARRAY_LEN(m) - 1) { 00471 m[i++] = tok; 00472 tok = strtok(NULL, ", "); 00473 } 00474 m[i] = NULL; 00475 } 00476 00477 *bits = 0; 00478 for (j = 0; j < i; j++) { 00479 if (!strcasecmp(m[j], "v17")) { 00480 *bits |= AST_FAX_MODEM_V17; 00481 } else if (!strcasecmp(m[j], "v27")) { 00482 *bits |= AST_FAX_MODEM_V27; 00483 } else if (!strcasecmp(m[j], "v29")) { 00484 *bits |= AST_FAX_MODEM_V29; 00485 } else if (!strcasecmp(m[j], "v34")) { 00486 *bits |= AST_FAX_MODEM_V34; 00487 } else { 00488 ast_log(LOG_WARNING, "ignoring invalid modem setting: '%s', valid options {v17 | v27 | v29 | v34}\n", m[j]); 00489 } 00490 } 00491 return 0; 00492 }
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] |
struct ast_custom_function acf_faxopt |
{ .name = "FAXOPT", .read = acf_faxopt_read, .write = acf_faxopt_write, }
FAXOPT dialplan function.
Definition at line 2887 of file res_fax.c.
Referenced by load_module(), and unload_module().
int active_sessions |
const char app_receivefax[] = "ReceiveFAX" [static] |
const char app_sendfax[] = "SendFAX" [static] |
struct ast_module_info* ast_module_info = &__mod_info [static] |
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 |
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 |
struct ast_datastore_info fax_datastore [static] |
{ .type = "res_fax", .destroy = destroy_callback, }
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 |
int fax_logger_level = -1 [static] |
int fax_rx_attempts |
int fax_tx_attempts |
struct { ... } faxregistry [static] |
The faxregistry is used to manage information and statistics for all FAX sessions.
Referenced by cli_fax_show_session(), cli_fax_show_sessions(), cli_fax_show_stats(), destroy_session(), fax_session_new(), fax_session_release(), fax_session_reserve(), fax_session_tab_complete(), generic_fax_exec(), load_module(), receivefax_exec(), sendfax_exec(), and unload_module().
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 |
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().