diff options
Diffstat (limited to 'main')
-rw-r--r-- | main/channel.c | 8 | ||||
-rw-r--r-- | main/manager.c | 14 | ||||
-rw-r--r-- | main/pbx.c | 20 |
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) |