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