Merged revisions 303907 via svnmerge from
authorMatthew Nicholson <mnicholson@digium.com>
Wed, 26 Jan 2011 19:58:14 +0000 (19:58 +0000)
committerMatthew Nicholson <mnicholson@digium.com>
Wed, 26 Jan 2011 19:58:14 +0000 (19:58 +0000)
https://origsvn.digium.com/svn/asterisk/branches/1.8

........
  r303907 | mnicholson | 2011-01-25 14:56:12 -0600 (Tue, 25 Jan 2011) | 2 lines

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

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@304152 65c4cc65-6c06-0410-ace0-fbb531ad65f3

include/asterisk/res_fax.h
res/res_fax.c

index 70715d5..9a52115 100644 (file)
@@ -58,10 +58,8 @@ enum ast_fax_modems {
 
 /*! \brief current state of a fax session */
 enum ast_fax_state {
-       /*! reserved state */
-       AST_FAX_STATE_RESERVED = 0,
        /*! uninitialized state */
-       AST_FAX_STATE_UNINITIALIZED,
+       AST_FAX_STATE_UNINITIALIZED = 0,
        /*! initialized state */
        AST_FAX_STATE_INITIALIZED,
        /*! fax resources open state */
@@ -70,6 +68,10 @@ enum ast_fax_state {
        AST_FAX_STATE_ACTIVE,
        /*! fax session complete */
        AST_FAX_STATE_COMPLETE,
+       /*! reserved state */
+       AST_FAX_STATE_RESERVED,
+       /*! inactive state */
+       AST_FAX_STATE_INACTIVE,
 };
 
 /*! \brief fax session options */
@@ -186,8 +188,6 @@ struct ast_fax_session {
        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 */
@@ -202,10 +202,6 @@ struct ast_fax_session {
        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;
-
-       /*! 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 */
@@ -250,14 +246,6 @@ struct ast_fax_tech {
        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);
 
index 9601dbc..5d66608 100644 (file)
@@ -593,6 +593,10 @@ const char *ast_fax_state_to_str(enum ast_fax_state state)
                return "Active";
        case AST_FAX_STATE_COMPLETE:
                return "Complete";
+       case AST_FAX_STATE_RESERVED:
+               return "Reserved";
+       case AST_FAX_STATE_INACTIVE:
+               return "Inactive";
        default:
                ast_log(LOG_WARNING, "unhandled FAX state: %d\n", state);
                return "Unknown";
@@ -633,16 +637,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) {
-               s->tech->release_token(s->token);
-               s->token = NULL;
+       if (token) {
+               s->tech->release_token(token);
        }
 
-       if (s->reserved) {
+       if (s->state == AST_FAX_STATE_RESERVED) {
                ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, -1);
-               s->reserved = 0;
+               s->state = AST_FAX_STATE_INACTIVE;
        }
 }
 
@@ -652,7 +655,7 @@ static void destroy_session(void *session)
        struct ast_fax_session *s = session;
 
        if (s->tech) {
-               fax_session_release(s);
+               fax_session_release(s, NULL);
                if (s->tech_pvt) {
                        s->tech->destroy_session(s);
                }
@@ -672,16 +675,15 @@ static void destroy_session(void *session)
                ast_smoother_free(s->smoother);
        }
 
-       if (s->active) {
+       if (s->state != AST_FAX_STATE_INACTIVE) {
                ast_atomic_fetchadd_int(&faxregistry.active_sessions, -1);
-               s->active = 0;
        }
 
        ast_free(s->channame);
        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 fax_module *faxmod;
@@ -690,7 +692,7 @@ static struct ast_fax_session *fax_session_reserve(struct ast_fax_session_detail
                return NULL;
        }
 
-       s->state = AST_FAX_STATE_RESERVED;
+       s->state = AST_FAX_STATE_INACTIVE;
 
        /* locate a FAX technology module that can handle said requirements
         * Note: the requirements have not yet been finalized as T.38
@@ -718,19 +720,19 @@ static struct ast_fax_session *fax_session_reserve(struct ast_fax_session_detail
                return s;
        }
 
-       if (!(s->token = s->tech->reserve_session(s))) {
+       if (!(*token = s->tech->reserve_session(s))) {
                ao2_ref(s, -1);
                return NULL;
        }
 
-       s->reserved = 1;
+       s->state = AST_FAX_STATE_RESERVED;
        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)
+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 fax_module *faxmod;
@@ -739,9 +741,9 @@ static struct ast_fax_session *fax_session_new(struct ast_fax_session_details *d
                s = reserved;
                ao2_ref(reserved, +1);
 
-               if (s->reserved) {
+               if (s->state == AST_FAX_STATE_RESERVED) {
                        ast_atomic_fetchadd_int(&faxregistry.reserved_sessions, -1);
-                       s->reserved = 0;
+                       s->state = AST_FAX_STATE_UNINITIALIZED;
                }
        }
 
@@ -749,18 +751,19 @@ static struct ast_fax_session *fax_session_new(struct ast_fax_session_details *d
                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))))) {
+                       fax_session_release(s, token);
                        ao2_ref(s, -1);
                        return NULL;
                }
                if (!(s->debug_info->dsp = ast_dsp_new())) {
                        ast_free(s->debug_info);
                        s->debug_info = NULL;
+                       fax_session_release(s, token);
                        ao2_ref(s, -1);
                        return NULL;
                }
@@ -768,11 +771,13 @@ static struct ast_fax_session *fax_session_new(struct ast_fax_session_details *d
        }       
 
        if (!(s->channame = ast_strdup(chan->name))) {
+               fax_session_release(s, token);
                ao2_ref(s, -1);
                return NULL;
        }
 
        if (!(s->chan_uniqueid = ast_strdup(chan->uniqueid))) {
+               fax_session_release(s, token);
                ao2_ref(s, -1);
                return NULL;
        }
@@ -783,7 +788,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);
 
-       if (!s->tech) {
+       if (!token) {
                /* locate a FAX technology module that can handle said requirements */
                AST_RWLIST_RDLOCK(&faxmodules);
                AST_RWLIST_TRAVERSE(&faxmodules, faxmod, list) {
@@ -804,7 +809,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");
                ao2_ref(s, -1);
                return NULL;
@@ -1069,7 +1074,7 @@ static struct ast_control_t38_parameters our_t38_parameters = {
 };
 
 /*! \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 timeout = RES_FAX_TIMEOUT;
@@ -1087,7 +1092,7 @@ static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_det
        chancount = 1;
 
        /* 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");
                report_fax_status(chan, details, "No Available Resource");
                return -1;
@@ -1485,6 +1490,7 @@ static int receivefax_exec(struct ast_channel *chan, const char *data)
        int channel_alive;
        struct ast_fax_session_details *details;
        struct ast_fax_session *s;
+       struct ast_fax_tech_token *token = NULL;
        struct ast_fax_document *doc;
        AST_DECLARE_APP_ARGS(args,
                AST_APP_ARG(filename);
@@ -1617,7 +1623,7 @@ static int receivefax_exec(struct ast_channel *chan, const char *data)
                details->option.allow_audio = AST_FAX_OPTFLAG_TRUE;
        }
 
-       if (!(s = fax_session_reserve(details))) {
+       if (!(s = fax_session_reserve(details, &token))) {
                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");
@@ -1631,6 +1637,7 @@ static int receivefax_exec(struct ast_channel *chan, const char *data)
                        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);
+                       fax_session_release(s, token);
                        ao2_ref(s, -1);
                        ao2_ref(details, -1);
                        return -1;
@@ -1641,6 +1648,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, resultstr, "error negotiating T.38");
                set_channel_variables(chan, details);
+               fax_session_release(s, token);
                ao2_ref(s, -1);
                ao2_ref(details, -1);
                return -1;
@@ -1651,6 +1659,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, resultstr, "error negotiating T.38");
                        set_channel_variables(chan, details);
+                       fax_session_release(s, token);
                        ao2_ref(s, -1);
                        ao2_ref(details, -1);
                        ast_log(LOG_ERROR, "error initializing channel '%s' in T.38 mode\n", chan->name);
@@ -1660,7 +1669,7 @@ static int receivefax_exec(struct ast_channel *chan, const char *data)
                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);
        }
 
@@ -1937,6 +1946,7 @@ static int sendfax_exec(struct ast_channel *chan, const char *data)
        int channel_alive, file_count;
        struct ast_fax_session_details *details;
        struct ast_fax_session *s;
+       struct ast_fax_tech_token *token = NULL;
        struct ast_fax_document *doc;
        AST_DECLARE_APP_ARGS(args,
                AST_APP_ARG(filenames);
@@ -2092,7 +2102,7 @@ static int sendfax_exec(struct ast_channel *chan, const char *data)
                details->option.request_t38 = AST_FAX_OPTFLAG_TRUE;
        }
 
-       if (!(s = fax_session_reserve(details))) {
+       if (!(s = fax_session_reserve(details, &token))) {
                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");
@@ -2106,6 +2116,7 @@ static int sendfax_exec(struct ast_channel *chan, const char *data)
                        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);
+                       fax_session_release(s, token);
                        ao2_ref(s, -1);
                        ao2_ref(details, -1);
                        return -1;
@@ -2116,6 +2127,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, resultstr, "error negotiating T.38");
                set_channel_variables(chan, details);
+               fax_session_release(s, token);
                ao2_ref(s, -1);
                ao2_ref(details, -1);
                return -1;
@@ -2126,6 +2138,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, resultstr, "error negotiating T.38");
                        set_channel_variables(chan, details);
+                       fax_session_release(s, token);
                        ao2_ref(s, -1);
                        ao2_ref(details, -1);
                        ast_log(LOG_ERROR, "error initializing channel '%s' in T.38 mode\n", chan->name);
@@ -2135,7 +2148,7 @@ static int sendfax_exec(struct ast_channel *chan, const char *data)
                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);
        }