Reimplemented fax session reservation to reverse the ABI breakage introduced in r297486.

git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.8@303907 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Matthew Nicholson
2011-01-25 20:56:12 +00:00
parent ab1f22bb75
commit 193a80b513
2 changed files with 43 additions and 42 deletions

View File

@@ -58,10 +58,8 @@ 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, AST_FAX_STATE_UNINITIALIZED = 0,
/*! initialized state */ /*! initialized state */
AST_FAX_STATE_INITIALIZED, AST_FAX_STATE_INITIALIZED,
/*! fax resources open state */ /*! fax resources open state */
@@ -70,6 +68,10 @@ enum ast_fax_state {
AST_FAX_STATE_ACTIVE, AST_FAX_STATE_ACTIVE,
/*! fax session complete */ /*! fax session complete */
AST_FAX_STATE_COMPLETE, AST_FAX_STATE_COMPLETE,
/*! reserved state */
AST_FAX_STATE_RESERVED,
/*! inactive state */
AST_FAX_STATE_INACTIVE,
}; };
/*! \brief fax session options */ /*! \brief fax session options */
@@ -186,8 +188,6 @@ 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 */
@@ -202,10 +202,6 @@ 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;
/*! 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 */
@@ -250,14 +246,6 @@ 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);

View File

@@ -638,6 +638,10 @@ const char *ast_fax_state_to_str(enum ast_fax_state state)
return "Active"; return "Active";
case AST_FAX_STATE_COMPLETE: case AST_FAX_STATE_COMPLETE:
return "Complete"; return "Complete";
case AST_FAX_STATE_RESERVED:
return "Reserved";
case AST_FAX_STATE_INACTIVE:
return "Inactive";
default: default:
ast_log(LOG_WARNING, "unhandled FAX state: %d\n", state); ast_log(LOG_WARNING, "unhandled FAX state: %d\n", state);
return "Unknown"; return "Unknown";
@@ -678,16 +682,15 @@ static unsigned int fax_rate_str_to_int(const char *ratestr)
} }
} }
static void fax_session_release(struct ast_fax_session *s) static void fax_session_release(struct ast_fax_session *s, struct ast_fax_tech_token *token)
{ {
if (s->token) { if (token) {
s->tech->release_token(s->token); s->tech->release_token(token);
s->token = NULL;
} }
if (s->reserved) { if (s->state == AST_FAX_STATE_RESERVED) {
ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, -1); ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, -1);
s->reserved = 0; s->state = AST_FAX_STATE_INACTIVE;
} }
} }
@@ -697,7 +700,7 @@ 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); fax_session_release(s, NULL);
if (s->tech_pvt) { if (s->tech_pvt) {
s->tech->destroy_session(s); s->tech->destroy_session(s);
} }
@@ -717,16 +720,15 @@ static void destroy_session(void *session)
ast_smoother_free(s->smoother); ast_smoother_free(s->smoother);
} }
if (s->active) { if (s->state != AST_FAX_STATE_INACTIVE) {
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);
} }
static struct ast_fax_session *fax_session_reserve(struct ast_fax_session_details *details) static struct ast_fax_session *fax_session_reserve(struct ast_fax_session_details *details, struct ast_fax_tech_token **token)
{ {
struct ast_fax_session *s; struct ast_fax_session *s;
struct fax_module *faxmod; struct fax_module *faxmod;
@@ -736,7 +738,7 @@ static struct ast_fax_session *fax_session_reserve(struct ast_fax_session_detail
return NULL; return NULL;
} }
s->state = AST_FAX_STATE_RESERVED; s->state = AST_FAX_STATE_INACTIVE;
/* locate a FAX technology module that can handle said requirements /* locate a FAX technology module that can handle said requirements
* Note: the requirements have not yet been finalized as T.38 * Note: the requirements have not yet been finalized as T.38
@@ -764,19 +766,19 @@ static struct ast_fax_session *fax_session_reserve(struct ast_fax_session_detail
return s; return s;
} }
if (!(s->token = s->tech->reserve_session(s))) { if (!(*token = s->tech->reserve_session(s))) {
ao2_ref(s, -1); ao2_ref(s, -1);
return NULL; return NULL;
} }
s->reserved = 1; s->state = AST_FAX_STATE_RESERVED;
ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, 1); ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, 1);
return s; return s;
} }
/*! \brief create a FAX session */ /*! \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) 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)
{ {
struct ast_fax_session *s = NULL; struct ast_fax_session *s = NULL;
struct fax_module *faxmod; struct fax_module *faxmod;
@@ -786,9 +788,9 @@ static struct ast_fax_session *fax_session_new(struct ast_fax_session_details *d
s = reserved; s = reserved;
ao2_ref(reserved, +1); ao2_ref(reserved, +1);
if (s->reserved) { if (s->state == AST_FAX_STATE_RESERVED) {
ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, -1); ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, -1);
s->reserved = 0; s->state = AST_FAX_STATE_UNINITIALIZED;
} }
} }
@@ -796,18 +798,19 @@ static struct ast_fax_session *fax_session_new(struct ast_fax_session_details *d
return NULL; 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; 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))))) {
fax_session_release(s, token);
ao2_ref(s, -1); ao2_ref(s, -1);
return NULL; return NULL;
} }
if (!(s->debug_info->dsp = ast_dsp_new())) { if (!(s->debug_info->dsp = ast_dsp_new())) {
ast_free(s->debug_info); ast_free(s->debug_info);
s->debug_info = NULL; s->debug_info = NULL;
fax_session_release(s, token);
ao2_ref(s, -1); ao2_ref(s, -1);
return NULL; return NULL;
} }
@@ -815,11 +818,13 @@ static struct ast_fax_session *fax_session_new(struct ast_fax_session_details *d
} }
if (!(s->channame = ast_strdup(chan->name))) { if (!(s->channame = ast_strdup(chan->name))) {
fax_session_release(s, token);
ao2_ref(s, -1); ao2_ref(s, -1);
return NULL; return NULL;
} }
if (!(s->chan_uniqueid = ast_strdup(chan->uniqueid))) { if (!(s->chan_uniqueid = ast_strdup(chan->uniqueid))) {
fax_session_release(s, token);
ao2_ref(s, -1); ao2_ref(s, -1);
return NULL; return NULL;
} }
@@ -830,7 +835,7 @@ static struct ast_fax_session *fax_session_new(struct ast_fax_session_details *d
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) { if (!token) {
/* 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) {
@@ -851,7 +856,7 @@ static struct ast_fax_session *fax_session_new(struct ast_fax_session_details *d
} }
} }
if (!(s->tech_pvt = s->tech->new_session(s, s->token))) { if (!(s->tech_pvt = s->tech->new_session(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);
return NULL; return NULL;
@@ -1116,7 +1121,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, struct ast_fax_session *reserved) 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)
{ {
int ms; int ms;
int timeout = RES_FAX_TIMEOUT; int timeout = RES_FAX_TIMEOUT;
@@ -1134,7 +1139,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, reserved))) { if (!(fax = fax_session_new(details, chan, reserved, token))) {
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;
@@ -1533,6 +1538,7 @@ static int receivefax_exec(struct ast_channel *chan, const char *data)
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_session *s;
struct ast_fax_tech_token *token = NULL;
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);
@@ -1676,7 +1682,7 @@ static int receivefax_exec(struct ast_channel *chan, const char *data)
details->option.allow_audio = AST_FAX_OPTFLAG_TRUE; details->option.allow_audio = AST_FAX_OPTFLAG_TRUE;
} }
if (!(s = fax_session_reserve(details))) { if (!(s = fax_session_reserve(details, &token))) {
ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
ast_string_field_set(details, resultstr, "error reserving fax session"); ast_string_field_set(details, resultstr, "error reserving fax session");
set_channel_variables(chan, details); set_channel_variables(chan, details);
@@ -1692,6 +1698,7 @@ static int receivefax_exec(struct ast_channel *chan, const char *data)
ast_string_field_set(details, resultstr, "error answering channel"); ast_string_field_set(details, resultstr, "error answering channel");
set_channel_variables(chan, details); set_channel_variables(chan, details);
ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", chan->name); ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", chan->name);
fax_session_release(s, token);
ao2_ref(s, -1); ao2_ref(s, -1);
ao2_ref(details, -1); ao2_ref(details, -1);
return -1; return -1;
@@ -1703,6 +1710,7 @@ static int receivefax_exec(struct ast_channel *chan, const char *data)
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);
fax_session_release(s, token);
ao2_ref(s, -1); ao2_ref(s, -1);
ao2_ref(details, -1); ao2_ref(details, -1);
return -1; return -1;
@@ -1714,6 +1722,7 @@ static int receivefax_exec(struct ast_channel *chan, const char *data)
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);
fax_session_release(s, token);
ao2_ref(s, -1); 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);
@@ -1723,7 +1732,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, s)) < 0) { if ((channel_alive = generic_fax_exec(chan, details, s, token)) < 0) {
ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
} }
@@ -2000,6 +2009,7 @@ static int sendfax_exec(struct ast_channel *chan, const char *data)
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_session *s;
struct ast_fax_tech_token *token = NULL;
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);
@@ -2167,7 +2177,7 @@ static int sendfax_exec(struct ast_channel *chan, const char *data)
details->option.request_t38 = AST_FAX_OPTFLAG_TRUE; details->option.request_t38 = AST_FAX_OPTFLAG_TRUE;
} }
if (!(s = fax_session_reserve(details))) { if (!(s = fax_session_reserve(details, &token))) {
ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
ast_string_field_set(details, resultstr, "error reserving fax session"); ast_string_field_set(details, resultstr, "error reserving fax session");
set_channel_variables(chan, details); set_channel_variables(chan, details);
@@ -2183,6 +2193,7 @@ static int sendfax_exec(struct ast_channel *chan, const char *data)
ast_string_field_set(details, resultstr, "error answering channel"); ast_string_field_set(details, resultstr, "error answering channel");
set_channel_variables(chan, details); set_channel_variables(chan, details);
ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", chan->name); ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", chan->name);
fax_session_release(s, token);
ao2_ref(s, -1); ao2_ref(s, -1);
ao2_ref(details, -1); ao2_ref(details, -1);
return -1; return -1;
@@ -2194,6 +2205,7 @@ static int sendfax_exec(struct ast_channel *chan, const char *data)
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);
fax_session_release(s, token);
ao2_ref(s, -1); ao2_ref(s, -1);
ao2_ref(details, -1); ao2_ref(details, -1);
return -1; return -1;
@@ -2205,6 +2217,7 @@ static int sendfax_exec(struct ast_channel *chan, const char *data)
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);
fax_session_release(s, token);
ao2_ref(s, -1); 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);
@@ -2214,7 +2227,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, s)) < 0) { if ((channel_alive = generic_fax_exec(chan, details, s, token)) < 0) {
ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1); ast_atomic_fetchadd_int(&faxregistry.fax_failures, 1);
} }