diff --git a/apps/app_agent_pool.c b/apps/app_agent_pool.c index a6a68f1a39f65ed8d6fcbfd262ba38fd3f0e7e49..5095001cf6287ae797d3f12fd96c3142e9e4d243 100644 --- a/apps/app_agent_pool.c +++ b/apps/app_agent_pool.c @@ -1442,7 +1442,7 @@ static void send_agent_login(struct ast_channel *chan, const char *agent) return; } - ast_channel_publish_blob(chan, ast_channel_agent_login_type(), blob); + ast_channel_publish_cached_blob(chan, ast_channel_agent_login_type(), blob); } static void send_agent_logoff(struct ast_channel *chan, const char *agent, long logintime) @@ -1458,7 +1458,7 @@ static void send_agent_logoff(struct ast_channel *chan, const char *agent, long return; } - ast_channel_publish_blob(chan, ast_channel_agent_logoff_type(), blob); + ast_channel_publish_cached_blob(chan, ast_channel_agent_logoff_type(), blob); } /*! diff --git a/apps/app_meetme.c b/apps/app_meetme.c index b6f5fffb9a748b52c27b8c272d435d998b5bf1ff..1a780e6ffc30063c904a12f8402203b642dd6b16 100644 --- a/apps/app_meetme.c +++ b/apps/app_meetme.c @@ -1379,9 +1379,7 @@ static void meetme_stasis_generate_msg(struct ast_conference *meetme_conference, } } - ast_channel_lock(chan); - msg = ast_channel_blob_create(chan, message_type, json_object); - ast_channel_unlock(chan); + msg = ast_channel_blob_create_from_cache(ast_channel_uniqueid(chan), message_type, json_object); if (!msg) { return; diff --git a/apps/app_queue.c b/apps/app_queue.c index 8e26135cd1258818f1c3f3e7c010bb50275288c4..fe6b00ab0f749e82490aae164d4da57e3b9a5c10 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -3510,9 +3510,7 @@ static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result * "Queue", q->name, "Position", qe->pos, "Count", q->count); - ast_channel_lock(qe->chan); - ast_channel_publish_blob(qe->chan, queue_caller_join_type(), blob); - ast_channel_unlock(qe->chan); + ast_channel_publish_cached_blob(qe->chan, queue_caller_join_type(), blob); ast_debug(1, "Queue '%s' Join, Channel '%s', Position '%d'\n", q->name, ast_channel_name(qe->chan), qe->pos ); } ao2_unlock(q); @@ -3791,9 +3789,7 @@ static void leave_queue(struct queue_ent *qe) "Queue", q->name, "Position", qe->pos, "Count", q->count); - ast_channel_lock(qe->chan); - ast_channel_publish_blob(qe->chan, queue_caller_leave_type(), blob); - ast_channel_unlock(qe->chan); + ast_channel_publish_cached_blob(qe->chan, queue_caller_leave_type(), blob); ast_debug(1, "Queue '%s' Leave, Channel '%s'\n", q->name, ast_channel_name(qe->chan)); /* Take us out of the queue */ if (prev) { @@ -4395,9 +4391,7 @@ static void record_abandoned(struct queue_ent *qe) qe->parent->callsabandoned++; ao2_unlock(qe->parent); - ast_channel_lock(qe->chan); - ast_channel_publish_blob(qe->chan, queue_caller_abandon_type(), blob); - ast_channel_unlock(qe->chan); + ast_channel_publish_cached_blob(qe->chan, queue_caller_abandon_type(), blob); } /*! \brief RNA == Ring No Answer. Common code that is executed when we try a queue member and they don't answer. */ diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h index 3575bae8fe7a57b933b14fb48f5776acbb638903..505e4bac9e1f960e7bce680e69b35f8fc40bcd01 100644 --- a/include/asterisk/channel.h +++ b/include/asterisk/channel.h @@ -4178,6 +4178,15 @@ void ast_channel_dialed_causes_clear(const struct ast_channel *chan); struct ast_flags *ast_channel_flags(struct ast_channel *chan); +/*! + * \since 12.4.0 + * \brief Return whether or not any manager variables have been set + * + * \retval 0 if no manager variables are expected + * \retval 1 if manager variables are expected + */ +int ast_channel_has_manager_vars(void); + /*! * \since 12 * \brief Sets the variables to be stored in the \a manager_vars field of all diff --git a/include/asterisk/stasis_channels.h b/include/asterisk/stasis_channels.h index b4097b31b35d4a715bcf1baddbd933d116bef670..a252a2a90bfea782681de9f2b8e82cecbcd526f4 100644 --- a/include/asterisk/stasis_channels.h +++ b/include/asterisk/stasis_channels.h @@ -39,17 +39,16 @@ struct ast_channel_snapshot { AST_DECLARE_STRING_FIELDS( AST_STRING_FIELD(name); /*!< ASCII unique channel name */ - AST_STRING_FIELD(type); /*!< Type of channel technology */ - AST_STRING_FIELD(accountcode); /*!< Account code for billing */ - AST_STRING_FIELD(peeraccount); /*!< Peer account code for billing */ - AST_STRING_FIELD(userfield); /*!< Userfield for CEL billing */ AST_STRING_FIELD(uniqueid); /*!< Unique Channel Identifier */ AST_STRING_FIELD(linkedid); /*!< Linked Channel Identifier -- gets propagated by linkage */ - AST_STRING_FIELD(hangupsource); /*!< Who is responsible for hanging up this channel */ AST_STRING_FIELD(appl); /*!< Current application */ AST_STRING_FIELD(data); /*!< Data passed to current application */ AST_STRING_FIELD(context); /*!< Dialplan: Current extension context */ AST_STRING_FIELD(exten); /*!< Dialplan: Current extension number */ + AST_STRING_FIELD(accountcode); /*!< Account code for billing */ + AST_STRING_FIELD(peeraccount); /*!< Peer account code for billing */ + AST_STRING_FIELD(userfield); /*!< Userfield for CEL billing */ + AST_STRING_FIELD(hangupsource); /*!< Who is responsible for hanging up this channel */ AST_STRING_FIELD(caller_name); /*!< Caller ID Name */ AST_STRING_FIELD(caller_number); /*!< Caller ID Number */ AST_STRING_FIELD(caller_dnid); /*!< Dialed ID Number */ @@ -59,31 +58,20 @@ struct ast_channel_snapshot { AST_STRING_FIELD(dialed_subaddr); /*!< Dialed subaddress */ AST_STRING_FIELD(connected_name); /*!< Connected Line Name */ AST_STRING_FIELD(connected_number); /*!< Connected Line Number */ - AST_STRING_FIELD(effective_name); /*!< Effective Connected Line Name */ - AST_STRING_FIELD(effective_number); /*!< Effective Connected Line Number */ AST_STRING_FIELD(language); /*!< The default spoken language for the channel */ AST_STRING_FIELD(bridgeid); /*!< Unique Bridge Identifier */ - AST_STRING_FIELD(nativeformats); /*!< Native formats on the channel */ - AST_STRING_FIELD(readformat); /*!< The current read format */ - AST_STRING_FIELD(writeformat); /*!< The current write format */ - AST_STRING_FIELD(writetrans); /*!< The current write translation path */ - AST_STRING_FIELD(readtrans); /*!< The current read translation path */ + AST_STRING_FIELD(type); /*!< Type of channel technology */ ); - char callid[AST_CALLID_BUFFER_LENGTH]; /*!< Callid for the channel */ struct timeval creationtime; /*!< The time of channel creation */ - struct timeval hanguptime; /*!< When the channel should hang up */ enum ast_channel_state state; /*!< State of line */ int priority; /*!< Dialplan: Current extension priority */ int amaflags; /*!< AMA flags for billing */ int hangupcause; /*!< Why is the channel hanged up. See causes.h */ int caller_pres; /*!< Caller ID presentation. */ struct ast_flags flags; /*!< channel flags of AST_FLAG_ type */ - ast_group_t callgroup; /*!< Call group */ - ast_group_t pickupgroup; /*!< Pickup group */ struct ast_flags softhangup_flags; /*!< softhangup channel flags */ struct varshead *manager_vars; /*!< Variables to be appended to manager events */ - struct varshead *channel_vars; /*!< Variables set on the channel */ int tech_properties; /*!< Properties of the channel's technology */ }; @@ -320,6 +308,23 @@ void ast_multi_channel_blob_add_channel(struct ast_multi_channel_blob *obj, void ast_channel_publish_blob(struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *blob); +/*! + * \brief Publish a channel blob message using the latest snapshot from the cache + * \since 12.4.0 + * + * \param chan Channel publishing the blob. + * \param type Type of stasis message. + * \param blob The blob being published. (NULL if no blob) + * + * \note As this only accesses the uniqueid and topic of the channel - neither of + * which should ever be changed on a channel anyhow - a channel does not have to + * be locked when calling this function. + * + * \return Nothing + */ +void ast_channel_publish_cached_blob(struct ast_channel *chan, struct stasis_message_type *type, + struct ast_json *blob); + /*! * \since 12 * \brief Set flag to indicate channel snapshot is being staged. diff --git a/main/aoc.c b/main/aoc.c index 7dd888ec2ae8d297aca5719b591bc593942219d4..de43efcb5e47193c28dca64d5fd40b391beea1b3 100644 --- a/main/aoc.c +++ b/main/aoc.c @@ -1871,7 +1871,7 @@ int ast_aoc_manager_event(const struct ast_aoc_decoded *decoded, struct ast_chan return 0; } - ast_channel_publish_blob(chan, msg_type, blob); + ast_channel_publish_cached_blob(chan, msg_type, blob); return 0; } diff --git a/main/bridge_channel.c b/main/bridge_channel.c index 9a1e40bba81329848a36a3c8e95f016ad27ac019..9b1b5737e73f71f82e5ecb5c903826dd28610cf3 100644 --- a/main/bridge_channel.c +++ b/main/bridge_channel.c @@ -838,18 +838,16 @@ int ast_bridge_channel_write_hold(struct ast_bridge_channel *bridge_channel, con datalen = 0; } - ast_channel_lock(bridge_channel->chan); - ast_channel_publish_blob(bridge_channel->chan, ast_channel_hold_type(), blob); - ast_channel_unlock(bridge_channel->chan); + ast_channel_publish_cached_blob(bridge_channel->chan, ast_channel_hold_type(), blob); + return ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_HOLD, moh_class, datalen); } int ast_bridge_channel_write_unhold(struct ast_bridge_channel *bridge_channel) { - ast_channel_lock(bridge_channel->chan); - ast_channel_publish_blob(bridge_channel->chan, ast_channel_unhold_type(), NULL); - ast_channel_unlock(bridge_channel->chan); + ast_channel_publish_cached_blob(bridge_channel->chan, ast_channel_unhold_type(), NULL); + return ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_UNHOLD, NULL, 0); } diff --git a/main/cel.c b/main/cel.c index e61adfcec1163805551b615139722b2edd0b6294..c7f4fc36653be3ccfb5ccdc183f1f312b5c2c4a8 100644 --- a/main/cel.c +++ b/main/cel.c @@ -1798,9 +1798,7 @@ void ast_cel_publish_event(struct ast_channel *chan, "event_type", event_type, "event_details", blob); - ast_channel_lock(chan); - message = ast_channel_blob_create(chan, cel_generic_type(), cel_blob); - ast_channel_unlock(chan); + message = ast_channel_blob_create_from_cache(ast_channel_uniqueid(chan), cel_generic_type(), cel_blob); if (message) { stasis_publish(ast_cel_topic(), message); } diff --git a/main/channel.c b/main/channel.c index dd353947982411f4abb8e4ad0d537ae85455e2a8..04c396a7195a1bbce76f1c7c2ee936387115235e 100644 --- a/main/channel.c +++ b/main/channel.c @@ -1270,7 +1270,6 @@ int ast_queue_hold(struct ast_channel *chan, const char *musicclass) struct ast_frame f = { AST_FRAME_CONTROL, .subclass.integer = AST_CONTROL_HOLD }; int res; - ast_channel_lock(chan); if (!ast_strlen_zero(musicclass)) { f.data.ptr = (void *) musicclass; f.datalen = strlen(musicclass) + 1; @@ -1279,10 +1278,10 @@ int ast_queue_hold(struct ast_channel *chan, const char *musicclass) "musicclass", musicclass); } - ast_channel_publish_blob(chan, ast_channel_hold_type(), blob); + ast_channel_publish_cached_blob(chan, ast_channel_hold_type(), blob); res = ast_queue_frame(chan, &f); - ast_channel_unlock(chan); + return res; } @@ -1291,11 +1290,10 @@ int ast_queue_unhold(struct ast_channel *chan) struct ast_frame f = { AST_FRAME_CONTROL, .subclass.integer = AST_CONTROL_UNHOLD }; int res; - ast_channel_lock(chan); - ast_channel_publish_blob(chan, ast_channel_unhold_type(), NULL); + ast_channel_publish_cached_blob(chan, ast_channel_unhold_type(), NULL); res = ast_queue_frame(chan, &f); - ast_channel_unlock(chan); + return res; } @@ -3639,7 +3637,7 @@ static void send_dtmf_begin_event(struct ast_channel *chan, return; } - ast_channel_publish_blob(chan, ast_channel_dtmf_begin_type(), blob); + ast_channel_publish_cached_blob(chan, ast_channel_dtmf_begin_type(), blob); } static void send_dtmf_end_event(struct ast_channel *chan, @@ -3656,7 +3654,7 @@ static void send_dtmf_end_event(struct ast_channel *chan, return; } - ast_channel_publish_blob(chan, ast_channel_dtmf_end_type(), blob); + ast_channel_publish_cached_blob(chan, ast_channel_dtmf_end_type(), blob); } static void ast_read_generator_actions(struct ast_channel *chan, struct ast_frame *f) @@ -3988,7 +3986,6 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio) ast_frfree(f); f = &ast_null_frame; } else { - /* Answer the CDR */ ast_setstate(chan, AST_STATE_UP); } } else if (f->subclass.integer == AST_CONTROL_READ_ACTION) { @@ -5332,10 +5329,6 @@ static int set_format(struct ast_channel *chan, generator_write_format_change(chan); } - ast_channel_lock(chan); - ast_channel_publish_snapshot(chan); - ast_channel_unlock(chan); - return 0; } @@ -5415,10 +5408,6 @@ static int set_format(struct ast_channel *chan, generator_write_format_change(chan); } - ast_channel_lock(chan); - ast_channel_publish_snapshot(chan); - ast_channel_unlock(chan); - return res; } @@ -7414,6 +7403,17 @@ static void free_channelvars(void) AST_RWLIST_UNLOCK(&channelvars); } +int ast_channel_has_manager_vars(void) +{ + int vars_present; + + AST_RWLIST_RDLOCK(&channelvars); + vars_present = !AST_LIST_EMPTY(&channelvars); + AST_RWLIST_UNLOCK(&channelvars); + + return vars_present; +} + void ast_channel_set_manager_vars(size_t varc, char **vars) { size_t i; @@ -7644,12 +7644,9 @@ void ast_set_variables(struct ast_channel *chan, struct ast_variable *vars) { struct ast_variable *cur; - ast_channel_stage_snapshot(chan); - - for (cur = vars; cur; cur = cur->next) + for (cur = vars; cur; cur = cur->next) { pbx_builtin_setvar_helper(chan, cur->name, cur->value); - - ast_channel_stage_snapshot_done(chan); + } } static void *silence_generator_alloc(struct ast_channel *chan, void *data) diff --git a/main/channel_internal_api.c b/main/channel_internal_api.c index 9cc99f3d53db6e3f6bf0b413b8eae64c22dfd0f1..0c5117e6d1c45882da342f1552a17493428cbde0 100644 --- a/main/channel_internal_api.c +++ b/main/channel_internal_api.c @@ -943,9 +943,8 @@ void ast_channel_callid_set(struct ast_channel *chan, struct ast_callid *callid) ast_channel_name(chan), call_identifier_to, call_identifier_from); - - ast_channel_publish_snapshot(chan); } + void ast_channel_state_set(struct ast_channel *chan, enum ast_channel_state value) { chan->state = value; @@ -1073,7 +1072,6 @@ void ast_channel_dtmf_tv_set(struct ast_channel *chan, struct timeval *value) void ast_channel_whentohangup_set(struct ast_channel *chan, struct timeval *value) { chan->whentohangup = *value; - ast_channel_publish_snapshot(chan); } void ast_channel_varshead_set(struct ast_channel *chan, struct varshead *value) { @@ -1131,7 +1129,6 @@ ast_group_t ast_channel_callgroup(const struct ast_channel *chan) void ast_channel_callgroup_set(struct ast_channel *chan, ast_group_t value) { chan->callgroup = value; - ast_channel_publish_snapshot(chan); } ast_group_t ast_channel_pickupgroup(const struct ast_channel *chan) { @@ -1140,7 +1137,6 @@ ast_group_t ast_channel_pickupgroup(const struct ast_channel *chan) void ast_channel_pickupgroup_set(struct ast_channel *chan, ast_group_t value) { chan->pickupgroup = value; - ast_channel_publish_snapshot(chan); } struct ast_namedgroups *ast_channel_named_callgroups(const struct ast_channel *chan) { diff --git a/main/cli.c b/main/cli.c index 0fbdb69f675c89d203ba41f174dc8caf2508e282..bff58695d819de49f713250eb809cb0d01d69329 100644 --- a/main/cli.c +++ b/main/cli.c @@ -1513,8 +1513,7 @@ static char *handle_nodebugchan_deprecated(struct ast_cli_entry *e, int cmd, str static char *handle_showchan(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { - RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup); - struct ast_channel_snapshot *snapshot; + struct ast_channel *chan; struct timeval now; char cdrtime[256]; struct ast_str *obuf;/*!< Buffer for CDR variables. */ @@ -1522,6 +1521,12 @@ static char *handle_showchan(struct ast_cli_entry *e, int cmd, struct ast_cli_ar long elapsed_seconds=0; int hour=0, min=0, sec=0; struct ast_var_t *var; + char nativeformats[256]; + struct ast_str *write_transpath = ast_str_alloca(256); + struct ast_str *read_transpath = ast_str_alloca(256); + struct ast_bridge *bridge; + struct ast_callid *callid; + char callid_buf[32]; switch (cmd) { case CLI_INIT: @@ -1538,25 +1543,27 @@ static char *handle_showchan(struct ast_cli_entry *e, int cmd, struct ast_cli_ar return CLI_SHOWUSAGE; } - now = ast_tvnow(); - - if (!(msg = stasis_cache_get(ast_channel_cache_by_name(), ast_channel_snapshot_type(), a->argv[3]))) { - ast_cli(a->fd, "%s is not a known channel\n", a->argv[3]); - return CLI_SUCCESS; - } - snapshot = stasis_message_data(msg); - obuf = ast_str_thread_get(&ast_str_thread_global_buf, 16); if (!obuf) { return CLI_FAILURE; } + output = ast_str_create(8192); if (!output) { return CLI_FAILURE; } - if (!ast_tvzero(snapshot->creationtime)) { - elapsed_seconds = now.tv_sec - snapshot->creationtime.tv_sec; + chan = ast_channel_get_by_name(a->argv[3]); + if (!chan) { + ast_cli(a->fd, "%s is not a known channel\n", a->argv[3]); + return CLI_SUCCESS; + } + + now = ast_tvnow(); + ast_channel_lock(chan); + + if (!ast_tvzero(ast_channel_creationtime(chan))) { + elapsed_seconds = now.tv_sec - ast_channel_creationtime(chan).tv_sec; hour = elapsed_seconds / 3600; min = (elapsed_seconds % 3600) / 60; sec = elapsed_seconds % 60; @@ -1565,6 +1572,16 @@ static char *handle_showchan(struct ast_cli_entry *e, int cmd, struct ast_cli_ar strcpy(cdrtime, "N/A"); } + ast_translate_path_to_str(ast_channel_writetrans(chan), &write_transpath); + ast_translate_path_to_str(ast_channel_readtrans(chan), &read_transpath); + + bridge = ast_channel_get_bridge(chan); + callid = ast_channel_callid(chan); + if (callid) { + ast_callid_strnprint(callid_buf, sizeof(callid_buf), callid); + ast_callid_unref(callid); + } + ast_str_append(&output, 0, " -- General --\n" " Name: %s\n" @@ -1597,51 +1614,63 @@ static char *handle_showchan(struct ast_cli_entry *e, int cmd, struct ast_cli_ar " Application: %s\n" " Data: %s\n" " Call Identifer: %s\n", - snapshot->name, - snapshot->type, - snapshot->uniqueid, - snapshot->linkedid, - S_OR(snapshot->caller_number, "(N/A)"), - S_OR(snapshot->caller_name, "(N/A)"), - S_OR(snapshot->connected_number, "(N/A)"), - S_OR(snapshot->connected_name, "(N/A)"), - S_OR(snapshot->effective_number, "(N/A)"), - S_OR(snapshot->effective_name, "(N/A)"), - S_OR(snapshot->caller_dnid, "(N/A)"), - snapshot->language, - ast_state2str(snapshot->state), - snapshot->state, - snapshot->nativeformats, - snapshot->writeformat, - snapshot->readformat, - !ast_strlen_zero(snapshot->writetrans) ? "Yes" : "No", - snapshot->writetrans, - !ast_strlen_zero(snapshot->readtrans) ? "Yes" : "No", - snapshot->readtrans, - (long) snapshot->hanguptime.tv_sec, + ast_channel_name(chan), + ast_channel_tech(chan)->type, + ast_channel_uniqueid(chan), + ast_channel_linkedid(chan), + S_COR(ast_channel_caller(chan)->id.number.valid, + ast_channel_caller(chan)->id.number.str, "(N/A)"), + S_COR(ast_channel_caller(chan)->id.name.valid, + ast_channel_caller(chan)->id.name.str, "(N/A)"), + S_COR(ast_channel_connected(chan)->id.number.valid, + ast_channel_connected(chan)->id.number.str, "(N/A)"), + S_COR(ast_channel_connected(chan)->id.name.valid, + ast_channel_connected(chan)->id.name.str, "(N/A)"), + S_COR(ast_channel_connected_effective_id(chan).number.valid, + ast_channel_connected_effective_id(chan).number.str, "(N/A)"), + S_COR(ast_channel_connected_effective_id(chan).name.valid, + ast_channel_connected_effective_id(chan).name.str, "(N/A)"), + S_OR(ast_channel_dialed(chan)->number.str, "(N/A)"), + ast_channel_language(chan), + ast_state2str(ast_channel_state(chan)), + ast_channel_state(chan), + ast_getformatname_multiple(nativeformats, sizeof(nativeformats), ast_channel_nativeformats(chan)), + ast_getformatname(ast_channel_writeformat(chan)), + ast_getformatname(ast_channel_readformat(chan)), + ast_str_strlen(write_transpath) ? "Yes" : "No", + ast_str_buffer(write_transpath), + ast_str_strlen(read_transpath) ? "Yes" : "No", + ast_str_buffer(read_transpath), + ast_channel_whentohangup(chan)->tv_sec, cdrtime, - S_OR(snapshot->bridgeid, "(Not bridged)"), - snapshot->context, - snapshot->exten, - snapshot->priority, - snapshot->callgroup, - snapshot->pickupgroup, - S_OR(snapshot->appl, "(N/A)"), - S_OR(snapshot->data, "(Empty)"), - S_OR(snapshot->callid, "(None)")); - + bridge ? bridge->uniqueid : "(Not bridged)", + ast_channel_context(chan), + ast_channel_exten(chan), + ast_channel_priority(chan), + ast_channel_callgroup(chan), + ast_channel_pickupgroup(chan), + S_OR(ast_channel_appl(chan), "(N/A)"), + S_OR(ast_channel_data(chan), "(Empty)"), + S_OR(callid_buf, "(None)") + ); ast_str_append(&output, 0, " Variables:\n"); - AST_LIST_TRAVERSE(snapshot->channel_vars, var, entries) { + AST_LIST_TRAVERSE(ast_channel_varshead(chan), var, entries) { ast_str_append(&output, 0, "%s=%s\n", ast_var_name(var), ast_var_value(var)); } - if (ast_cdr_serialize_variables(snapshot->name, &obuf, '=', '\n')) { + if (ast_cdr_serialize_variables(ast_channel_name(chan), &obuf, '=', '\n')) { ast_str_append(&output, 0, " CDR Variables:\n%s\n", ast_str_buffer(obuf)); } + ast_channel_unlock(chan); + ast_cli(a->fd, "%s", ast_str_buffer(output)); ast_free(output); + + ao2_cleanup(bridge); + ast_channel_unref(chan); + return CLI_SUCCESS; } diff --git a/main/core_local.c b/main/core_local.c index 98db5e575a65eeca6f7faa9070666c51e27f37b2..e803f29ec0d369051e81df2f17fb1d5eef287b19 100644 --- a/main/core_local.c +++ b/main/core_local.c @@ -328,12 +328,12 @@ static struct ast_multi_channel_blob *local_channel_optimization_blob(struct loc RAII_VAR(struct ast_channel_snapshot *, local_one_snapshot, NULL, ao2_cleanup); RAII_VAR(struct ast_channel_snapshot *, local_two_snapshot, NULL, ao2_cleanup); - local_one_snapshot = ast_channel_snapshot_create(p->base.owner); + local_one_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(p->base.owner)); if (!local_one_snapshot) { return NULL; } - local_two_snapshot = ast_channel_snapshot_create(p->base.chan); + local_two_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(p->base.chan)); if (!local_two_snapshot) { return NULL; } @@ -371,7 +371,7 @@ static void local_optimization_started_cb(struct ast_unreal_pvt *base, struct as if (source) { RAII_VAR(struct ast_channel_snapshot *, source_snapshot, NULL, ao2_cleanup); - source_snapshot = ast_channel_snapshot_create(source); + source_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(source)); if (!source_snapshot) { return; } @@ -516,12 +516,12 @@ static void publish_local_bridge_message(struct local_pvt *p) goto end; } - one_snapshot = ast_channel_snapshot_create(owner); + one_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(owner)); if (!one_snapshot) { goto end; } - two_snapshot = ast_channel_snapshot_create(chan); + two_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(chan)); if (!two_snapshot) { goto end; } diff --git a/main/dial.c b/main/dial.c index 2563c707b5cc7445f5e7cedaec098c4cc66eb1c5..f03d43d257c3a5560dcffc2853cd580c0578c1ed 100644 --- a/main/dial.c +++ b/main/dial.c @@ -323,7 +323,7 @@ static int begin_dial_prerun(struct ast_dial_channel *channel, struct ast_channe ast_channel_appl_set(channel->owner, "AppDial2"); ast_channel_data_set(channel->owner, "(Outgoing Line)"); - ast_publish_channel_state(channel->owner); + memset(ast_channel_whentohangup(channel->owner), 0, sizeof(*ast_channel_whentohangup(channel->owner))); /* Inherit everything from he who spawned this dial */ diff --git a/main/endpoints.c b/main/endpoints.c index 9cc0178e0dad2182a8d71a94a100e5c6b8ae2c52..10b32e268d4899823e894fd5432a7db90f5b5b8b 100644 --- a/main/endpoints.c +++ b/main/endpoints.c @@ -203,9 +203,6 @@ int ast_endpoint_add_channel(struct ast_endpoint *endpoint, ast_str_container_add(endpoint->channel_ids, ast_channel_uniqueid(chan)); ao2_unlock(endpoint); - ast_channel_lock(chan); - ast_publish_channel_state(chan); - ast_channel_unlock(chan); endpoint_publish_snapshot(endpoint); return 0; diff --git a/main/manager.c b/main/manager.c index 7a7e8903ae955fee3aaa1ddfde614abfe8e9a691..6e056a163387b5f2cf6ded123ee4438957206a19 100644 --- a/main/manager.c +++ b/main/manager.c @@ -99,6 +99,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/bridge.h" #include "asterisk/features_config.h" #include "asterisk/rtp_engine.h" +#include "asterisk/translate.h" /*** DOCUMENTATION <manager name="Ping" language="en_US"> @@ -3846,95 +3847,110 @@ static int action_getvar(struct mansession *s, const struct message *m) static int action_status(struct mansession *s, const struct message *m) { const char *name = astman_get_header(m, "Channel"); - const char *cvariables = astman_get_header(m, "Variables"); - char *variables = ast_strdupa(S_OR(cvariables, "")); - RAII_VAR(struct ao2_container *, cached_channels, NULL, ao2_cleanup); - struct stasis_message *msg; + const char *chan_variables = astman_get_header(m, "Variables"); + const char *id = astman_get_header(m, "ActionID"); + char *variables = ast_strdupa(S_OR(chan_variables, "")); + struct ast_str *variable_str = ast_str_create(1024); + struct ast_str *write_transpath = ast_str_alloca(256); + struct ast_str *read_transpath = ast_str_alloca(256); + struct ast_channel *chan; + char nativeformats[256]; int channels = 0; int all = ast_strlen_zero(name); /* set if we want all channels */ - const char *id = astman_get_header(m, "ActionID"); - char idText[256]; + char id_text[256]; + struct ast_channel_iterator *it_chans = NULL; AST_DECLARE_APP_ARGS(vars, AST_APP_ARG(name)[100]; ); - struct ast_str *str = ast_str_create(1000); - struct ao2_iterator it_chans; - struct timeval now = ast_tvnow(); - if (!ast_strlen_zero(id)) { - snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id); - } else { - idText[0] = '\0'; + if (!variable_str) { + astman_send_error(s, m, "Memory Allocation Failure"); + return 1; } if (!(function_capable_string_allowed_with_auths(variables, s->session->writeperm))) { + ast_free(variable_str); astman_send_error(s, m, "Status Access Forbidden: Variables"); return 0; } if (all) { - if (!(cached_channels = stasis_cache_dump(ast_channel_cache_by_name(), ast_channel_snapshot_type()))) { - ast_free(str); + if (!(it_chans = ast_channel_iterator_all_new())) { + ast_free(variable_str); astman_send_error(s, m, "Memory Allocation Failure"); return 1; } - it_chans = ao2_iterator_init(cached_channels, 0); - msg = ao2_iterator_next(&it_chans); + chan = ast_channel_iterator_next(it_chans); } else { - if (!(msg = stasis_cache_get(ast_channel_cache_by_name(), ast_channel_snapshot_type(), name))) { + chan = ast_channel_get_by_name(name); + if (!chan) { astman_send_error(s, m, "No such channel"); - ast_free(str); + ast_free(variable_str); return 0; } } astman_send_ack(s, m, "Channel status will follow"); - if (!ast_strlen_zero(cvariables)) { + if (!ast_strlen_zero(id)) { + snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id); + } else { + id_text[0] = '\0'; + } + + if (!ast_strlen_zero(chan_variables)) { AST_STANDARD_APP_ARGS(vars, variables); } /* if we look by name, we break after the first iteration */ - for (; msg; ao2_ref(msg, -1), msg = all ? ao2_iterator_next(&it_chans) : NULL) { - struct ast_channel_snapshot *snapshot = stasis_message_data(msg); - struct ast_channel *c; - struct ast_str *built = ast_manager_build_channel_state_string_prefix(snapshot, ""); - long elapsed_seconds = 0; + for (; chan; all ? chan = ast_channel_iterator_next(it_chans) : 0) { + struct timeval now; + long elapsed_seconds; + struct ast_bridge *bridge; - if (!built) { - continue; - } + ast_channel_lock(chan); + + now = ast_tvnow(); + elapsed_seconds = ast_tvdiff_sec(now, ast_channel_creationtime(chan)); - if (!ast_strlen_zero(cvariables) && (c = ast_channel_get_by_name(snapshot->name))) { + if (!ast_strlen_zero(chan_variables)) { int i; - ast_str_reset(str); + ast_str_reset(variable_str); for (i = 0; i < vars.argc; i++) { char valbuf[512], *ret = NULL; if (vars.name[i][strlen(vars.name[i]) - 1] == ')') { - if (ast_func_read(c, vars.name[i], valbuf, sizeof(valbuf)) < 0) { + if (ast_func_read(chan, vars.name[i], valbuf, sizeof(valbuf)) < 0) { valbuf[0] = '\0'; } ret = valbuf; } else { - pbx_retrieve_variable(c, vars.name[i], &ret, valbuf, sizeof(valbuf), NULL); + pbx_retrieve_variable(chan, vars.name[i], &ret, valbuf, sizeof(valbuf), NULL); } - ast_str_append(&str, 0, "Variable: %s=%s\r\n", vars.name[i], ret); + ast_str_append(&variable_str, 0, "Variable: %s=%s\r\n", vars.name[i], ret); } - ast_channel_unref(c); } channels++; - - if (!ast_tvzero(snapshot->creationtime)) { - elapsed_seconds = now.tv_sec - snapshot->creationtime.tv_sec; - } + bridge = ast_channel_get_bridge(chan); astman_append(s, "Event: Status\r\n" "Privilege: Call\r\n" + "Channel: %s\r\n" + "ChannelState: %u\r\n" + "ChannelStateDesc: %s\r\n" + "CallerIDNum: %s\r\n" + "CallerIDName: %s\r\n" + "ConnectedLineNum: %s\r\n" + "ConnectedLineName: %s\r\n" + "Accountcode: %s\r\n" + "Context: %s\r\n" + "Exten: %s\r\n" + "Priority: %d\r\n" + "Uniqueid: %s\r\n" "Type: %s\r\n" "DNID: %s\r\n" "EffectiveConnectedLineNum: %s\r\n" @@ -3954,43 +3970,56 @@ static int action_status(struct mansession *s, const struct message *m) "Seconds: %ld\r\n" "%s" "%s" - "%s" "\r\n", - snapshot->type, - snapshot->caller_dnid, - S_OR(snapshot->effective_number, "<unknown>"), - S_OR(snapshot->effective_name, "<unknown>"), - snapshot->hanguptime.tv_sec, - snapshot->bridgeid, - snapshot->linkedid, - snapshot->appl, - snapshot->data, - snapshot->nativeformats, - snapshot->readformat, - snapshot->readtrans, - snapshot->writeformat, - snapshot->writetrans, - snapshot->callgroup, - snapshot->pickupgroup, - (long) elapsed_seconds, - ast_str_buffer(built), - ast_str_buffer(str), - idText); + ast_channel_name(chan), + ast_channel_state(chan), + ast_state2str(ast_channel_state(chan)), + S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, "<unknown>"), + S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, "<unknown>"), + S_COR(ast_channel_connected(chan)->id.number.valid, ast_channel_connected(chan)->id.number.str, "<unknown>"), + S_COR(ast_channel_connected(chan)->id.name.valid, ast_channel_connected(chan)->id.name.str, "<unknown>"), + ast_channel_accountcode(chan), + ast_channel_context(chan), + ast_channel_exten(chan), + ast_channel_priority(chan), + ast_channel_uniqueid(chan), + ast_channel_tech(chan)->type, + S_OR(ast_channel_dialed(chan)->number.str, ""), + S_COR(ast_channel_connected_effective_id(chan).number.valid, ast_channel_connected_effective_id(chan).number.str, "<unknown>"), + S_COR(ast_channel_connected_effective_id(chan).name.valid, ast_channel_connected_effective_id(chan).name.str, "<unknown>"), + ast_channel_whentohangup(chan)->tv_sec, + bridge ? bridge->uniqueid : "", + ast_channel_linkedid(chan), + ast_channel_appl(chan), + ast_channel_data(chan), + ast_getformatname_multiple(nativeformats, sizeof(nativeformats), ast_channel_nativeformats(chan)), + ast_getformatname(ast_channel_readformat(chan)), + ast_translate_path_to_str(ast_channel_readtrans(chan), &read_transpath), + ast_getformatname(ast_channel_writeformat(chan)), + ast_translate_path_to_str(ast_channel_writetrans(chan), &write_transpath), + ast_channel_callgroup(chan), + ast_channel_pickupgroup(chan), + (long)elapsed_seconds, + ast_str_buffer(variable_str), + id_text); + + ao2_cleanup(bridge); - ast_free(built); + ast_channel_unlock(chan); + chan = ast_channel_unref(chan); } - if (all) { - ao2_iterator_destroy(&it_chans); + if (it_chans) { + ast_channel_iterator_destroy(it_chans); } astman_append(s, "Event: StatusComplete\r\n" "%s" "Items: %d\r\n" - "\r\n", idText, channels); + "\r\n", id_text, channels); - ast_free(str); + ast_free(variable_str); return 0; } diff --git a/main/pbx.c b/main/pbx.c index b1c50e5abb86b56f1e311634d8cc29bc79e564c9..3c7b127e6f9c035ca5c675ebeff5dd0ab35b2790 100644 --- a/main/pbx.c +++ b/main/pbx.c @@ -8369,8 +8369,7 @@ static char *handle_show_device2extenstate(struct ast_cli_entry *e, int cmd, str /*! \brief CLI support for listing chanvar's variables in a parseable way */ static char *handle_show_chanvar(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { - RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup); - struct ast_channel_snapshot *snapshot; + struct ast_channel *chan; struct ast_var_t *var; switch (cmd) { @@ -8384,19 +8383,23 @@ static char *handle_show_chanvar(struct ast_cli_entry *e, int cmd, struct ast_cl return ast_complete_channels(a->line, a->word, a->pos, a->n, 3); } - if (a->argc != e->args + 1) + if (a->argc != e->args + 1) { return CLI_SHOWUSAGE; + } - if (!(msg = stasis_cache_get(ast_channel_cache_by_name(), ast_channel_snapshot_type(), a->argv[3]))) { + chan = ast_channel_get_by_name(a->argv[e->args]); + if (!chan) { ast_cli(a->fd, "Channel '%s' not found\n", a->argv[e->args]); return CLI_FAILURE; } - snapshot = stasis_message_data(msg); - AST_LIST_TRAVERSE(snapshot->channel_vars, var, entries) { + ast_channel_lock(chan); + AST_LIST_TRAVERSE(ast_channel_varshead(chan), var, entries) { ast_cli(a->fd, "%s=%s\n", ast_var_name(var), ast_var_value(var)); } + ast_channel_unlock(chan); + ast_channel_unref(chan); return CLI_SUCCESS; } @@ -10187,7 +10190,7 @@ static void *pbx_outgoing_exec(void *data) struct ast_app *app = pbx_findapp(outgoing->app); if (app) { - ast_verb(4, "Launching %s(%s) on %s\n", outgoing->app, outgoing->appdata, + ast_verb(4, "Launching %s(%s) on %s\n", outgoing->app, S_OR(outgoing->appdata, ""), ast_channel_name(ast_dial_answered(outgoing->dial))); pbx_exec(ast_dial_answered(outgoing->dial), app, outgoing->appdata); } else { @@ -11444,14 +11447,11 @@ int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const AST_LIST_TRAVERSE_SAFE_END; if (value && (newvariable = ast_var_assign(name, value))) { - if (headp == &globals) + if (headp == &globals) { ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value); + } AST_LIST_INSERT_HEAD(headp, newvariable, entries); ast_channel_publish_varset(chan, name, value); - - if (headp != &globals) { - ast_channel_publish_snapshot(chan); - } } if (chan) diff --git a/main/pickup.c b/main/pickup.c index a415f1672876dc941ff63ef85f317dcc57fc8cce..5be0c03abecfc29112a1966879d3ac74884ec575 100644 --- a/main/pickup.c +++ b/main/pickup.c @@ -361,9 +361,7 @@ int ast_do_pickup(struct ast_channel *chan, struct ast_channel *target) goto pickup_failed; } - ast_channel_lock(target); - target_snapshot = ast_channel_snapshot_create(target); - ast_channel_unlock(target); + target_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(target)); if (!target_snapshot) { goto pickup_failed; } diff --git a/main/stasis_bridges.c b/main/stasis_bridges.c index 1e0b36edffcd2fc4303bace00e57477e20638efc..c5df5f4f9300a98dd31ac7ec5eb62e4287759340 100644 --- a/main/stasis_bridges.c +++ b/main/stasis_bridges.c @@ -407,9 +407,7 @@ struct stasis_message *ast_bridge_blob_create( } if (chan) { - ast_channel_lock(chan); - obj->channel = ast_channel_snapshot_create(chan); - ast_channel_unlock(chan); + obj->channel = ast_channel_snapshot_get_latest(ast_channel_uniqueid(chan)); if (obj->channel == NULL) { return NULL; } @@ -593,9 +591,7 @@ static int bridge_channel_snapshot_pair_init(struct ast_bridge_channel_pair *pai } } - ast_channel_lock(pair->channel); - snapshot_pair->channel_snapshot = ast_channel_snapshot_create(pair->channel); - ast_channel_unlock(pair->channel); + snapshot_pair->channel_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(pair->channel)); if (!snapshot_pair->channel_snapshot) { return -1; } @@ -1072,9 +1068,7 @@ void ast_bridge_publish_attended_transfer_link(int is_external, enum ast_transfe transfer_msg->dest_type = AST_ATTENDED_TRANSFER_DEST_LINK; for (i = 0; i < 2; ++i) { - ast_channel_lock(locals[i]); - transfer_msg->dest.links[i] = ast_channel_snapshot_create(locals[i]); - ast_channel_unlock(locals[i]); + transfer_msg->dest.links[i] = ast_channel_snapshot_get_latest(ast_channel_uniqueid(locals[i])); if (!transfer_msg->dest.links[i]) { return; } diff --git a/main/stasis_cache.c b/main/stasis_cache.c index c1dab8539b767ad424d3a7ae15d359781023c98a..8b4304e5f4f3f1a8b61627820c09e161750db198 100644 --- a/main/stasis_cache.c +++ b/main/stasis_cache.c @@ -127,9 +127,17 @@ struct stasis_caching_topic *stasis_caching_unsubscribe_and_join(struct stasis_c return NULL; } +/*! + * \brief The key for an entry in the cache + * \note The items in this struct must be immutable for the item in the cache + */ struct cache_entry_key { + /*! The message type of the item stored in the cache */ struct stasis_message_type *type; + /*! The unique ID of the item stored in the cache */ const char *id; + /*! The hash, computed from \c type and \c id */ + unsigned int hash; }; struct stasis_cache_entry { @@ -166,6 +174,12 @@ static void cache_entry_dtor(void *obj) AST_VECTOR_FREE(&entry->remote); } +static void cache_entry_compute_hash(struct cache_entry_key *key) +{ + key->hash = ast_hashtab_hash_string(stasis_message_type_name(key->type)); + key->hash += ast_hashtab_hash_string(key->id); +} + static struct stasis_cache_entry *cache_entry_create(struct stasis_message_type *type, const char *id, struct stasis_message *snapshot) { struct stasis_cache_entry *entry; @@ -187,6 +201,7 @@ static struct stasis_cache_entry *cache_entry_create(struct stasis_message_type return NULL; } entry->key.type = ao2_bump(type); + cache_entry_compute_hash(&entry->key); is_remote = ast_eid_cmp(&ast_eid_default, stasis_message_eid(snapshot)) ? 1 : 0; if (AST_VECTOR_INIT(&entry->remote, is_remote)) { @@ -211,7 +226,6 @@ static int cache_entry_hash(const void *obj, int flags) { const struct stasis_cache_entry *object; const struct cache_entry_key *key; - int hash = 0; switch (flags & OBJ_SEARCH_MASK) { case OBJ_SEARCH_KEY: @@ -227,9 +241,7 @@ static int cache_entry_hash(const void *obj, int flags) return 0; } - hash += ast_hashtab_hash_string(stasis_message_type_name(key->type)); - hash += ast_hashtab_hash_string(key->id); - return hash; + return (int)key->hash; } static int cache_entry_cmp(void *obj, void *arg, int flags) @@ -347,6 +359,7 @@ static struct stasis_cache_entry *cache_find(struct ao2_container *entries, stru search_key.type = type; search_key.id = id; + cache_entry_compute_hash(&search_key); entry = ao2_find(entries, &search_key, OBJ_SEARCH_KEY | OBJ_NOLOCK); /* Ensure that what we looked for is what we found. */ diff --git a/main/stasis_channels.c b/main/stasis_channels.c index f38edb0e1f605fca34a252fc2f0079a6a127c3e9..ad9da50cfb76f62e9c7513f8a600735f989df487 100644 --- a/main/stasis_channels.c +++ b/main/stasis_channels.c @@ -195,18 +195,12 @@ static void channel_snapshot_dtor(void *obj) ast_string_field_free_memory(snapshot); ao2_cleanup(snapshot->manager_vars); - ao2_cleanup(snapshot->channel_vars); } struct ast_channel_snapshot *ast_channel_snapshot_create(struct ast_channel *chan) { struct ast_channel_snapshot *snapshot; struct ast_bridge *bridge; - char nativeformats[256]; - struct ast_str *write_transpath = ast_str_alloca(256); - struct ast_str *read_transpath = ast_str_alloca(256); - struct ast_party_id effective_connected_id; - struct ast_callid *callid; /* no snapshots for dummy channels */ if (!ast_channel_tech(chan)) { @@ -263,38 +257,16 @@ struct ast_channel_snapshot *ast_channel_snapshot_create(struct ast_channel *cha ao2_cleanup(bridge); } - ast_string_field_set(snapshot, nativeformats, ast_getformatname_multiple(nativeformats, sizeof(nativeformats), - ast_channel_nativeformats(chan))); - ast_string_field_set(snapshot, readformat, ast_getformatname(ast_channel_readformat(chan))); - ast_string_field_set(snapshot, writeformat, ast_getformatname(ast_channel_writeformat(chan))); - ast_string_field_set(snapshot, writetrans, ast_translate_path_to_str(ast_channel_writetrans(chan), &write_transpath)); - ast_string_field_set(snapshot, readtrans, ast_translate_path_to_str(ast_channel_readtrans(chan), &read_transpath)); - - effective_connected_id = ast_channel_connected_effective_id(chan); - ast_string_field_set(snapshot, effective_name, - S_COR(effective_connected_id.name.valid, effective_connected_id.name.str, "")); - ast_string_field_set(snapshot, effective_number, - S_COR(effective_connected_id.number.valid, effective_connected_id.number.str, "")); - - if ((callid = ast_channel_callid(chan))) { - ast_callid_strnprint(snapshot->callid, sizeof(snapshot->callid), callid); - ast_callid_unref(callid); - } - snapshot->creationtime = ast_channel_creationtime(chan); - snapshot->hanguptime = *(ast_channel_whentohangup(chan)); snapshot->state = ast_channel_state(chan); snapshot->priority = ast_channel_priority(chan); snapshot->amaflags = ast_channel_amaflags(chan); snapshot->hangupcause = ast_channel_hangupcause(chan); ast_copy_flags(&snapshot->flags, ast_channel_flags(chan), 0xFFFFFFFF); snapshot->caller_pres = ast_party_id_presentation(&ast_channel_caller(chan)->id); - snapshot->callgroup = ast_channel_callgroup(chan); - snapshot->pickupgroup = ast_channel_pickupgroup(chan); ast_set_flag(&snapshot->softhangup_flags, ast_channel_softhangup_internal_flag(chan)); snapshot->manager_vars = ast_channel_get_manager_vars(chan); - snapshot->channel_vars = ast_channel_get_vars(chan); snapshot->tech_properties = ast_channel_tech(chan)->properties; return snapshot; @@ -347,7 +319,11 @@ void ast_channel_publish_dial_forward(struct ast_channel *caller, struct ast_cha if (caller) { ast_channel_lock(caller); - caller_snapshot = ast_channel_snapshot_create(caller); + if (ast_strlen_zero(dialstatus)) { + caller_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(caller)); + } else { + caller_snapshot = ast_channel_snapshot_create(caller); + } ast_channel_unlock(caller); if (!caller_snapshot) { return; @@ -356,7 +332,11 @@ void ast_channel_publish_dial_forward(struct ast_channel *caller, struct ast_cha } ast_channel_lock(peer); - peer_snapshot = ast_channel_snapshot_create(peer); + if (ast_strlen_zero(dialstatus)) { + peer_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(peer)); + } else { + peer_snapshot = ast_channel_snapshot_create(peer); + } ast_channel_unlock(peer); if (!peer_snapshot) { return; @@ -682,9 +662,24 @@ void ast_channel_publish_snapshot(struct ast_channel *chan) stasis_publish(ast_channel_topic(chan), message); } +void ast_channel_publish_cached_blob(struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *blob) +{ + struct stasis_message *message; + + if (!blob) { + blob = ast_json_null(); + } + + message = ast_channel_blob_create_from_cache(ast_channel_uniqueid(chan), type, blob); + if (message) { + stasis_publish(ast_channel_topic(chan), message); + } + ao2_cleanup(message); +} + void ast_channel_publish_blob(struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *blob) { - RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup); + struct stasis_message *message; if (!blob) { blob = ast_json_null(); @@ -694,11 +689,12 @@ void ast_channel_publish_blob(struct ast_channel *chan, struct stasis_message_ty if (message) { stasis_publish(ast_channel_topic(chan), message); } + ao2_cleanup(message); } void ast_channel_publish_varset(struct ast_channel *chan, const char *name, const char *value) { - RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref); + struct ast_json *blob; ast_assert(name != NULL); ast_assert(value != NULL); @@ -711,7 +707,15 @@ void ast_channel_publish_varset(struct ast_channel *chan, const char *name, cons return; } - ast_channel_publish_blob(chan, ast_channel_varset_type(), blob); + if (chan && !ast_channel_has_manager_vars()) { + ast_channel_publish_cached_blob(chan, ast_channel_varset_type(), blob); + } else { + /* This function is NULL safe. If there are manager variables, + * we have to produce the full snapshot. + */ + ast_channel_publish_blob(chan, ast_channel_varset_type(), blob); + } + ast_json_unref(blob); } static struct ast_manager_event_blob *varset_to_ami(struct stasis_message *msg) @@ -1179,3 +1183,4 @@ int ast_stasis_channels_init(void) return res; } + diff --git a/res/ari/resource_channels.c b/res/ari/resource_channels.c index 30ced1b2ff8cb48586e01be34bd70c81bd3d5c3e..647344303064175032ea8bdc3ff33d30a8678d25 100644 --- a/res/ari/resource_channels.c +++ b/res/ari/resource_channels.c @@ -859,7 +859,7 @@ static void ari_channels_handle_originate_with_id(const char *args_endpoint, return; } - snapshot = ast_channel_snapshot_create(chan); + snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(chan)); ast_channel_unlock(chan); if (!ast_strlen_zero(args_app)) { @@ -1086,7 +1086,7 @@ static void ari_channels_handle_snoop_channel( return; } - snapshot = ast_channel_snapshot_create(snoop); + snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(snoop)); ast_ari_response_ok(response, ast_channel_snapshot_to_json(snapshot, NULL)); } diff --git a/res/res_agi.c b/res/res_agi.c index e223603a6299a1b883b844f076dea8f7813fd382..3adf36bacc4fdd5b6246c5ebff92988ad166fb59 100644 --- a/res/res_agi.c +++ b/res/res_agi.c @@ -1481,11 +1481,11 @@ static enum agi_result launch_asyncagi(struct ast_channel *chan, int argc, char to execute based on the setup info */ ast_uri_encode(agi_buffer, ami_buffer, AMI_BUF_SIZE, ast_uri_http); startblob = ast_json_pack("{s: s}", "Env", ami_buffer); - ast_channel_lock(chan); - ast_channel_publish_blob(chan, agi_async_start_type(), startblob); - hungup = ast_check_hangup(chan); - ast_channel_unlock(chan); + ast_channel_publish_cached_blob(chan, agi_async_start_type(), startblob); + + hungup = ast_check_hangup_locked(chan); + for (;;) { /* * Process as many commands as we can. Commands are added via @@ -1529,9 +1529,7 @@ static enum agi_result launch_asyncagi(struct ast_channel *chan, int argc, char if (execblob && !ast_strlen_zero(cmd->cmd_id)) { ast_json_object_set(execblob, "CommandId", ast_json_string_create(cmd->cmd_id)); } - ast_channel_lock(chan); - ast_channel_publish_blob(chan, agi_async_exec_type(), execblob); - ast_channel_unlock(chan); + ast_channel_publish_cached_blob(chan, agi_async_exec_type(), execblob); free_agi_cmd(cmd); @@ -1591,9 +1589,7 @@ async_agi_done: ast_speech_destroy(async_agi.speech); } /* notify manager users this channel cannot be controlled anymore by Async AGI */ - ast_channel_lock(chan); - ast_channel_publish_blob(chan, agi_async_end_type(), NULL); - ast_channel_unlock(chan); + ast_channel_publish_cached_blob(chan, agi_async_end_type(), NULL); async_agi_abort: /* close the pipe */ @@ -3665,9 +3661,7 @@ static void publish_async_exec_end(struct ast_channel *chan, int command_id, con "Command", command, "ResultCode", result_code, "Result", result); - ast_channel_lock(chan); - ast_channel_publish_blob(chan, agi_exec_end_type(), blob); - ast_channel_unlock(chan); + ast_channel_publish_cached_blob(chan, agi_exec_end_type(), blob); } static enum agi_result agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf, int dead) @@ -3685,9 +3679,7 @@ static enum agi_result agi_handle_command(struct ast_channel *chan, AGI *agi, ch startblob = ast_json_pack("{s: i, s: s}", "CommandId", command_id, "Command", ami_cmd); - ast_channel_lock(chan); - ast_channel_publish_blob(chan, agi_exec_start_type(), startblob); - ast_channel_unlock(chan); + ast_channel_publish_cached_blob(chan, agi_exec_start_type(), startblob); parse_args(buf, &argc, argv); c = find_command(argv, 0); diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c index 511b61393c849b1e69f0b14a11bb9fd02dcef6af..ea3326969d0de82cc55a2e602ddb29df03592e3d 100644 --- a/res/res_pjsip/pjsip_configuration.c +++ b/res/res_pjsip/pjsip_configuration.c @@ -1393,8 +1393,8 @@ static int cli_channel_print_header(void *obj, void *arg, int flags) indent = CLI_INDENT_TO_SPACES(context->indent_level); filler = CLI_LAST_TABSTOP - indent - 38; ast_str_append(&context->output_buffer, 0, - "%*s: <Codec> Exten: <DialedExten%*.*s> CLCID: <ConnectedLineCID.......>\n", - indent, "Codec", filler, filler, CLI_HEADER_FILLER); + "%*s: <DialedExten%*.*s> CLCID: <ConnectedLineCID.......>\n", + indent, "Exten", filler, filler, CLI_HEADER_FILLER); context->indent_level--; } @@ -1438,9 +1438,8 @@ static int cli_channel_print_body(void *obj, void *arg, int flags) flexwidth = CLI_LAST_TABSTOP - indent - 25; ast_str_append(&context->output_buffer, 0, - "%*s: %-7s Exten: %-*.*s CLCID: \"%s\" <%s>\n", - indent, "Codec", - snapshot->nativeformats, + "%*s: %-*.*s CLCID: \"%s\" <%s>\n", + indent, "Exten", flexwidth, flexwidth, snapshot->exten, snapshot->connected_name,