summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
Diffstat (limited to 'main')
-rw-r--r--main/channel.c8
-rw-r--r--main/manager.c14
-rw-r--r--main/pbx.c20
3 files changed, 35 insertions, 7 deletions
diff --git a/main/channel.c b/main/channel.c
index f7e9d631a..d5f1d31c1 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -5620,8 +5620,14 @@ struct ast_channel *__ast_request_and_dial(const char *type, struct ast_format_c
ast_channel_hangupcause_hash_set(chan, f->data.ptr, f->datalen);
break;
- /* Ignore these */
case AST_CONTROL_PROGRESS:
+ if (oh && oh->connect_on_early_media) {
+ *outstate = f->subclass.integer;
+ timeout = 0; /* trick to force exit from the while() */
+ break;
+ }
+ /* Fallthrough */
+ /* Ignore these */
case AST_CONTROL_PROCEEDING:
case AST_CONTROL_HOLD:
case AST_CONTROL_UNHOLD:
diff --git a/main/manager.c b/main/manager.c
index 12aa851c7..e1bf19f68 100644
--- a/main/manager.c
+++ b/main/manager.c
@@ -465,6 +465,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
<parameter name="Account">
<para>Account code.</para>
</parameter>
+ <parameter name="EarlyMedia">
+ <para>Set to <literal>true</literal> to force call bridge on early media..</para>
+ </parameter>
<parameter name="Async">
<para>Set to <literal>true</literal> for fast origination.</para>
</parameter>
@@ -3915,6 +3918,7 @@ action_command_cleanup:
struct fast_originate_helper {
int timeout;
struct ast_format_cap *cap; /*!< Codecs used for a call */
+ int early_media;
AST_DECLARE_STRING_FIELDS (
AST_STRING_FIELD(tech);
/*! data can contain a channel name, extension number, username, password, etc. */
@@ -3966,7 +3970,7 @@ static void *fast_originate(void *data)
in->timeout, in->context, in->exten, in->priority, &reason, 1,
S_OR(in->cid_num, NULL),
S_OR(in->cid_name, NULL),
- in->vars, in->account, &chan);
+ in->vars, in->account, &chan, in->early_media);
}
/* Any vars memory was passed to the ast_pbx_outgoing_xxx() calls. */
in->vars = NULL;
@@ -4245,6 +4249,7 @@ static int action_originate(struct mansession *s, const struct message *m)
const char *async = astman_get_header(m, "Async");
const char *id = astman_get_header(m, "ActionID");
const char *codecs = astman_get_header(m, "Codecs");
+ const char *early_media = astman_get_header(m, "Earlymedia");
struct ast_variable *vars = NULL;
char *tech, *data;
char *l = NULL, *n = NULL;
@@ -4257,6 +4262,7 @@ static int action_originate(struct mansession *s, const struct message *m)
struct ast_format_cap *cap = ast_format_cap_alloc_nolock();
struct ast_format tmp_fmt;
pthread_t th;
+ int bridge_early = 0;
if (!cap) {
astman_send_error(s, m, "Internal Error. Memory allocation failure.");
@@ -4359,6 +4365,9 @@ static int action_originate(struct mansession *s, const struct message *m)
}
}
+ /* For originate async - we can bridge in early media stage */
+ bridge_early = ast_true(early_media);
+
if (ast_true(async)) {
struct fast_originate_helper *fast;
@@ -4384,6 +4393,7 @@ static int action_originate(struct mansession *s, const struct message *m)
fast->cap = cap;
cap = NULL; /* transfered originate helper the capabilities structure. It is now responsible for freeing it. */
fast->timeout = to;
+ fast->early_media = bridge_early;
fast->priority = pi;
if (ast_pthread_create_detached(&th, NULL, fast_originate, fast)) {
destroy_fast_originate_helper(fast);
@@ -4397,7 +4407,7 @@ static int action_originate(struct mansession *s, const struct message *m)
/* Any vars memory was passed to ast_pbx_outgoing_app(). */
} else {
if (exten && context && pi) {
- res = ast_pbx_outgoing_exten(tech, cap, data, to, context, exten, pi, &reason, 1, l, n, vars, account, NULL);
+ res = ast_pbx_outgoing_exten(tech, cap, data, to, context, exten, pi, &reason, 1, l, n, vars, account, NULL, bridge_early);
/* Any vars memory was passed to ast_pbx_outgoing_exten(). */
} else {
astman_send_error(s, m, "Originate with 'Exten' requires 'Context' and 'Priority'");
diff --git a/main/pbx.c b/main/pbx.c
index ef04d6644..3195da3bc 100644
--- a/main/pbx.c
+++ b/main/pbx.c
@@ -9559,6 +9559,7 @@ struct async_stat {
int timeout;
char app[AST_MAX_EXTENSION];
char appdata[1024];
+ int early_media; /* Connect the bridge if early media arrives, don't wait for answer */
};
static void *async_wait(void *data)
@@ -9569,6 +9570,7 @@ static void *async_wait(void *data)
int res;
struct ast_frame *f;
struct ast_app *app;
+ int have_early_media = 0;
if (chan) {
struct ast_callid *callid = ast_channel_callid(chan);
@@ -9593,10 +9595,18 @@ static void *async_wait(void *data)
ast_frfree(f);
break;
}
+ if (as->early_media && f->subclass.integer == AST_CONTROL_PROGRESS) {
+ have_early_media = 1;
+ ast_frfree(f);
+ break;
+ }
}
ast_frfree(f);
}
- if (ast_channel_state(chan) == AST_STATE_UP) {
+ if (ast_channel_state(chan) == AST_STATE_UP || have_early_media) {
+ if (have_early_media) {
+ ast_debug(2, "Activating pbx since we have early media \n");
+ }
if (!ast_strlen_zero(as->app)) {
app = pbx_findapp(as->app);
if (app) {
@@ -9657,7 +9667,7 @@ static int ast_pbx_outgoing_cdr_failed(void)
return 0; /* success */
}
-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 **channel)
+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 **channel, int early_media)
{
struct ast_channel *chan;
struct async_stat *as;
@@ -9666,6 +9676,8 @@ int ast_pbx_outgoing_exten(const char *type, struct ast_format_cap *cap, const c
int res = -1, cdr_res = -1;
struct outgoing_helper oh;
+ oh.connect_on_early_media = early_media;
+
callid_created = ast_callid_threadstorage_auto(&callid);
if (synchronous) {
@@ -9695,9 +9707,9 @@ int ast_pbx_outgoing_exten(const char *type, struct ast_format_cap *cap, const c
}
}
- if (ast_channel_state(chan) == AST_STATE_UP) {
+ if (ast_channel_state(chan) == AST_STATE_UP || (early_media && *reason == AST_CONTROL_PROGRESS)) {
res = 0;
- ast_verb(4, "Channel %s was answered.\n", ast_channel_name(chan));
+ ast_verb(4, "Channel %s %s\n", ast_channel_name(chan), ast_channel_state(chan) == AST_STATE_UP ? "was answered" : "got early media");
if (synchronous > 1) {
if (channel)