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