diff options
author | twilson <twilson@f38db490-d61c-443f-a65b-d21fe96a405b> | 2008-06-11 23:47:23 +0000 |
---|---|---|
committer | twilson <twilson@f38db490-d61c-443f-a65b-d21fe96a405b> | 2008-06-11 23:47:23 +0000 |
commit | 54034751542eb884cb134a826244eca9680765ea (patch) | |
tree | be1898af8b75b8f1bfe8692a851dcede310ecaa8 | |
parent | 02e87fc6524c2df91cfa8662689f3b33985e3eae (diff) |
Backport fix for 11520--for some reason I didn't do this back in February when I patched for trunk.
git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.4@121992 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r-- | apps/app_dial.c | 63 | ||||
-rw-r--r-- | include/asterisk/app.h | 12 | ||||
-rw-r--r-- | include/asterisk/global_datastores.h | 11 | ||||
-rw-r--r-- | main/app.c | 12 | ||||
-rw-r--r-- | main/global_datastores.c | 38 | ||||
-rw-r--r-- | res/res_features.c | 17 |
6 files changed, 146 insertions, 7 deletions
diff --git a/apps/app_dial.c b/apps/app_dial.c index d5e5fe8c9..bf98a3216 100644 --- a/apps/app_dial.c +++ b/apps/app_dial.c @@ -789,6 +789,19 @@ static int valid_priv_reply(struct ast_flags *opts, int res) return 0; } +static void set_dial_features(struct ast_flags *opts, struct ast_dial_features *features) +{ + struct ast_flags perm_opts = {.flags = 0}; + + ast_copy_flags(&perm_opts, opts, + OPT_CALLER_TRANSFER | OPT_CALLER_PARK | OPT_CALLER_MONITOR | OPT_CALLER_HANGUP | + OPT_CALLEE_TRANSFER | OPT_CALLEE_PARK | OPT_CALLEE_MONITOR | OPT_CALLEE_HANGUP); + + memset(features->options, 0, sizeof(features->options)); + + ast_app_options2str(dial_exec_options, &perm_opts, features->options, sizeof(features->options)); +} + static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags *peerflags, int *continue_exec) { int res = -1; @@ -831,6 +844,9 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags struct ast_flags 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)) { @@ -1086,6 +1102,28 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags } ast_copy_flags(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; + } + + 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, "&")) ) { @@ -1096,6 +1134,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) { @@ -1245,6 +1284,30 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags else ast_copy_string(tmp->chan->exten, chan->exten, sizeof(tmp->chan->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; + } + + 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(tmp->chan); + ast_channel_datastore_add(tmp->chan, ds_callee_features); + ast_channel_unlock(tmp->chan); + + /* Place the call, but don't wait on the answer */ res = ast_call(tmp->chan, numsubst, 0); diff --git a/include/asterisk/app.h b/include/asterisk/app.h index 7abff8e53..e23b3b477 100644 --- a/include/asterisk/app.h +++ b/include/asterisk/app.h @@ -411,8 +411,16 @@ struct ast_app_option { */ int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *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_options2str(const struct ast_app_option *options, struct ast_flags *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); diff --git a/include/asterisk/global_datastores.h b/include/asterisk/global_datastores.h index 72edabac5..510034b0d 100644 --- a/include/asterisk/global_datastores.h +++ b/include/asterisk/global_datastores.h @@ -26,11 +26,22 @@ #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 diff --git a/main/app.c b/main/app.c index ffad73507..33083649f 100644 --- a/main/app.c +++ b/main/app.c @@ -1387,6 +1387,18 @@ char *ast_read_textfile(const char *filename) return output; } +void ast_app_options2str(const struct ast_app_option *options, struct ast_flags *flags, char *buf, size_t len) +{ + unsigned int i, found = 0; + + for (i = 32; i < 128 && found < len;i++) { + if (ast_test_flag(flags, options[i].flag)) { + buf[found++] = i; + } + } + buf[found] = '\0'; +} + int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr) { char *s; diff --git a/main/global_datastores.c b/main/global_datastores.c index 9b87b2cb4..ca04a0fe9 100644 --- a/main/global_datastores.c +++ b/main/global_datastores.c @@ -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, +}; diff --git a/res/res_features.c b/res/res_features.c index 9c7fef79f..32f01ee2f 100644 --- a/res/res_features.c +++ b/res/res_features.c @@ -62,6 +62,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/adsi.h" #include "asterisk/devicestate.h" #include "asterisk/monitor.h" +#include "asterisk/global_datastores.h" #define DEFAULT_PARK_TIME 45000 #define DEFAULT_TRANSFER_DIGIT_TIMEOUT 3000 @@ -1711,7 +1712,21 @@ static void *do_parking_thread(void *ignore) } if (con) { char returnexten[AST_MAX_EXTENSION]; - snprintf(returnexten, sizeof(returnexten), "%s|30|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|30|%s", peername, dialfeatures->options); + else /* Existing default */ + snprintf(returnexten, sizeof(returnexten), "%s|30|t", peername); + ast_add_extension2(con, 1, peername, 1, NULL, NULL, "Dial", strdup(returnexten), ast_free, registrar); } set_c_e_p(chan, parking_con_dial, peername, 1); |