This reverts the changes I made for 11583; will
authorSteve Murphy <murf@digium.com>
Mon, 2 Feb 2009 19:02:24 +0000 (19:02 +0000)
committerSteve Murphy <murf@digium.com>
Mon, 2 Feb 2009 19:02:24 +0000 (19:02 +0000)
reviewboard this before committing again...
reopened 11583 until all Russell's issues are
resolved.

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

CHANGES
apps/app_dial.c
include/asterisk/features.h
main/features.c

diff --git a/CHANGES b/CHANGES
index 6db7a98..cb8b7e5 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -128,8 +128,6 @@ Miscellaneous
  * The contrib/scripts/ directory now has a script called sip_nat_settings that will
    give you the correct output for an asterisk box behind nat. It will give you the
    externhost and localnet settings.
- * The 'one-touch' disconnect feature is now available during Dial,
-   instead of just when a call is connected.
 
 Asterisk Manager Interface
 --------------------------
index 3fff300..849c0c5 100644 (file)
@@ -560,7 +560,6 @@ struct chanlist {
        uint64_t flags;
 };
 
-static int detect_disconnect(struct ast_channel *chan, char code);
 
 static void hanguptree(struct chanlist *outgoing, struct ast_channel *exception, int answered_elsewhere)
 {
@@ -1055,8 +1054,8 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
                                }
 
                                if (ast_test_flag64(peerflags, OPT_CALLER_HANGUP) &&
-                                               detect_disconnect(in, f->subclass)) {
-                                       ast_verb(3, "User requested call disconnect.\n");
+                                               (f->subclass == '*')) { /* hmm it it not guaranteed to be '*' anymore. */
+                                       ast_verb(3, "User hit %c to disconnect call.\n", f->subclass);
                                        *to = 0;
                                        strcpy(pa->status, "CANCEL");
                                        ast_cdr_noanswer(in->cdr);
@@ -1100,58 +1099,6 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
        return peer;
 }
 
-static char featurecode[FEATURE_MAX_LEN + 1] = "";
-
-static int detect_disconnect(struct ast_channel *chan, char code)
-{
-       struct feature_interpret_result result;
-       int x;
-       struct ast_flags features;
-       int res = FEATURE_RETURN_PASSDIGITS;
-       struct ast_call_feature *feature;
-       char *cptr;
-       const char *dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
-       int len;
-
-       len = strlen(featurecode);
-       if (len >= FEATURE_MAX_LEN) {
-               featurecode[0] = '\0';
-       }
-       cptr = &featurecode[strlen(featurecode)];
-       cptr[0] = code;
-       cptr[1] = '\0';
-
-       memset(&features, 0, sizeof(struct ast_flags));
-       ast_set_flag(&features, AST_FEATURE_DISCONNECT);
-
-       ast_features_lock();
-
-       res = ast_feature_detect(chan, &features, featurecode, &result, dynamic_features);
-
-       if (res != FEATURE_RETURN_STOREDIGITS)
-               featurecode[0] = '\0';
-
-
-       if (result.builtin_feature && result.builtin_feature->feature_mask & AST_FEATURE_DISCONNECT) {
-               ast_features_unlock();
-               return 1;
-       }
-               
-       for (x = 0; x < result.num_dyn_features; ++x) {
-               feature = result.dynamic_features[x];
-               if (feature->feature_mask & AST_FEATURE_DISCONNECT) {
-                       ast_features_unlock();
-                       return 1;
-               }
-       }
-
-       ast_features_unlock();
-
-       return 0;
-}
-
-
-
 static void replace_macro_delimiter(char *s)
 {
        for (; *s; s++)
index f0e54a7..4d58188 100644 (file)
 
 #define PARK_APP_NAME "Park"
 
-#define FEATURE_RETURN_HANGUP          -1
-#define FEATURE_RETURN_SUCCESSBREAK     0
-#define FEATURE_RETURN_PASSDIGITS       21
-#define FEATURE_RETURN_STOREDIGITS      22
-#define FEATURE_RETURN_SUCCESS          23
-#define FEATURE_RETURN_KEEPTRYING    24
-
-typedef int (*feature_operation)(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data);
-
 /*! \brief main call feature structure */
 
 enum {
@@ -62,7 +53,7 @@ struct ast_call_feature {
        char sname[FEATURE_SNAME_LEN];
        char exten[FEATURE_MAX_LEN];
        char default_exten[FEATURE_MAX_LEN];
-       feature_operation operation;
+       int (*operation)(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data);
        unsigned int flags;
        char app[FEATURE_APP_LEN];              
        char app_args[FEATURE_APP_ARGS_LEN];
@@ -70,20 +61,12 @@ struct ast_call_feature {
        AST_LIST_ENTRY(ast_call_feature) feature_entry;
 };
 
-#define AST_FEATURE_RETURN_HANGUP                   FEATURE_RETURN_HANGUP
-#define AST_FEATURE_RETURN_SUCCESSBREAK             FEATURE_RETURN_SUCCESSBREAK
-#define AST_FEATURE_RETURN_PASSDIGITS               FEATURE_RETURN_PASSDIGITS
-#define AST_FEATURE_RETURN_STOREDIGITS              FEATURE_RETURN_STOREDIGITS
-#define AST_FEATURE_RETURN_SUCCESS                  FEATURE_RETURN_SUCCESS
-#define AST_FEATURE_RETURN_KEEPTRYING               FEATURE_RETURN_KEEPTRYING
-
-struct feature_interpret_result {
-    struct ast_call_feature *builtin_feature;
-    struct ast_call_feature *dynamic_features[20];
-    struct ast_call_feature *group_features[20];
-    int num_dyn_features;
-    int num_grp_features;
-};
+#define AST_FEATURE_RETURN_HANGUP                   -1
+#define AST_FEATURE_RETURN_SUCCESSBREAK             0
+#define AST_FEATURE_RETURN_PASSDIGITS               21
+#define AST_FEATURE_RETURN_STOREDIGITS              22
+#define AST_FEATURE_RETURN_SUCCESS                  23
+#define AST_FEATURE_RETURN_KEEPTRYING               24
 
 /*!
  * \brief Park a call and read back parked location 
@@ -139,12 +122,6 @@ void ast_register_feature(struct ast_call_feature *feature);
     \param feature the ast_call_feature object which was registered before*/
 void ast_unregister_feature(struct ast_call_feature *feature);
 
-int ast_feature_detect(struct ast_channel *chan, const struct ast_flags *features, char *code, struct feature_interpret_result *result, const char *dynamic_features);
-
-void ast_features_lock(void);
-void ast_features_unlock(void);
-
-
 /*! \brief look for a call feature entry by its sname
        \param name a string ptr, should match "automon", "blindxfer", "atxfer", etc. */
 struct ast_call_feature *ast_find_call_feature(const char *name);
index 9d463c2..6ad1c12 100644 (file)
@@ -856,8 +856,8 @@ static int masq_park_call_announce(struct ast_channel *rchan, struct ast_channel
        return masq_park_call(rchan, peer, timeout, extout, 1, NULL);
 }
 
-#define FEATURE_SENSE_CHAN     (1 << 0)
-#define FEATURE_SENSE_PEER     (1 << 1)
+#define FEATURE_SENSE_CHAN     (1 << 0)
+#define FEATURE_SENSE_PEER     (1 << 1)
 
 /*! 
  * \brief set caller and callee according to the direction 
@@ -1935,40 +1935,44 @@ static int remap_feature(const char *name, const char *value)
        return res;
 }
 
-void ast_features_lock(void)
-{
-       ast_rwlock_rdlock(&features_lock);
-       AST_RWLIST_WRLOCK(&feature_list);
-       AST_RWLIST_RDLOCK(&feature_groups);
-}
-
-void ast_features_unlock(void)
-{
-       AST_RWLIST_UNLOCK(&feature_groups);
-       AST_RWLIST_UNLOCK(&feature_list);
-       ast_rwlock_unlock(&features_lock);
-}
-
-int ast_feature_detect(struct ast_channel *chan, const struct ast_flags *features, char *code, struct feature_interpret_result *result, const char *dynamic_features)
+/*!
+ * \brief Check the dynamic features
+ * \param chan,peer,config,code,sense
+ *
+ * Lock features list, browse for code, unlock list
+ * \retval res on success.
+ * \retval -1 on failure.
+*/
+static int ast_feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
 {
        int x;
-       int res = FEATURE_RETURN_PASSDIGITS;
+       struct ast_flags features;
        struct ast_call_feature *feature;
        struct feature_group *fg = NULL;
        struct feature_group_exten *fge;
+       const char *dynamic_features;
        char *tmp, *tok;
-       
-       result->builtin_feature = NULL;
-       result->num_dyn_features = 0;
-       result->num_grp_features = 0;
-       
-       
+       int res = AST_FEATURE_RETURN_PASSDIGITS;
+       int feature_detected = 0;
+
+       if (sense == FEATURE_SENSE_CHAN) {
+               ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);
+               dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
+       }
+       else {
+               ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);
+               dynamic_features = pbx_builtin_getvar_helper(peer, "DYNAMIC_FEATURES");
+       }
+       ast_debug(3, "Feature interpret: chan=%s, peer=%s, code=%s, sense=%d, features=%d, dynamic=%s\n", chan->name, peer->name, code, sense, features.flags, dynamic_features);
+
+       ast_rwlock_rdlock(&features_lock);
        for (x = 0; x < FEATURES_COUNT; x++) {
-               if ((ast_test_flag(features, builtin_features[x].feature_mask)) &&
+               if ((ast_test_flag(&features, builtin_features[x].feature_mask)) &&
                    !ast_strlen_zero(builtin_features[x].exten)) {
                        /* Feature is up for consideration */
                        if (!strcmp(builtin_features[x].exten, code)) {
-                               result->builtin_feature = &builtin_features[x];
+                               res = builtin_features[x].operation(chan, peer, config, code, sense, NULL);
+                               feature_detected = 1;
                                break;
                        } else if (!strncmp(builtin_features[x].exten, code, strlen(code))) {
                                if (res == AST_FEATURE_RETURN_PASSDIGITS)
@@ -1976,13 +1980,15 @@ int ast_feature_detect(struct ast_channel *chan, const struct ast_flags *feature
                        }
                }
        }
+       ast_rwlock_unlock(&features_lock);
 
-       if (ast_strlen_zero(dynamic_features))
+       if (ast_strlen_zero(dynamic_features) || feature_detected)
                return res;
 
        tmp = ast_strdupa(dynamic_features);
 
        while ((tok = strsep(&tmp, "#"))) {
+               AST_RWLIST_RDLOCK(&feature_groups);
 
                fg = find_group(tok);
 
@@ -1990,9 +1996,10 @@ int ast_feature_detect(struct ast_channel *chan, const struct ast_flags *feature
                        AST_LIST_TRAVERSE(&fg->features, fge, entry) {
                                if (strcasecmp(fge->exten, code))
                                        continue;
-                               
-                               result->group_features[result->num_grp_features++] = fge->feature;
-                               if (result->num_grp_features >= (sizeof(result->group_features) / sizeof(result->group_features[0]))) {
+
+                               res = fge->feature->operation(chan, peer, config, code, sense, fge->feature);
+                               if (res != AST_FEATURE_RETURN_KEEPTRYING) {
+                                       AST_RWLIST_UNLOCK(&feature_groups);
                                        break;
                                }
                                res = AST_FEATURE_RETURN_PASSDIGITS;
@@ -2001,74 +2008,29 @@ int ast_feature_detect(struct ast_channel *chan, const struct ast_flags *feature
                                break;
                }
 
+               AST_RWLIST_UNLOCK(&feature_groups);
+
+               AST_RWLIST_RDLOCK(&feature_list);
+
                if (!(feature = find_dynamic_feature(tok))) {
+                       AST_RWLIST_UNLOCK(&feature_list);
                        continue;
                }
                        
                /* Feature is up for consideration */
                if (!strcmp(feature->exten, code)) {
                        ast_verb(3, " Feature Found: %s exten: %s\n",feature->sname, tok);
-                       result->dynamic_features[result->num_dyn_features++] = feature;
-                       if (result->num_dyn_features >= (sizeof(result->dynamic_features) / sizeof(result->dynamic_features[0]))) {
+                       res = feature->operation(chan, peer, config, code, sense, feature);
+                       if (res != AST_FEATURE_RETURN_KEEPTRYING) {
+                               AST_RWLIST_UNLOCK(&feature_list);
                                break;
                        }
                        res = AST_FEATURE_RETURN_PASSDIGITS;
                } else if (!strncmp(feature->exten, code, strlen(code)))
                        res = AST_FEATURE_RETURN_STOREDIGITS;
-       }
-       return res;
-}
-
- /*!
-  * \brief Check the dynamic features
-  * \param chan,peer,config,code,sense
-  *
-  * Lock features list, browse for code, unlock list
-  * \retval res on success.
-  * \retval -1 on failure.
- */
-static int ast_feature_interpret(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
-{
-       struct feature_interpret_result result;
-       int x;
-       struct ast_flags features;
-       int res = AST_FEATURE_RETURN_PASSDIGITS;
-       struct ast_call_feature *feature;
-       const char *dynamic_features;
-       
-       if (sense == FEATURE_SENSE_CHAN) {
-               ast_copy_flags(&features, &(config->features_caller), AST_FLAGS_ALL);
-               dynamic_features = pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES");
-       } else {
-               ast_copy_flags(&features, &(config->features_callee), AST_FLAGS_ALL);
-               dynamic_features = pbx_builtin_getvar_helper(peer, "DYNAMIC_FEATURES");
-       }
-       ast_debug(3, "Feature interpret: chan=%s, peer=%s, code=%s, sense=%d, features=%d, dynamic=%s\n", chan->name, peer->name, code, sense, features.flags, dynamic_features);
-       
-       ast_features_lock();
-       res = ast_feature_detect(chan, &features, code, &result, dynamic_features);
-       
-       if (result.builtin_feature) {
-               res = result.builtin_feature->operation(chan, peer, config, code, sense, NULL);
-       }
 
-       for (x = 0; x < result.num_grp_features; ++x) {
-               feature = result.group_features[x];
-               res = feature->operation(chan, peer, config, code, sense, feature);
-               if (res != FEATURE_RETURN_KEEPTRYING) {
-                       break;
-               }
-               res = FEATURE_RETURN_PASSDIGITS;
-       }
-       for (x = 0; x < result.num_dyn_features; ++x) {
-               feature = result.dynamic_features[x];
-               res = feature->operation(chan, peer, config, code, sense, feature);
-               if (res != FEATURE_RETURN_KEEPTRYING) {
-                       break;
-               }
-               res = FEATURE_RETURN_PASSDIGITS;
+               AST_RWLIST_UNLOCK(&feature_list);
        }
-       ast_features_unlock();
        
        return res;
 }