time(&end);
ast_channel_lock(chan);
+ ast_channel_stage_snapshot(chan);
snprintf(buf, sizeof(buf), "%d", ast_channel_get_up_time(chan));
pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", buf);
snprintf(buf, sizeof(buf), "%d", ast_channel_get_duration(chan));
pbx_builtin_setvar_helper(chan, "DIALEDTIME", buf);
+ ast_channel_stage_snapshot_done(chan);
ast_channel_unlock(chan);
}
struct ast_party_caller caller;
/* Reset all DIAL variables back to blank, to prevent confusion (in case we don't reset all of them). */
+ ast_channel_stage_snapshot(chan);
pbx_builtin_setvar_helper(chan, "DIALSTATUS", "");
pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", "");
pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", "");
pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", "");
pbx_builtin_setvar_helper(chan, "DIALEDTIME", "");
+ ast_channel_stage_snapshot_done(chan);
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "Dial requires an argument (technology/resource)\n");
chanlist_free(tmp);
continue;
}
+
+ ast_channel_stage_snapshot(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);
else
ast_channel_exten_set(tc, ast_channel_exten(chan));
+ ast_channel_stage_snapshot_done(tc);
+
ast_channel_unlock(tc);
ast_channel_unlock(chan);
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
}
ast_channel_unlock(peer);
pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", number);
+ ast_channel_stage_snapshot_done(chan);
if (!ast_strlen_zero(args.url) && ast_channel_supports_html(peer) ) {
ast_debug(1, "app_dial: sendurl=%s.\n", args.url);
/* chan and peer are going into the PBX; as such neither are considered
* outgoing channels any longer */
ast_clear_flag(ast_channel_flags(chan), AST_FLAG_OUTGOING);
+ ast_channel_stage_snapshot(peer);
ast_clear_flag(ast_channel_flags(peer), AST_FLAG_OUTGOING);
ast_replace_subargument_delimiter(opt_args[OPT_ARG_GOTO]);
ast_channel_context_set(peer, ast_channel_context(chan));
ast_channel_exten_set(peer, ast_channel_exten(chan));
ast_channel_priority_set(peer, ast_channel_priority(chan) + 2);
+ ast_channel_stage_snapshot_done(peer);
if (ast_pbx_start(peer)) {
ast_autoservice_chan_hangup_peer(chan, peer);
}
#include "asterisk/abstract_jb.h"
#include "asterisk/musiconhold.h"
#include "asterisk/poll-compat.h"
+#include "asterisk/stasis_channels.h"
/*! Global jitterbuffer configuration - by default, jb is disabled
* \note Values shown here match the defaults shown in alsa.conf.sample */
if (!(tmp = ast_channel_alloc(1, state, 0, 0, "", p->exten, p->context, linkedid, 0, "ALSA/%s", indevname)))
return NULL;
+ ast_channel_stage_snapshot(tmp);
+
ast_channel_tech_set(tmp, &alsa_tech);
ast_channel_set_fd(tmp, 0, readdev);
ast_format_set(ast_channel_readformat(tmp), AST_FORMAT_SLINEAR, 0);
p->owner = tmp;
ast_module_ref(ast_module_info->self);
ast_jb_configure(tmp, &global_jbconf);
+
+ ast_channel_stage_snapshot_done(tmp);
+
if (state != AST_STATE_DOWN) {
if (ast_pbx_start(tmp)) {
ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
#include "asterisk/musiconhold.h"
#include "asterisk/callerid.h"
#include "asterisk/astobj2.h"
+#include "asterisk/stasis_channels.h"
/*!
* \brief The sample rate to request from PortAudio
return NULL;
}
+ ast_channel_stage_snapshot(chan);
+
ast_channel_tech_set(chan, &console_tech);
ast_format_set(ast_channel_readformat(chan), AST_FORMAT_SLINEAR16, 0);
ast_format_set(ast_channel_writeformat(chan), AST_FORMAT_SLINEAR16, 0);
ast_jb_configure(chan, &global_jbconf);
+ ast_channel_stage_snapshot_done(chan);
+
if (state != AST_STATE_DOWN) {
if (ast_pbx_start(chan)) {
ast_channel_hangupcause_set(chan, AST_CAUSE_SWITCH_CONGESTION);
return NULL;
}
+ ast_channel_stage_snapshot(tmp);
+
if (callid) {
ast_channel_callid_set(tmp, callid);
}
for (v = i->vars ; v ; v = v->next)
pbx_builtin_setvar_helper(tmp, v->name, v->value);
+ ast_channel_stage_snapshot_done(tmp);
+
ast_module_ref(ast_module_info->self);
dahdi_ami_channel_event(i, tmp);
ast_log(LOG_WARNING, "Unable to allocate Gtalk channel structure!\n");
return NULL;
}
+
+ ast_channel_stage_snapshot(tmp);
+
ast_channel_tech_set(tmp, >alk_tech);
/* Select our native format based on codec preference until we receive
ast_channel_priority_set(tmp, 1);
if (i->rtp)
ast_jb_configure(tmp, &global_jbconf);
+
+ ast_channel_stage_snapshot_done(tmp);
+
if (state != AST_STATE_DOWN && ast_pbx_start(tmp)) {
ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
ast_channel_hangupcause_set(tmp, AST_CAUSE_SWITCH_CONGESTION);
#include "asterisk/bridge.h"
#include "asterisk/stasis.h"
#include "asterisk/stasis_system.h"
+#include "asterisk/stasis_channels.h"
#include "iax2/include/iax2.h"
#include "iax2/include/firmware.h"
return NULL;
}
+ ast_channel_stage_snapshot(tmp);
+
if ((callid = iaxs[callno]->callid)) {
ast_channel_callid_set(tmp, callid);
}
}
}
+ ast_channel_stage_snapshot_done(tmp);
+
if (state != AST_STATE_DOWN) {
if (ast_pbx_start(tmp)) {
ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
#include "asterisk/abstract_jb.h"
#include "asterisk/jabber.h"
#include "asterisk/jingle.h"
+#include "asterisk/stasis_channels.h"
#define JINGLE_CONFIG "jingle.conf"
ast_log(LOG_WARNING, "Unable to allocate Jingle channel structure!\n");
return NULL;
}
+
+ ast_channel_stage_snapshot(tmp);
+
ast_channel_tech_set(tmp, &jingle_tech);
/* Select our native format based on codec preference until we receive
ast_channel_priority_set(tmp, 1);
if (i->rtp)
ast_jb_configure(tmp, &global_jbconf);
+
+ ast_channel_stage_snapshot_done(tmp);
+
if (state != AST_STATE_DOWN && ast_pbx_start(tmp)) {
ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
ast_channel_hangupcause_set(tmp, AST_CAUSE_SWITCH_CONGESTION);
#include "asterisk/bridge.h"
#include "asterisk/features_config.h"
#include "asterisk/parking.h"
+#include "asterisk/stasis_channels.h"
/*
* Define to work around buggy dlink MGCP phone firmware which
tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, linkedid, i->accountcode, i->exten, i->context, i->amaflags, "MGCP/%s@%s-%d", i->name, i->parent->name, sub->id);
if (tmp) {
+ ast_channel_stage_snapshot(tmp);
ast_channel_tech_set(tmp, &mgcp_tech);
ast_format_cap_copy(ast_channel_nativeformats(tmp), i->cap);
if (ast_format_cap_is_empty(ast_channel_nativeformats(tmp))) {
if (sub->rtp) {
ast_jb_configure(tmp, &global_jbconf);
}
+
+ ast_channel_stage_snapshot_done(tmp);
+
if (state != AST_STATE_DOWN) {
if (ast_pbx_start(tmp)) {
ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
#include "asterisk/astobj.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/xmpp.h"
+#include "asterisk/stasis_channels.h"
/*** DOCUMENTATION
<configInfo name="chan_motif" language="en_US">
return NULL;
}
+ ast_channel_stage_snapshot(chan);
+
ast_channel_tech_set(chan, &jingle_tech);
ast_channel_tech_pvt_set(chan, session);
jingle_set_owner(session, chan);
ao2_unlock(endpoint);
+ ast_channel_stage_snapshot_done(chan);
+
return chan;
}
return NULL;
}
+ ast_channel_stage_snapshot(chan);
+
/* If res_pjsip_session is ever updated to create/destroy ast_sip_session_media
* during a call such as if multiple same-type stream support is introduced,
* these will need to be recaptured as well */
ast_endpoint_add_channel(session->endpoint->persistent, chan);
+ ast_channel_stage_snapshot_done(chan);
+
return chan;
}
} while (sip_pvt_trylock(p));
}
+ if (p->rtp || p->vrtp || p->trtp) {
+ ast_channel_stage_snapshot(oldowner);
+ }
+
if (p->rtp) {
ast_rtp_instance_set_stats_vars(oldowner, p->rtp);
}
}
pbx_builtin_setvar_helper(oldowner, "RTPTEXTQOS", quality);
}
+ if (p->rtp || p->vrtp || p->trtp) {
+ ast_channel_stage_snapshot_done(oldowner);
+ }
/* Send a hangup */
if (ast_channel_state(oldowner) == AST_STATE_UP) {
}
}
+ ast_channel_stage_snapshot(tmp);
+
/* If we sent in a callid, bind it to the channel. */
if (callid) {
ast_channel_callid_set(tmp, callid);
append_history(i, "NewChan", "Channel %s - from %s", ast_channel_name(tmp), i->callid);
}
+ ast_channel_stage_snapshot_done(tmp);
+
return tmp;
}
}
}
+ if ((p->rtp || p->vrtp || p->trtp) && p->owner) {
+ ast_channel_stage_snapshot(p->owner);
+ }
+
/* Get RTCP quality before end of call */
if (p->rtp) {
if (p->do_history) {
}
}
+ if ((p->rtp || p->vrtp || p->trtp) && p->owner) {
+ ast_channel_stage_snapshot_done(p->owner);
+ }
+
stop_media_flows(p); /* Immediately stop RTP, VRTP and UDPTL as applicable */
stop_session_timer(p); /* Stop Session-Timer */
#include "asterisk/stasis_endpoints.h"
#include "asterisk/bridge.h"
#include "asterisk/parking.h"
+#include "asterisk/stasis_channels.h"
/*** DOCUMENTATION
<manager name="SKINNYdevices" language="en_US">
AST_LIST_INSERT_HEAD(&l->sub, sub, list);
//l->activesub = sub;
}
+ ast_channel_stage_snapshot(tmp);
ast_channel_tech_set(tmp, &skinny_tech);
ast_channel_tech_pvt_set(tmp, sub);
ast_format_cap_copy(ast_channel_nativeformats(tmp), l->cap);
for (v = l->chanvars ; v ; v = v->next)
pbx_builtin_setvar_helper(tmp, v->name, v->value);
+ ast_channel_stage_snapshot_done(tmp);
+
if (state != AST_STATE_DOWN) {
if (ast_pbx_start(tmp)) {
ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
#include "asterisk/astdb.h"
#include "asterisk/features_config.h"
#include "asterisk/bridge.h"
-
+#include "asterisk/stasis_channels.h"
#define DEFAULTCONTEXT "default"
#define DEFAULTCALLERID "Unknown"
return NULL;
}
+ ast_channel_stage_snapshot(tmp);
+
ast_format_cap_copy(ast_channel_nativeformats(tmp), l->cap);
if (ast_format_cap_is_empty(ast_channel_nativeformats(tmp))) {
ast_format_cap_copy(ast_channel_nativeformats(tmp), global_cap);
}
}
ast_channel_priority_set(tmp, 1);
+
+ ast_channel_stage_snapshot_done(tmp);
+
if (state != AST_STATE_DOWN) {
if (unistimdebug) {
ast_verb(0, "Starting pbx in unistim_new\n");
ast_mutex_lock(&pri->lock);
sig_pri_lock_private(pri->pvts[chanpos]);
if (c) {
+ ast_channel_stage_snapshot(c);
#if defined(HAVE_PRI_SUBADDR)
if (e->ring.calling.subaddress.valid) {
/* Set Calling Subaddress */
PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
#endif
}
+ ast_channel_stage_snapshot_done(c);
}
if (c && !ast_pthread_create_detached(&threadid, NULL, pri_ss_thread, pri->pvts[chanpos])) {
ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
* will do anything with the channel we have just
* created.
*/
+ ast_channel_stage_snapshot(c);
#if defined(HAVE_PRI_SUBADDR)
if (e->ring.calling.subaddress.valid) {
/* Set Calling Subaddress */
sig_pri_handle_subcmds(pri, chanpos, e->e, e->ring.subcmds,
e->ring.call);
+
+ ast_channel_stage_snapshot_done(c);
}
if (c && !ast_pbx_start(c)) {
ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
sig_ss7_set_echocanceller(p, 1);
+ ast_channel_stage_snapshot(c);
+
/*
* It is reasonably safe to set the following
* channel variables while the channel private
p->generic_name[0] = 0;
}
+ ast_channel_stage_snapshot_done(c);
+
sig_ss7_unlock_private(p);
ast_channel_unlock(c);
* occur.
*/
AST_FLAG_DEAD = (1 << 24),
+ /*!
+ * Channel snapshot should not be published, it is being staged for an explicit
+ * publish.
+ */
+ AST_FLAG_SNAPSHOT_STAGE = (1 << 25),
};
/*! \brief ast_bridge_config flags */
void ast_channel_publish_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.
+ *
+ * \param chan Channel being staged.
+ */
+void ast_channel_stage_snapshot(struct ast_channel *chan);
+
+/*!
+ * \since 12
+ * \brief Clear flag to indicate channel snapshot is being staged, and publish snapshot.
+ *
+ * \param chan Channel being staged.
+ */
+void ast_channel_stage_snapshot_done(struct ast_channel *chan);
+
/*!
* \since 12
* \brief Publish a \ref ast_channel_snapshot for a channel.
static void update_bridge_vars_set(struct ast_channel *chan, const char *name, const char *pvtid)
{
+ ast_channel_stage_snapshot(chan);
pbx_builtin_setvar_helper(chan, "BRIDGEPEER", name);
pbx_builtin_setvar_helper(chan, "BRIDGEPVTCALLID", pvtid);
+ ast_channel_stage_snapshot_done(chan);
}
/*!
/* Channel structure allocation failure. */
return NULL;
}
+
+ ast_channel_stage_snapshot(tmp);
+
if (!(nativeformats = ast_format_cap_alloc())) {
ao2_ref(tmp, -1);
/* format capabilities structure allocation failure */
* And now, since the channel structure is built, and has its name, let
* the world know of its existance
*/
- ast_channel_publish_snapshot(tmp);
+ ast_channel_stage_snapshot_done(tmp);
return tmp;
}
{
struct ast_variable *cur;
+ ast_channel_stage_snapshot(chan);
+
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)
cap_request = NULL;
cap_all_audio = ast_format_cap_destroy(cap_all_audio);
+ ast_channel_stage_snapshot(channel->owner);
+
ast_channel_appl_set(channel->owner, "AppDial2");
ast_channel_data_set(channel->owner, "(Outgoing Line)");
ast_publish_channel_state(channel->owner);
ast_channel_transfercapability_set(channel->owner, ast_channel_transfercapability(chan));
}
+ ast_channel_stage_snapshot_done(channel->owner);
+
return 0;
}
return -1;
}
- ast_set_variables(dialed, vars);
+ if (vars) {
+ ast_set_variables(dialed, vars);
+ }
if (account) {
ast_channel_accountcode_set(dialed, account);
return obj->blob;
}
+void ast_channel_stage_snapshot(struct ast_channel *chan)
+{
+ ast_set_flag(ast_channel_flags(chan), AST_FLAG_SNAPSHOT_STAGE);
+}
+
+void ast_channel_stage_snapshot_done(struct ast_channel *chan)
+{
+ ast_clear_flag(ast_channel_flags(chan), AST_FLAG_SNAPSHOT_STAGE);
+ ast_channel_publish_snapshot(chan);
+}
+
void ast_channel_publish_snapshot(struct ast_channel *chan)
{
RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
+ if (ast_test_flag(ast_channel_flags(chan), AST_FLAG_SNAPSHOT_STAGE)) {
+ return;
+ }
+
snapshot = ast_channel_snapshot_create(chan);
if (!snapshot) {
return;