mirror of
https://github.com/asterisk/asterisk.git
synced 2025-11-01 19:43:03 +00:00
Add support for reserving a fax session before answering the channel.
Note: this change breaks ABI compatibility. FAX-217 git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.8@297486 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -58,8 +58,10 @@ enum ast_fax_modems {
|
|||||||
|
|
||||||
/*! \brief current state of a fax session */
|
/*! \brief current state of a fax session */
|
||||||
enum ast_fax_state {
|
enum ast_fax_state {
|
||||||
|
/*! reserved state */
|
||||||
|
AST_FAX_STATE_RESERVED = 0,
|
||||||
/*! uninitialized state */
|
/*! uninitialized state */
|
||||||
AST_FAX_STATE_UNINITIALIZED = 0,
|
AST_FAX_STATE_UNINITIALIZED,
|
||||||
/*! initialized state */
|
/*! initialized state */
|
||||||
AST_FAX_STATE_INITIALIZED,
|
AST_FAX_STATE_INITIALIZED,
|
||||||
/*! fax resources open state */
|
/*! fax resources open state */
|
||||||
@@ -168,6 +170,7 @@ struct ast_fax_session_details {
|
|||||||
|
|
||||||
struct ast_fax_tech;
|
struct ast_fax_tech;
|
||||||
struct ast_fax_debug_info;
|
struct ast_fax_debug_info;
|
||||||
|
struct ast_fax_tech_token;
|
||||||
|
|
||||||
/*! \brief The data required to handle a fax session */
|
/*! \brief The data required to handle a fax session */
|
||||||
struct ast_fax_session {
|
struct ast_fax_session {
|
||||||
@@ -183,6 +186,8 @@ struct ast_fax_session {
|
|||||||
unsigned long frames_sent;
|
unsigned long frames_sent;
|
||||||
/*! the fax technology callbacks */
|
/*! the fax technology callbacks */
|
||||||
const struct ast_fax_tech *tech;
|
const struct ast_fax_tech *tech;
|
||||||
|
/*! the token used to reserve this session */
|
||||||
|
struct ast_fax_tech_token *token;
|
||||||
/*! private implementation pointer */
|
/*! private implementation pointer */
|
||||||
void *tech_pvt;
|
void *tech_pvt;
|
||||||
/*! fax state */
|
/*! fax state */
|
||||||
@@ -197,9 +202,11 @@ struct ast_fax_session {
|
|||||||
struct ast_fax_debug_info *debug_info;
|
struct ast_fax_debug_info *debug_info;
|
||||||
/*! used to take variable-sized frames in and output frames of an expected size to the fax stack */
|
/*! used to take variable-sized frames in and output frames of an expected size to the fax stack */
|
||||||
struct ast_smoother *smoother;
|
struct ast_smoother *smoother;
|
||||||
};
|
|
||||||
|
|
||||||
struct ast_fax_tech_token;
|
/*! some flags to track the stat counters for this session */
|
||||||
|
unsigned int reserved:1;
|
||||||
|
unsigned int active:1;
|
||||||
|
};
|
||||||
|
|
||||||
/*! \brief used to register a FAX technology module with res_fax */
|
/*! \brief used to register a FAX technology module with res_fax */
|
||||||
struct ast_fax_tech {
|
struct ast_fax_tech {
|
||||||
@@ -243,6 +250,14 @@ struct ast_fax_tech {
|
|||||||
char * (* const cli_show_settings)(int);
|
char * (* const cli_show_settings)(int);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*! \brief used by res_fax to reserve a FAX session */
|
||||||
|
struct ast_fax_tech_token {
|
||||||
|
/*! the fax technology callbacks */
|
||||||
|
const struct ast_fax_tech *tech;
|
||||||
|
/*! private implementation pointer */
|
||||||
|
void *tech_pvt;
|
||||||
|
};
|
||||||
|
|
||||||
/*! \brief register a fax technology */
|
/*! \brief register a fax technology */
|
||||||
int ast_fax_tech_register(struct ast_fax_tech *tech);
|
int ast_fax_tech_register(struct ast_fax_tech *tech);
|
||||||
|
|
||||||
|
|||||||
166
res/res_fax.c
166
res/res_fax.c
@@ -220,6 +220,8 @@ static int fax_logger_level = -1;
|
|||||||
static struct {
|
static struct {
|
||||||
/*! The number of active FAX sessions */
|
/*! The number of active FAX sessions */
|
||||||
int active_sessions;
|
int active_sessions;
|
||||||
|
/*! The number of reserved FAX sessions */
|
||||||
|
int reserved_sessions;
|
||||||
/*! active sessions are astobj2 objects */
|
/*! active sessions are astobj2 objects */
|
||||||
struct ao2_container *container;
|
struct ao2_container *container;
|
||||||
/*! Total number of Tx FAX attempts */
|
/*! Total number of Tx FAX attempts */
|
||||||
@@ -631,12 +633,26 @@ static unsigned int fax_rate_str_to_int(const char *ratestr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void fax_session_release(struct ast_fax_session *s)
|
||||||
|
{
|
||||||
|
if (s->token) {
|
||||||
|
s->tech->release_token(s->token);
|
||||||
|
s->token = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->reserved) {
|
||||||
|
ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, -1);
|
||||||
|
s->reserved = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*! \brief destroy a FAX session structure */
|
/*! \brief destroy a FAX session structure */
|
||||||
static void destroy_session(void *session)
|
static void destroy_session(void *session)
|
||||||
{
|
{
|
||||||
struct ast_fax_session *s = session;
|
struct ast_fax_session *s = session;
|
||||||
|
|
||||||
if (s->tech) {
|
if (s->tech) {
|
||||||
|
fax_session_release(s);
|
||||||
if (s->tech_pvt) {
|
if (s->tech_pvt) {
|
||||||
s->tech->destroy_session(s);
|
s->tech->destroy_session(s);
|
||||||
}
|
}
|
||||||
@@ -656,14 +672,16 @@ static void destroy_session(void *session)
|
|||||||
ast_smoother_free(s->smoother);
|
ast_smoother_free(s->smoother);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s->active) {
|
||||||
ast_atomic_fetchadd_int(&faxregistry.active_sessions, -1);
|
ast_atomic_fetchadd_int(&faxregistry.active_sessions, -1);
|
||||||
|
s->active = 0;
|
||||||
|
}
|
||||||
|
|
||||||
ast_free(s->channame);
|
ast_free(s->channame);
|
||||||
ast_free(s->chan_uniqueid);
|
ast_free(s->chan_uniqueid);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief create a FAX session */
|
static struct ast_fax_session *fax_session_reserve(struct ast_fax_session_details *details)
|
||||||
static struct ast_fax_session *fax_session_new(struct ast_fax_session_details *details, struct ast_channel *chan)
|
|
||||||
{
|
{
|
||||||
struct ast_fax_session *s;
|
struct ast_fax_session *s;
|
||||||
struct fax_module *faxmod;
|
struct fax_module *faxmod;
|
||||||
@@ -672,7 +690,68 @@ static struct ast_fax_session *fax_session_new(struct ast_fax_session_details *d
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s->state = AST_FAX_STATE_RESERVED;
|
||||||
|
|
||||||
|
/* locate a FAX technology module that can handle said requirements
|
||||||
|
* Note: the requirements have not yet been finalized as T.38
|
||||||
|
* negotiation has not yet occured. */
|
||||||
|
AST_RWLIST_RDLOCK(&faxmodules);
|
||||||
|
AST_RWLIST_TRAVERSE(&faxmodules, faxmod, list) {
|
||||||
|
if ((faxmod->tech->caps & details->caps) != details->caps) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ast_debug(4, "Reserving a FAX session from '%s'.\n", faxmod->tech->description);
|
||||||
|
ast_module_ref(faxmod->tech->module);
|
||||||
|
s->tech = faxmod->tech;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
AST_RWLIST_UNLOCK(&faxmodules);
|
||||||
|
|
||||||
|
if (!faxmod) {
|
||||||
|
ast_log(LOG_ERROR, "Could not locate a FAX technology module with capabilities (0x%X)\n", details->caps);
|
||||||
|
ao2_ref(s, -1);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!s->tech->reserve_session) {
|
||||||
|
ast_log(LOG_WARNING, "Selected FAX technology module (%s) does not support reserving sessions.\n", s->tech->description);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(s->token = s->tech->reserve_session(s))) {
|
||||||
|
ao2_ref(s, -1);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
s->reserved = 1;
|
||||||
|
ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, 1);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief create a FAX session */
|
||||||
|
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_session *s = NULL;
|
||||||
|
struct fax_module *faxmod;
|
||||||
|
|
||||||
|
if (reserved) {
|
||||||
|
s = reserved;
|
||||||
|
ao2_ref(reserved, +1);
|
||||||
|
|
||||||
|
if (s->reserved) {
|
||||||
|
ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, -1);
|
||||||
|
s->reserved = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!s && !(s = ao2_alloc(sizeof(*s), destroy_session))) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
s->active = 1;
|
||||||
ast_atomic_fetchadd_int(&faxregistry.active_sessions, 1);
|
ast_atomic_fetchadd_int(&faxregistry.active_sessions, 1);
|
||||||
|
s->state = AST_FAX_STATE_UNINITIALIZED;
|
||||||
|
|
||||||
if (details->option.debug && (details->caps & AST_FAX_TECH_AUDIO)) {
|
if (details->option.debug && (details->caps & AST_FAX_TECH_AUDIO)) {
|
||||||
if (!(s->debug_info = ast_calloc(1, sizeof(*(s->debug_info))))) {
|
if (!(s->debug_info = ast_calloc(1, sizeof(*(s->debug_info))))) {
|
||||||
@@ -701,10 +780,10 @@ static struct ast_fax_session *fax_session_new(struct ast_fax_session_details *d
|
|||||||
s->chan = chan;
|
s->chan = chan;
|
||||||
s->details = details;
|
s->details = details;
|
||||||
ao2_ref(s->details, 1);
|
ao2_ref(s->details, 1);
|
||||||
s->state = AST_FAX_STATE_UNINITIALIZED;
|
|
||||||
|
|
||||||
details->id = s->id = ast_atomic_fetchadd_int(&faxregistry.nextsessionname, 1);
|
details->id = s->id = ast_atomic_fetchadd_int(&faxregistry.nextsessionname, 1);
|
||||||
|
|
||||||
|
if (!s->tech) {
|
||||||
/* locate a FAX technology module that can handle said requirements */
|
/* locate a FAX technology module that can handle said requirements */
|
||||||
AST_RWLIST_RDLOCK(&faxmodules);
|
AST_RWLIST_RDLOCK(&faxmodules);
|
||||||
AST_RWLIST_TRAVERSE(&faxmodules, faxmod, list) {
|
AST_RWLIST_TRAVERSE(&faxmodules, faxmod, list) {
|
||||||
@@ -723,17 +802,17 @@ static struct ast_fax_session *fax_session_new(struct ast_fax_session_details *d
|
|||||||
ao2_ref(s, -1);
|
ao2_ref(s, -1);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (!(s->tech_pvt = s->tech->new_session(s, NULL))) {
|
}
|
||||||
|
|
||||||
|
if (!(s->tech_pvt = s->tech->new_session(s, s->token))) {
|
||||||
ast_log(LOG_ERROR, "FAX session failed to initialize.\n");
|
ast_log(LOG_ERROR, "FAX session failed to initialize.\n");
|
||||||
ao2_ref(s, -1);
|
ao2_ref(s, -1);
|
||||||
ast_module_unref(faxmod->tech->module);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
/* link the session to the session container */
|
/* link the session to the session container */
|
||||||
if (!(ao2_link(faxregistry.container, s))) {
|
if (!(ao2_link(faxregistry.container, s))) {
|
||||||
ast_log(LOG_ERROR, "failed to add FAX session '%d' to container.\n", s->id);
|
ast_log(LOG_ERROR, "failed to add FAX session '%d' to container.\n", s->id);
|
||||||
ao2_ref(s, -1);
|
ao2_ref(s, -1);
|
||||||
ast_module_unref(faxmod->tech->module);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
ast_debug(4, "channel '%s' using FAX session '%d'\n", s->channame, s->id);
|
ast_debug(4, "channel '%s' using FAX session '%d'\n", s->channame, s->id);
|
||||||
@@ -987,7 +1066,7 @@ static struct ast_control_t38_parameters our_t38_parameters = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/*! \brief this is the generic FAX session handling function */
|
/*! \brief this is the generic FAX session handling function */
|
||||||
static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_details *details)
|
static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_details *details, struct ast_fax_session *reserved)
|
||||||
{
|
{
|
||||||
int ms;
|
int ms;
|
||||||
int timeout = RES_FAX_TIMEOUT;
|
int timeout = RES_FAX_TIMEOUT;
|
||||||
@@ -1005,7 +1084,7 @@ static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_det
|
|||||||
chancount = 1;
|
chancount = 1;
|
||||||
|
|
||||||
/* create the FAX session */
|
/* create the FAX session */
|
||||||
if (!(fax = fax_session_new(details, chan))) {
|
if (!(fax = fax_session_new(details, chan, reserved))) {
|
||||||
ast_log(LOG_ERROR, "Can't create a FAX session, FAX attempt failed.\n");
|
ast_log(LOG_ERROR, "Can't create a FAX session, FAX attempt failed.\n");
|
||||||
report_fax_status(chan, details, "No Available Resource");
|
report_fax_status(chan, details, "No Available Resource");
|
||||||
return -1;
|
return -1;
|
||||||
@@ -1402,6 +1481,7 @@ static int receivefax_exec(struct ast_channel *chan, const char *data)
|
|||||||
char *parse, modems[128] = "";
|
char *parse, modems[128] = "";
|
||||||
int channel_alive;
|
int channel_alive;
|
||||||
struct ast_fax_session_details *details;
|
struct ast_fax_session_details *details;
|
||||||
|
struct ast_fax_session *s;
|
||||||
struct ast_fax_document *doc;
|
struct ast_fax_document *doc;
|
||||||
AST_DECLARE_APP_ARGS(args,
|
AST_DECLARE_APP_ARGS(args,
|
||||||
AST_APP_ARG(filename);
|
AST_APP_ARG(filename);
|
||||||
@@ -1498,15 +1578,6 @@ static int receivefax_exec(struct ast_channel *chan, const char *data)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* make sure the channel is up */
|
|
||||||
if (chan->_state != AST_STATE_UP) {
|
|
||||||
if (ast_answer(chan)) {
|
|
||||||
ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", chan->name);
|
|
||||||
ao2_ref(details, -1);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ast_atomic_fetchadd_int(&faxregistry.fax_rx_attempts, 1);
|
ast_atomic_fetchadd_int(&faxregistry.fax_rx_attempts, 1);
|
||||||
|
|
||||||
pbx_builtin_setvar_helper(chan, "FAXERROR", "Channel Problems");
|
pbx_builtin_setvar_helper(chan, "FAXERROR", "Channel Problems");
|
||||||
@@ -1551,11 +1622,32 @@ static int receivefax_exec(struct ast_channel *chan, const char *data)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(s = fax_session_reserve(details))) {
|
||||||
|
ast_string_field_set(details, resultstr, "error reserving fax session");
|
||||||
|
set_channel_variables(chan, details);
|
||||||
|
ast_log(LOG_ERROR, "Unable to reserve FAX session.\n");
|
||||||
|
ao2_ref(details, -1);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* make sure the channel is up */
|
||||||
|
if (chan->_state != AST_STATE_UP) {
|
||||||
|
if (ast_answer(chan)) {
|
||||||
|
ast_string_field_set(details, resultstr, "error answering channel");
|
||||||
|
set_channel_variables(chan, details);
|
||||||
|
ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", chan->name);
|
||||||
|
ao2_ref(s, -1);
|
||||||
|
ao2_ref(details, -1);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (details->caps & AST_FAX_TECH_T38) {
|
if (details->caps & AST_FAX_TECH_T38) {
|
||||||
if (receivefax_t38_init(chan, details)) {
|
if (receivefax_t38_init(chan, details)) {
|
||||||
ast_string_field_set(details, error, "T38_NEG_ERROR");
|
ast_string_field_set(details, error, "T38_NEG_ERROR");
|
||||||
ast_string_field_set(details, resultstr, "error negotiating T.38");
|
ast_string_field_set(details, resultstr, "error negotiating T.38");
|
||||||
set_channel_variables(chan, details);
|
set_channel_variables(chan, details);
|
||||||
|
ao2_ref(s, -1);
|
||||||
ao2_ref(details, -1);
|
ao2_ref(details, -1);
|
||||||
ast_log(LOG_ERROR, "error initializing channel '%s' in T.38 mode\n", chan->name);
|
ast_log(LOG_ERROR, "error initializing channel '%s' in T.38 mode\n", chan->name);
|
||||||
return -1;
|
return -1;
|
||||||
@@ -1564,7 +1656,7 @@ static int receivefax_exec(struct ast_channel *chan, const char *data)
|
|||||||
details->option.send_ced = 1;
|
details->option.send_ced = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((channel_alive = generic_fax_exec(chan, details)) < 0) {
|
if ((channel_alive = generic_fax_exec(chan, details, s)) < 0) {
|
||||||
ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
|
ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1602,6 +1694,7 @@ static int receivefax_exec(struct ast_channel *chan, const char *data)
|
|||||||
args.filename);
|
args.filename);
|
||||||
ast_channel_unlock(chan);
|
ast_channel_unlock(chan);
|
||||||
|
|
||||||
|
ao2_ref(s, -1);
|
||||||
ao2_ref(details, -1);
|
ao2_ref(details, -1);
|
||||||
|
|
||||||
/* If the channel hungup return -1; otherwise, return 0 to continue in the dialplan */
|
/* If the channel hungup return -1; otherwise, return 0 to continue in the dialplan */
|
||||||
@@ -1839,6 +1932,7 @@ static int sendfax_exec(struct ast_channel *chan, const char *data)
|
|||||||
char *parse, *filenames, *c, modems[128] = "";
|
char *parse, *filenames, *c, modems[128] = "";
|
||||||
int channel_alive, file_count;
|
int channel_alive, file_count;
|
||||||
struct ast_fax_session_details *details;
|
struct ast_fax_session_details *details;
|
||||||
|
struct ast_fax_session *s;
|
||||||
struct ast_fax_document *doc;
|
struct ast_fax_document *doc;
|
||||||
AST_DECLARE_APP_ARGS(args,
|
AST_DECLARE_APP_ARGS(args,
|
||||||
AST_APP_ARG(filenames);
|
AST_APP_ARG(filenames);
|
||||||
@@ -1936,15 +2030,6 @@ static int sendfax_exec(struct ast_channel *chan, const char *data)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* make sure the channel is up */
|
|
||||||
if (chan->_state != AST_STATE_UP) {
|
|
||||||
if (ast_answer(chan)) {
|
|
||||||
ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", chan->name);
|
|
||||||
ao2_ref(details, -1);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ast_atomic_fetchadd_int(&faxregistry.fax_tx_attempts, 1);
|
ast_atomic_fetchadd_int(&faxregistry.fax_tx_attempts, 1);
|
||||||
|
|
||||||
file_count = 0;
|
file_count = 0;
|
||||||
@@ -2011,11 +2096,32 @@ static int sendfax_exec(struct ast_channel *chan, const char *data)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(s = fax_session_reserve(details))) {
|
||||||
|
ast_string_field_set(details, resultstr, "error reserving fax session");
|
||||||
|
set_channel_variables(chan, details);
|
||||||
|
ast_log(LOG_ERROR, "Unable to reserve FAX session.\n");
|
||||||
|
ao2_ref(details, -1);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* make sure the channel is up */
|
||||||
|
if (chan->_state != AST_STATE_UP) {
|
||||||
|
if (ast_answer(chan)) {
|
||||||
|
ast_string_field_set(details, resultstr, "error answering channel");
|
||||||
|
set_channel_variables(chan, details);
|
||||||
|
ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", chan->name);
|
||||||
|
ao2_ref(s, -1);
|
||||||
|
ao2_ref(details, -1);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (details->caps & AST_FAX_TECH_T38) {
|
if (details->caps & AST_FAX_TECH_T38) {
|
||||||
if (sendfax_t38_init(chan, details)) {
|
if (sendfax_t38_init(chan, details)) {
|
||||||
ast_string_field_set(details, error, "T38_NEG_ERROR");
|
ast_string_field_set(details, error, "T38_NEG_ERROR");
|
||||||
ast_string_field_set(details, resultstr, "error negotiating T.38");
|
ast_string_field_set(details, resultstr, "error negotiating T.38");
|
||||||
set_channel_variables(chan, details);
|
set_channel_variables(chan, details);
|
||||||
|
ao2_ref(s, -1);
|
||||||
ao2_ref(details, -1);
|
ao2_ref(details, -1);
|
||||||
ast_log(LOG_ERROR, "error initializing channel '%s' in T.38 mode\n", chan->name);
|
ast_log(LOG_ERROR, "error initializing channel '%s' in T.38 mode\n", chan->name);
|
||||||
return -1;
|
return -1;
|
||||||
@@ -2024,7 +2130,7 @@ static int sendfax_exec(struct ast_channel *chan, const char *data)
|
|||||||
details->option.send_cng = 1;
|
details->option.send_cng = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((channel_alive = generic_fax_exec(chan, details)) < 0) {
|
if ((channel_alive = generic_fax_exec(chan, details, s)) < 0) {
|
||||||
ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
|
ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2036,6 +2142,7 @@ static int sendfax_exec(struct ast_channel *chan, const char *data)
|
|||||||
|
|
||||||
if (!(filenames = generate_filenames_string(details, "FileName: ", "\r\n"))) {
|
if (!(filenames = generate_filenames_string(details, "FileName: ", "\r\n"))) {
|
||||||
ast_log(LOG_ERROR, "Error generating SendFAX manager event\n");
|
ast_log(LOG_ERROR, "Error generating SendFAX manager event\n");
|
||||||
|
ao2_ref(s, -1);
|
||||||
ao2_ref(details, -1);
|
ao2_ref(details, -1);
|
||||||
return (!channel_alive) ? -1 : 0;
|
return (!channel_alive) ? -1 : 0;
|
||||||
}
|
}
|
||||||
@@ -2069,6 +2176,7 @@ static int sendfax_exec(struct ast_channel *chan, const char *data)
|
|||||||
|
|
||||||
ast_free(filenames);
|
ast_free(filenames);
|
||||||
|
|
||||||
|
ao2_ref(s, -1);
|
||||||
ao2_ref(details, -1);
|
ao2_ref(details, -1);
|
||||||
|
|
||||||
/* If the channel hungup return -1; otherwise, return 0 to continue in the dialplan */
|
/* If the channel hungup return -1; otherwise, return 0 to continue in the dialplan */
|
||||||
@@ -2307,6 +2415,7 @@ static char *cli_fax_show_stats(struct ast_cli_entry *e, int cmd, struct ast_cli
|
|||||||
|
|
||||||
ast_cli(a->fd, "\nFAX Statistics:\n---------------\n\n");
|
ast_cli(a->fd, "\nFAX Statistics:\n---------------\n\n");
|
||||||
ast_cli(a->fd, "%-20.20s : %d\n", "Current Sessions", faxregistry.active_sessions);
|
ast_cli(a->fd, "%-20.20s : %d\n", "Current Sessions", faxregistry.active_sessions);
|
||||||
|
ast_cli(a->fd, "%-20.20s : %d\n", "Reserved Sessions", faxregistry.reserved_sessions);
|
||||||
ast_cli(a->fd, "%-20.20s : %d\n", "Transmit Attempts", faxregistry.fax_tx_attempts);
|
ast_cli(a->fd, "%-20.20s : %d\n", "Transmit Attempts", faxregistry.fax_tx_attempts);
|
||||||
ast_cli(a->fd, "%-20.20s : %d\n", "Receive Attempts", faxregistry.fax_rx_attempts);
|
ast_cli(a->fd, "%-20.20s : %d\n", "Receive Attempts", faxregistry.fax_rx_attempts);
|
||||||
ast_cli(a->fd, "%-20.20s : %d\n", "Completed FAXes", faxregistry.fax_complete);
|
ast_cli(a->fd, "%-20.20s : %d\n", "Completed FAXes", faxregistry.fax_complete);
|
||||||
@@ -2616,6 +2725,7 @@ static int load_module(void)
|
|||||||
|
|
||||||
/* initialize the registry */
|
/* initialize the registry */
|
||||||
faxregistry.active_sessions = 0;
|
faxregistry.active_sessions = 0;
|
||||||
|
faxregistry.reserved_sessions = 0;
|
||||||
if (!(faxregistry.container = ao2_container_alloc(FAX_MAXBUCKETS, session_hash_cb, session_cmp_cb))) {
|
if (!(faxregistry.container = ao2_container_alloc(FAX_MAXBUCKETS, session_hash_cb, session_cmp_cb))) {
|
||||||
return AST_MODULE_LOAD_DECLINE;
|
return AST_MODULE_LOAD_DECLINE;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user