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