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