#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 an ast_fax_state to a string | |
int | ast_fax_tech_register (struct ast_fax_tech *tech) |
register a fax technology | |
void | ast_fax_tech_unregister (struct ast_fax_tech *tech) |
unregister a fax technology | |
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, } |
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 | |
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 |
Kevin P. Fleming <kpfleming@digium.com>
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 | ) |
Value:
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 1024 of file res_fax.c.
Referenced by generic_fax_exec().
#define GENERIC_FAX_EXEC_ERROR_QUIET | ( | fax, | |||
chan, | |||||
errorstr, | |||||
reason | ) |
Value:
do { \ GENERIC_FAX_EXEC_SET_VARS(fax, chan, errorstr, reason); \ res = ms = -1; \ } while (0)
#define GENERIC_FAX_EXEC_SET_VARS | ( | fax, | |||
chan, | |||||
errorstr, | |||||
reason | ) |
#define RES_FAX_MODEM (AST_FAX_MODEM_V17 | AST_FAX_MODEM_V27 | AST_FAX_MODEM_V29) |
#define RES_FAX_TIMEOUT 10000 |
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 2732 of file res_fax.c.
References ao2_ref, ast_copy_string(), ast_fax_modem_to_str(), ast_free, AST_LIST_EMPTY, AST_LIST_FIRST, ast_log(), ast_fax_session_details::documents, ast_fax_session_details::ecm, ast_fax_session_details::error, find_details(), generate_filenames_string(), ast_fax_session_details::headerinfo, ast_fax_session_details::id, ast_fax_session_details::localstationid, LOG_ERROR, LOG_WARNING, ast_fax_session_details::maxrate, ast_fax_session_details::minrate, ast_fax_session_details::modems, ast_channel::name, ast_fax_session_details::option, ast_fax_session_details::pages_transferred, ast_fax_session_details::remotestationid, ast_fax_session_details::resolution, ast_fax_session_details::result, ast_fax_session_details::resultstr, and ast_fax_session_details::transfer_rate.
02733 { 02734 struct ast_fax_session_details *details = find_details(chan); 02735 int res = 0; 02736 char *filenames; 02737 02738 if (!details) { 02739 ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s) because it has never been written.\n", chan->name, data); 02740 return -1; 02741 } 02742 if (!strcasecmp(data, "ecm")) { 02743 ast_copy_string(buf, details->option.ecm ? "yes" : "no", len); 02744 } else if (!strcasecmp(data, "error")) { 02745 ast_copy_string(buf, details->error, len); 02746 } else if (!strcasecmp(data, "filename")) { 02747 if (AST_LIST_EMPTY(&details->documents)) { 02748 ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s) because it has never been written.\n", chan->name, data); 02749 res = -1; 02750 } else { 02751 ast_copy_string(buf, AST_LIST_FIRST(&details->documents)->filename, len); 02752 } 02753 } else if (!strcasecmp(data, "filenames")) { 02754 if (AST_LIST_EMPTY(&details->documents)) { 02755 ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s) because it has never been written.\n", chan->name, data); 02756 res = -1; 02757 } else if ((filenames = generate_filenames_string(details, "", ","))) { 02758 ast_copy_string(buf, filenames, len); 02759 ast_free(filenames); 02760 } else { 02761 ast_log(LOG_ERROR, "channel '%s' can't read FAXOPT(%s), there was an error generating the filenames list.\n", chan->name, data); 02762 res = -1; 02763 } 02764 } else if (!strcasecmp(data, "headerinfo")) { 02765 ast_copy_string(buf, details->headerinfo, len); 02766 } else if (!strcasecmp(data, "localstationid")) { 02767 ast_copy_string(buf, details->localstationid, len); 02768 } else if (!strcasecmp(data, "maxrate")) { 02769 snprintf(buf, len, "%d", details->maxrate); 02770 } else if (!strcasecmp(data, "minrate")) { 02771 snprintf(buf, len, "%d", details->minrate); 02772 } else if (!strcasecmp(data, "pages")) { 02773 snprintf(buf, len, "%d", details->pages_transferred); 02774 } else if (!strcasecmp(data, "rate")) { 02775 ast_copy_string(buf, details->transfer_rate, len); 02776 } else if (!strcasecmp(data, "remotestationid")) { 02777 ast_copy_string(buf, details->remotestationid, len); 02778 } else if (!strcasecmp(data, "resolution")) { 02779 ast_copy_string(buf, details->resolution, len); 02780 } else if (!strcasecmp(data, "sessionid")) { 02781 snprintf(buf, len, "%d", details->id); 02782 } else if (!strcasecmp(data, "status")) { 02783 ast_copy_string(buf, details->result, len); 02784 } else if (!strcasecmp(data, "statusstr")) { 02785 ast_copy_string(buf, details->resultstr, len); 02786 } else if ((!strcasecmp(data, "modem")) || (!strcasecmp(data, "modems"))) { 02787 ast_fax_modem_to_str(details->modems, buf, len); 02788 } else { 02789 ast_log(LOG_WARNING, "channel '%s' can't read FAXOPT(%s) because it is unhandled!\n", chan->name, data); 02790 res = -1; 02791 } 02792 ao2_ref(details, -1); 02793 02794 return res; 02795 }
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 2798 of file res_fax.c.
References ao2_ref, ast_debug, ast_false(), ast_fax_maxrate(), ast_fax_minrate(), AST_FAX_OPTFLAG_FALSE, AST_FAX_OPTFLAG_TRUE, ast_log(), ast_skip_blanks(), ast_string_field_set, ast_true(), ast_fax_session_details::ecm, fax_rate_str_to_int(), find_or_create_details(), ast_fax_session_details::headerinfo, ast_fax_session_details::localstationid, LOG_WARNING, ast_fax_session_details::maxrate, ast_fax_session_details::minrate, ast_fax_session_details::modems, ast_channel::name, ast_fax_session_details::option, and update_modem_bits().
02799 { 02800 int res = 0; 02801 struct ast_fax_session_details *details; 02802 02803 if (!(details = find_or_create_details(chan))) { 02804 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); 02805 return -1; 02806 } 02807 ast_debug(3, "channel '%s' setting FAXOPT(%s) to '%s'\n", chan->name, data, value); 02808 02809 if (!strcasecmp(data, "ecm")) { 02810 const char *val = ast_skip_blanks(value); 02811 if (ast_true(val)) { 02812 details->option.ecm = AST_FAX_OPTFLAG_TRUE; 02813 } else if (ast_false(val)) { 02814 details->option.ecm = AST_FAX_OPTFLAG_FALSE; 02815 } else { 02816 ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(ecm).\n", value); 02817 } 02818 } else if (!strcasecmp(data, "headerinfo")) { 02819 ast_string_field_set(details, headerinfo, value); 02820 } else if (!strcasecmp(data, "localstationid")) { 02821 ast_string_field_set(details, localstationid, value); 02822 } else if (!strcasecmp(data, "maxrate")) { 02823 details->maxrate = fax_rate_str_to_int(value); 02824 if (!details->maxrate) { 02825 details->maxrate = ast_fax_maxrate(); 02826 } 02827 } else if (!strcasecmp(data, "minrate")) { 02828 details->minrate = fax_rate_str_to_int(value); 02829 if (!details->minrate) { 02830 details->minrate = ast_fax_minrate(); 02831 } 02832 } else if ((!strcasecmp(data, "modem")) || (!strcasecmp(data, "modems"))) { 02833 update_modem_bits(&details->modems, value); 02834 } else { 02835 ast_log(LOG_WARNING, "channel '%s' set FAXOPT(%s) to '%s' is unhandled!\n", chan->name, data, value); 02836 res = -1; 02837 } 02838 02839 ao2_ref(details, -1); 02840 02841 return res; 02842 }
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(), and sendfax_exec().
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 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
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, fax_module::list, and fax_module::tech.
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
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::list, 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(), and sendfax_exec().
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 2386 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.
02387 { 02388 int flag; 02389 const char *what; 02390 02391 switch (cmd) { 02392 case CLI_INIT: 02393 e->command = "fax set debug {on|off}"; 02394 e->usage = 02395 "Usage: fax set debug { on | off }\n" 02396 " Enable/Disable FAX debugging on new FAX sessions. The basic FAX debugging will result in\n" 02397 " additional events sent to manager sessions with 'call' class permissions. When\n" 02398 " verbosity is greater than '5' events will be displayed to the console and audio versus\n" 02399 " energy analysis will be performed and displayed to the console.\n"; 02400 return NULL; 02401 case CLI_GENERATE: 02402 return NULL; 02403 } 02404 02405 what = a->argv[e->args-1]; /* guaranteed to exist */ 02406 if (!strcasecmp(what, "on")) { 02407 flag = 1; 02408 } else if (!strcasecmp(what, "off")) { 02409 flag = 0; 02410 } else { 02411 return CLI_SHOWUSAGE; 02412 } 02413 02414 global_fax_debug = flag; 02415 ast_cli(a->fd, "\n\nFAX Debug %s\n\n", (flag) ? "Enabled" : "Disabled"); 02416 02417 return CLI_SUCCESS; 02418 }
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 2421 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::list, fax_module::tech, ast_fax_tech::type, and ast_cli_entry::usage.
02422 { 02423 struct fax_module *fax; 02424 unsigned int num_modules = 0; 02425 02426 switch (cmd) { 02427 case CLI_INIT: 02428 e->command = "fax show capabilities"; 02429 e->usage = 02430 "Usage: fax show capabilities\n" 02431 " Shows the capabilities of the registered FAX technology modules\n"; 02432 return NULL; 02433 case CLI_GENERATE: 02434 return NULL; 02435 } 02436 02437 ast_cli(a->fd, "\n\nRegistered FAX Technology Modules:\n\n"); 02438 AST_RWLIST_RDLOCK(&faxmodules); 02439 AST_RWLIST_TRAVERSE(&faxmodules, fax, list) { 02440 ast_cli(a->fd, "%-15s : %s\n%-15s : %s\n%-15s : ", "Type", fax->tech->type, "Description", fax->tech->description, "Capabilities"); 02441 fax->tech->cli_show_capabilities(a->fd); 02442 num_modules++; 02443 } 02444 AST_RWLIST_UNLOCK(&faxmodules); 02445 ast_cli(a->fd, "%d registered modules\n\n", num_modules); 02446 02447 return CLI_SUCCESS; 02448 }
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 2489 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.
02490 { 02491 struct ast_fax_session *s, tmp; 02492 02493 switch (cmd) { 02494 case CLI_INIT: 02495 e->command = "fax show session"; 02496 e->usage = 02497 "Usage: fax show session <session number>\n" 02498 " Shows status of the named FAX session\n"; 02499 return NULL; 02500 case CLI_GENERATE: 02501 return fax_session_tab_complete(a); 02502 } 02503 02504 if (a->argc != 4) { 02505 return CLI_SHOWUSAGE; 02506 } 02507 02508 if (sscanf(a->argv[3], "%d", &tmp.id) != 1) { 02509 ast_log(LOG_ERROR, "invalid session id: '%s'\n", a->argv[3]); 02510 return RESULT_SUCCESS; 02511 } 02512 02513 ast_cli(a->fd, "\nFAX Session Details:\n--------------------\n\n"); 02514 s = ao2_find(faxregistry.container, &tmp, OBJ_POINTER); 02515 if (s) { 02516 s->tech->cli_show_session(s, a->fd); 02517 ao2_ref(s, -1); 02518 } 02519 ast_cli(a->fd, "\n\n"); 02520 02521 return CLI_SUCCESS; 02522 }
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 2558 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(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, faxregistry, ast_cli_args::fd, generate_filenames_string(), LOG_ERROR, session_count, and ast_cli_entry::usage.
02559 { 02560 struct ast_fax_session *s; 02561 struct ao2_iterator i; 02562 int session_count; 02563 char *filenames; 02564 02565 switch (cmd) { 02566 case CLI_INIT: 02567 e->command = "fax show sessions"; 02568 e->usage = 02569 "Usage: fax show sessions\n" 02570 " Shows the current FAX sessions\n"; 02571 return NULL; 02572 case CLI_GENERATE: 02573 return NULL; 02574 } 02575 02576 ast_cli(a->fd, "\nCurrent FAX Sessions:\n\n"); 02577 ast_cli(a->fd, "%-20.20s %-10.10s %-10.10s %-5.5s %-10.10s %-15.15s %-30.30s\n", 02578 "Channel", "Tech", "FAXID", "Type", "Operation", "State", "File(s)"); 02579 i = ao2_iterator_init(faxregistry.container, 0); 02580 while ((s = ao2_iterator_next(&i))) { 02581 ao2_lock(s); 02582 02583 if (!(filenames = generate_filenames_string(s->details, "", ", "))) { 02584 ast_log(LOG_ERROR, "Error printing filenames for 'fax show sessions' command\n"); 02585 ao2_unlock(s); 02586 ao2_ref(s, -1); 02587 ao2_iterator_destroy(&i); 02588 return CLI_FAILURE; 02589 } 02590 02591 ast_cli(a->fd, "%-20.20s %-10.10s %-10d %-5.5s %-10.10s %-15.15s %-30s\n", 02592 s->channame, s->tech->type, s->id, 02593 (s->details->caps & AST_FAX_TECH_AUDIO) ? "G.711" : "T.38", 02594 (s->details->caps & AST_FAX_TECH_SEND) ? "send" : "receive", 02595 ast_fax_state_to_str(s->state), filenames); 02596 02597 ast_free(filenames); 02598 ao2_unlock(s); 02599 ao2_ref(s, -1); 02600 } 02601 ao2_iterator_destroy(&i); 02602 session_count = ao2_container_count(faxregistry.container); 02603 ast_cli(a->fd, "\n%d FAX sessions\n\n", session_count); 02604 02605 return CLI_SUCCESS; 02606 }
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 2451 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_module::list, fax_options::maxrate, fax_options::minrate, fax_options::modems, fax_options::statusevents, fax_module::tech, ast_fax_tech::type, and ast_cli_entry::usage.
02452 { 02453 struct fax_module *fax; 02454 char modems[128] = ""; 02455 struct fax_options options; 02456 02457 switch (cmd) { 02458 case CLI_INIT: 02459 e->command = "fax show settings"; 02460 e->usage = 02461 "Usage: fax show settings\n" 02462 " Show the global settings and defaults of both the FAX core and technology modules\n"; 02463 return NULL; 02464 case CLI_GENERATE: 02465 return NULL; 02466 } 02467 02468 get_general_options(&options); 02469 02470 ast_cli(a->fd, "FAX For Asterisk Settings:\n"); 02471 ast_cli(a->fd, "\tECM: %s\n", options.ecm ? "Enabled" : "Disabled"); 02472 ast_cli(a->fd, "\tStatus Events: %s\n", options.statusevents ? "On" : "Off"); 02473 ast_cli(a->fd, "\tMinimum Bit Rate: %d\n", options.minrate); 02474 ast_cli(a->fd, "\tMaximum Bit Rate: %d\n", options.maxrate); 02475 ast_fax_modem_to_str(options.modems, modems, sizeof(modems)); 02476 ast_cli(a->fd, "\tModem Modulations Allowed: %s\n", modems); 02477 ast_cli(a->fd, "\n\nFAX Technology Modules:\n\n"); 02478 AST_RWLIST_RDLOCK(&faxmodules); 02479 AST_RWLIST_TRAVERSE(&faxmodules, fax, list) { 02480 ast_cli(a->fd, "%s (%s) Settings:\n", fax->tech->type, fax->tech->description); 02481 fax->tech->cli_show_settings(a->fd); 02482 } 02483 AST_RWLIST_UNLOCK(&faxmodules); 02484 02485 return CLI_SUCCESS; 02486 }
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 2525 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::list, fax_module::tech, and ast_cli_entry::usage.
02526 { 02527 struct fax_module *fax; 02528 02529 switch (cmd) { 02530 case CLI_INIT: 02531 e->command = "fax show stats"; 02532 e->usage = 02533 "Usage: fax show stats\n" 02534 " Shows a statistical summary of FAX transmissions\n"; 02535 return NULL; 02536 case CLI_GENERATE: 02537 return NULL; 02538 } 02539 02540 ast_cli(a->fd, "\nFAX Statistics:\n---------------\n\n"); 02541 ast_cli(a->fd, "%-20.20s : %d\n", "Current Sessions", faxregistry.active_sessions); 02542 ast_cli(a->fd, "%-20.20s : %d\n", "Reserved Sessions", faxregistry.reserved_sessions); 02543 ast_cli(a->fd, "%-20.20s : %d\n", "Transmit Attempts", faxregistry.fax_tx_attempts); 02544 ast_cli(a->fd, "%-20.20s : %d\n", "Receive Attempts", faxregistry.fax_rx_attempts); 02545 ast_cli(a->fd, "%-20.20s : %d\n", "Completed FAXes", faxregistry.fax_complete); 02546 ast_cli(a->fd, "%-20.20s : %d\n", "Failed FAXes", faxregistry.fax_failures); 02547 AST_RWLIST_RDLOCK(&faxmodules); 02548 AST_RWLIST_TRAVERSE(&faxmodules, fax, list) { 02549 fax->tech->cli_show_stats(a->fd); 02550 } 02551 AST_RWLIST_UNLOCK(&faxmodules); 02552 ast_cli(a->fd, "\n\n"); 02553 02554 return CLI_SUCCESS; 02555 }
static char* cli_fax_show_version | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 2354 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::list, fax_module::tech, ast_cli_entry::usage, and ast_fax_tech::version.
02355 { 02356 struct fax_module *fax; 02357 02358 switch(cmd) { 02359 case CLI_INIT: 02360 e->command = "fax show version"; 02361 e->usage = 02362 "Usage: fax show version\n" 02363 " Show versions of FAX For Asterisk components.\n"; 02364 return NULL; 02365 case CLI_GENERATE: 02366 return NULL; 02367 } 02368 02369 if (a->argc != 3) { 02370 return CLI_SHOWUSAGE; 02371 } 02372 02373 ast_cli(a->fd, "FAX For Asterisk Components:\n"); 02374 ast_cli(a->fd, "\tApplications: %s\n", ast_get_version()); 02375 AST_RWLIST_RDLOCK(&faxmodules); 02376 AST_RWLIST_TRAVERSE(&faxmodules, fax, list) { 02377 ast_cli(a->fd, "\t%s: %s\n", fax->tech->description, fax->tech->version); 02378 } 02379 AST_RWLIST_UNLOCK(&faxmodules); 02380 ast_cli(a->fd, "\n"); 02381 02382 return CLI_SUCCESS; 02383 }
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.
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 1085 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_T38_REFUSED, AST_T38_REQUEST_TERMINATE, AST_T38_TERMINATED, ast_waitfor(), ast_frame::data, ast_frame::datalen, ast_frame::frametype, ast_frame_subclass::integer, LOG_ERROR, LOG_WARNING, ast_channel::name, ast_frame::ptr, ast_control_t38_parameters::request_response, and ast_frame::subclass.
Referenced by receivefax_exec(), sendfax_exec(), and transmit_t38().
01086 { 01087 int ms; 01088 struct ast_frame *frame = NULL; 01089 struct ast_control_t38_parameters t38_parameters = { .request_response = AST_T38_REQUEST_TERMINATE, }; 01090 01091 ast_debug(1, "Shutting down T.38 on %s\n", chan->name); 01092 if (ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0) { 01093 ast_debug(1, "error while disabling T.38 on channel '%s'\n", chan->name); 01094 return -1; 01095 } 01096 01097 /* wait up to five seconds for negotiation to complete */ 01098 ms = 5000; 01099 01100 while (ms > 0) { 01101 ms = ast_waitfor(chan, ms); 01102 if (ms < 0) { 01103 ast_debug(1, "error while disabling T.38 on channel '%s'\n", chan->name); 01104 return -1; 01105 } 01106 01107 if (ms == 0) { /* all done, nothing happened */ 01108 ast_debug(1, "channel '%s' timed-out during T.38 shutdown\n", chan->name); 01109 break; 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 return 0; 01140 }
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] |
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_details::debug, ast_fax_tech::description, destroy_session(), fax_session_release(), faxregistry, ast_fax_session_details::id, fax_module::list, LOG_ERROR, ast_fax_tech::module, ast_channel::name, ast_fax_session_details::option, ast_fax_session::state, fax_module::tech, and ast_channel::uniqueid.
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] |
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, fax_module::list, LOG_ERROR, ast_fax_tech::module, ast_fax_session::state, 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 2326 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().
02327 { 02328 int tklen; 02329 int wordnum = 0; 02330 char *name = NULL; 02331 struct ao2_iterator i; 02332 struct ast_fax_session *s; 02333 char tbuf[5]; 02334 02335 if (a->pos != 3) { 02336 return NULL; 02337 } 02338 02339 tklen = strlen(a->word); 02340 i = ao2_iterator_init(faxregistry.container, 0); 02341 while ((s = ao2_iterator_next(&i))) { 02342 snprintf(tbuf, sizeof(tbuf), "%d", s->id); 02343 if (!strncasecmp(a->word, tbuf, tklen) && ++wordnum > a->n) { 02344 name = ast_strdup(tbuf); 02345 ao2_ref(s, -1); 02346 break; 02347 } 02348 ao2_ref(s, -1); 02349 } 02350 ao2_iterator_destroy(&i); 02351 return name; 02352 }
static struct ast_fax_session_details* find_details | ( | struct ast_channel * | chan | ) | [static] |
returns a reference counted pointer to a fax datastore, if it exists
Definition at line 349 of file res_fax.c.
References ao2_ref, ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_log(), ast_datastore::data, fax_datastore, LOG_WARNING, and ast_channel::name.
Referenced by acf_faxopt_read(), and find_or_create_details().
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] |
returns a reference counted details structure from the channel's fax datastore. If the datastore does not exist it will be created
Definition at line 417 of file res_fax.c.
References ao2_ref, ast_channel_datastore_add(), ast_channel_lock, ast_channel_unlock, ast_datastore_alloc, ast_log(), ast_datastore::data, fax_datastore, find_details(), LOG_WARNING, ast_channel::name, and session_details_new().
Referenced by acf_faxopt_write(), receivefax_exec(), and sendfax_exec().
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 1150 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_set_read_format(), ast_set_write_format(), ast_smoother_feed, ast_smoother_free(), ast_smoother_new(), ast_smoother_read(), ast_string_field_set, ast_strlen_zero(), AST_T38_NEGOTIATED, AST_T38_REFUSED, AST_T38_REQUEST_NEGOTIATE, ast_tvnow(), ast_verb, ast_waitfor_nandfds(), ast_write(), ast_fax_debug_info::base_tv, ast_fax_tech::cancel_session, ast_fax_session_details::caps, chancount, ast_frame_subclass::codec, ast_frame::data, ast_frame::datalen, debug_check_frame_for_silence(), ast_fax_session::debug_info, errno, f, fax_session_new(), faxregistry, ast_fax_session::fd, ast_fax_session::frames_received, ast_fax_session::frames_sent, ast_frame::frametype, ast_fax_tech::generate_silence, GENERIC_FAX_EXEC_ERROR, GENERIC_FAX_EXEC_SET_VARS, ast_fax_session_details::headerinfo, ast_fax_session::id, ast_frame_subclass::integer, ast_fax_session_details::localstationid, LOG_ERROR, LOG_WARNING, ast_channel::name, ast_fax_session_details::our_t38_parameters, pbx_builtin_getvar_helper(), ast_frame::ptr, ast_fax_tech::read, ast_channel::readformat, report_fax_status(), ast_control_t38_parameters::request_response, RES_FAX_TIMEOUT, ast_fax_session_details::result, set_channel_variables(), ast_fax_session::smoother, ast_fax_tech::start_session, ast_frame::subclass, ast_fax_tech::switch_to_t38, t38_parameters_ast_to_fax(), t38_parameters_fax_to_ast(), T38_STATE_NEGOTIATED, ast_fax_session::tech, ast_fax_session_details::their_t38_parameters, ast_fax_tech::write, and ast_channel::writeformat.
Referenced by receivefax_exec(), and sendfax_exec().
01151 { 01152 int ms; 01153 int timeout = RES_FAX_TIMEOUT; 01154 int res = 0, chancount; 01155 unsigned int expected_frametype = -1; 01156 union ast_frame_subclass expected_framesubclass = { .integer = -1 }; 01157 unsigned int t38negotiated = (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED); 01158 struct ast_control_t38_parameters t38_parameters; 01159 const char *tempvar; 01160 struct ast_fax_session *fax = NULL; 01161 struct ast_frame *frame = NULL; 01162 struct ast_channel *c = chan; 01163 unsigned int orig_write_format = 0, orig_read_format = 0; 01164 01165 chancount = 1; 01166 01167 /* create the FAX session */ 01168 if (!(fax = fax_session_new(details, chan, reserved, token))) { 01169 ast_log(LOG_ERROR, "Can't create a FAX session, FAX attempt failed.\n"); 01170 report_fax_status(chan, details, "No Available Resource"); 01171 return -1; 01172 } 01173 01174 ast_channel_lock(chan); 01175 /* update session details */ 01176 if (ast_strlen_zero(details->headerinfo) && (tempvar = pbx_builtin_getvar_helper(chan, "LOCALHEADERINFO"))) { 01177 ast_string_field_set(details, headerinfo, tempvar); 01178 } 01179 if (ast_strlen_zero(details->localstationid)) { 01180 tempvar = pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"); 01181 ast_string_field_set(details, localstationid, tempvar ? tempvar : "unknown"); 01182 } 01183 ast_channel_unlock(chan); 01184 01185 report_fax_status(chan, details, "Allocating Resources"); 01186 01187 if (details->caps & AST_FAX_TECH_AUDIO) { 01188 expected_frametype = AST_FRAME_VOICE;; 01189 expected_framesubclass.codec = AST_FORMAT_SLINEAR; 01190 orig_write_format = chan->writeformat; 01191 if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) { 01192 ast_log(LOG_ERROR, "channel '%s' failed to set write format to signed linear'.\n", chan->name); 01193 ao2_lock(faxregistry.container); 01194 ao2_unlink(faxregistry.container, fax); 01195 ao2_unlock(faxregistry.container); 01196 ao2_ref(fax, -1); 01197 ast_channel_unlock(chan); 01198 return -1; 01199 } 01200 orig_read_format = chan->readformat; 01201 if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0) { 01202 ast_log(LOG_ERROR, "channel '%s' failed to set read format to signed linear.\n", chan->name); 01203 ao2_lock(faxregistry.container); 01204 ao2_unlink(faxregistry.container, fax); 01205 ao2_unlock(faxregistry.container); 01206 ao2_ref(fax, -1); 01207 ast_channel_unlock(chan); 01208 return -1; 01209 } 01210 if (fax->smoother) { 01211 ast_smoother_free(fax->smoother); 01212 fax->smoother = NULL; 01213 } 01214 if (!(fax->smoother = ast_smoother_new(320))) { 01215 ast_log(LOG_WARNING, "Channel '%s' FAX session '%d' failed to obtain a smoother.\n", chan->name, fax->id); 01216 } 01217 } else { 01218 expected_frametype = AST_FRAME_MODEM; 01219 expected_framesubclass.codec = AST_MODEM_T38; 01220 } 01221 01222 if (fax->debug_info) { 01223 fax->debug_info->base_tv = ast_tvnow(); 01224 } 01225 01226 /* reset our result fields just in case the fax tech driver wants to 01227 * set custom error messages */ 01228 ast_string_field_set(details, result, ""); 01229 ast_string_field_set(details, resultstr, ""); 01230 ast_string_field_set(details, error, ""); 01231 set_channel_variables(chan, details); 01232 01233 if (fax->tech->start_session(fax) < 0) { 01234 GENERIC_FAX_EXEC_ERROR(fax, chan, "INIT_ERROR", "failed to start FAX session"); 01235 } 01236 01237 report_fax_status(chan, details, "FAX Transmission In Progress"); 01238 01239 ast_debug(5, "channel %s will wait on FAX fd %d\n", chan->name, fax->fd); 01240 01241 /* handle frames for the session */ 01242 ms = 1000; 01243 while ((res > -1) && (ms > -1) && (timeout > 0)) { 01244 struct ast_channel *ready_chan; 01245 int ofd, exception; 01246 01247 ms = 1000; 01248 errno = 0; 01249 ready_chan = ast_waitfor_nandfds(&c, chancount, &fax->fd, 1, &exception, &ofd, &ms); 01250 if (ready_chan) { 01251 if (!(frame = ast_read(chan))) { 01252 /* the channel is probably gone, so lets stop polling on it and let the 01253 * FAX session complete before we exit the application. if needed, 01254 * send the FAX stack silence so the modems can finish their session without 01255 * any problems */ 01256 ast_debug(1, "Channel '%s' did not return a frame; probably hung up.\n", chan->name); 01257 GENERIC_FAX_EXEC_SET_VARS(fax, chan, "HANGUP", "remote channel hungup"); 01258 c = NULL; 01259 chancount = 0; 01260 timeout -= (1000 - ms); 01261 fax->tech->cancel_session(fax); 01262 if (fax->tech->generate_silence) { 01263 fax->tech->generate_silence(fax); 01264 } 01265 continue; 01266 } 01267 01268 if ((frame->frametype == AST_FRAME_CONTROL) && 01269 (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) && 01270 (frame->datalen == sizeof(t38_parameters))) { 01271 unsigned int was_t38 = t38negotiated; 01272 struct ast_control_t38_parameters *parameters = frame->data.ptr; 01273 01274 switch (parameters->request_response) { 01275 case AST_T38_REQUEST_NEGOTIATE: 01276 /* the other end has requested a switch to T.38, so reply that we are willing, if we can 01277 * do T.38 as well 01278 */ 01279 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters); 01280 t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED; 01281 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)); 01282 break; 01283 case AST_T38_NEGOTIATED: 01284 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters); 01285 t38negotiated = 1; 01286 break; 01287 default: 01288 break; 01289 } 01290 if (t38negotiated && !was_t38) { 01291 fax->tech->switch_to_t38(fax); 01292 details->caps &= ~AST_FAX_TECH_AUDIO; 01293 expected_frametype = AST_FRAME_MODEM; 01294 expected_framesubclass.codec = AST_MODEM_T38; 01295 if (fax->smoother) { 01296 ast_smoother_free(fax->smoother); 01297 fax->smoother = NULL; 01298 } 01299 01300 report_fax_status(chan, details, "T.38 Negotiated"); 01301 01302 ast_verb(3, "Channel '%s' switched to T.38 FAX session '%d'.\n", chan->name, fax->id); 01303 } 01304 } else if ((frame->frametype == expected_frametype) && 01305 (!memcmp(&frame->subclass, &expected_framesubclass, sizeof(frame->subclass)))) { 01306 struct ast_frame *f; 01307 01308 if (fax->smoother) { 01309 /* push the frame into a smoother */ 01310 if (ast_smoother_feed(fax->smoother, frame) < 0) { 01311 GENERIC_FAX_EXEC_ERROR(fax, chan, "UNKNOWN", "Failed to feed the smoother"); 01312 } 01313 while ((f = ast_smoother_read(fax->smoother)) && (f->data.ptr)) { 01314 if (fax->debug_info) { 01315 debug_check_frame_for_silence(fax, 1, f); 01316 } 01317 /* write the frame to the FAX stack */ 01318 fax->tech->write(fax, f); 01319 fax->frames_received++; 01320 if (f != frame) { 01321 ast_frfree(f); 01322 } 01323 } 01324 } else { 01325 /* write the frame to the FAX stack */ 01326 fax->tech->write(fax, frame); 01327 fax->frames_received++; 01328 } 01329 timeout = RES_FAX_TIMEOUT; 01330 } 01331 ast_frfree(frame); 01332 } else if (ofd == fax->fd) { 01333 /* read a frame from the FAX stack and send it out the channel. 01334 * the FAX stack will return a NULL if the FAX session has already completed */ 01335 if (!(frame = fax->tech->read(fax))) { 01336 break; 01337 } 01338 01339 if (fax->debug_info && (frame->frametype == AST_FRAME_VOICE)) { 01340 debug_check_frame_for_silence(fax, 0, frame); 01341 } 01342 01343 ast_write(chan, frame); 01344 fax->frames_sent++; 01345 ast_frfree(frame); 01346 timeout = RES_FAX_TIMEOUT; 01347 } else { 01348 if (ms && (ofd < 0)) { 01349 if ((errno == 0) || (errno == EINTR)) { 01350 timeout -= (1000 - ms); 01351 if (timeout <= 0) 01352 GENERIC_FAX_EXEC_ERROR(fax, chan, "TIMEOUT", "fax session timed-out"); 01353 continue; 01354 } else { 01355 ast_log(LOG_WARNING, "something bad happened while channel '%s' was polling.\n", chan->name); 01356 GENERIC_FAX_EXEC_ERROR(fax, chan, "UNKNOWN", "error polling data"); 01357 res = ms; 01358 break; 01359 } 01360 } else { 01361 /* nothing happened */ 01362 if (timeout > 0) { 01363 timeout -= 1000; 01364 if (timeout <= 0) 01365 GENERIC_FAX_EXEC_ERROR(fax, chan, "TIMEOUT", "fax session timed-out"); 01366 continue; 01367 } else { 01368 ast_log(LOG_WARNING, "channel '%s' timed-out during the FAX transmission.\n", chan->name); 01369 GENERIC_FAX_EXEC_ERROR(fax, chan, "TIMEOUT", "fax session timed-out"); 01370 break; 01371 } 01372 } 01373 } 01374 } 01375 ast_debug(3, "channel '%s' - event loop stopped { timeout: %d, ms: %d, res: %d }\n", chan->name, timeout, ms, res); 01376 01377 set_channel_variables(chan, details); 01378 01379 if (!strcasecmp(details->result, "FAILED")) { 01380 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 01381 } else { 01382 ast_atomic_fetchadd_int(&faxregistry.fax_complete, 1); 01383 } 01384 01385 if (fax) { 01386 ao2_lock(faxregistry.container); 01387 ao2_unlink(faxregistry.container, fax); 01388 ao2_unlock(faxregistry.container); 01389 ao2_ref(fax, -1); 01390 } 01391 01392 /* if the channel is still alive, and we changed its read/write formats, 01393 * restore them now 01394 */ 01395 if (chancount) { 01396 if (orig_read_format) { 01397 ast_set_read_format(chan, orig_read_format); 01398 } 01399 if (orig_write_format) { 01400 ast_set_write_format(chan, orig_write_format); 01401 } 01402 } 01403 01404 /* return the chancount so the calling function can determine if the channel hungup during this FAX session or not */ 01405 return chancount; 01406 }
static void get_general_options | ( | struct fax_options * | options | ) | [static] |
Definition at line 2625 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().
02626 { 02627 ast_rwlock_rdlock(&options_lock); 02628 *options = general_options; 02629 ast_rwlock_unlock(&options_lock); 02630 }
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 2878 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().
02879 { 02880 int res; 02881 02882 /* initialize the registry */ 02883 faxregistry.active_sessions = 0; 02884 faxregistry.reserved_sessions = 0; 02885 if (!(faxregistry.container = ao2_container_alloc(FAX_MAXBUCKETS, session_hash_cb, session_cmp_cb))) { 02886 return AST_MODULE_LOAD_DECLINE; 02887 } 02888 02889 if (set_config(0) < 0) { 02890 ast_log(LOG_ERROR, "failed to load configuration file '%s'\n", config); 02891 ao2_ref(faxregistry.container, -1); 02892 return AST_MODULE_LOAD_DECLINE; 02893 } 02894 02895 /* register CLI operations and applications */ 02896 if (ast_register_application_xml(app_sendfax, sendfax_exec) < 0) { 02897 ast_log(LOG_WARNING, "failed to register '%s'.\n", app_sendfax); 02898 ao2_ref(faxregistry.container, -1); 02899 return AST_MODULE_LOAD_DECLINE; 02900 } 02901 if (ast_register_application_xml(app_receivefax, receivefax_exec) < 0) { 02902 ast_log(LOG_WARNING, "failed to register '%s'.\n", app_receivefax); 02903 ast_unregister_application(app_sendfax); 02904 ao2_ref(faxregistry.container, -1); 02905 return AST_MODULE_LOAD_DECLINE; 02906 } 02907 ast_cli_register_multiple(fax_cli, ARRAY_LEN(fax_cli)); 02908 res = ast_custom_function_register(&acf_faxopt); 02909 fax_logger_level = ast_logger_register_level("FAX"); 02910 02911 return res; 02912 }
static int receivefax_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
initiate a receive FAX session
Definition at line 1561 of file res_fax.c.
References ast_channel::_state, ast_fax_session_details::allow_audio, ao2_ref, args, ast_answer(), AST_APP_ARG, ast_app_parse_options(), ast_atomic_fetchadd_int(), ast_calloc, ast_channel_get_t38_state(), ast_channel_lock, ast_channel_unlock, ast_debug, AST_DECLARE_APP_ARGS, ast_fax_modem_to_str(), AST_FAX_OPTFLAG_TRUE, AST_FAX_TECH_RECEIVE, AST_FAX_TECH_T38, AST_LIST_INSERT_TAIL, ast_log(), AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_verb, ast_fax_session_details::caps, check_modem_rate(), manager_event_info::cid, manager_event_info::context, ast_fax_session_details::debug, disable_t38(), ast_fax_session_details::documents, EVENT_FLAG_CALL, manager_event_info::exten, fax_exec_options, fax_session_release(), fax_session_reserve(), faxregistry, ast_fax_document::filename, find_or_create_details(), generic_fax_exec(), get_manager_event_info(), global_fax_debug, LOG_ERROR, LOG_WARNING, manager_event, ast_fax_session_details::maxrate, ast_fax_session_details::minrate, ast_fax_session_details::modems, ast_channel::name, 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().
01562 { 01563 char *parse, modems[128] = ""; 01564 int channel_alive; 01565 struct ast_fax_session_details *details; 01566 struct ast_fax_session *s; 01567 struct ast_fax_tech_token *token = NULL; 01568 struct ast_fax_document *doc; 01569 AST_DECLARE_APP_ARGS(args, 01570 AST_APP_ARG(filename); 01571 AST_APP_ARG(options); 01572 ); 01573 struct ast_flags opts = { 0, }; 01574 struct manager_event_info info; 01575 01576 /* initialize output channel variables */ 01577 pbx_builtin_setvar_helper(chan, "FAXSTATUS", "FAILED"); 01578 pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", NULL); 01579 pbx_builtin_setvar_helper(chan, "FAXPAGES", "0"); 01580 pbx_builtin_setvar_helper(chan, "FAXBITRATE", NULL); 01581 pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", NULL); 01582 01583 /* if we ran receivefax then we attempted to receive a fax, even if we 01584 * never start a fax session */ 01585 ast_atomic_fetchadd_int(&faxregistry.fax_rx_attempts, 1); 01586 01587 /* Get a FAX session details structure from the channel's FAX datastore and create one if 01588 * it does not already exist. */ 01589 if (!(details = find_or_create_details(chan))) { 01590 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 01591 pbx_builtin_setvar_helper(chan, "FAXERROR", "MEMORY_ERROR"); 01592 pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "error allocating memory"); 01593 ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n"); 01594 return -1; 01595 } 01596 01597 ast_string_field_set(details, result, "FAILED"); 01598 ast_string_field_set(details, resultstr, "error starting fax session"); 01599 ast_string_field_set(details, error, "INIT_ERROR"); 01600 set_channel_variables(chan, details); 01601 01602 if (details->maxrate < details->minrate) { 01603 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 01604 ast_string_field_set(details, error, "INVALID_ARGUMENTS"); 01605 ast_string_field_set(details, resultstr, "maxrate is less than minrate"); 01606 set_channel_variables(chan, details); 01607 ast_log(LOG_ERROR, "maxrate %d is less than minrate %d\n", details->maxrate, details->minrate); 01608 ao2_ref(details, -1); 01609 return -1; 01610 } 01611 01612 if (check_modem_rate(details->modems, details->minrate)) { 01613 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 01614 ast_fax_modem_to_str(details->modems, modems, sizeof(modems)); 01615 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %d\n", modems, details->minrate); 01616 ast_string_field_set(details, error, "INVALID_ARGUMENTS"); 01617 ast_string_field_set(details, resultstr, "incompatible 'modems' and 'minrate' settings"); 01618 set_channel_variables(chan, details); 01619 ao2_ref(details, -1); 01620 return -1; 01621 } 01622 01623 if (check_modem_rate(details->modems, details->maxrate)) { 01624 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 01625 ast_fax_modem_to_str(details->modems, modems, sizeof(modems)); 01626 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %d\n", modems, details->maxrate); 01627 ast_string_field_set(details, error, "INVALID_ARGUMENTS"); 01628 ast_string_field_set(details, resultstr, "incompatible 'modems' and 'maxrate' settings"); 01629 set_channel_variables(chan, details); 01630 ao2_ref(details, -1); 01631 return -1; 01632 } 01633 01634 if (ast_strlen_zero(data)) { 01635 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 01636 ast_string_field_set(details, error, "INVALID_ARGUMENTS"); 01637 ast_string_field_set(details, resultstr, "invalid arguments"); 01638 set_channel_variables(chan, details); 01639 ast_log(LOG_WARNING, "%s requires an argument (filename[,options])\n", app_receivefax); 01640 ao2_ref(details, -1); 01641 return -1; 01642 } 01643 parse = ast_strdupa(data); 01644 AST_STANDARD_APP_ARGS(args, parse); 01645 01646 if (!ast_strlen_zero(args.options) && 01647 ast_app_parse_options(fax_exec_options, &opts, NULL, args.options)) { 01648 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 01649 ast_string_field_set(details, error, "INVALID_ARGUMENTS"); 01650 ast_string_field_set(details, resultstr, "invalid arguments"); 01651 set_channel_variables(chan, details); 01652 ao2_ref(details, -1); 01653 return -1; 01654 } 01655 if (ast_strlen_zero(args.filename)) { 01656 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 01657 ast_string_field_set(details, error, "INVALID_ARGUMENTS"); 01658 ast_string_field_set(details, resultstr, "invalid arguments"); 01659 set_channel_variables(chan, details); 01660 ast_log(LOG_WARNING, "%s requires an argument (filename[,options])\n", app_receivefax); 01661 ao2_ref(details, -1); 01662 return -1; 01663 } 01664 01665 /* check for unsupported FAX application options */ 01666 if (ast_test_flag(&opts, OPT_CALLERMODE) || ast_test_flag(&opts, OPT_CALLEDMODE)) { 01667 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 01668 ast_string_field_set(details, error, "INVALID_ARGUMENTS"); 01669 ast_string_field_set(details, resultstr, "invalid arguments"); 01670 set_channel_variables(chan, details); 01671 ast_log(LOG_WARNING, "%s does not support polling\n", app_receivefax); 01672 ao2_ref(details, -1); 01673 return -1; 01674 } 01675 01676 pbx_builtin_setvar_helper(chan, "FAXERROR", "Channel Problems"); 01677 pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "Error before FAX transmission started."); 01678 01679 if (!(doc = ast_calloc(1, sizeof(*doc) + strlen(args.filename) + 1))) { 01680 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 01681 ast_string_field_set(details, error, "MEMORY_ERROR"); 01682 ast_string_field_set(details, resultstr, "error allocating memory"); 01683 set_channel_variables(chan, details); 01684 ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n"); 01685 ao2_ref(details, -1); 01686 return -1; 01687 } 01688 01689 strcpy(doc->filename, args.filename); 01690 AST_LIST_INSERT_TAIL(&details->documents, doc, next); 01691 01692 ast_verb(3, "Channel '%s' receiving FAX '%s'\n", chan->name, args.filename); 01693 01694 details->caps = AST_FAX_TECH_RECEIVE; 01695 01696 /* check for debug */ 01697 if (ast_test_flag(&opts, OPT_DEBUG) || global_fax_debug) { 01698 details->option.debug = AST_FAX_OPTFLAG_TRUE; 01699 } 01700 01701 /* check for request for status events */ 01702 if (ast_test_flag(&opts, OPT_STATUS)) { 01703 details->option.statusevents = AST_FAX_OPTFLAG_TRUE; 01704 } 01705 01706 if ((ast_channel_get_t38_state(chan) == T38_STATE_UNAVAILABLE) || 01707 ast_test_flag(&opts, OPT_ALLOWAUDIO)) { 01708 details->option.allow_audio = AST_FAX_OPTFLAG_TRUE; 01709 } 01710 01711 if (!(s = fax_session_reserve(details, &token))) { 01712 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 01713 ast_string_field_set(details, resultstr, "error reserving fax session"); 01714 set_channel_variables(chan, details); 01715 ast_log(LOG_ERROR, "Unable to reserve FAX session.\n"); 01716 ao2_ref(details, -1); 01717 return -1; 01718 } 01719 01720 /* make sure the channel is up */ 01721 if (chan->_state != AST_STATE_UP) { 01722 if (ast_answer(chan)) { 01723 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 01724 ast_string_field_set(details, resultstr, "error answering channel"); 01725 set_channel_variables(chan, details); 01726 ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", chan->name); 01727 fax_session_release(s, token); 01728 ao2_ref(s, -1); 01729 ao2_ref(details, -1); 01730 return -1; 01731 } 01732 } 01733 01734 if (set_fax_t38_caps(chan, details)) { 01735 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 01736 ast_string_field_set(details, error, "T38_NEG_ERROR"); 01737 ast_string_field_set(details, resultstr, "error negotiating T.38"); 01738 set_channel_variables(chan, details); 01739 fax_session_release(s, token); 01740 ao2_ref(s, -1); 01741 ao2_ref(details, -1); 01742 return -1; 01743 } 01744 01745 if (details->caps & AST_FAX_TECH_T38) { 01746 if (receivefax_t38_init(chan, details)) { 01747 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 01748 ast_string_field_set(details, error, "T38_NEG_ERROR"); 01749 ast_string_field_set(details, resultstr, "error negotiating T.38"); 01750 set_channel_variables(chan, details); 01751 fax_session_release(s, token); 01752 ao2_ref(s, -1); 01753 ao2_ref(details, -1); 01754 ast_log(LOG_ERROR, "error initializing channel '%s' in T.38 mode\n", chan->name); 01755 return -1; 01756 } 01757 } else { 01758 details->option.send_ced = 1; 01759 } 01760 01761 if ((channel_alive = generic_fax_exec(chan, details, s, token)) < 0) { 01762 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 01763 } 01764 01765 if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) { 01766 if (disable_t38(chan)) { 01767 ast_debug(1, "error disabling T.38 mode on %s\n", chan->name); 01768 } 01769 } 01770 01771 /* send out the AMI completion event */ 01772 ast_channel_lock(chan); 01773 01774 get_manager_event_info(chan, &info); 01775 manager_event(EVENT_FLAG_CALL, 01776 "ReceiveFAX", 01777 "Channel: %s\r\n" 01778 "Context: %s\r\n" 01779 "Exten: %s\r\n" 01780 "CallerID: %s\r\n" 01781 "RemoteStationID: %s\r\n" 01782 "LocalStationID: %s\r\n" 01783 "PagesTransferred: %s\r\n" 01784 "Resolution: %s\r\n" 01785 "TransferRate: %s\r\n" 01786 "FileName: %s\r\n", 01787 chan->name, 01788 info.context, 01789 info.exten, 01790 info.cid, 01791 S_OR(pbx_builtin_getvar_helper(chan, "REMOTESTATIONID"), ""), 01792 S_OR(pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"), ""), 01793 S_OR(pbx_builtin_getvar_helper(chan, "FAXPAGES"), ""), 01794 S_OR(pbx_builtin_getvar_helper(chan, "FAXRESOLUTION"), ""), 01795 S_OR(pbx_builtin_getvar_helper(chan, "FAXBITRATE"), ""), 01796 args.filename); 01797 ast_channel_unlock(chan); 01798 01799 ao2_ref(s, -1); 01800 ao2_ref(details, -1); 01801 01802 /* If the channel hungup return -1; otherwise, return 0 to continue in the dialplan */ 01803 return (!channel_alive) ? -1 : 0; 01804 }
static int receivefax_t38_init | ( | struct ast_channel * | chan, | |
struct ast_fax_session_details * | details | |||
) | [static] |
Definition at line 1408 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_T38_NEGOTIATED, AST_T38_REFUSED, AST_T38_REQUEST_NEGOTIATE, ast_waitfor(), ast_fax_session_details::caps, ast_frame::data, ast_frame::datalen, ast_frame::frametype, ast_frame_subclass::integer, LOG_ERROR, LOG_WARNING, ast_channel::name, ast_fax_session_details::option, 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().
01409 { 01410 int ms; 01411 struct ast_frame *frame = NULL; 01412 struct ast_control_t38_parameters t38_parameters; 01413 01414 t38_parameters_ast_to_fax(&details->our_t38_parameters, &our_t38_parameters); 01415 01416 /* don't send any audio if we've already received a T.38 reinvite */ 01417 if (ast_channel_get_t38_state(chan) != T38_STATE_NEGOTIATING) { 01418 /* generate 3 seconds of CED */ 01419 if (ast_playtones_start(chan, 1024, "!2100/3000", 1)) { 01420 ast_log(LOG_ERROR, "error generating CED tone on %s\n", chan->name); 01421 return -1; 01422 } 01423 01424 ms = 3000; 01425 while (ms > 0) { 01426 ms = ast_waitfor(chan, ms); 01427 if (ms < 0) { 01428 ast_log(LOG_ERROR, "error while generating CED tone on %s\n", chan->name); 01429 ast_playtones_stop(chan); 01430 return -1; 01431 } 01432 01433 if (ms == 0) { /* all done, nothing happened */ 01434 break; 01435 } 01436 01437 if (!(frame = ast_read(chan))) { 01438 ast_log(LOG_ERROR, "error reading frame while generating CED tone on %s\n", chan->name); 01439 ast_playtones_stop(chan); 01440 return -1; 01441 } 01442 01443 if ((frame->frametype == AST_FRAME_CONTROL) && 01444 (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) && 01445 (frame->datalen == sizeof(t38_parameters))) { 01446 struct ast_control_t38_parameters *parameters = frame->data.ptr; 01447 01448 switch (parameters->request_response) { 01449 case AST_T38_REQUEST_NEGOTIATE: 01450 /* the other end has requested a switch to T.38, so reply that we are willing, if we can 01451 * do T.38 as well 01452 */ 01453 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters); 01454 t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED; 01455 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)); 01456 ast_playtones_stop(chan); 01457 break; 01458 case AST_T38_NEGOTIATED: 01459 ast_debug(1, "Negotiated T.38 for receive on %s\n", chan->name); 01460 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters); 01461 details->caps &= ~AST_FAX_TECH_AUDIO; 01462 report_fax_status(chan, details, "T.38 Negotiated"); 01463 break; 01464 default: 01465 break; 01466 } 01467 } 01468 ast_frfree(frame); 01469 } 01470 01471 ast_playtones_stop(chan); 01472 } 01473 01474 /* if T.38 was negotiated, we are done initializing */ 01475 if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) { 01476 return 0; 01477 } 01478 01479 /* request T.38 */ 01480 ast_debug(1, "Negotiating T.38 for receive on %s\n", chan->name); 01481 01482 /* wait up to five seconds for negotiation to complete */ 01483 ms = 5000; 01484 01485 /* set parameters based on the session's parameters */ 01486 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters); 01487 t38_parameters.request_response = AST_T38_REQUEST_NEGOTIATE; 01488 if ((ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0)) { 01489 return -1; 01490 } 01491 01492 while (ms > 0) { 01493 ms = ast_waitfor(chan, ms); 01494 if (ms < 0) { 01495 ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", chan->name); 01496 return -1; 01497 } 01498 01499 if (ms == 0) { /* all done, nothing happened */ 01500 ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 negotiation.\n", chan->name); 01501 details->caps &= ~AST_FAX_TECH_T38; 01502 break; 01503 } 01504 01505 if (!(frame = ast_read(chan))) { 01506 ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", chan->name); 01507 return -1; 01508 } 01509 01510 if ((frame->frametype == AST_FRAME_CONTROL) && 01511 (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) && 01512 (frame->datalen == sizeof(t38_parameters))) { 01513 struct ast_control_t38_parameters *parameters = frame->data.ptr; 01514 01515 switch (parameters->request_response) { 01516 case AST_T38_REQUEST_NEGOTIATE: 01517 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters); 01518 t38_parameters.request_response = AST_T38_NEGOTIATED; 01519 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)); 01520 break; 01521 case AST_T38_NEGOTIATED: 01522 ast_debug(1, "Negotiated T.38 for receive on %s\n", chan->name); 01523 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters); 01524 details->caps &= ~AST_FAX_TECH_AUDIO; 01525 report_fax_status(chan, details, "T.38 Negotiated"); 01526 ms = 0; 01527 break; 01528 case AST_T38_REFUSED: 01529 ast_log(LOG_WARNING, "channel '%s' refused to negotiate T.38\n", chan->name); 01530 details->caps &= ~AST_FAX_TECH_T38; 01531 ms = 0; 01532 break; 01533 default: 01534 ast_log(LOG_ERROR, "channel '%s' failed to negotiate T.38\n", chan->name); 01535 details->caps &= ~AST_FAX_TECH_T38; 01536 ms = 0; 01537 break; 01538 } 01539 } 01540 ast_frfree(frame); 01541 } 01542 01543 /* if T.38 was negotiated, we are done initializing */ 01544 if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) { 01545 return 0; 01546 } 01547 01548 /* if we made it here, then T.38 failed, check the 'f' flag */ 01549 if (details->option.allow_audio != AST_FAX_OPTFLAG_TRUE) { 01550 ast_log(LOG_WARNING, "Audio FAX not allowed on channel '%s' and T.38 negotiation failed; aborting.\n", chan->name); 01551 return -1; 01552 } 01553 01554 /* ok, audio fallback is allowed */ 01555 details->caps |= AST_FAX_TECH_AUDIO; 01556 01557 return 0; 01558 }
static int reload_module | ( | void | ) | [static] |
Definition at line 2914 of file res_fax.c.
References set_config().
02915 { 02916 set_config(1); 02917 return 0; 02918 }
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(), ast_fax_session_details::localstationid, manager_event, ast_channel::name, ast_fax_session_details::option, and ast_fax_session_details::statusevents.
Referenced by generic_fax_exec(), receivefax_t38_init(), and sendfax_t38_init().
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 2032 of file res_fax.c.
References ast_channel::_state, ast_fax_session_details::allow_audio, ao2_ref, args, ast_answer(), AST_APP_ARG, ast_app_parse_options(), ast_atomic_fetchadd_int(), ast_calloc, ast_channel_get_t38_state(), ast_channel_lock, ast_channel_unlock, ast_debug, AST_DECLARE_APP_ARGS, ast_fax_modem_to_str(), AST_FAX_OPTFLAG_TRUE, AST_FAX_TECH_MULTI_DOC, AST_FAX_TECH_SEND, AST_FAX_TECH_T38, ast_free, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_log(), AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, ast_verb, ast_fax_session_details::caps, check_modem_rate(), manager_event_info::cid, manager_event_info::context, ast_fax_session_details::debug, disable_t38(), ast_fax_session_details::documents, EVENT_FLAG_CALL, manager_event_info::exten, fax_exec_options, fax_session_release(), fax_session_reserve(), faxregistry, ast_fax_document::filename, find_or_create_details(), generate_filenames_string(), generic_fax_exec(), get_manager_event_info(), global_fax_debug, LOG_ERROR, LOG_WARNING, manager_event, ast_fax_session_details::maxrate, ast_fax_session_details::minrate, ast_fax_session_details::modems, ast_channel::name, 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, strsep(), T38_STATE_NEGOTIATED, and T38_STATE_UNAVAILABLE.
Referenced by load_module().
02033 { 02034 char *parse, *filenames, *c, modems[128] = ""; 02035 int channel_alive, file_count; 02036 struct ast_fax_session_details *details; 02037 struct ast_fax_session *s; 02038 struct ast_fax_tech_token *token = NULL; 02039 struct ast_fax_document *doc; 02040 AST_DECLARE_APP_ARGS(args, 02041 AST_APP_ARG(filenames); 02042 AST_APP_ARG(options); 02043 ); 02044 struct ast_flags opts = { 0, }; 02045 struct manager_event_info info; 02046 02047 /* initialize output channel variables */ 02048 pbx_builtin_setvar_helper(chan, "FAXSTATUS", "FAILED"); 02049 pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", NULL); 02050 pbx_builtin_setvar_helper(chan, "FAXPAGES", "0"); 02051 pbx_builtin_setvar_helper(chan, "FAXBITRATE", NULL); 02052 pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", NULL); 02053 02054 /* if we ran sendfax then we attempted to send a fax, even if we never 02055 * start a fax session */ 02056 ast_atomic_fetchadd_int(&faxregistry.fax_tx_attempts, 1); 02057 02058 /* Get a requirement structure and set it. This structure is used 02059 * to tell the FAX technology module about the higher level FAX session */ 02060 if (!(details = find_or_create_details(chan))) { 02061 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 02062 pbx_builtin_setvar_helper(chan, "FAXERROR", "MEMORY_ERROR"); 02063 pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", "error allocating memory"); 02064 ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n"); 02065 return -1; 02066 } 02067 02068 ast_string_field_set(details, result, "FAILED"); 02069 ast_string_field_set(details, resultstr, "error starting fax session"); 02070 ast_string_field_set(details, error, "INIT_ERROR"); 02071 set_channel_variables(chan, details); 02072 02073 if (details->maxrate < details->minrate) { 02074 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 02075 ast_string_field_set(details, error, "INVALID_ARGUMENTS"); 02076 ast_string_field_set(details, resultstr, "maxrate is less than minrate"); 02077 set_channel_variables(chan, details); 02078 ast_log(LOG_ERROR, "maxrate %d is less than minrate %d\n", details->maxrate, details->minrate); 02079 ao2_ref(details, -1); 02080 return -1; 02081 } 02082 02083 if (check_modem_rate(details->modems, details->minrate)) { 02084 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 02085 ast_fax_modem_to_str(details->modems, modems, sizeof(modems)); 02086 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %d\n", modems, details->minrate); 02087 ast_string_field_set(details, error, "INVALID_ARGUMENTS"); 02088 ast_string_field_set(details, resultstr, "incompatible 'modems' and 'minrate' settings"); 02089 set_channel_variables(chan, details); 02090 ao2_ref(details, -1); 02091 return -1; 02092 } 02093 02094 if (check_modem_rate(details->modems, details->maxrate)) { 02095 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 02096 ast_fax_modem_to_str(details->modems, modems, sizeof(modems)); 02097 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %d\n", modems, details->maxrate); 02098 ast_string_field_set(details, error, "INVALID_ARGUMENTS"); 02099 ast_string_field_set(details, resultstr, "incompatible 'modems' and 'maxrate' settings"); 02100 set_channel_variables(chan, details); 02101 ao2_ref(details, -1); 02102 return -1; 02103 } 02104 02105 if (ast_strlen_zero(data)) { 02106 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 02107 ast_string_field_set(details, error, "INVALID_ARGUMENTS"); 02108 ast_string_field_set(details, resultstr, "invalid arguments"); 02109 set_channel_variables(chan, details); 02110 ast_log(LOG_WARNING, "%s requires an argument (filename[&filename[&filename]][,options])\n", app_sendfax); 02111 ao2_ref(details, -1); 02112 return -1; 02113 } 02114 parse = ast_strdupa(data); 02115 AST_STANDARD_APP_ARGS(args, parse); 02116 02117 02118 if (!ast_strlen_zero(args.options) && 02119 ast_app_parse_options(fax_exec_options, &opts, NULL, args.options)) { 02120 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 02121 ast_string_field_set(details, error, "INVALID_ARGUMENTS"); 02122 ast_string_field_set(details, resultstr, "invalid arguments"); 02123 set_channel_variables(chan, details); 02124 ao2_ref(details, -1); 02125 return -1; 02126 } 02127 if (ast_strlen_zero(args.filenames)) { 02128 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 02129 ast_string_field_set(details, error, "INVALID_ARGUMENTS"); 02130 ast_string_field_set(details, resultstr, "invalid arguments"); 02131 set_channel_variables(chan, details); 02132 ast_log(LOG_WARNING, "%s requires an argument (filename[&filename[&filename]],options])\n", app_sendfax); 02133 ao2_ref(details, -1); 02134 return -1; 02135 } 02136 02137 /* check for unsupported FAX application options */ 02138 if (ast_test_flag(&opts, OPT_CALLERMODE) || ast_test_flag(&opts, OPT_CALLEDMODE)) { 02139 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 02140 ast_string_field_set(details, error, "INVALID_ARGUMENTS"); 02141 ast_string_field_set(details, resultstr, "invalid arguments"); 02142 set_channel_variables(chan, details); 02143 ast_log(LOG_WARNING, "%s does not support polling\n", app_sendfax); 02144 ao2_ref(details, -1); 02145 return -1; 02146 } 02147 02148 file_count = 0; 02149 filenames = args.filenames; 02150 while ((c = strsep(&filenames, "&"))) { 02151 if (access(c, (F_OK | R_OK)) < 0) { 02152 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 02153 ast_string_field_set(details, error, "FILE_ERROR"); 02154 ast_string_field_set(details, resultstr, "error reading file"); 02155 set_channel_variables(chan, details); 02156 ast_log(LOG_ERROR, "access failure. Verify '%s' exists and check permissions.\n", args.filenames); 02157 ao2_ref(details, -1); 02158 return -1; 02159 } 02160 02161 if (!(doc = ast_calloc(1, sizeof(*doc) + strlen(c) + 1))) { 02162 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 02163 ast_string_field_set(details, error, "MEMORY_ERROR"); 02164 ast_string_field_set(details, resultstr, "error allocating memory"); 02165 set_channel_variables(chan, details); 02166 ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n"); 02167 ao2_ref(details, -1); 02168 return -1; 02169 } 02170 02171 strcpy(doc->filename, c); 02172 AST_LIST_INSERT_TAIL(&details->documents, doc, next); 02173 file_count++; 02174 } 02175 02176 if (file_count > 1) { 02177 details->caps |= AST_FAX_TECH_MULTI_DOC; 02178 } 02179 02180 ast_verb(3, "Channel '%s' sending FAX:\n", chan->name); 02181 AST_LIST_TRAVERSE(&details->documents, doc, next) { 02182 ast_verb(3, " %s\n", doc->filename); 02183 } 02184 02185 details->caps = AST_FAX_TECH_SEND; 02186 02187 /* check for debug */ 02188 if (ast_test_flag(&opts, OPT_DEBUG) || global_fax_debug) { 02189 details->option.debug = AST_FAX_OPTFLAG_TRUE; 02190 } 02191 02192 /* check for request for status events */ 02193 if (ast_test_flag(&opts, OPT_STATUS)) { 02194 details->option.statusevents = AST_FAX_OPTFLAG_TRUE; 02195 } 02196 02197 if ((ast_channel_get_t38_state(chan) == T38_STATE_UNAVAILABLE) || 02198 ast_test_flag(&opts, OPT_ALLOWAUDIO)) { 02199 details->option.allow_audio = AST_FAX_OPTFLAG_TRUE; 02200 } 02201 02202 if (ast_test_flag(&opts, OPT_REQUEST_T38)) { 02203 details->option.request_t38 = AST_FAX_OPTFLAG_TRUE; 02204 } 02205 02206 if (!(s = fax_session_reserve(details, &token))) { 02207 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 02208 ast_string_field_set(details, resultstr, "error reserving fax session"); 02209 set_channel_variables(chan, details); 02210 ast_log(LOG_ERROR, "Unable to reserve FAX session.\n"); 02211 ao2_ref(details, -1); 02212 return -1; 02213 } 02214 02215 /* make sure the channel is up */ 02216 if (chan->_state != AST_STATE_UP) { 02217 if (ast_answer(chan)) { 02218 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 02219 ast_string_field_set(details, resultstr, "error answering channel"); 02220 set_channel_variables(chan, details); 02221 ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", chan->name); 02222 fax_session_release(s, token); 02223 ao2_ref(s, -1); 02224 ao2_ref(details, -1); 02225 return -1; 02226 } 02227 } 02228 02229 if (set_fax_t38_caps(chan, details)) { 02230 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 02231 ast_string_field_set(details, error, "T38_NEG_ERROR"); 02232 ast_string_field_set(details, resultstr, "error negotiating T.38"); 02233 set_channel_variables(chan, details); 02234 fax_session_release(s, token); 02235 ao2_ref(s, -1); 02236 ao2_ref(details, -1); 02237 return -1; 02238 } 02239 02240 if (details->caps & AST_FAX_TECH_T38) { 02241 if (sendfax_t38_init(chan, details)) { 02242 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 02243 ast_string_field_set(details, error, "T38_NEG_ERROR"); 02244 ast_string_field_set(details, resultstr, "error negotiating T.38"); 02245 set_channel_variables(chan, details); 02246 fax_session_release(s, token); 02247 ao2_ref(s, -1); 02248 ao2_ref(details, -1); 02249 ast_log(LOG_ERROR, "error initializing channel '%s' in T.38 mode\n", chan->name); 02250 return -1; 02251 } 02252 } else { 02253 details->option.send_cng = 1; 02254 } 02255 02256 if ((channel_alive = generic_fax_exec(chan, details, s, token)) < 0) { 02257 ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); 02258 } 02259 02260 if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) { 02261 if (disable_t38(chan)) { 02262 ast_debug(1, "error disabling T.38 mode on %s\n", chan->name); 02263 } 02264 } 02265 02266 if (!(filenames = generate_filenames_string(details, "FileName: ", "\r\n"))) { 02267 ast_log(LOG_ERROR, "Error generating SendFAX manager event\n"); 02268 ao2_ref(s, -1); 02269 ao2_ref(details, -1); 02270 return (!channel_alive) ? -1 : 0; 02271 } 02272 02273 /* send out the AMI completion event */ 02274 ast_channel_lock(chan); 02275 get_manager_event_info(chan, &info); 02276 manager_event(EVENT_FLAG_CALL, 02277 "SendFAX", 02278 "Channel: %s\r\n" 02279 "Context: %s\r\n" 02280 "Exten: %s\r\n" 02281 "CallerID: %s\r\n" 02282 "RemoteStationID: %s\r\n" 02283 "LocalStationID: %s\r\n" 02284 "PagesTransferred: %s\r\n" 02285 "Resolution: %s\r\n" 02286 "TransferRate: %s\r\n" 02287 "%s\r\n", 02288 chan->name, 02289 info.context, 02290 info.exten, 02291 info.cid, 02292 S_OR(pbx_builtin_getvar_helper(chan, "REMOTESTATIONID"), ""), 02293 S_OR(pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"), ""), 02294 S_OR(pbx_builtin_getvar_helper(chan, "FAXPAGES"), ""), 02295 S_OR(pbx_builtin_getvar_helper(chan, "FAXRESOLUTION"), ""), 02296 S_OR(pbx_builtin_getvar_helper(chan, "FAXBITRATE"), ""), 02297 filenames); 02298 ast_channel_unlock(chan); 02299 02300 ast_free(filenames); 02301 02302 ao2_ref(s, -1); 02303 ao2_ref(details, -1); 02304 02305 /* If the channel hungup return -1; otherwise, return 0 to continue in the dialplan */ 02306 return (!channel_alive) ? -1 : 0; 02307 }
static int sendfax_t38_init | ( | struct ast_channel * | chan, | |
struct ast_fax_session_details * | details | |||
) | [static] |
Definition at line 1806 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_T38_NEGOTIATED, AST_T38_REFUSED, AST_T38_REQUEST_NEGOTIATE, ast_waitfor(), ast_fax_session_details::caps, ast_frame::data, ast_frame::datalen, ast_frame::frametype, ast_frame_subclass::integer, LOG_ERROR, LOG_WARNING, ast_channel::name, ast_fax_session_details::option, 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().
01807 { 01808 int ms; 01809 struct ast_frame *frame = NULL; 01810 struct ast_control_t38_parameters t38_parameters; 01811 01812 t38_parameters_ast_to_fax(&details->our_t38_parameters, &our_t38_parameters); 01813 01814 /* send CNG tone while listening for the receiver to initiate a switch 01815 * to T.38 mode; if they do, stop sending the CNG tone and proceed with 01816 * the switch. 01817 * 01818 * 10500 is enough time for 3 CNG tones 01819 */ 01820 ms = 10500; 01821 01822 /* don't send any audio if we've already received a T.38 reinvite */ 01823 if (ast_channel_get_t38_state(chan) != T38_STATE_NEGOTIATING) { 01824 if (ast_playtones_start(chan, 1024, "!1100/500,!0/3000,!1100/500,!0/3000,!1100/500,!0/3000", 1)) { 01825 ast_log(LOG_ERROR, "error generating CNG tone on %s\n", chan->name); 01826 return -1; 01827 } 01828 } 01829 01830 while (ms > 0) { 01831 ms = ast_waitfor(chan, ms); 01832 if (ms < 0) { 01833 ast_log(LOG_ERROR, "error while generating CNG tone on %s\n", chan->name); 01834 ast_playtones_stop(chan); 01835 return -1; 01836 } 01837 01838 if (ms == 0) { /* all done, nothing happened */ 01839 break; 01840 } 01841 01842 if (!(frame = ast_read(chan))) { 01843 ast_log(LOG_ERROR, "error reading frame while generating CNG tone on %s\n", chan->name); 01844 ast_playtones_stop(chan); 01845 return -1; 01846 } 01847 01848 if ((frame->frametype == AST_FRAME_CONTROL) && 01849 (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) && 01850 (frame->datalen == sizeof(t38_parameters))) { 01851 struct ast_control_t38_parameters *parameters = frame->data.ptr; 01852 01853 switch (parameters->request_response) { 01854 case AST_T38_REQUEST_NEGOTIATE: 01855 /* the other end has requested a switch to T.38, so reply that we are willing, if we can 01856 * do T.38 as well 01857 */ 01858 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters); 01859 t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED; 01860 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)); 01861 ast_playtones_stop(chan); 01862 break; 01863 case AST_T38_NEGOTIATED: 01864 ast_debug(1, "Negotiated T.38 for send on %s\n", chan->name); 01865 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters); 01866 details->caps &= ~AST_FAX_TECH_AUDIO; 01867 report_fax_status(chan, details, "T.38 Negotiated"); 01868 ms = 0; 01869 break; 01870 default: 01871 break; 01872 } 01873 } 01874 ast_frfree(frame); 01875 } 01876 01877 ast_playtones_stop(chan); 01878 01879 if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) { 01880 return 0; 01881 } 01882 01883 /* T.38 negotiation did not happen, initiate a switch if requested */ 01884 if (details->option.request_t38 == AST_FAX_OPTFLAG_TRUE) { 01885 ast_debug(1, "Negotiating T.38 for send on %s\n", chan->name); 01886 01887 /* wait up to five seconds for negotiation to complete */ 01888 ms = 5000; 01889 01890 /* set parameters based on the session's parameters */ 01891 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters); 01892 t38_parameters.request_response = AST_T38_REQUEST_NEGOTIATE; 01893 if ((ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0)) { 01894 return -1; 01895 } 01896 01897 while (ms > 0) { 01898 ms = ast_waitfor(chan, ms); 01899 if (ms < 0) { 01900 ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", chan->name); 01901 return -1; 01902 } 01903 01904 if (ms == 0) { /* all done, nothing happened */ 01905 ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 negotiation.\n", chan->name); 01906 details->caps &= ~AST_FAX_TECH_T38; 01907 break; 01908 } 01909 01910 if (!(frame = ast_read(chan))) { 01911 ast_log(LOG_WARNING, "error on '%s' while waiting for T.38 negotiation.\n", chan->name); 01912 return -1; 01913 } 01914 01915 if ((frame->frametype == AST_FRAME_CONTROL) && 01916 (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) && 01917 (frame->datalen == sizeof(t38_parameters))) { 01918 struct ast_control_t38_parameters *parameters = frame->data.ptr; 01919 01920 switch (parameters->request_response) { 01921 case AST_T38_REQUEST_NEGOTIATE: 01922 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters); 01923 t38_parameters.request_response = AST_T38_NEGOTIATED; 01924 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)); 01925 break; 01926 case AST_T38_NEGOTIATED: 01927 ast_debug(1, "Negotiated T.38 for receive on %s\n", chan->name); 01928 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters); 01929 details->caps &= ~AST_FAX_TECH_AUDIO; 01930 report_fax_status(chan, details, "T.38 Negotiated"); 01931 ms = 0; 01932 break; 01933 case AST_T38_REFUSED: 01934 ast_log(LOG_WARNING, "channel '%s' refused to negotiate T.38\n", chan->name); 01935 details->caps &= ~AST_FAX_TECH_T38; 01936 ms = 0; 01937 break; 01938 default: 01939 ast_log(LOG_ERROR, "channel '%s' failed to negotiate T.38\n", chan->name); 01940 details->caps &= ~AST_FAX_TECH_T38; 01941 ms = 0; 01942 break; 01943 } 01944 } 01945 ast_frfree(frame); 01946 } 01947 01948 /* if T.38 was negotiated, we are done initializing */ 01949 if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) { 01950 return 0; 01951 } 01952 01953 /* send one more CNG tone to get audio going again for some 01954 * carriers if we are going to fall back to audio mode */ 01955 if (details->option.allow_audio == AST_FAX_OPTFLAG_TRUE) { 01956 if (ast_playtones_start(chan, 1024, "!1100/500,!0/3000", 1)) { 01957 ast_log(LOG_ERROR, "error generating second CNG tone on %s\n", chan->name); 01958 return -1; 01959 } 01960 01961 ms = 3500; 01962 while (ms > 0) { 01963 ms = ast_waitfor(chan, ms); 01964 if (ms < 0) { 01965 ast_log(LOG_ERROR, "error while generating second CNG tone on %s\n", chan->name); 01966 ast_playtones_stop(chan); 01967 return -1; 01968 } 01969 01970 if (ms == 0) { /* all done, nothing happened */ 01971 break; 01972 } 01973 01974 if (!(frame = ast_read(chan))) { 01975 ast_log(LOG_ERROR, "error reading frame while generating second CNG tone on %s\n", chan->name); 01976 ast_playtones_stop(chan); 01977 return -1; 01978 } 01979 01980 if ((frame->frametype == AST_FRAME_CONTROL) && 01981 (frame->subclass.integer == AST_CONTROL_T38_PARAMETERS) && 01982 (frame->datalen == sizeof(t38_parameters))) { 01983 struct ast_control_t38_parameters *parameters = frame->data.ptr; 01984 01985 switch (parameters->request_response) { 01986 case AST_T38_REQUEST_NEGOTIATE: 01987 /* the other end has requested a switch to T.38, so reply that we are willing, if we can 01988 * do T.38 as well 01989 */ 01990 t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters); 01991 t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED; 01992 ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)); 01993 ast_playtones_stop(chan); 01994 break; 01995 case AST_T38_NEGOTIATED: 01996 ast_debug(1, "Negotiated T.38 for send on %s\n", chan->name); 01997 t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters); 01998 details->caps &= ~AST_FAX_TECH_AUDIO; 01999 report_fax_status(chan, details, "T.38 Negotiated"); 02000 ms = 0; 02001 break; 02002 default: 02003 break; 02004 } 02005 } 02006 ast_frfree(frame); 02007 } 02008 02009 ast_playtones_stop(chan); 02010 02011 /* if T.38 was negotiated, we are done initializing */ 02012 if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) { 02013 return 0; 02014 } 02015 } 02016 } 02017 02018 /* if we made it here, then T.38 failed, check the 'f' flag */ 02019 if (details->option.allow_audio == AST_FAX_OPTFLAG_FALSE) { 02020 ast_log(LOG_WARNING, "Audio FAX not allowed on channel '%s' and T.38 negotiation failed; aborting.\n", chan->name); 02021 return -1; 02022 } 02023 02024 /* ok, audio fallback is allowed */ 02025 details->caps |= AST_FAX_TECH_AUDIO; 02026 02027 return 0; 02028 }
static int session_cmp_cb | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
compare callback for ao2
Definition at line 2318 of file res_fax.c.
References CMP_MATCH, CMP_STOP, and ast_fax_session::id.
Referenced by load_module().
02319 { 02320 struct ast_fax_session *lhs = obj, *rhs = arg; 02321 02322 return (lhs->id == rhs->id) ? CMP_MATCH | CMP_STOP : 0; 02323 }
static struct ast_fax_session_details* session_details_new | ( | void | ) | [static] |
create a FAX session details structure
Definition at line 383 of file res_fax.c.
References ao2_alloc, ao2_ref, AST_FAX_OPTFLAG_FALSE, AST_LIST_HEAD_INIT_NOLOCK, ast_string_field_init, destroy_session_details(), fax_options::ecm, get_general_options(), fax_options::maxrate, fax_options::minrate, fax_options::modems, and fax_options::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 2310 of file res_fax.c.
References ast_fax_session::id.
Referenced by load_module().
02311 { 02312 const struct ast_fax_session *s = obj; 02313 02314 return s->id; 02315 }
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::error, ast_fax_session_details::localstationid, ast_fax_session_details::pages_transferred, pbx_builtin_setvar_helper(), ast_fax_session_details::remotestationid, ast_fax_session_details::resolution, ast_fax_session_details::result, ast_fax_session_details::resultstr, S_OR, and ast_fax_session_details::transfer_rate.
Referenced by generic_fax_exec(), receivefax_exec(), and sendfax_exec().
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 2633 of file res_fax.c.
References ast_config_load2(), ast_debug, ast_log(), ast_variable_browse(), config, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, default_options, fax_rate_str_to_int(), LOG_NOTICE, fax_options::minrate, ast_variable::name, ast_variable::next, set_general_options(), and ast_variable::value.
02634 { 02635 struct ast_config *cfg; 02636 struct ast_variable *v; 02637 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 02638 char modems[128] = ""; 02639 struct fax_options options; 02640 int res = 0; 02641 02642 options = default_options; 02643 02644 /* When we're not reloading, we have to be certain to set the general options 02645 * to the defaults in case config loading goes wrong at some point. On a reload, 02646 * the general options need to stay the same as what they were prior to the 02647 * reload rather than being reset to the defaults. 02648 */ 02649 if (!reload) { 02650 set_general_options(&options); 02651 } 02652 02653 /* read configuration */ 02654 if (!(cfg = ast_config_load2(config, "res_fax", config_flags))) { 02655 ast_log(LOG_NOTICE, "Configuration file '%s' not found, %s options.\n", 02656 config, reload ? "not changing" : "using default"); 02657 return 0; 02658 } 02659 02660 if (cfg == CONFIG_STATUS_FILEINVALID) { 02661 ast_log(LOG_NOTICE, "Configuration file '%s' is invalid, %s options.\n", 02662 config, reload ? "not changing" : "using default"); 02663 return 0; 02664 } 02665 02666 if (cfg == CONFIG_STATUS_FILEUNCHANGED) { 02667 return 0; 02668 } 02669 02670 if (reload) { 02671 options = default_options; 02672 } 02673 02674 /* create configuration */ 02675 for (v = ast_variable_browse(cfg, "general"); v; v = v->next) { 02676 int rate; 02677 02678 if (!strcasecmp(v->name, "minrate")) { 02679 ast_debug(3, "reading minrate '%s' from configuration file\n", v->value); 02680 if ((rate = fax_rate_str_to_int(v->value)) == 0) { 02681 res = -1; 02682 goto end; 02683 } 02684 options.minrate = rate; 02685 } else if (!strcasecmp(v->name, "maxrate")) { 02686 ast_debug(3, "reading maxrate '%s' from configuration file\n", v->value); 02687 if ((rate = fax_rate_str_to_int(v->value)) == 0) { 02688 res = -1; 02689 goto end; 02690 } 02691 options.maxrate = rate; 02692 } else if (!strcasecmp(v->name, "statusevents")) { 02693 ast_debug(3, "reading statusevents '%s' from configuration file\n", v->value); 02694 options.statusevents = ast_true(v->value); 02695 } else if (!strcasecmp(v->name, "ecm")) { 02696 ast_debug(3, "reading ecm '%s' from configuration file\n", v->value); 02697 options.ecm = ast_true(v->value); 02698 } else if ((!strcasecmp(v->name, "modem")) || (!strcasecmp(v->name, "modems"))) { 02699 options.modems = 0; 02700 update_modem_bits(&options.modems, v->value); 02701 } 02702 } 02703 02704 if (options.maxrate < options.minrate) { 02705 ast_log(LOG_ERROR, "maxrate %d is less than minrate %d\n", options.maxrate, options.minrate); 02706 res = -1; 02707 goto end; 02708 } 02709 02710 if (check_modem_rate(options.modems, options.minrate)) { 02711 ast_fax_modem_to_str(options.modems, modems, sizeof(modems)); 02712 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'minrate' setting %d\n", modems, options.minrate); 02713 res = -1; 02714 goto end; 02715 } 02716 02717 if (check_modem_rate(options.modems, options.maxrate)) { 02718 ast_fax_modem_to_str(options.modems, modems, sizeof(modems)); 02719 ast_log(LOG_ERROR, "'modems' setting '%s' is incompatible with 'maxrate' setting %d\n", modems, options.maxrate); 02720 res = -1; 02721 goto end; 02722 } 02723 02724 set_general_options(&options); 02725 02726 end: 02727 ast_config_destroy(cfg); 02728 return res; 02729 }
static int set_fax_t38_caps | ( | struct ast_channel * | chan, | |
struct ast_fax_session_details * | details | |||
) | [static] |
Definition at line 1052 of file res_fax.c.
References ast_channel_get_t38_state(), AST_CONTROL_T38_PARAMETERS, AST_FAX_TECH_AUDIO, AST_FAX_TECH_T38, ast_indicate_data(), ast_log(), AST_T38_REQUEST_PARMS, ast_fax_session_details::caps, LOG_ERROR, ast_channel::name, ast_control_t38_parameters::request_response, T38_STATE_NEGOTIATING, T38_STATE_UNAVAILABLE, and T38_STATE_UNKNOWN.
Referenced by receivefax_exec(), and sendfax_exec().
01053 { 01054 switch (ast_channel_get_t38_state(chan)) { 01055 case T38_STATE_UNKNOWN: 01056 details->caps |= AST_FAX_TECH_T38; 01057 break; 01058 case T38_STATE_UNAVAILABLE: 01059 details->caps |= AST_FAX_TECH_AUDIO; 01060 break; 01061 case T38_STATE_NEGOTIATING: { 01062 /* the other end already sent us a T.38 reinvite, so we need to prod the channel 01063 * driver into resending their parameters to us if it supports doing so... if 01064 * not, we can't proceed, because we can't create a proper reply without them. 01065 * if it does work, the channel driver will send an AST_CONTROL_T38_PARAMETERS 01066 * with a request of AST_T38_REQUEST_NEGOTIATE, which will be read by the function 01067 * that gets called after this one completes 01068 */ 01069 struct ast_control_t38_parameters parameters = { .request_response = AST_T38_REQUEST_PARMS, }; 01070 if (ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, ¶meters, sizeof(parameters)) != AST_T38_REQUEST_PARMS) { 01071 ast_log(LOG_ERROR, "channel '%s' is in an unsupported T.38 negotiation state, cannot continue.\n", chan->name); 01072 return -1; 01073 } 01074 details->caps |= AST_FAX_TECH_T38; 01075 break; 01076 } 01077 default: 01078 ast_log(LOG_ERROR, "channel '%s' is in an unsupported T.38 negotiation state, cannot continue.\n", chan->name); 01079 return -1; 01080 } 01081 01082 return 0; 01083 }
static void set_general_options | ( | const struct fax_options * | options | ) | [static] |
Definition at line 2618 of file res_fax.c.
References ast_rwlock_unlock, ast_rwlock_wrlock, general_options, and options_lock.
Referenced by set_config().
02619 { 02620 ast_rwlock_wrlock(&options_lock); 02621 general_options = *options; 02622 ast_rwlock_unlock(&options_lock); 02623 }
static void t38_parameters_ast_to_fax | ( | struct ast_fax_t38_parameters * | dst, | |
const struct ast_control_t38_parameters * | src | |||
) | [static] |
Definition at line 1030 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().
01031 { 01032 dst->version = src->version; 01033 dst->max_ifp = src->max_ifp; 01034 dst->rate = src->rate; 01035 dst->rate_management = src->rate_management; 01036 dst->fill_bit_removal = src->fill_bit_removal; 01037 dst->transcoding_mmr = src->transcoding_mmr; 01038 dst->transcoding_jbig = src->transcoding_jbig; 01039 }
static void t38_parameters_fax_to_ast | ( | struct ast_control_t38_parameters * | dst, | |
const struct ast_fax_t38_parameters * | src | |||
) | [static] |
Definition at line 1041 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().
01042 { 01043 dst->version = src->version; 01044 dst->max_ifp = src->max_ifp; 01045 dst->rate = src->rate; 01046 dst->rate_management = src->rate_management; 01047 dst->fill_bit_removal = src->fill_bit_removal; 01048 dst->transcoding_mmr = src->transcoding_mmr; 01049 dst->transcoding_jbig = src->transcoding_jbig; 01050 }
static int unload_module | ( | void | ) | [static] |
unload res_fax
Definition at line 2852 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.
02853 { 02854 ast_cli_unregister_multiple(fax_cli, ARRAY_LEN(fax_cli)); 02855 02856 if (ast_custom_function_unregister(&acf_faxopt) < 0) { 02857 ast_log(LOG_WARNING, "failed to unregister function '%s'\n", acf_faxopt.name); 02858 } 02859 02860 if (ast_unregister_application(app_sendfax) < 0) { 02861 ast_log(LOG_WARNING, "failed to unregister '%s'\n", app_sendfax); 02862 } 02863 02864 if (ast_unregister_application(app_receivefax) < 0) { 02865 ast_log(LOG_WARNING, "failed to unregister '%s'\n", app_receivefax); 02866 } 02867 02868 if (fax_logger_level != -1) { 02869 ast_logger_unregister_level("FAX"); 02870 } 02871 02872 ao2_ref(faxregistry.container, -1); 02873 02874 return 0; 02875 }
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().
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 |
Initial value:
{ .name = "FAXOPT", .read = acf_faxopt_read, .write = acf_faxopt_write, }
Definition at line 2845 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] |
struct ao2_container* container |
struct fax_options default_options [static] |
struct ast_cli_entry fax_cli[] [static] |
int fax_complete |
struct ast_datastore_info fax_datastore [static] |
Initial value:
{ .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] |
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 1142 of file res_fax.c.
Referenced by receivefax_t38_init(), and sendfax_t38_init().