diff options
-rw-r--r-- | apps/app_dial.c | 26 | ||||
-rw-r--r-- | apps/app_originate.c | 8 | ||||
-rw-r--r-- | channels/chan_pjsip.c | 57 | ||||
-rw-r--r-- | channels/chan_sip.c | 4 | ||||
-rw-r--r-- | funcs/func_periodic_hook.c | 4 | ||||
-rw-r--r-- | include/asterisk/pbx.h | 29 | ||||
-rw-r--r-- | main/channel.c | 21 | ||||
-rw-r--r-- | main/manager.c | 15 | ||||
-rw-r--r-- | main/pbx.c | 2 | ||||
-rw-r--r-- | main/rtp_engine.c | 14 | ||||
-rw-r--r-- | pbx/pbx_spool.c | 10 | ||||
-rw-r--r-- | res/res_clioriginate.c | 8 |
12 files changed, 131 insertions, 67 deletions
diff --git a/apps/app_dial.c b/apps/app_dial.c index ba3f33252..250340579 100644 --- a/apps/app_dial.c +++ b/apps/app_dial.c @@ -2538,16 +2538,14 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast continue; } - ast_channel_lock(tc); - ast_channel_stage_snapshot(tc); - ast_channel_unlock(tc); - ast_channel_get_device_name(tc, device_name, sizeof(device_name)); if (!ignore_cc) { ast_cc_extension_monitor_add_dialstring(chan, tmp->interface, device_name); } ast_channel_lock_both(tc, chan); + ast_channel_stage_snapshot(tc); + pbx_builtin_setvar_helper(tc, "DIALEDPEERNUMBER", tmp->number); /* Setup outgoing SDP to match incoming one */ @@ -2563,7 +2561,6 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast ast_channel_appl_set(tc, "AppDial"); ast_channel_data_set(tc, "(Outgoing Line)"); - ast_channel_publish_snapshot(tc); memset(ast_channel_whentohangup(tc), 0, sizeof(*ast_channel_whentohangup(tc))); @@ -2788,15 +2785,14 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast } } else { const char *number; + const char *name; int dial_end_raised = 0; int cause = -1; - if (ast_test_flag64(&opts, OPT_CALLER_ANSWER)) + if (ast_test_flag64(&opts, OPT_CALLER_ANSWER)) { ast_answer(chan); + } - strcpy(pa.status, "ANSWER"); - ast_channel_stage_snapshot(chan); - pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status); /* Ah ha! Someone answered within the desired timeframe. Of course after this we will always return with -1 so that it is hung up properly after the conversation. */ @@ -2818,10 +2814,10 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast hanguptree(&out_chans, peer, cause >= 0 ? cause : AST_CAUSE_ANSWERED_ELSEWHERE); /* If appropriate, log that we have a destination channel and set the answer time */ - if (ast_channel_name(peer)) - pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", ast_channel_name(peer)); ast_channel_lock(peer); + name = ast_strdupa(ast_channel_name(peer)); + number = pbx_builtin_getvar_helper(peer, "DIALEDPEERNUMBER"); if (ast_strlen_zero(number)) { number = NULL; @@ -2829,8 +2825,16 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast number = ast_strdupa(number); } ast_channel_unlock(peer); + ast_channel_lock(chan); + ast_channel_stage_snapshot(chan); + + strcpy(pa.status, "ANSWER"); + pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status); + + pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", name); pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", number); + ast_channel_stage_snapshot_done(chan); ast_channel_unlock(chan); diff --git a/apps/app_originate.c b/apps/app_originate.c index 15898b240..eb4d63432 100644 --- a/apps/app_originate.c +++ b/apps/app_originate.c @@ -178,15 +178,15 @@ static int originate_exec(struct ast_channel *chan, const char *data) chantech, chandata, args.arg1, exten, priority); ast_pbx_outgoing_exten(chantech, cap_slin, chandata, - timeout * 1000, args.arg1, exten, priority, &outgoing_status, 1, NULL, - NULL, NULL, NULL, NULL, 0, NULL); + timeout * 1000, args.arg1, exten, priority, &outgoing_status, + AST_OUTGOING_WAIT, NULL, NULL, NULL, NULL, NULL, 0, NULL); } 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, - timeout * 1000, args.arg1, args.arg2, &outgoing_status, 1, NULL, - NULL, NULL, NULL, NULL, NULL); + timeout * 1000, args.arg1, args.arg2, &outgoing_status, + AST_OUTGOING_WAIT, NULL, NULL, NULL, NULL, NULL, NULL); } else { ast_log(LOG_ERROR, "Incorrect type, it should be 'exten' or 'app': %s\n", args.type); diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c index 6e3d087a4..8a1921c82 100644 --- a/channels/chan_pjsip.c +++ b/channels/chan_pjsip.c @@ -2078,22 +2078,53 @@ static int request(void *obj) AST_NONSTANDARD_APP_ARGS(args, tmp, '/'); - /* If a request user has been specified extract it from the endpoint name portion */ - if ((endpoint_name = strchr(args.endpoint, '@'))) { - request_user = args.endpoint; - *endpoint_name++ = '\0'; + if (ast_sip_get_disable_multi_domain()) { + /* If a request user has been specified extract it from the endpoint name portion */ + if ((endpoint_name = strchr(args.endpoint, '@'))) { + request_user = args.endpoint; + *endpoint_name++ = '\0'; + } else { + endpoint_name = args.endpoint; + } + + if (ast_strlen_zero(endpoint_name)) { + ast_log(LOG_ERROR, "Unable to create PJSIP channel with empty endpoint name\n"); + req_data->cause = AST_CAUSE_CHANNEL_UNACCEPTABLE; + return -1; + } else if (!(endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", endpoint_name))) { + ast_log(LOG_ERROR, "Unable to create PJSIP channel - endpoint '%s' was not found\n", endpoint_name); + req_data->cause = AST_CAUSE_NO_ROUTE_DESTINATION; + return -1; + } } else { + /* First try to find an exact endpoint match, for single (user) or multi-domain (user@domain) */ endpoint_name = args.endpoint; - } + if (ast_strlen_zero(endpoint_name)) { + ast_log(LOG_ERROR, "Unable to create PJSIP channel with empty endpoint name\n"); + req_data->cause = AST_CAUSE_CHANNEL_UNACCEPTABLE; + return -1; + } else if (!(endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", endpoint_name))) { + /* It seems it's not a multi-domain endpoint or single endpoint exact match, + * it's possible that it's a SIP trunk with a specified user (user@trunkname), + * so extract the user before @ sign. + */ + if ((endpoint_name = strchr(args.endpoint, '@'))) { + request_user = args.endpoint; + *endpoint_name++ = '\0'; + } - if (ast_strlen_zero(endpoint_name)) { - ast_log(LOG_ERROR, "Unable to create PJSIP channel with empty endpoint name\n"); - req_data->cause = AST_CAUSE_CHANNEL_UNACCEPTABLE; - return -1; - } else if (!(endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", endpoint_name))) { - ast_log(LOG_ERROR, "Unable to create PJSIP channel - endpoint '%s' was not found\n", endpoint_name); - req_data->cause = AST_CAUSE_NO_ROUTE_DESTINATION; - return -1; + if (ast_strlen_zero(endpoint_name)) { + ast_log(LOG_ERROR, "Unable to create PJSIP channel with empty endpoint name\n"); + req_data->cause = AST_CAUSE_CHANNEL_UNACCEPTABLE; + return -1; + } + + if (!(endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", endpoint_name))) { + ast_log(LOG_ERROR, "Unable to create PJSIP channel - endpoint '%s' was not found\n", endpoint_name); + req_data->cause = AST_CAUSE_NO_ROUTE_DESTINATION; + return -1; + } + } } if (!(session = ast_sip_session_create_outgoing(endpoint, NULL, args.aor, request_user, req_data->caps))) { diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 83f72b9ad..15a3b2584 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -8143,7 +8143,9 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit if (!fmt) { ast_log(LOG_WARNING, "No compatible formats could be found for %s\n", ast_channel_name(tmp)); ao2_ref(caps, -1); - tmp = ast_channel_unref(tmp); + ast_channel_stage_snapshot_done(tmp); + ast_channel_unlock(tmp); + ast_hangup(tmp); return NULL; } } diff --git a/funcs/func_periodic_hook.c b/funcs/func_periodic_hook.c index cb019b41e..f459e3576 100644 --- a/funcs/func_periodic_hook.c +++ b/funcs/func_periodic_hook.c @@ -183,8 +183,8 @@ static void *hook_launch_thread(void *data) }; ast_pbx_outgoing_exten("Local", NULL, full_exten_name, 60, - arg->context, arg->exten, 1, NULL, 0, NULL, NULL, &chan_name_var, - NULL, NULL, 1, NULL); + arg->context, arg->exten, 1, NULL, AST_OUTGOING_NO_WAIT, + NULL, NULL, &chan_name_var, NULL, NULL, 1, NULL); hook_thread_arg_destroy(arg); diff --git a/include/asterisk/pbx.h b/include/asterisk/pbx.h index 1fc8df8c9..770a1a984 100644 --- a/include/asterisk/pbx.h +++ b/include/asterisk/pbx.h @@ -1130,6 +1130,12 @@ int ast_async_goto(struct ast_channel *chan, const char *context, const char *ex */ int ast_async_goto_by_name(const char *chan, const char *context, const char *exten, int priority); +enum ast_pbx_outgoing_sync { + AST_OUTGOING_NO_WAIT = 0, /*!< Don't wait for originated call to answer */ + AST_OUTGOING_WAIT = 1, /*!< Wait for originated call to answer */ + AST_OUTGOING_WAIT_COMPLETE = 2, /*!< Wait for originated call to answer and hangup */ +}; + /*! * \brief Synchronously or asynchronously make an outbound call and send it to a * particular extension @@ -1143,11 +1149,15 @@ int ast_async_goto_by_name(const char *chan, const char *context, const char *ex * \param priority The destination priority for the outbound channel * \param reason Optional. If provided, the dialed status of the outgoing channel. * Codes are AST_CONTROL_xxx values. Valid only if synchronous is non-zero. - * \param synchronous If zero then don't wait for anything. - * If one then block until the outbound channel answers or the call fails. - * If greater than one then wait for the call to complete or if the call doesn't - * answer and failed@context exists then run a channel named OutgoingSpoolFailed - * at failed@context. + * \param synchronous defined by the ast_pbx_outgoing_sync enum. + * If \c AST_OUTGOING_NO_WAIT then don't wait for anything. + * If \c AST_OUTGOING_WAIT then block until the outbound channel answers or + * the call fails. + * If \c AST_OUTGOING_WAIT_COMPLETE then wait for the call to complete or + * fail. + * If \c AST_OUTGOING_WAIT or \c AST_OUTGOING_WAIT_COMPLETE is specified, + * the call doesn't answer, and \c failed@context exists then run a channel + * named \c OutgoingSpoolFailed at \c failed@context. * \param cid_num The caller ID number to set on the outbound channel * \param cid_name The caller ID name to set on the outbound channel * \param vars Variables to set on the outbound channel @@ -1181,9 +1191,12 @@ int ast_pbx_outgoing_exten(const char *type, struct ast_format_cap *cap, const c * \param appdata Data to pass to the application * \param reason Optional. If provided, the dialed status of the outgoing channel. * Codes are AST_CONTROL_xxx values. Valid only if synchronous is non-zero. - * \param synchronous If zero then don't wait for anything. - * If one then block until the outbound channel answers or the call fails. - * If greater than one then wait for the call to complete. + * \param synchronous defined by the ast_pbx_outgoing_sync enum. + * If \c AST_OUTGOING_NO_WAIT then don't wait for anything. + * If \c AST_OUTGOING_WAIT then block until the outbound channel answers or + * the call fails. + * If \c AST_OUTGOING_WAIT_COMPLETE then wait for the call to complete or + * fail. * \param cid_num The caller ID number to set on the outbound channel * \param cid_name The caller ID name to set on the outbound channel * \param vars Variables to set on the outbound channel diff --git a/main/channel.c b/main/channel.c index 28cfa79df..3d51651fd 100644 --- a/main/channel.c +++ b/main/channel.c @@ -820,7 +820,12 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char ast_channel_stage_snapshot(tmp); if (!(nativeformats = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) { - /* format capabilities structure allocation failure */ + /* + * Aborting the channel creation. We do not need to complete staging + * the channel snapshot because the channel has not been finalized or + * linked into the channels container yet. Nobody else knows about + * this channel nor will anybody ever know about it. + */ return ast_channel_unref(tmp); } ast_format_cap_append(nativeformats, ast_format_none, 0); @@ -846,6 +851,7 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char if (!(schedctx = ast_sched_context_create())) { ast_log(LOG_WARNING, "Channel allocation failed: Unable to create schedule context\n"); + /* See earlier channel creation abort comment above. */ return ast_channel_unref(tmp); } ast_channel_sched_set(tmp, schedctx); @@ -860,6 +866,7 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char ast_channel_caller(tmp)->id.name.valid = 1; ast_channel_caller(tmp)->id.name.str = ast_strdup(cid_name); if (!ast_channel_caller(tmp)->id.name.str) { + /* See earlier channel creation abort comment above. */ return ast_channel_unref(tmp); } } @@ -867,6 +874,7 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char ast_channel_caller(tmp)->id.number.valid = 1; ast_channel_caller(tmp)->id.number.str = ast_strdup(cid_num); if (!ast_channel_caller(tmp)->id.number.str) { + /* See earlier channel creation abort comment above. */ return ast_channel_unref(tmp); } } @@ -880,6 +888,7 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char } if (needqueue && ast_channel_internal_alertpipe_init(tmp)) { + /* See earlier channel creation abort comment above. */ return ast_channel_unref(tmp); } @@ -971,20 +980,14 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char if (assignedids && (does_id_conflict(assignedids->uniqueid) || does_id_conflict(assignedids->uniqueid2))) { ast_channel_internal_errno_set(AST_CHANNEL_ERROR_ID_EXISTS); ao2_unlock(channels); - /* This is a bit unorthodox, but we can't just call ast_channel_stage_snapshot_done() - * because that will result in attempting to publish the channel snapshot. That causes - * badness in some places, such as CDRs. So we need to manually clear the flag on the - * channel that says that a snapshot is being cleared. - */ - ast_clear_flag(ast_channel_flags(tmp), AST_FLAG_SNAPSHOT_STAGE); ast_channel_unlock(tmp); + /* See earlier channel creation abort comment above. */ return ast_channel_unref(tmp); } + /* Finalize and link into the channels container. */ ast_channel_internal_finalize(tmp); - ast_atomic_fetchadd_int(&chancount, +1); - ao2_link_flags(channels, tmp, OBJ_NOLOCK); ao2_unlock(channels); diff --git a/main/manager.c b/main/manager.c index 251085a81..00e8420c3 100644 --- a/main/manager.c +++ b/main/manager.c @@ -5096,13 +5096,15 @@ static void *fast_originate(void *data) if (!ast_strlen_zero(in->app)) { res = ast_pbx_outgoing_app(in->tech, in->cap, in->data, - in->timeout, in->app, in->appdata, &reason, 1, + in->timeout, in->app, in->appdata, &reason, + AST_OUTGOING_WAIT, S_OR(in->cid_num, NULL), S_OR(in->cid_name, NULL), in->vars, in->account, &chan, &assignedids); } else { res = ast_pbx_outgoing_exten(in->tech, in->cap, in->data, - in->timeout, in->context, in->exten, in->priority, &reason, 1, + in->timeout, in->context, in->exten, in->priority, &reason, + AST_OUTGOING_WAIT, S_OR(in->cid_num, NULL), S_OR(in->cid_name, NULL), in->vars, in->account, &chan, in->early_media, &assignedids); @@ -5573,11 +5575,16 @@ static int action_originate(struct mansession *s, const struct message *m) } } } else if (!ast_strlen_zero(app)) { - res = ast_pbx_outgoing_app(tech, cap, data, to, app, appdata, &reason, 1, l, n, vars, account, NULL, assignedids.uniqueid ? &assignedids : NULL); + res = ast_pbx_outgoing_app(tech, cap, data, to, app, appdata, &reason, + AST_OUTGOING_WAIT, l, n, vars, account, NULL, + assignedids.uniqueid ? &assignedids : NULL); ast_variables_destroy(vars); } else { if (exten && context && pi) { - res = ast_pbx_outgoing_exten(tech, cap, data, to, context, exten, pi, &reason, 1, l, n, vars, account, NULL, bridge_early, assignedids.uniqueid ? &assignedids : NULL); + res = ast_pbx_outgoing_exten(tech, cap, data, to, + context, exten, pi, &reason, AST_OUTGOING_WAIT, + l, n, vars, account, NULL, bridge_early, + assignedids.uniqueid ? &assignedids : NULL); ast_variables_destroy(vars); } else { astman_send_error(s, m, "Originate with 'Exten' requires 'Context' and 'Priority'"); diff --git a/main/pbx.c b/main/pbx.c index 5002999b4..5ac97aad4 100644 --- a/main/pbx.c +++ b/main/pbx.c @@ -7768,7 +7768,7 @@ int ast_pbx_outgoing_exten(const char *type, struct ast_format_cap *cap, const c early_media, assignedids); if (res < 0 /* Call failed to get connected for some reason. */ - && 1 < synchronous + && 0 < synchronous && ast_exists_extension(NULL, context, "failed", 1, NULL)) { struct ast_channel *failed; diff --git a/main/rtp_engine.c b/main/rtp_engine.c index 5c7b7a07b..0f09e2f8a 100644 --- a/main/rtp_engine.c +++ b/main/rtp_engine.c @@ -1394,16 +1394,16 @@ void ast_rtp_instance_set_stats_vars(struct ast_channel *chan, struct ast_rtp_in { char quality_buf[AST_MAX_USER_FIELD]; char *quality; - struct ast_channel *bridge = ast_channel_bridge_peer(chan); + struct ast_channel *bridge; - ast_channel_lock(chan); - ast_channel_stage_snapshot(chan); - ast_channel_unlock(chan); + bridge = ast_channel_bridge_peer(chan); if (bridge) { - ast_channel_lock(bridge); + ast_channel_lock_both(chan, bridge); ast_channel_stage_snapshot(bridge); - ast_channel_unlock(bridge); + } else { + ast_channel_lock(chan); } + ast_channel_stage_snapshot(chan); quality = ast_rtp_instance_get_quality(instance, AST_RTP_INSTANCE_STAT_FIELD_QUALITY, quality_buf, sizeof(quality_buf)); @@ -1441,11 +1441,9 @@ void ast_rtp_instance_set_stats_vars(struct ast_channel *chan, struct ast_rtp_in } } - ast_channel_lock(chan); ast_channel_stage_snapshot_done(chan); ast_channel_unlock(chan); if (bridge) { - ast_channel_lock(bridge); ast_channel_stage_snapshot_done(bridge); ast_channel_unlock(bridge); ast_channel_unref(bridge); diff --git a/pbx/pbx_spool.c b/pbx/pbx_spool.c index 4228be9b0..444f74d8b 100644 --- a/pbx/pbx_spool.c +++ b/pbx/pbx_spool.c @@ -399,15 +399,17 @@ static void *attempt_thread(void *data) int res, reason; if (!ast_strlen_zero(o->app)) { ast_verb(3, "Attempting call on %s/%s for application %s(%s) (Retry %d)\n", o->tech, o->dest, o->app, o->data, o->retries); - res = ast_pbx_outgoing_app(o->tech, o->capabilities, o->dest, o->waittime * 1000, - o->app, o->data, &reason, 2 /* wait to finish */, o->cid_num, o->cid_name, + res = ast_pbx_outgoing_app(o->tech, o->capabilities, o->dest, + o->waittime * 1000, o->app, o->data, &reason, + AST_OUTGOING_WAIT_COMPLETE, o->cid_num, o->cid_name, o->vars, o->account, NULL, NULL); } else { ast_verb(3, "Attempting call on %s/%s for %s@%s:%d (Retry %d)\n", o->tech, o->dest, o->exten, o->context,o->priority, o->retries); res = ast_pbx_outgoing_exten(o->tech, o->capabilities, o->dest, o->waittime * 1000, o->context, o->exten, o->priority, &reason, - 2 /* wait to finish */, o->cid_num, o->cid_name, o->vars, o->account, NULL, - ast_test_flag(&o->options, SPOOL_FLAG_EARLY_MEDIA), NULL); + AST_OUTGOING_WAIT_COMPLETE, o->cid_num, o->cid_name, + o->vars, o->account, NULL, ast_test_flag(&o->options, SPOOL_FLAG_EARLY_MEDIA), + NULL); } if (res) { ast_log(LOG_NOTICE, "Call failed to go through, reason (%d) %s\n", reason, ast_channel_reason2str(reason)); diff --git a/res/res_clioriginate.c b/res/res_clioriginate.c index 3903b6c3b..4303711f1 100644 --- a/res/res_clioriginate.c +++ b/res/res_clioriginate.c @@ -74,7 +74,9 @@ static char *orig_app(int fd, const char *chan, const char *app, const char *app return CLI_FAILURE; } ast_format_cap_append(cap, ast_format_slin, 0); - ast_pbx_outgoing_app(chantech, cap, chandata, TIMEOUT * 1000, app, appdata, &reason, 0, NULL, NULL, NULL, NULL, NULL, NULL); + ast_pbx_outgoing_app(chantech, cap, chandata, TIMEOUT * 1000, app, appdata, + &reason, AST_OUTGOING_NO_WAIT, NULL, NULL, NULL, NULL, + NULL, NULL); ao2_ref(cap, -1); return CLI_SUCCESS; @@ -118,7 +120,9 @@ static char *orig_exten(int fd, const char *chan, const char *data) return CLI_FAILURE; } ast_format_cap_append(cap, ast_format_slin, 0); - ast_pbx_outgoing_exten(chantech, cap, chandata, TIMEOUT * 1000, context, exten, 1, &reason, 0, NULL, NULL, NULL, NULL, NULL, 0, NULL); + ast_pbx_outgoing_exten(chantech, cap, chandata, TIMEOUT * 1000, context, + exten, 1, &reason, AST_OUTGOING_NO_WAIT, NULL, NULL, + NULL, NULL, NULL, 0, NULL); ao2_ref(cap, -1); return CLI_SUCCESS; |