diff -Naur asterisk-13.12.2-orig/apps/app_originate.c asterisk-13.12.2/apps/app_originate.c
--- asterisk-13.12.2-orig/apps/app_originate.c 2016-11-10 14:34:55.000000000 -0500
+++ asterisk-13.12.2/apps/app_originate.c 2016-11-14 21:27:36.238248133 -0500
@@ -74,6 +74,30 @@
Timeout in seconds. Default is 30 seconds.
+
+
+
+
+
+
This application originates an outbound call and connects it to a specified extension or application. This application will block until the outgoing call fails or gets answered. At that point, this application will exit with the status variable set and dialplan processing will continue.
@@ -97,6 +121,25 @@
***/
+
+enum {
+ OPT_PREDIAL_CALLEE = (1 << 0),
+ OPT_PREDIAL_CALLER = (1 << 1),
+};
+
+enum {
+ OPT_ARG_PREDIAL_CALLEE,
+ OPT_ARG_PREDIAL_CALLER,
+ /* note: this entry _MUST_ be the last one in the enum */
+ OPT_ARG_ARRAY_SIZE,
+};
+
+AST_APP_OPTIONS(originate_exec_options, BEGIN_OPTIONS
+ AST_APP_OPTION_ARG('b', OPT_PREDIAL_CALLEE, OPT_ARG_PREDIAL_CALLEE),
+ AST_APP_OPTION_ARG('B', OPT_PREDIAL_CALLER, OPT_ARG_PREDIAL_CALLER),
+END_OPTIONS );
+
+
static int originate_exec(struct ast_channel *chan, const char *data)
{
AST_DECLARE_APP_ARGS(args,
@@ -106,7 +149,11 @@
AST_APP_ARG(arg2);
AST_APP_ARG(arg3);
AST_APP_ARG(timeout);
+ AST_APP_ARG(options);
);
+ struct ast_flags64 opts = { 0, };
+ char *opt_args[OPT_ARG_ARRAY_SIZE];
+ char *predial_callee = NULL;
char *parse;
char *chantech, *chandata;
int res = -1;
@@ -159,6 +206,27 @@
goto return_cleanup;
}
+ if (!ast_strlen_zero(args.options) &&
+ ast_app_parse_options64(originate_exec_options, &opts, opt_args, args.options)) {
+ ast_log(LOG_ERROR, "Invalid options: '%s'\n", args.options);
+ goto return_cleanup;
+ }
+
+ /* PREDIAL: Run gosub on the caller's channel */
+ if (ast_test_flag64(&opts, OPT_PREDIAL_CALLER)
+ && !ast_strlen_zero(opt_args[OPT_ARG_PREDIAL_CALLER])) {
+ ast_replace_subargument_delimiter(opt_args[OPT_ARG_PREDIAL_CALLER]);
+ ast_debug(1, "Predial caller '%s' \n",opt_args[OPT_ARG_PREDIAL_CALLER]);
+ ast_app_exec_sub(NULL, chan, opt_args[OPT_ARG_PREDIAL_CALLER], 0);
+ }
+
+ if (ast_test_flag64(&opts, OPT_PREDIAL_CALLEE)
+ && !ast_strlen_zero(opt_args[OPT_ARG_PREDIAL_CALLEE])) {
+ ast_replace_subargument_delimiter(opt_args[OPT_ARG_PREDIAL_CALLEE]);
+ predial_callee = opt_args[OPT_ARG_PREDIAL_CALLEE];
+ ast_debug(1, "Predial callee '%s'\n",predial_callee);
+ }
+
if (!strcasecmp(args.type, "exten")) {
int priority = 1; /* Initialized in case priority not specified */
const char *exten = args.arg2;
@@ -177,16 +245,16 @@
ast_debug(1, "Originating call to '%s/%s' and connecting them to extension %s,%s,%d\n",
chantech, chandata, args.arg1, exten, priority);
- ast_pbx_outgoing_exten(chantech, cap_slin, chandata,
+ __ast_pbx_outgoing_exten(chantech, cap_slin, chandata,
timeout * 1000, args.arg1, exten, priority, &outgoing_status, 1, NULL,
- NULL, NULL, NULL, NULL, 0, NULL);
+ NULL, NULL, NULL, NULL, 0, NULL, predial_callee);
} else if (!strcasecmp(args.type, "app")) {
ast_debug(1, "Originating call to '%s/%s' and connecting them to %s(%s)\n",
chantech, chandata, args.arg1, S_OR(args.arg2, ""));
- ast_pbx_outgoing_app(chantech, cap_slin, chandata,
+ __ast_pbx_outgoing_app(chantech, cap_slin, chandata,
timeout * 1000, args.arg1, args.arg2, &outgoing_status, 1, NULL,
- NULL, NULL, NULL, NULL, NULL);
+ NULL, NULL, NULL, NULL, NULL, predial_callee);
} else {
ast_log(LOG_ERROR, "Incorrect type, it should be 'exten' or 'app': %s\n",
args.type);
diff -Naur asterisk-13.12.2-orig/include/asterisk/pbx.h asterisk-13.12.2/include/asterisk/pbx.h
--- asterisk-13.12.2-orig/include/asterisk/pbx.h 2016-11-10 14:34:55.000000000 -0500
+++ asterisk-13.12.2/include/asterisk/pbx.h 2016-11-14 15:24:08.609732634 -0500
@@ -1167,6 +1167,12 @@
const char *account, struct ast_channel **locked_channel, int early_media,
const struct ast_assigned_ids *assignedids);
+int __ast_pbx_outgoing_exten(const char *type, struct ast_format_cap *cap, const char *addr,
+ int timeout, const char *context, const char *exten, int priority, int *reason,
+ int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars,
+ const char *account, struct ast_channel **locked_channel, int early_media,
+ const struct ast_assigned_ids *assignedids, const char *predial_callee);
+
/*!
* \brief Synchronously or asynchronously make an outbound call and execute an
* application on the channel.
@@ -1202,6 +1208,12 @@
const char *account, struct ast_channel **locked_channel,
const struct ast_assigned_ids *assignedids);
+int __ast_pbx_outgoing_app(const char *type, struct ast_format_cap *cap, const char *addr,
+ int timeout, const char *app, const char *appdata, int *reason, int synchronous,
+ const char *cid_num, const char *cid_name, struct ast_variable *vars,
+ const char *account, struct ast_channel **locked_channel,
+ const struct ast_assigned_ids *assignedids, const char *predial_callee);
+
/*!
* \brief Evaluate a condition
*
diff -Naur asterisk-13.12.2-orig/main/pbx.c asterisk-13.12.2/main/pbx.c
--- asterisk-13.12.2-orig/main/pbx.c 2016-11-10 14:34:55.000000000 -0500
+++ asterisk-13.12.2/main/pbx.c 2016-11-14 23:39:06.912488641 -0500
@@ -7589,12 +7589,14 @@
const char *app, const char *appdata, int *reason, int synchronous,
const char *cid_num, const char *cid_name, struct ast_variable *vars,
const char *account, struct ast_channel **locked_channel, int early_media,
- const struct ast_assigned_ids *assignedids)
+ const struct ast_assigned_ids *assignedids, const char *predial_callee)
{
RAII_VAR(struct pbx_outgoing *, outgoing, NULL, ao2_cleanup);
struct ast_channel *dialed;
pthread_t thread;
-
+ char tmp_cid_name[128];
+ char tmp_cid_num[128];
+
outgoing = ao2_alloc(sizeof(*outgoing), pbx_outgoing_destroy);
if (!outgoing) {
return -1;
@@ -7619,6 +7621,10 @@
}
ast_dial_set_global_timeout(outgoing->dial, timeout);
+
+ if (predial_callee) {
+ ast_dial_option_global_enable(outgoing->dial, AST_DIAL_OPTION_PREDIAL, (void *)predial_callee);
+ }
if (ast_dial_prerun(outgoing->dial, NULL, cap)) {
if (synchronous && reason) {
@@ -7644,6 +7650,24 @@
ast_channel_stage_snapshot_done(dialed);
}
ast_set_flag(ast_channel_flags(dialed), AST_FLAG_ORIGINATED);
+
+ if (predial_callee) {
+ char *tmp = NULL;
+ /*
+ * The predial sub routine may have set callerid.
+ * If so then override whatever passed into this function
+ */
+ tmp = S_COR(ast_channel_caller(dialed)->id.number.valid, ast_channel_caller(dialed)->id.number.str, NULL);
+ if (tmp) {
+ ast_copy_string(tmp_cid_num, tmp, sizeof(tmp_cid_num));
+ cid_num = tmp_cid_num;
+ }
+ tmp = S_COR(ast_channel_caller(dialed)->id.name.valid, ast_channel_caller(dialed)->id.name.str, NULL);
+ if (tmp) {
+ ast_copy_string(tmp_cid_name, tmp, sizeof(tmp_cid_name));
+ cid_name = tmp_cid_name;
+ }
+ }
ast_channel_unlock(dialed);
if (!ast_strlen_zero(cid_num) || !ast_strlen_zero(cid_name)) {
@@ -7752,6 +7776,16 @@
const char *account, struct ast_channel **locked_channel, int early_media,
const struct ast_assigned_ids *assignedids)
{
+ return __ast_pbx_outgoing_exten(type, cap, addr, timeout, context, exten, priority, reason,
+ synchronous, cid_num, cid_name, vars, account, locked_channel, early_media, assignedids, NULL);
+}
+
+int __ast_pbx_outgoing_exten(const char *type, struct ast_format_cap *cap, const char *addr,
+ int timeout, const char *context, const char *exten, int priority, int *reason,
+ int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars,
+ const char *account, struct ast_channel **locked_channel, int early_media,
+ const struct ast_assigned_ids *assignedids, const char *predial_callee)
+{
int res;
int my_reason;
@@ -7765,7 +7799,7 @@
res = pbx_outgoing_attempt(type, cap, addr, timeout, context, exten, priority,
NULL, NULL, reason, synchronous, cid_num, cid_name, vars, account, locked_channel,
- early_media, assignedids);
+ early_media, assignedids, predial_callee);
if (res < 0 /* Call failed to get connected for some reason. */
&& 1 < synchronous
@@ -7806,6 +7840,16 @@
const char *account, struct ast_channel **locked_channel,
const struct ast_assigned_ids *assignedids)
{
+ return __ast_pbx_outgoing_app(type, cap, addr, timeout, app, appdata, reason, synchronous,
+ cid_num, cid_name, vars, account, locked_channel, assignedids, NULL);
+}
+
+int __ast_pbx_outgoing_app(const char *type, struct ast_format_cap *cap, const char *addr,
+ int timeout, const char *app, const char *appdata, int *reason, int synchronous,
+ const char *cid_num, const char *cid_name, struct ast_variable *vars,
+ const char *account, struct ast_channel **locked_channel,
+ const struct ast_assigned_ids *assignedids, const char *predial_callee)
+{
if (reason) {
*reason = 0;
}
@@ -7818,7 +7862,7 @@
return pbx_outgoing_attempt(type, cap, addr, timeout, NULL, NULL, 0, app, appdata,
reason, synchronous, cid_num, cid_name, vars, account, locked_channel, 0,
- assignedids);
+ assignedids, predial_callee);
}
/* this is the guts of destroying a context --