[asterisk-commits] mnicholson: trunk r297496 - in /trunk: ./ include/asterisk/ res/
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Fri Dec 3 09:32:26 CST 2010
Author: mnicholson
Date: Fri Dec 3 09:32:22 2010
New Revision: 297496
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=297496
Log:
Merged revisions 297157,297486,297495 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.8
........
r297157 | mnicholson | 2010-12-01 13:47:33 -0600 (Wed, 01 Dec 2010) | 2 lines
Changed some NOTICE and WARNING messages to DEBUG messages.
........
r297486 | mnicholson | 2010-12-02 15:30:47 -0600 (Thu, 02 Dec 2010) | 6 lines
Add support for reserving a fax session before answering the channel.
Note: this change breaks ABI compatibility.
FAX-217
........
r297495 | mnicholson | 2010-12-03 09:21:52 -0600 (Fri, 03 Dec 2010) | 4 lines
Print a DEBUG message instead of a WARNING message when the selected fax tech does not support reserving sessions.
Answer the channel before quering it for t.38 support. This is necessary for the query to work properly over local channels.
........
Modified:
trunk/ (props changed)
trunk/include/asterisk/res_fax.h
trunk/res/res_fax.c
Propchange: trunk/
------------------------------------------------------------------------------
Binary property 'branch-1.8-merged' - no diff available.
Modified: trunk/include/asterisk/res_fax.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/res_fax.h?view=diff&rev=297496&r1=297495&r2=297496
==============================================================================
--- trunk/include/asterisk/res_fax.h (original)
+++ trunk/include/asterisk/res_fax.h Fri Dec 3 09:32:22 2010
@@ -58,8 +58,10 @@
/*! \brief current state of a fax session */
enum ast_fax_state {
+ /*! reserved state */
+ AST_FAX_STATE_RESERVED = 0,
/*! uninitialized state */
- AST_FAX_STATE_UNINITIALIZED = 0,
+ AST_FAX_STATE_UNINITIALIZED,
/*! initialized state */
AST_FAX_STATE_INITIALIZED,
/*! fax resources open state */
@@ -168,7 +170,8 @@
struct ast_fax_tech;
struct ast_fax_debug_info;
-
+struct ast_fax_tech_token;
+
/*! \brief The data required to handle a fax session */
struct ast_fax_session {
/*! session id */
@@ -183,6 +186,8 @@
unsigned long frames_sent;
/*! the fax technology callbacks */
const struct ast_fax_tech *tech;
+ /*! the token used to reserve this session */
+ struct ast_fax_tech_token *token;
/*! private implementation pointer */
void *tech_pvt;
/*! fax state */
@@ -197,9 +202,11 @@
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 */
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 */
struct ast_fax_tech {
@@ -242,7 +249,15 @@
/*! displays settings from the fax technology module */
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 */
int ast_fax_tech_register(struct ast_fax_tech *tech);
Modified: trunk/res/res_fax.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/res_fax.c?view=diff&rev=297496&r1=297495&r2=297496
==============================================================================
--- trunk/res/res_fax.c (original)
+++ trunk/res/res_fax.c Fri Dec 3 09:32:22 2010
@@ -220,6 +220,8 @@
static struct {
/*! The number of active FAX sessions */
int active_sessions;
+ /*! The number of reserved FAX sessions */
+ int reserved_sessions;
/*! active sessions are astobj2 objects */
struct ao2_container *container;
/*! Total number of Tx FAX attempts */
@@ -631,12 +633,26 @@
}
}
+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 */
static void destroy_session(void *session)
{
struct ast_fax_session *s = session;
if (s->tech) {
+ fax_session_release(s);
if (s->tech_pvt) {
s->tech->destroy_session(s);
}
@@ -656,14 +672,16 @@
ast_smoother_free(s->smoother);
}
- ast_atomic_fetchadd_int(&faxregistry.active_sessions, -1);
+ if (s->active) {
+ ast_atomic_fetchadd_int(&faxregistry.active_sessions, -1);
+ s->active = 0;
+ }
ast_free(s->channame);
ast_free(s->chan_uniqueid);
}
-/*! \brief create a FAX session */
-static struct ast_fax_session *fax_session_new(struct ast_fax_session_details *details, struct ast_channel *chan)
+static struct ast_fax_session *fax_session_reserve(struct ast_fax_session_details *details)
{
struct ast_fax_session *s;
struct fax_module *faxmod;
@@ -672,7 +690,68 @@
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_debug(1, "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);
+ s->state = AST_FAX_STATE_UNINITIALIZED;
if (details->option.debug && (details->caps & AST_FAX_TECH_AUDIO)) {
if (!(s->debug_info = ast_calloc(1, sizeof(*(s->debug_info))))) {
@@ -701,39 +780,39 @@
s->chan = chan;
s->details = details;
ao2_ref(s->details, 1);
- s->state = AST_FAX_STATE_UNINITIALIZED;
details->id = s->id = ast_atomic_fetchadd_int(&faxregistry.nextsessionname, 1);
- /* locate a FAX technology module that can handle said requirements */
- AST_RWLIST_RDLOCK(&faxmodules);
- AST_RWLIST_TRAVERSE(&faxmodules, faxmod, list) {
- if ((faxmod->tech->caps & details->caps) != details->caps) {
- continue;
- }
- ast_debug(4, "Requesting a new 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_pvt = s->tech->new_session(s, NULL))) {
+ if (!s->tech) {
+ /* locate a FAX technology module that can handle said requirements */
+ AST_RWLIST_RDLOCK(&faxmodules);
+ AST_RWLIST_TRAVERSE(&faxmodules, faxmod, list) {
+ if ((faxmod->tech->caps & details->caps) != details->caps) {
+ continue;
+ }
+ ast_debug(4, "Requesting a new 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_pvt = s->tech->new_session(s, s->token))) {
ast_log(LOG_ERROR, "FAX session failed to initialize.\n");
ao2_ref(s, -1);
- ast_module_unref(faxmod->tech->module);
return NULL;
}
/* link the session to the session container */
if (!(ao2_link(faxregistry.container, s))) {
ast_log(LOG_ERROR, "failed to add FAX session '%d' to container.\n", s->id);
ao2_ref(s, -1);
- ast_module_unref(faxmod->tech->module);
return NULL;
}
ast_debug(4, "channel '%s' using FAX session '%d'\n", s->channame, s->id);
@@ -930,7 +1009,7 @@
ast_debug(1, "Shutting down T.38 on %s\n", chan->name);
if (ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) != 0) {
- ast_log(LOG_WARNING, "error while disabling T.38 on channel '%s'\n", chan->name);
+ ast_debug(1, "error while disabling T.38 on channel '%s'\n", chan->name);
return -1;
}
@@ -940,12 +1019,12 @@
while (ms > 0) {
ms = ast_waitfor(chan, ms);
if (ms < 0) {
- ast_log(LOG_WARNING, "error while disabling T.38 on channel '%s'\n", chan->name);
+ ast_debug(1, "error while disabling T.38 on channel '%s'\n", chan->name);
return -1;
}
if (ms == 0) { /* all done, nothing happened */
- ast_log(LOG_WARNING, "channel '%s' timed-out during T.38 shutdown\n", chan->name);
+ ast_debug(1, "channel '%s' timed-out during T.38 shutdown\n", chan->name);
break;
}
@@ -987,7 +1066,7 @@
};
/*! \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 timeout = RES_FAX_TIMEOUT;
@@ -1005,7 +1084,7 @@
chancount = 1;
/* 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");
report_fax_status(chan, details, "No Available Resource");
return -1;
@@ -1093,7 +1172,7 @@
* FAX session complete before we exit the application. if needed,
* send the FAX stack silence so the modems can finish their session without
* any problems */
- ast_log(LOG_NOTICE, "Channel '%s' did not return a frame; probably hung up.\n", chan->name);
+ ast_debug(1, "Channel '%s' did not return a frame; probably hung up.\n", chan->name);
GENERIC_FAX_EXEC_SET_VARS(fax, chan, "HANGUP", "remote channel hungup");
c = NULL;
chancount = 0;
@@ -1295,7 +1374,7 @@
ast_playtones_stop(chan);
break;
case AST_T38_NEGOTIATED:
- ast_log(LOG_NOTICE, "Negotiated T.38 for receive on %s\n", chan->name);
+ ast_debug(1, "Negotiated T.38 for receive on %s\n", chan->name);
t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
details->caps &= ~AST_FAX_TECH_AUDIO;
report_fax_status(chan, details, "T.38 Negotiated");
@@ -1316,7 +1395,7 @@
}
/* request T.38 */
- ast_log(LOG_NOTICE, "Negotiating T.38 for receive on %s\n", chan->name);
+ ast_debug(1, "Negotiating T.38 for receive on %s\n", chan->name);
/* wait up to five seconds for negotiation to complete */
ms = 5000;
@@ -1358,7 +1437,7 @@
ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
break;
case AST_T38_NEGOTIATED:
- ast_log(LOG_NOTICE, "Negotiated T.38 for receive on %s\n", chan->name);
+ ast_debug(1, "Negotiated T.38 for receive on %s\n", chan->name);
t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
details->caps &= ~AST_FAX_TECH_AUDIO;
report_fax_status(chan, details, "T.38 Negotiated");
@@ -1402,6 +1481,7 @@
char *parse, modems[128] = "";
int channel_alive;
struct ast_fax_session_details *details;
+ struct ast_fax_session *s;
struct ast_fax_document *doc;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(filename);
@@ -1498,15 +1578,6 @@
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);
pbx_builtin_setvar_helper(chan, "FAXERROR", "Channel Problems");
@@ -1543,10 +1614,31 @@
details->option.allow_audio = AST_FAX_OPTFLAG_TRUE;
}
+ 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 (set_fax_t38_caps(chan, details)) {
ast_string_field_set(details, error, "T38_NEG_ERROR");
ast_string_field_set(details, resultstr, "error negotiating T.38");
set_channel_variables(chan, details);
+ ao2_ref(s, -1);
ao2_ref(details, -1);
return -1;
}
@@ -1556,6 +1648,7 @@
ast_string_field_set(details, error, "T38_NEG_ERROR");
ast_string_field_set(details, resultstr, "error negotiating T.38");
set_channel_variables(chan, details);
+ ao2_ref(s, -1);
ao2_ref(details, -1);
ast_log(LOG_ERROR, "error initializing channel '%s' in T.38 mode\n", chan->name);
return -1;
@@ -1564,13 +1657,13 @@
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);
}
if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) {
if (disable_t38(chan)) {
- ast_log(LOG_WARNING, "error disabling T.38 mode on %s\n", chan->name);
+ ast_debug(1, "error disabling T.38 mode on %s\n", chan->name);
}
}
@@ -1602,6 +1695,7 @@
args.filename);
ast_channel_unlock(chan);
+ ao2_ref(s, -1);
ao2_ref(details, -1);
/* If the channel hungup return -1; otherwise, return 0 to continue in the dialplan */
@@ -1666,7 +1760,7 @@
ast_playtones_stop(chan);
break;
case AST_T38_NEGOTIATED:
- ast_log(LOG_NOTICE, "Negotiated T.38 for send on %s\n", chan->name);
+ ast_debug(1, "Negotiated T.38 for send on %s\n", chan->name);
t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
details->caps &= ~AST_FAX_TECH_AUDIO;
report_fax_status(chan, details, "T.38 Negotiated");
@@ -1687,7 +1781,7 @@
/* T.38 negotiation did not happen, initiate a switch if requested */
if (details->option.request_t38 == AST_FAX_OPTFLAG_TRUE) {
- ast_log(LOG_NOTICE, "Negotiating T.38 for send on %s\n", chan->name);
+ ast_debug(1, "Negotiating T.38 for send on %s\n", chan->name);
/* wait up to five seconds for negotiation to complete */
ms = 5000;
@@ -1729,7 +1823,7 @@
ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
break;
case AST_T38_NEGOTIATED:
- ast_log(LOG_NOTICE, "Negotiated T.38 for receive on %s\n", chan->name);
+ ast_debug(1, "Negotiated T.38 for receive on %s\n", chan->name);
t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
details->caps &= ~AST_FAX_TECH_AUDIO;
report_fax_status(chan, details, "T.38 Negotiated");
@@ -1798,7 +1892,7 @@
ast_playtones_stop(chan);
break;
case AST_T38_NEGOTIATED:
- ast_log(LOG_NOTICE, "Negotiated T.38 for send on %s\n", chan->name);
+ ast_debug(1, "Negotiated T.38 for send on %s\n", chan->name);
t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
details->caps &= ~AST_FAX_TECH_AUDIO;
report_fax_status(chan, details, "T.38 Negotiated");
@@ -1839,6 +1933,7 @@
char *parse, *filenames, *c, modems[128] = "";
int channel_alive, file_count;
struct ast_fax_session_details *details;
+ struct ast_fax_session *s;
struct ast_fax_document *doc;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(filenames);
@@ -1934,15 +2029,6 @@
ast_log(LOG_WARNING, "%s does not support polling\n", app_sendfax);
ao2_ref(details, -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);
@@ -2003,10 +2089,31 @@
details->option.request_t38 = AST_FAX_OPTFLAG_TRUE;
}
+ 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 (set_fax_t38_caps(chan, details)) {
ast_string_field_set(details, error, "T38_NEG_ERROR");
ast_string_field_set(details, resultstr, "error negotiating T.38");
set_channel_variables(chan, details);
+ ao2_ref(s, -1);
ao2_ref(details, -1);
return -1;
}
@@ -2016,6 +2123,7 @@
ast_string_field_set(details, error, "T38_NEG_ERROR");
ast_string_field_set(details, resultstr, "error negotiating T.38");
set_channel_variables(chan, details);
+ ao2_ref(s, -1);
ao2_ref(details, -1);
ast_log(LOG_ERROR, "error initializing channel '%s' in T.38 mode\n", chan->name);
return -1;
@@ -2024,18 +2132,19 @@
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);
}
if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) {
if (disable_t38(chan)) {
- ast_log(LOG_WARNING, "error disabling T.38 mode on %s\n", chan->name);
+ ast_debug(1, "error disabling T.38 mode on %s\n", chan->name);
}
}
if (!(filenames = generate_filenames_string(details, "FileName: ", "\r\n"))) {
ast_log(LOG_ERROR, "Error generating SendFAX manager event\n");
+ ao2_ref(s, -1);
ao2_ref(details, -1);
return (!channel_alive) ? -1 : 0;
}
@@ -2069,6 +2178,7 @@
ast_free(filenames);
+ ao2_ref(s, -1);
ao2_ref(details, -1);
/* If the channel hungup return -1; otherwise, return 0 to continue in the dialplan */
@@ -2307,6 +2417,7 @@
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", "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", "Receive Attempts", faxregistry.fax_rx_attempts);
ast_cli(a->fd, "%-20.20s : %d\n", "Completed FAXes", faxregistry.fax_complete);
@@ -2616,6 +2727,7 @@
/* initialize the registry */
faxregistry.active_sessions = 0;
+ faxregistry.reserved_sessions = 0;
if (!(faxregistry.container = ao2_container_alloc(FAX_MAXBUCKETS, session_hash_cb, session_cmp_cb))) {
return AST_MODULE_LOAD_DECLINE;
}
More information about the asterisk-commits
mailing list