Backport fix for 11520--for some reason I didn't do this back in February when I patched for trunk.

git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@121992 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Terry Wilson
2008-06-11 23:47:23 +00:00
parent 1c7d9e4c9a
commit c340004d76
6 changed files with 146 additions and 7 deletions

View File

@@ -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);

View File

@@ -411,6 +411,14 @@ struct ast_app_option {
*/
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr);
/*! \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 */

View File

@@ -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

View File

@@ -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;

View 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",
.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,
};

View File

@@ -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];
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);