Asterisk, when parking can drop rights a caller when a parking timeout occurs. Also...
authorTerry Wilson <twilson@digium.com>
Sat, 1 Mar 2008 01:30:37 +0000 (01:30 +0000)
committerTerry Wilson <twilson@digium.com>
Sat, 1 Mar 2008 01:30:37 +0000 (01:30 +0000)
(closes issue #11520)
Reported by: pliew
Tested by: otherwiseguy

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

apps/app_dial.c
include/asterisk/app.h
include/asterisk/global_datastores.h
main/app.c
main/features.c
main/global_datastores.c

index dc818fa..f93ba0d 100644 (file)
@@ -1208,6 +1208,19 @@ static int setup_privacy_args(struct privacy_args *pa,
        return 1; /* success */
 }
 
+static void set_dial_features(struct ast_flags64 *opts, struct ast_dial_features *features)
+{
+       struct ast_flags64 perm_opts = {.flags = 0};
+
+       ast_copy_flags64(&perm_opts, opts,
+               OPT_CALLER_TRANSFER | OPT_CALLER_PARK | OPT_CALLER_MONITOR | OPT_CALLER_MIXMONITOR | OPT_CALLER_HANGUP |
+               OPT_CALLEE_TRANSFER | OPT_CALLEE_PARK | OPT_CALLEE_MONITOR | OPT_CALLEE_MIXMONITOR | OPT_CALLEE_HANGUP);
+
+       memset(features->options, 0, sizeof(features->options));
+
+       ast_app_options2str64(dial_exec_options, &perm_opts, features->options, sizeof(features->options));
+}
+
 static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags64 *peerflags, int *continue_exec)
 {
        int res = -1; /* default: error */
@@ -1243,6 +1256,9 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
        struct ast_flags64 opts = { 0, };
        char *opt_args[OPT_ARG_ARRAY_SIZE];
        struct ast_datastore *datastore = NULL;
+       struct ast_datastore *ds_caller_features = NULL;
+       struct ast_datastore *ds_callee_features = NULL;
+       struct ast_dial_features *caller_features;
        int fulldial = 0, num_dialed = 0;
 
        if (ast_strlen_zero(data)) {
@@ -1316,6 +1332,29 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
        }
 
        ast_copy_flags64(peerflags, &opts, OPT_DTMF_EXIT | OPT_GO_ON | OPT_ORIGINAL_CLID | OPT_CALLER_HANGUP | OPT_IGNORE_FORWARDING);
+
+       /* Create datastore for channel dial features for caller */
+       if (!(ds_caller_features = ast_channel_datastore_alloc(&dial_features_info, NULL))) {
+               ast_log(LOG_WARNING, "Unable to create channel datastore for dial features. Aborting!\n");
+               goto out;
+       }
+
+       if (!(caller_features = ast_malloc(sizeof(*caller_features)))) {
+               ast_log(LOG_WARNING, "Unable to allocate memory for feature flags. Aborting!\n");
+               goto out;
+       }
+
+       ast_copy_flags(&(caller_features->features_callee), &(config.features_caller), AST_FLAGS_ALL);
+       caller_features->is_caller = 1;
+       set_dial_features(&opts, caller_features);
+
+       ds_caller_features->inheritance = DATASTORE_INHERIT_FOREVER;
+       ds_caller_features->data = caller_features;
+
+       ast_channel_lock(chan);
+       ast_channel_datastore_add(chan, ds_caller_features);
+       ast_channel_unlock(chan);
+
        /* loop through the list of dial destinations */
        rest = args.peers;
        while ((cur = strsep(&rest, "&")) ) {
@@ -1327,6 +1366,7 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
                char *tech = strsep(&number, "/");
                /* find if we already dialed this interface */
                struct ast_dialed_interface *di;
+               struct ast_dial_features *callee_features;
                AST_LIST_HEAD(, ast_dialed_interface) *dialed_interfaces;
                num_dialed++;
                if (!number) {
@@ -1466,6 +1506,30 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
                else
                        ast_copy_string(tc->exten, chan->exten, sizeof(tc->exten));
 
+               /* Save callee features */
+               if (!(ds_callee_features = ast_channel_datastore_alloc(&dial_features_info, NULL))) {
+                       ast_log(LOG_WARNING, "Unable to create channel datastore for dial features. Aborting!\n");
+                       ast_free(tmp);
+                       goto out;
+               }
+
+               if (!(callee_features = ast_malloc(sizeof(*callee_features)))) {
+                       ast_log(LOG_WARNING, "Unable to allocate memory for feature flags. Aborting!\n");
+                       ast_free(tmp);
+                       goto out;
+               }
+
+               ast_copy_flags(&(callee_features->features_callee), &(config.features_callee), AST_FLAGS_ALL);
+               callee_features->is_caller = 0;
+               set_dial_features(&opts, callee_features);
+
+               ds_callee_features->inheritance = DATASTORE_INHERIT_FOREVER;
+               ds_callee_features->data = callee_features;
+
+               ast_channel_lock(chan);
+               ast_channel_datastore_add(tc, ds_callee_features);
+               ast_channel_unlock(chan);
+
                res = ast_call(tc, numsubst, 0); /* Place the call, but don't wait on the answer */
 
                /* Save the info in cdr's that we called them */
index 6d9aaa7..7c66d47 100644 (file)
@@ -461,8 +461,16 @@ int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags
  */
 int ast_app_parse_options64(const struct ast_app_option *options, struct ast_flags64 *flags, char **args, char *optstr);
 
-/*! \brief Present a dialtone and collect a certain length extension. 
-    \return Returns 1 on valid extension entered, -1 on hangup, or 0 on invalid extension. 
+/*! \brief Given a list of options array, return an option string based on passed flags
+       \param options The array of possible options declared with AST_APP_OPTIONS
+       \param flags The flags of the options that you wish to populate the buffer with
+       \param buf The buffer to fill with the string of options
+       \param len The maximum length of buf
+*/
+void ast_app_options2str64(const struct ast_app_option *options, struct ast_flags64 *flags, char *buf, size_t len);
+
+/*! \brief Present a dialtone and collect a certain length extension.
+    \return Returns 1 on valid extension entered, -1 on hangup, or 0 on invalid extension.
 \note Note that if 'collect' holds digits already, new digits will be appended, so be sure it's initialized properly */
 int ast_app_dtget(struct ast_channel *chan, const char *context, char *collect, size_t size, int maxlen, int timeout);
 
index 72edaba..510034b 100644 (file)
 
 #include "asterisk/channel.h"
 
+#define MAX_DIAL_FEATURE_OPTIONS 30
+
 extern const struct ast_datastore_info dialed_interface_info;
 
+extern const struct ast_datastore_info dial_features_info;
+
 struct ast_dialed_interface {
        AST_LIST_ENTRY(ast_dialed_interface) list;
        char interface[1];
 };
 
+struct ast_dial_features {
+       struct ast_flags features_caller;
+       struct ast_flags features_callee;
+       char options[MAX_DIAL_FEATURE_OPTIONS];
+       int is_caller;
+};
+
 #endif
index 99eaec3..6e09059 100644 (file)
@@ -1670,6 +1670,17 @@ int ast_app_parse_options64(const struct ast_app_option *options, struct ast_fla
        return res;
 }
 
+void ast_app_options2str64(const struct ast_app_option *options, struct ast_flags64 *flags, char *buf, size_t len)
+{
+       unsigned int i, found = 0;
+       for (i = 32; i < 128 && found < len; i++) {
+               if (ast_test_flag64(flags, options[i].flag)) {
+                       buf[found++] = i;
+               }
+       }
+       buf[found] = '\0';
+}
+
 int ast_get_encoded_char(const char *stream, char *result, size_t *consumed)
 {
        int i;
index 7779c06..69aae8c 100644 (file)
@@ -53,6 +53,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/devicestate.h"
 #include "asterisk/monitor.h"
 #include "asterisk/audiohook.h"
+#include "asterisk/global_datastores.h"
 
 #define DEFAULT_PARK_TIME 45000
 #define DEFAULT_TRANSFER_DIGIT_TIMEOUT 3000
@@ -2232,10 +2233,24 @@ static void *do_parking_thread(void *ignore)
                                        }
                                        if (con) {
                                                char returnexten[AST_MAX_EXTENSION];
-                                               snprintf(returnexten, sizeof(returnexten), "%s,,t", peername);
+                                               struct ast_datastore *features_datastore;
+                                               struct ast_dial_features *dialfeatures = NULL;
+
+                                               ast_channel_lock(chan);
+
+                                               if ((features_datastore = ast_channel_datastore_find(chan, &dial_features_info, NULL)))
+                                                       dialfeatures = features_datastore->data;
+
+                                               ast_channel_unlock(chan);
+
+                                               if (dialfeatures)
+                                                       snprintf(returnexten, sizeof(returnexten), "%s,,%s", peername, dialfeatures->options);
+                                               else /* Existing default */
+                                                       snprintf(returnexten, sizeof(returnexten), "%s,,t", peername);
+
                                                ast_add_extension2(con, 1, peername_flat, 1, NULL, NULL, "Dial", ast_strdup(returnexten), ast_free_ptr, registrar);
                                        }
-                                       if (comebacktoorigin) { 
+                                       if (comebacktoorigin) {
                                                set_c_e_p(chan, parking_con_dial, peername_flat, 1);
                                        } else {
                                                ast_log(LOG_WARNING, "now going to parkedcallstimeout,s,1 | ps is %d\n",pu->parkingnum);
index 9b87b2c..ca04a0f 100644 (file)
@@ -35,8 +35,9 @@ static void dialed_interface_destroy(void *data)
        struct ast_dialed_interface *di = NULL;
        AST_LIST_HEAD(, ast_dialed_interface) *dialed_interface_list = data;
        
-       if (!dialed_interface_list)
+       if (!dialed_interface_list) {
                return;
+       }
 
        AST_LIST_LOCK(dialed_interface_list);
        while ((di = AST_LIST_REMOVE_HEAD(dialed_interface_list, list)))
@@ -53,11 +54,13 @@ static void *dialed_interface_duplicate(void *data)
        AST_LIST_HEAD(, ast_dialed_interface) *old_list;
        AST_LIST_HEAD(, ast_dialed_interface) *new_list = NULL;
 
-       if(!(old_list = data))
+       if(!(old_list = data)) {
                return NULL;
+       }
 
-       if(!(new_list = ast_calloc(1, sizeof(*new_list))))
+       if(!(new_list = ast_calloc(1, sizeof(*new_list)))) {
                return NULL;
+       }
 
        AST_LIST_HEAD_INIT(new_list);
        AST_LIST_LOCK(old_list);
@@ -76,8 +79,35 @@ static void *dialed_interface_duplicate(void *data)
        return new_list;
 }
 
+
+static void *dial_features_duplicate(void *data)
+{
+       struct ast_dial_features *df = data, *df_copy;
+
+       if (!(df_copy = ast_calloc(1, sizeof(*df)))) {
+               return NULL;
+       }
+
+       memcpy(df_copy, df, sizeof(*df));
+
+       return df_copy;
+}
+
+static void dial_features_destroy(void *data) {
+       struct ast_dial_features *df = data;
+       if (df) {
+               ast_free(df);
+       }
+}
+
 const struct ast_datastore_info dialed_interface_info = {
-       .type ="dialed-interface",
+       .type = "dialed-interface",
        .destroy = dialed_interface_destroy,
        .duplicate = dialed_interface_duplicate,
 };
+
+const struct ast_datastore_info dial_features_info = {
+       .type = "dial-features",
+       .destroy = dial_features_destroy,
+       .duplicate = dial_features_duplicate,
+};