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