channel locking: Add locking for channel snapshot creation

Original commit message by mmichelson (asterisk 12 r403311):

"This adds channel locks around calls to create channel snapshots as well
as other functions which operate on a channel and then end up
creating a channel snapshot. Functions that expect the channel to be
locked prior to being called have had their documentation updated to
indicate such."

The above was initially committed and then reverted at r403398.  The problem
was found to be in core_local.c in the publish_local_bridge_message function.
The ast_unreal_lock_all function locks and adds a reference to the returned
channels and while they were being unlocked they were not being unreffed when
no longer needed.  Fixed by unreffing the channels.

Also in bridge.c a lock was obtained on "other->chan", but then an attempt was
made to unlock "other" and not the previously locked channel.  Fixed by
unlocking "other->chan"

(closes issue ASTERISK-22709)
Reported by: John Bigelow
........

Merged revisions 404237 from http://svn.asterisk.org/svn/asterisk/branches/12


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@404260 65c4cc65-6c06-0410-ace0-fbb531ad65f3
changes/97/197/1
Kevin Harwell 12 years ago
parent 86b5e11607
commit 28c0cb28d0

@ -878,7 +878,6 @@ static struct ast_channel *mbl_new(int state, struct mbl_pvt *pvt, char *cid_num
if (pvt->sco_socket != -1) { if (pvt->sco_socket != -1) {
ast_channel_set_fd(chn, 0, pvt->sco_socket); ast_channel_set_fd(chn, 0, pvt->sco_socket);
} }
ast_channel_unlock(chn); ast_channel_unlock(chn);
return chn; return chn;

@ -2164,8 +2164,8 @@ int onCallEstablished(ooCallData *call)
} }
ast_queue_control(c, AST_CONTROL_ANSWER); ast_queue_control(c, AST_CONTROL_ANSWER);
ast_channel_unlock(p->owner);
ast_publish_channel_state(c); ast_publish_channel_state(c);
ast_channel_unlock(p->owner);
} }
ast_mutex_unlock(&p->lock); ast_mutex_unlock(&p->lock);

@ -1465,7 +1465,9 @@ static void agent_logout(struct agent_pvt *agent)
ast_bridge_destroy(caller_bridge, AST_CAUSE_USER_BUSY); ast_bridge_destroy(caller_bridge, AST_CAUSE_USER_BUSY);
} }
ast_channel_lock(logged);
send_agent_logoff(logged, agent->username, time_logged_in); send_agent_logoff(logged, agent->username, time_logged_in);
ast_channel_unlock(logged);
ast_verb(2, "Agent '%s' logged out. Logged in for %ld seconds.\n", ast_verb(2, "Agent '%s' logged out. Logged in for %ld seconds.\n",
agent->username, time_logged_in); agent->username, time_logged_in);
ast_channel_unref(logged); ast_channel_unref(logged);
@ -2046,7 +2048,9 @@ static int agent_login_exec(struct ast_channel *chan, const char *data)
ast_verb(2, "Agent '%s' logged in (format %s/%s)\n", agent->username, ast_verb(2, "Agent '%s' logged in (format %s/%s)\n", agent->username,
ast_getformatname(ast_channel_readformat(chan)), ast_getformatname(ast_channel_readformat(chan)),
ast_getformatname(ast_channel_writeformat(chan))); ast_getformatname(ast_channel_writeformat(chan)));
ast_channel_lock(chan);
send_agent_login(chan, agent->username); send_agent_login(chan, agent->username);
ast_channel_unlock(chan);
agent_run(agent, chan); agent_run(agent, chan);
return -1; return -1;

@ -1379,7 +1379,9 @@ static int alloc_playback_chan(struct confbridge_conference *conference)
} }
/* To make sure playback_chan has the same language of that profile */ /* To make sure playback_chan has the same language of that profile */
ast_channel_lock(conference->playback_chan);
ast_channel_language_set(conference->playback_chan, conference->b_profile.language); ast_channel_language_set(conference->playback_chan, conference->b_profile.language);
ast_channel_unlock(conference->playback_chan);
ast_debug(1, "Created announcer channel '%s' to conference bridge '%s'\n", ast_debug(1, "Created announcer channel '%s' to conference bridge '%s'\n",
ast_channel_name(conference->playback_chan), conference->name); ast_channel_name(conference->playback_chan), conference->name);

@ -2104,6 +2104,7 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
struct ast_party_caller caller; struct ast_party_caller caller;
/* Reset all DIAL variables back to blank, to prevent confusion (in case we don't reset all of them). */ /* Reset all DIAL variables back to blank, to prevent confusion (in case we don't reset all of them). */
ast_channel_lock(chan);
ast_channel_stage_snapshot(chan); ast_channel_stage_snapshot(chan);
pbx_builtin_setvar_helper(chan, "DIALSTATUS", ""); pbx_builtin_setvar_helper(chan, "DIALSTATUS", "");
pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", ""); pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", "");
@ -2111,6 +2112,7 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", ""); pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", "");
pbx_builtin_setvar_helper(chan, "DIALEDTIME", ""); pbx_builtin_setvar_helper(chan, "DIALEDTIME", "");
ast_channel_stage_snapshot_done(chan); ast_channel_stage_snapshot_done(chan);
ast_channel_unlock(chan);
if (ast_strlen_zero(data)) { if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "Dial requires an argument (technology/resource)\n"); ast_log(LOG_WARNING, "Dial requires an argument (technology/resource)\n");
@ -2443,15 +2445,17 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
continue; continue;
} }
ast_channel_lock(tc);
ast_channel_stage_snapshot(tc); ast_channel_stage_snapshot(tc);
ast_channel_unlock(tc);
ast_channel_get_device_name(tc, device_name, sizeof(device_name)); ast_channel_get_device_name(tc, device_name, sizeof(device_name));
if (!ignore_cc) { if (!ignore_cc) {
ast_cc_extension_monitor_add_dialstring(chan, tmp->interface, device_name); ast_cc_extension_monitor_add_dialstring(chan, tmp->interface, device_name);
} }
pbx_builtin_setvar_helper(tc, "DIALEDPEERNUMBER", tmp->number);
ast_channel_lock_both(tc, chan); ast_channel_lock_both(tc, chan);
pbx_builtin_setvar_helper(tc, "DIALEDPEERNUMBER", tmp->number);
/* Setup outgoing SDP to match incoming one */ /* Setup outgoing SDP to match incoming one */
if (!AST_LIST_FIRST(&out_chans) && !rest && CAN_EARLY_BRIDGE(peerflags, chan, tc)) { if (!AST_LIST_FIRST(&out_chans) && !rest && CAN_EARLY_BRIDGE(peerflags, chan, tc)) {
@ -2724,8 +2728,10 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
number = ast_strdupa(number); number = ast_strdupa(number);
} }
ast_channel_unlock(peer); ast_channel_unlock(peer);
ast_channel_lock(chan);
pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", number); pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", number);
ast_channel_stage_snapshot_done(chan); ast_channel_stage_snapshot_done(chan);
ast_channel_unlock(chan);
if (!ast_strlen_zero(args.url) && ast_channel_supports_html(peer) ) { if (!ast_strlen_zero(args.url) && ast_channel_supports_html(peer) ) {
ast_debug(1, "app_dial: sendurl=%s.\n", args.url); ast_debug(1, "app_dial: sendurl=%s.\n", args.url);
@ -2811,16 +2817,18 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
/* chan and peer are going into the PBX; as such neither are considered /* chan and peer are going into the PBX; as such neither are considered
* outgoing channels any longer */ * outgoing channels any longer */
ast_clear_flag(ast_channel_flags(chan), AST_FLAG_OUTGOING); 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_replace_subargument_delimiter(opt_args[OPT_ARG_GOTO]);
ast_parseable_goto(chan, opt_args[OPT_ARG_GOTO]); ast_parseable_goto(chan, opt_args[OPT_ARG_GOTO]);
/* peer goes to the same context and extension as chan, so just copy info from chan*/ /* peer goes to the same context and extension as chan, so just copy info from chan*/
ast_channel_lock(peer);
ast_channel_stage_snapshot(peer);
ast_clear_flag(ast_channel_flags(peer), AST_FLAG_OUTGOING);
ast_channel_context_set(peer, ast_channel_context(chan)); ast_channel_context_set(peer, ast_channel_context(chan));
ast_channel_exten_set(peer, ast_channel_exten(chan)); ast_channel_exten_set(peer, ast_channel_exten(chan));
ast_channel_priority_set(peer, ast_channel_priority(chan) + 2); ast_channel_priority_set(peer, ast_channel_priority(chan) + 2);
ast_channel_stage_snapshot_done(peer); ast_channel_stage_snapshot_done(peer);
ast_channel_unlock(peer);
if (ast_pbx_start(peer)) { if (ast_pbx_start(peer)) {
ast_autoservice_chan_hangup_peer(chan, peer); ast_autoservice_chan_hangup_peer(chan, peer);
} }
@ -2970,7 +2978,9 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
if (!res) { if (!res) {
if (!ast_tvzero(calldurationlimit)) { if (!ast_tvzero(calldurationlimit)) {
struct timeval whentohangup = ast_tvadd(ast_tvnow(), calldurationlimit); struct timeval whentohangup = ast_tvadd(ast_tvnow(), calldurationlimit);
ast_channel_lock(peer);
ast_channel_whentohangup_set(peer, &whentohangup); ast_channel_whentohangup_set(peer, &whentohangup);
ast_channel_unlock(peer);
} }
if (!ast_strlen_zero(dtmfcalled)) { if (!ast_strlen_zero(dtmfcalled)) {
ast_verb(3, "Sending DTMF '%s' to the called party.\n", dtmfcalled); ast_verb(3, "Sending DTMF '%s' to the called party.\n", dtmfcalled);

@ -381,8 +381,11 @@ static int disa_exec(struct ast_channel *chan, const char *data)
ast_set_callerid(chan, ourcidnum, ourcidname, ourcidnum); ast_set_callerid(chan, ourcidnum, ourcidname, ourcidnum);
} }
if (!ast_strlen_zero(acctcode)) if (!ast_strlen_zero(acctcode)) {
ast_channel_lock(chan);
ast_channel_accountcode_set(chan, acctcode); ast_channel_accountcode_set(chan, acctcode);
ast_channel_unlock(chan);
}
if (special_noanswer) { if (special_noanswer) {
ast_clear_flag(&cdr_flags, AST_CDR_FLAG_DISABLE); ast_clear_flag(&cdr_flags, AST_CDR_FLAG_DISABLE);

@ -1384,7 +1384,9 @@ 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); msg = ast_channel_blob_create(chan, message_type, json_object);
ast_channel_unlock(chan);
if (!msg) { if (!msg) {
return; return;

@ -2040,8 +2040,12 @@ static void queue_publish_multi_channel_blob(struct ast_channel *caller, struct
RAII_VAR(struct ast_channel_snapshot *, caller_snapshot, NULL, ao2_cleanup); RAII_VAR(struct ast_channel_snapshot *, caller_snapshot, NULL, ao2_cleanup);
RAII_VAR(struct ast_channel_snapshot *, agent_snapshot, NULL, ao2_cleanup); RAII_VAR(struct ast_channel_snapshot *, agent_snapshot, NULL, ao2_cleanup);
ast_channel_lock(caller);
caller_snapshot = ast_channel_snapshot_create(caller); caller_snapshot = ast_channel_snapshot_create(caller);
ast_channel_unlock(caller);
ast_channel_lock(agent);
agent_snapshot = ast_channel_snapshot_create(agent); agent_snapshot = ast_channel_snapshot_create(agent);
ast_channel_unlock(agent);
if (!caller_snapshot || !agent_snapshot) { if (!caller_snapshot || !agent_snapshot) {
return; return;
@ -3452,7 +3456,9 @@ static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *
"Queue", q->name, "Queue", q->name,
"Position", qe->pos, "Position", qe->pos,
"Count", q->count); "Count", q->count);
ast_channel_lock(qe->chan);
ast_channel_publish_blob(qe->chan, queue_caller_join_type(), blob); ast_channel_publish_blob(qe->chan, queue_caller_join_type(), blob);
ast_channel_unlock(qe->chan);
ast_debug(1, "Queue '%s' Join, Channel '%s', Position '%d'\n", q->name, ast_channel_name(qe->chan), qe->pos ); ast_debug(1, "Queue '%s' Join, Channel '%s', Position '%d'\n", q->name, ast_channel_name(qe->chan), qe->pos );
} }
ao2_unlock(q); ao2_unlock(q);
@ -3731,7 +3737,9 @@ static void leave_queue(struct queue_ent *qe)
"Queue", q->name, "Queue", q->name,
"Position", qe->pos, "Position", qe->pos,
"Count", q->count); "Count", q->count);
ast_channel_lock(qe->chan);
ast_channel_publish_blob(qe->chan, queue_caller_leave_type(), blob); ast_channel_publish_blob(qe->chan, queue_caller_leave_type(), blob);
ast_channel_unlock(qe->chan);
ast_debug(1, "Queue '%s' Leave, Channel '%s'\n", q->name, ast_channel_name(qe->chan)); ast_debug(1, "Queue '%s' Leave, Channel '%s'\n", q->name, ast_channel_name(qe->chan));
/* Take us out of the queue */ /* Take us out of the queue */
if (prev) { if (prev) {
@ -4329,10 +4337,13 @@ static void record_abandoned(struct queue_ent *qe)
"Position", qe->pos, "Position", qe->pos,
"OriginalPosition", qe->opos, "OriginalPosition", qe->opos,
"HoldTime", (int)(time(NULL) - qe->start)); "HoldTime", (int)(time(NULL) - qe->start));
ast_channel_publish_blob(qe->chan, queue_caller_abandon_type(), blob);
qe->parent->callsabandoned++; qe->parent->callsabandoned++;
ao2_unlock(qe->parent); 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);
} }
/*! \brief RNA == Ring No Answer. Common code that is executed when we try a queue member and they don't answer. */ /*! \brief RNA == Ring No Answer. Common code that is executed when we try a queue member and they don't answer. */

@ -114,7 +114,9 @@ static int userevent_exec(struct ast_channel *chan, const char *data)
} }
} }
ast_channel_lock(chan);
ast_channel_publish_blob(chan, ast_channel_user_event_type(), blob); ast_channel_publish_blob(chan, ast_channel_user_event_type(), blob);
ast_channel_unlock(chan);
return 0; return 0;
} }

@ -10958,8 +10958,11 @@ static int vm_execmain(struct ast_channel *chan, const char *data)
#endif #endif
/* Set language from config to override channel language */ /* Set language from config to override channel language */
if (!ast_strlen_zero(vmu->language)) if (!ast_strlen_zero(vmu->language)) {
ast_channel_lock(chan);
ast_channel_language_set(chan, vmu->language); ast_channel_language_set(chan, vmu->language);
ast_channel_unlock(chan);
}
/* Retrieve urgent, old and new message counts */ /* Retrieve urgent, old and new message counts */
ast_debug(1, "Before open_mailbox\n"); ast_debug(1, "Before open_mailbox\n");

@ -601,7 +601,6 @@ static struct ast_channel *alsa_new(struct chan_alsa_pvt *p, int state, const ch
ast_jb_configure(tmp, &global_jbconf); ast_jb_configure(tmp, &global_jbconf);
ast_channel_stage_snapshot_done(tmp); ast_channel_stage_snapshot_done(tmp);
ast_channel_unlock(tmp); ast_channel_unlock(tmp);
if (state != AST_STATE_DOWN) { if (state != AST_STATE_DOWN) {

@ -444,7 +444,6 @@ static struct ast_channel *console_new(struct console_pvt *pvt, const char *ext,
ast_jb_configure(chan, &global_jbconf); ast_jb_configure(chan, &global_jbconf);
ast_channel_stage_snapshot_done(chan); ast_channel_stage_snapshot_done(chan);
ast_channel_unlock(chan); ast_channel_unlock(chan);
if (state != AST_STATE_DOWN) { if (state != AST_STATE_DOWN) {

@ -1667,7 +1667,9 @@ static void publish_dahdichannel(struct ast_channel *chan, int span, const char
return; return;
} }
ast_channel_lock(chan);
ast_channel_publish_blob(chan, dahdichannel_type(), blob); ast_channel_publish_blob(chan, dahdichannel_type(), blob);
ast_channel_unlock(chan);
} }
/*! /*!
@ -9616,6 +9618,7 @@ static void *analog_ss_thread(void *data)
getforward = 0; getforward = 0;
} else { } else {
res = tone_zone_play_tone(p->subs[idx].dfd, -1); res = tone_zone_play_tone(p->subs[idx].dfd, -1);
ast_channel_lock(chan);
ast_channel_exten_set(chan, exten); ast_channel_exten_set(chan, exten);
if (!ast_strlen_zero(p->cid_num)) { if (!ast_strlen_zero(p->cid_num)) {
if (!p->hidecallerid) if (!p->hidecallerid)
@ -9628,6 +9631,7 @@ static void *analog_ss_thread(void *data)
ast_set_callerid(chan, NULL, p->cid_name, NULL); ast_set_callerid(chan, NULL, p->cid_name, NULL);
} }
ast_setstate(chan, AST_STATE_RING); ast_setstate(chan, AST_STATE_RING);
ast_channel_unlock(chan);
dahdi_ec_enable(p); dahdi_ec_enable(p);
res = ast_pbx_run(chan); res = ast_pbx_run(chan);
if (res) { if (res) {
@ -10391,8 +10395,10 @@ static void *analog_ss_thread(void *data)
my_handle_notify_message(chan, p, flags, -1); my_handle_notify_message(chan, p, flags, -1);
ast_channel_lock(chan);
ast_setstate(chan, AST_STATE_RING); ast_setstate(chan, AST_STATE_RING);
ast_channel_rings_set(chan, 1); ast_channel_rings_set(chan, 1);
ast_channel_unlock(chan);
p->ringt = p->ringt_base; p->ringt = p->ringt_base;
res = ast_pbx_run(chan); res = ast_pbx_run(chan);
if (res) { if (res) {

@ -1226,7 +1226,6 @@ static struct ast_channel *gtalk_new(struct gtalk *client, struct gtalk_pvt *i,
ast_jb_configure(tmp, &global_jbconf); ast_jb_configure(tmp, &global_jbconf);
ast_channel_stage_snapshot_done(tmp); ast_channel_stage_snapshot_done(tmp);
ast_channel_unlock(tmp); ast_channel_unlock(tmp);
if (state != AST_STATE_DOWN && ast_pbx_start(tmp)) { if (state != AST_STATE_DOWN && ast_pbx_start(tmp)) {
@ -1421,7 +1420,9 @@ static int gtalk_newcall(struct gtalk *client, ikspak *pak)
ast_format_cap_joint_copy(p->cap, p->peercap, p->jointcap); ast_format_cap_joint_copy(p->cap, p->peercap, p->jointcap);
ast_mutex_unlock(&p->lock); ast_mutex_unlock(&p->lock);
ast_channel_lock(chan);
ast_setstate(chan, AST_STATE_RING); ast_setstate(chan, AST_STATE_RING);
ast_channel_unlock(chan);
if (ast_format_cap_is_empty(p->jointcap)) { if (ast_format_cap_is_empty(p->jointcap)) {
ast_log(LOG_WARNING, "Capabilities don't match : us - %s, peer - %s, combined - %s \n", ast_getformatname_multiple(s1, BUFSIZ, p->cap), ast_log(LOG_WARNING, "Capabilities don't match : us - %s, peer - %s, combined - %s \n", ast_getformatname_multiple(s1, BUFSIZ, p->cap),
ast_getformatname_multiple(s2, BUFSIZ, p->peercap), ast_getformatname_multiple(s2, BUFSIZ, p->peercap),

@ -5804,7 +5804,6 @@ static struct ast_channel *ast_iax2_new(int callno, int state, iax2_format capab
} }
ast_channel_stage_snapshot_done(tmp); ast_channel_stage_snapshot_done(tmp);
ast_channel_unlock(tmp); ast_channel_unlock(tmp);
if (state != AST_STATE_DOWN) { if (state != AST_STATE_DOWN) {
@ -12237,7 +12236,9 @@ static struct ast_channel *iax2_request(const char *type, struct ast_format_cap
if (c) { if (c) {
struct ast_format_cap *joint; struct ast_format_cap *joint;
if (callid) { if (callid) {
ast_channel_lock(c);
ast_channel_callid_set(c, callid); ast_channel_callid_set(c, callid);
ast_channel_unlock(c);
} }
/* Choose a format we can live with */ /* Choose a format we can live with */

@ -941,7 +941,6 @@ static struct ast_channel *jingle_new(struct jingle *client, struct jingle_pvt *
ast_jb_configure(tmp, &global_jbconf); ast_jb_configure(tmp, &global_jbconf);
ast_channel_stage_snapshot_done(tmp); ast_channel_stage_snapshot_done(tmp);
ast_channel_unlock(tmp); ast_channel_unlock(tmp);
if (state != AST_STATE_DOWN && ast_pbx_start(tmp)) { if (state != AST_STATE_DOWN && ast_pbx_start(tmp)) {
@ -1117,7 +1116,9 @@ static int jingle_newcall(struct jingle *client, ikspak *pak)
} }
ast_mutex_unlock(&p->lock); ast_mutex_unlock(&p->lock);
ast_channel_lock(chan);
ast_setstate(chan, AST_STATE_RING); ast_setstate(chan, AST_STATE_RING);
ast_channel_unlock(chan);
res = ast_pbx_start(chan); res = ast_pbx_start(chan);
switch (res) { switch (res) {

@ -1570,7 +1570,6 @@ static struct ast_channel *mgcp_new(struct mgcp_subchannel *sub, int state, cons
} }
ast_channel_stage_snapshot_done(tmp); ast_channel_stage_snapshot_done(tmp);
ast_channel_unlock(tmp); ast_channel_unlock(tmp);
if (state != AST_STATE_DOWN) { if (state != AST_STATE_DOWN) {
@ -3048,6 +3047,7 @@ static void *mgcp_ss(void *data)
} else { } else {
/*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/ /*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
ast_indicate(chan, -1); ast_indicate(chan, -1);
ast_channel_lock(chan);
ast_channel_exten_set(chan, p->dtmf_buf); ast_channel_exten_set(chan, p->dtmf_buf);
ast_channel_dialed(chan)->number.str = ast_strdup(p->dtmf_buf); ast_channel_dialed(chan)->number.str = ast_strdup(p->dtmf_buf);
memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf)); memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
@ -3056,6 +3056,7 @@ static void *mgcp_ss(void *data)
p->hidecallerid ? "" : p->cid_name, p->hidecallerid ? "" : p->cid_name,
ast_channel_caller(chan)->ani.number.valid ? NULL : p->cid_num); ast_channel_caller(chan)->ani.number.valid ? NULL : p->cid_num);
ast_setstate(chan, AST_STATE_RING); ast_setstate(chan, AST_STATE_RING);
ast_channel_unlock(chan);
if (p->dtmfmode & MGCP_DTMF_HYBRID) { if (p->dtmfmode & MGCP_DTMF_HYBRID) {
p->dtmfmode |= MGCP_DTMF_INBAND; p->dtmfmode |= MGCP_DTMF_INBAND;
ast_indicate(chan, -1); ast_indicate(chan, -1);

@ -5954,7 +5954,9 @@ static int read_config(struct chan_list *ch)
chan_misdn_log(1, port, "read_config: Getting Config\n"); chan_misdn_log(1, port, "read_config: Getting Config\n");
misdn_cfg_get(port, MISDN_CFG_LANGUAGE, lang, sizeof(lang)); misdn_cfg_get(port, MISDN_CFG_LANGUAGE, lang, sizeof(lang));
ast_channel_lock(ast);
ast_channel_language_set(ast, lang); ast_channel_language_set(ast, lang);
ast_channel_unlock(ast);
misdn_cfg_get(port, MISDN_CFG_MUSICCLASS, ch->mohinterpret, sizeof(ch->mohinterpret)); misdn_cfg_get(port, MISDN_CFG_MUSICCLASS, ch->mohinterpret, sizeof(ch->mohinterpret));
@ -6000,7 +6002,9 @@ static int read_config(struct chan_list *ch)
misdn_cfg_get(bc->port, MISDN_CFG_CONTEXT, ch->context, sizeof(ch->context)); misdn_cfg_get(bc->port, MISDN_CFG_CONTEXT, ch->context, sizeof(ch->context));
ast_channel_lock(ast);
ast_channel_context_set(ast, ch->context); ast_channel_context_set(ast, ch->context);
ast_channel_unlock(ast);
#ifdef MISDN_1_2 #ifdef MISDN_1_2
update_pipeline_config(bc); update_pipeline_config(bc);
@ -6017,8 +6021,10 @@ static int read_config(struct chan_list *ch)
misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg)); misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg));
misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg)); misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg));
chan_misdn_log(5, port, " --> * CallGrp:%s PickupGrp:%s\n", ast_print_group(buf, sizeof(buf), cg), ast_print_group(buf2, sizeof(buf2), pg)); chan_misdn_log(5, port, " --> * CallGrp:%s PickupGrp:%s\n", ast_print_group(buf, sizeof(buf), cg), ast_print_group(buf2, sizeof(buf2), pg));
ast_channel_lock(ast);
ast_channel_pickupgroup_set(ast, pg); ast_channel_pickupgroup_set(ast, pg);
ast_channel_callgroup_set(ast, cg); ast_channel_callgroup_set(ast, cg);
ast_channel_unlock(ast);
misdn_cfg_get(port, MISDN_CFG_NAMEDPICKUPGROUP, &npg, sizeof(npg)); misdn_cfg_get(port, MISDN_CFG_NAMEDPICKUPGROUP, &npg, sizeof(npg));
misdn_cfg_get(port, MISDN_CFG_NAMEDCALLGROUP, &ncg, sizeof(ncg)); misdn_cfg_get(port, MISDN_CFG_NAMEDCALLGROUP, &ncg, sizeof(ncg));
@ -6031,8 +6037,10 @@ static int read_config(struct chan_list *ch)
ast_free(tmp_str); ast_free(tmp_str);
} }
ast_channel_lock(ast);
ast_channel_named_pickupgroups_set(ast, npg); ast_channel_named_pickupgroups_set(ast, npg);
ast_channel_named_callgroups_set(ast, ncg); ast_channel_named_callgroups_set(ast, ncg);
ast_channel_unlock(ast);
if (ch->originator == ORG_AST) { if (ch->originator == ORG_AST) {
char callerid[BUFFERSIZE + 1]; char callerid[BUFFERSIZE + 1];
@ -6086,7 +6094,9 @@ static int read_config(struct chan_list *ch)
/* Add configured prefix to dialed.number */ /* Add configured prefix to dialed.number */
misdn_add_number_prefix(bc->port, bc->dialed.number_type, bc->dialed.number, sizeof(bc->dialed.number)); misdn_add_number_prefix(bc->port, bc->dialed.number_type, bc->dialed.number, sizeof(bc->dialed.number));
ast_channel_lock(ast);
ast_channel_exten_set(ast, bc->dialed.number); ast_channel_exten_set(ast, bc->dialed.number);
ast_channel_unlock(ast);
misdn_cfg_get(bc->port, MISDN_CFG_OVERLAP_DIAL, &ch->overlap_dial, sizeof(ch->overlap_dial)); misdn_cfg_get(bc->port, MISDN_CFG_OVERLAP_DIAL, &ch->overlap_dial, sizeof(ch->overlap_dial));
ast_mutex_init(&ch->overlap_tv_lock); ast_mutex_init(&ch->overlap_tv_lock);
@ -10232,8 +10242,10 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
export_ch(chan, bc, ch); export_ch(chan, bc, ch);
ast_channel_lock(ch->ast);
ast_channel_rings_set(ch->ast, 1); ast_channel_rings_set(ch->ast, 1);
ast_setstate(ch->ast, AST_STATE_RINGING); ast_setstate(ch->ast, AST_STATE_RINGING);
ast_channel_unlock(ch->ast);
/* Update asterisk channel caller information */ /* Update asterisk channel caller information */
chan_misdn_log(2, bc->port, " --> TON: %s(%d)\n", misdn_to_str_ton(bc->caller.number_type), bc->caller.number_type); chan_misdn_log(2, bc->port, " --> TON: %s(%d)\n", misdn_to_str_ton(bc->caller.number_type), bc->caller.number_type);
@ -10532,7 +10544,9 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
} }
ast_queue_control(ch->ast, AST_CONTROL_RINGING); ast_queue_control(ch->ast, AST_CONTROL_RINGING);
ast_channel_lock(ch->ast);
ast_setstate(ch->ast, AST_STATE_RINGING); ast_setstate(ch->ast, AST_STATE_RINGING);
ast_channel_unlock(ch->ast);
cb_log(7, bc->port, " --> Set State Ringing\n"); cb_log(7, bc->port, " --> Set State Ringing\n");

@ -852,7 +852,6 @@ static struct ast_channel *jingle_new(struct jingle_endpoint *endpoint, struct j
ao2_unlock(endpoint); ao2_unlock(endpoint);
ast_channel_stage_snapshot_done(chan); ast_channel_stage_snapshot_done(chan);
ast_channel_unlock(chan); ast_channel_unlock(chan);
return chan; return chan;
@ -2414,7 +2413,9 @@ static void jingle_action_session_initiate(struct jingle_endpoint *endpoint, str
ao2_link(endpoint->state->sessions, session); ao2_link(endpoint->state->sessions, session);
ast_channel_lock(chan);
ast_setstate(chan, AST_STATE_RING); ast_setstate(chan, AST_STATE_RING);
ast_channel_unlock(chan);
res = ast_pbx_start(chan); res = ast_pbx_start(chan);
switch (res) { switch (res) {

@ -799,6 +799,7 @@ static struct ast_channel *oss_new(struct chan_oss_pvt *o, char *ext, char *ctx,
c = ast_channel_alloc(1, state, o->cid_num, o->cid_name, "", ext, ctx, linkedid, 0, "Console/%s", o->device + 5); c = ast_channel_alloc(1, state, o->cid_num, o->cid_name, "", ext, ctx, linkedid, 0, "Console/%s", o->device + 5);
if (c == NULL) if (c == NULL)
return NULL; return NULL;
ast_channel_lock(c);
ast_channel_tech_set(c, &oss_tech); ast_channel_tech_set(c, &oss_tech);
if (o->sounddev < 0) if (o->sounddev < 0)
setformat(o, O_RDWR); setformat(o, O_RDWR);

@ -862,6 +862,7 @@ static struct ast_channel *phone_new(struct phone_pvt *i, int state, char *cntx,
struct ast_format tmpfmt; struct ast_format tmpfmt;
tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, "", i->ext, i->context, linkedid, 0, "Phone/%s", i->dev + 5); tmp = ast_channel_alloc(1, state, i->cid_num, i->cid_name, "", i->ext, i->context, linkedid, 0, "Phone/%s", i->dev + 5);
if (tmp) { if (tmp) {
ast_channel_lock(tmp);
ast_channel_tech_set(tmp, cur_tech); ast_channel_tech_set(tmp, cur_tech);
ast_channel_set_fd(tmp, 0, i->fd); ast_channel_set_fd(tmp, 0, i->fd);
/* XXX Switching formats silently causes kernel panics XXX */ /* XXX Switching formats silently causes kernel panics XXX */

@ -364,6 +364,7 @@ static struct ast_channel *chan_pjsip_new(struct ast_sip_session *session, int s
return NULL; return NULL;
} }
ast_channel_stage_snapshot(chan); ast_channel_stage_snapshot(chan);
ast_channel_tech_pvt_set(chan, channel); ast_channel_tech_pvt_set(chan, channel);
@ -1835,9 +1836,11 @@ static void chan_pjsip_incoming_response(struct ast_sip_session *session, struct
switch (status.code) { switch (status.code) {
case 180: case 180:
ast_queue_control(session->channel, AST_CONTROL_RINGING); ast_queue_control(session->channel, AST_CONTROL_RINGING);
ast_channel_lock(session->channel);
if (ast_channel_state(session->channel) != AST_STATE_UP) { if (ast_channel_state(session->channel) != AST_STATE_UP) {
ast_setstate(session->channel, AST_STATE_RINGING); ast_setstate(session->channel, AST_STATE_RINGING);
} }
ast_channel_unlock(session->channel);
break; break;
case 183: case 183:
ast_queue_control(session->channel, AST_CONTROL_PROGRESS); ast_queue_control(session->channel, AST_CONTROL_PROGRESS);

@ -4845,6 +4845,7 @@ static void *skinny_newcall(void *data)
struct skinny_device *d = l->device; struct skinny_device *d = l->device;
int res = 0; int res = 0;
ast_channel_lock(c);
ast_set_callerid(c, ast_set_callerid(c,
l->hidecallerid ? "" : l->cid_num, l->hidecallerid ? "" : l->cid_num,
l->hidecallerid ? "" : l->cid_name, l->hidecallerid ? "" : l->cid_name,
@ -4858,6 +4859,7 @@ static void *skinny_newcall(void *data)
ast_party_name_init(&ast_channel_connected(c)->id.name); ast_party_name_init(&ast_channel_connected(c)->id.name);
#endif #endif
ast_setstate(c, AST_STATE_RING); ast_setstate(c, AST_STATE_RING);
ast_channel_unlock(c);
if (!sub->rtp) { if (!sub->rtp) {
start_rtp(sub); start_rtp(sub);
} }
@ -5501,7 +5503,6 @@ static struct ast_channel *skinny_new(struct skinny_line *l, struct skinny_subli
pbx_builtin_setvar_helper(tmp, v->name, v->value); pbx_builtin_setvar_helper(tmp, v->name, v->value);
ast_channel_stage_snapshot_done(tmp); ast_channel_stage_snapshot_done(tmp);
ast_channel_unlock(tmp); ast_channel_unlock(tmp);
if (state != AST_STATE_DOWN) { if (state != AST_STATE_DOWN) {

@ -2517,10 +2517,12 @@ static void *unistim_ss(void *data)
int res; int res;
ast_verb(3, "Starting switch on '%s@%s-%d' to %s\n", l->name, l->parent->name, sub->softkey, s->device->phone_number); ast_verb(3, "Starting switch on '%s@%s-%d' to %s\n", l->name, l->parent->name, sub->softkey, s->device->phone_number);
ast_channel_lock(chan);
ast_channel_exten_set(chan, s->device->phone_number); ast_channel_exten_set(chan, s->device->phone_number);
ast_setstate(chan, AST_STATE_RING);
ast_channel_unlock(chan);
ast_copy_string(s->device->redial_number, s->device->phone_number, ast_copy_string(s->device->redial_number, s->device->phone_number,
sizeof(s->device->redial_number)); sizeof(s->device->redial_number));
ast_setstate(chan, AST_STATE_RING);
res = ast_pbx_run(chan); res = ast_pbx_run(chan);
if (res) { if (res) {
ast_log(LOG_WARNING, "PBX exited non-zero\n"); ast_log(LOG_WARNING, "PBX exited non-zero\n");
@ -5627,7 +5629,6 @@ static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state
ast_channel_priority_set(tmp, 1); ast_channel_priority_set(tmp, 1);
ast_channel_stage_snapshot_done(tmp); ast_channel_stage_snapshot_done(tmp);
ast_channel_unlock(tmp); ast_channel_unlock(tmp);
if (state != AST_STATE_DOWN) { if (state != AST_STATE_DOWN) {

@ -2471,7 +2471,6 @@ static struct ast_channel *vpb_new(struct vpb_pvt *me, enum ast_channel_state st
ast_channel_exten_set(tmp, "s"); ast_channel_exten_set(tmp, "s");
if (!ast_strlen_zero(me->language)) if (!ast_strlen_zero(me->language))
ast_channel_language_set(tmp, me->language); ast_channel_language_set(tmp, me->language);
ast_channel_unlock(tmp); ast_channel_unlock(tmp);
me->owner = tmp; me->owner = tmp;

@ -2120,6 +2120,7 @@ static void *__analog_ss_thread(void *data)
getforward = 0; getforward = 0;
} else { } else {
res = analog_play_tone(p, idx, -1); res = analog_play_tone(p, idx, -1);
ast_channel_lock(chan);
ast_channel_exten_set(chan, exten); ast_channel_exten_set(chan, exten);
if (!ast_strlen_zero(p->cid_num)) { if (!ast_strlen_zero(p->cid_num)) {
if (!p->hidecallerid) { if (!p->hidecallerid) {
@ -2134,6 +2135,7 @@ static void *__analog_ss_thread(void *data)
} }
} }
ast_setstate(chan, AST_STATE_RING); ast_setstate(chan, AST_STATE_RING);
ast_channel_unlock(chan);
analog_set_echocanceller(p, 1); analog_set_echocanceller(p, 1);
res = ast_pbx_run(chan); res = ast_pbx_run(chan);
if (res) { if (res) {
@ -2615,8 +2617,10 @@ static void *__analog_ss_thread(void *data)
analog_handle_notify_message(chan, p, flags, -1); analog_handle_notify_message(chan, p, flags, -1);
ast_channel_lock(chan);
ast_setstate(chan, AST_STATE_RING); ast_setstate(chan, AST_STATE_RING);
ast_channel_rings_set(chan, 1); ast_channel_rings_set(chan, 1);
ast_channel_unlock(chan);
analog_set_ringtimeout(p, p->ringt_base); analog_set_ringtimeout(p, p->ringt_base);
res = ast_pbx_run(chan); res = ast_pbx_run(chan);
if (res) { if (res) {

@ -2160,7 +2160,9 @@ static void *pri_ss_thread(void *data)
#endif /* defined(ISSUE_16789) */ #endif /* defined(ISSUE_16789) */
sig_pri_set_echocanceller(p, 1); sig_pri_set_echocanceller(p, 1);
ast_channel_lock(chan);
ast_setstate(chan, AST_STATE_RING); ast_setstate(chan, AST_STATE_RING);
ast_channel_unlock(chan);
res = ast_pbx_run(chan); res = ast_pbx_run(chan);
if (res) { if (res) {
ast_log(LOG_WARNING, "PBX exited non-zero!\n"); ast_log(LOG_WARNING, "PBX exited non-zero!\n");

@ -155,7 +155,9 @@ static int timeout_write(struct ast_channel *chan, const char *cmd, char *data,
switch (*data) { switch (*data) {
case 'a': case 'a':
case 'A': case 'A':
ast_channel_lock(chan);
ast_channel_setwhentohangup_tv(chan, when); ast_channel_setwhentohangup_tv(chan, when);
ast_channel_unlock(chan);
if (!ast_tvzero(*ast_channel_whentohangup(chan))) { if (!ast_tvzero(*ast_channel_whentohangup(chan))) {
when = ast_tvadd(when, ast_tvnow()); when = ast_tvadd(when, ast_tvnow());
ast_strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S.%3q %Z", ast_strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S.%3q %Z",

@ -497,7 +497,10 @@ int ast_aoc_s_add_special_arrangement(struct ast_aoc_decoded *decoded,
*/ */
int ast_aoc_decoded2str(const struct ast_aoc_decoded *decoded, struct ast_str **msg); int ast_aoc_decoded2str(const struct ast_aoc_decoded *decoded, struct ast_str **msg);
/*! \brief generate AOC manager event for an AOC-S, AOC-D, or AOC-E msg */ /*!
* \brief generate AOC manager event for an AOC-S, AOC-D, or AOC-E msg
* \pre chan is locked
*/
int ast_aoc_manager_event(const struct ast_aoc_decoded *decoded, struct ast_channel *chan); int ast_aoc_manager_event(const struct ast_aoc_decoded *decoded, struct ast_channel *chan);
/*! \brief get the message type, AOC-D, AOC-E, or AOC Request */ /*! \brief get the message type, AOC-D, AOC-E, or AOC Request */

@ -1538,8 +1538,7 @@ int ast_channel_cmpwhentohangup_tv(struct ast_channel *chan, struct timeval offs
* \details * \details
* This function sets the absolute time out on a channel (when to hang up). * This function sets the absolute time out on a channel (when to hang up).
* *
* \note This function does not require that the channel is locked before * \pre chan is locked
* calling it.
* *
* \return Nothing * \return Nothing
* \sa ast_channel_setwhentohangup_tv() * \sa ast_channel_setwhentohangup_tv()
@ -1555,8 +1554,7 @@ void ast_channel_setwhentohangup(struct ast_channel *chan, time_t offset) __attr
* *
* This function sets the absolute time out on a channel (when to hang up). * This function sets the absolute time out on a channel (when to hang up).
* *
* \note This function does not require that the channel is locked before * \pre chan is locked
* calling it.
* *
* \return Nothing * \return Nothing
* \since 1.6.1 * \since 1.6.1
@ -2340,6 +2338,8 @@ void ast_channel_inherit_variables(const struct ast_channel *parent, struct ast_
* \param chan the channel * \param chan the channel
* \param vars a linked list of variables * \param vars a linked list of variables
* *
* \pre chan is locked
*
* \details * \details
* Variable names can be for a regular channel variable or a dialplan function * Variable names can be for a regular channel variable or a dialplan function
* that has the ability to be written to. * that has the ability to be written to.
@ -3806,6 +3806,15 @@ void ast_channel_name_set(struct ast_channel *chan, const char *name);
void ast_channel_##field##_build_va(struct ast_channel *chan, const char *fmt, va_list ap) __attribute__((format(printf, 2, 0))); \ void ast_channel_##field##_build_va(struct ast_channel *chan, const char *fmt, va_list ap) __attribute__((format(printf, 2, 0))); \
void ast_channel_##field##_build(struct ast_channel *chan, const char *fmt, ...) __attribute__((format(printf, 2, 3))) void ast_channel_##field##_build(struct ast_channel *chan, const char *fmt, ...) __attribute__((format(printf, 2, 3)))
/*!
* The following string fields result in channel snapshot creation and
* should have the channel locked when called:
*
* \li language
* \li accountcode
* \li peeracccount
* \li linkedid
*/
DECLARE_STRINGFIELD_SETTERS_FOR(name); DECLARE_STRINGFIELD_SETTERS_FOR(name);
DECLARE_STRINGFIELD_SETTERS_FOR(language); DECLARE_STRINGFIELD_SETTERS_FOR(language);
DECLARE_STRINGFIELD_SETTERS_FOR(musicclass); DECLARE_STRINGFIELD_SETTERS_FOR(musicclass);
@ -3857,6 +3866,10 @@ void ast_channel_sending_dtmf_digit_set(struct ast_channel *chan, char value);
struct timeval ast_channel_sending_dtmf_tv(const struct ast_channel *chan); struct timeval ast_channel_sending_dtmf_tv(const struct ast_channel *chan);
void ast_channel_sending_dtmf_tv_set(struct ast_channel *chan, struct timeval value); void ast_channel_sending_dtmf_tv_set(struct ast_channel *chan, struct timeval value);
enum ama_flags ast_channel_amaflags(const struct ast_channel *chan); enum ama_flags ast_channel_amaflags(const struct ast_channel *chan);
/*!
* \pre chan is locked
*/
void ast_channel_amaflags_set(struct ast_channel *chan, enum ama_flags value); void ast_channel_amaflags_set(struct ast_channel *chan, enum ama_flags value);
int ast_channel_epfd(const struct ast_channel *chan); int ast_channel_epfd(const struct ast_channel *chan);
void ast_channel_epfd_set(struct ast_channel *chan, int value); void ast_channel_epfd_set(struct ast_channel *chan, int value);
@ -3940,6 +3953,10 @@ enum ast_channel_adsicpe ast_channel_adsicpe(const struct ast_channel *chan);
void ast_channel_adsicpe_set(struct ast_channel *chan, enum ast_channel_adsicpe value); void ast_channel_adsicpe_set(struct ast_channel *chan, enum ast_channel_adsicpe value);
enum ast_channel_state ast_channel_state(const struct ast_channel *chan); enum ast_channel_state ast_channel_state(const struct ast_channel *chan);
struct ast_callid *ast_channel_callid(const struct ast_channel *chan); struct ast_callid *ast_channel_callid(const struct ast_channel *chan);
/*!
* \pre chan is locked
*/
void ast_channel_callid_set(struct ast_channel *chan, struct ast_callid *value); void ast_channel_callid_set(struct ast_channel *chan, struct ast_callid *value);
/* XXX Internal use only, make sure to move later */ /* XXX Internal use only, make sure to move later */
@ -3980,6 +3997,10 @@ void ast_channel_connected_set(struct ast_channel *chan, struct ast_party_connec
void ast_channel_dialed_set(struct ast_channel *chan, struct ast_party_dialed *value); void ast_channel_dialed_set(struct ast_channel *chan, struct ast_party_dialed *value);
void ast_channel_redirecting_set(struct ast_channel *chan, struct ast_party_redirecting *value); void ast_channel_redirecting_set(struct ast_channel *chan, struct ast_party_redirecting *value);
void ast_channel_dtmf_tv_set(struct ast_channel *chan, struct timeval *value); void ast_channel_dtmf_tv_set(struct ast_channel *chan, struct timeval *value);
/*!
* \pre chan is locked
*/
void ast_channel_whentohangup_set(struct ast_channel *chan, struct timeval *value); void ast_channel_whentohangup_set(struct ast_channel *chan, struct timeval *value);
void ast_channel_varshead_set(struct ast_channel *chan, struct varshead *value); void ast_channel_varshead_set(struct ast_channel *chan, struct varshead *value);
struct timeval ast_channel_creationtime(struct ast_channel *chan); struct timeval ast_channel_creationtime(struct ast_channel *chan);
@ -3995,8 +4016,14 @@ struct ast_readq_list *ast_channel_readq(struct ast_channel *chan);
/* Typedef accessors */ /* Typedef accessors */
ast_group_t ast_channel_callgroup(const struct ast_channel *chan); ast_group_t ast_channel_callgroup(const struct ast_channel *chan);
/*!
* \pre chan is locked
*/
void ast_channel_callgroup_set(struct ast_channel *chan, ast_group_t value); void ast_channel_callgroup_set(struct ast_channel *chan, ast_group_t value);
ast_group_t ast_channel_pickupgroup(const struct ast_channel *chan); ast_group_t ast_channel_pickupgroup(const struct ast_channel *chan);
/*!
* \pre chan is locked
*/
void ast_channel_pickupgroup_set(struct ast_channel *chan, ast_group_t value); void ast_channel_pickupgroup_set(struct ast_channel *chan, ast_group_t value);
struct ast_namedgroups *ast_channel_named_callgroups(const struct ast_channel *chan); struct ast_namedgroups *ast_channel_named_callgroups(const struct ast_channel *chan);
void ast_channel_named_callgroups_set(struct ast_channel *chan, struct ast_namedgroups *value); void ast_channel_named_callgroups_set(struct ast_channel *chan, struct ast_namedgroups *value);
@ -4043,6 +4070,9 @@ ast_timing_func_t ast_channel_timingfunc(const struct ast_channel *chan);
void ast_channel_timingfunc_set(struct ast_channel *chan, ast_timing_func_t value); void ast_channel_timingfunc_set(struct ast_channel *chan, ast_timing_func_t value);
struct ast_bridge *ast_channel_internal_bridge(const struct ast_channel *chan); struct ast_bridge *ast_channel_internal_bridge(const struct ast_channel *chan);
/*!
* \pre chan is locked
*/
void ast_channel_internal_bridge_set(struct ast_channel *chan, struct ast_bridge *value); void ast_channel_internal_bridge_set(struct ast_channel *chan, struct ast_bridge *value);
struct ast_bridge_channel *ast_channel_internal_bridge_channel(const struct ast_channel *chan); struct ast_bridge_channel *ast_channel_internal_bridge_channel(const struct ast_channel *chan);

@ -47,7 +47,10 @@ enum ast_channel_state {
AST_STATE_MUTE = (1 << 16), /*!< Do not transmit voice data */ AST_STATE_MUTE = (1 << 16), /*!< Do not transmit voice data */
}; };
/*! \brief Change the state of a channel */ /*!
* \brief Change the state of a channel
* \pre chan is locked
*/
int ast_setstate(struct ast_channel *chan, enum ast_channel_state); int ast_setstate(struct ast_channel *chan, enum ast_channel_state);
#endif /* __AST_CHANNELSTATE_H__ */ #endif /* __AST_CHANNELSTATE_H__ */

@ -203,6 +203,9 @@ struct stasis_message_type *ast_channel_left_bridge_type(void);
* should also be treated as immutable and not modified after it is put into the * should also be treated as immutable and not modified after it is put into the
* message. * message.
* *
* \pre bridge is locked.
* \pre No channels are locked.
*
* \param bridge Channel blob is associated with, or NULL for global/all bridges. * \param bridge Channel blob is associated with, or NULL for global/all bridges.
* \param blob JSON object representing the data. * \param blob JSON object representing the data.
* \return \ref ast_bridge_blob message. * \return \ref ast_bridge_blob message.
@ -217,6 +220,9 @@ struct stasis_message *ast_bridge_blob_create(struct stasis_message_type *type,
* \since 12 * \since 12
* \brief Publish a bridge channel enter event * \brief Publish a bridge channel enter event
* *
* \pre bridge is locked.
* \pre No channels are locked.
*
* \param bridge The bridge a channel entered * \param bridge The bridge a channel entered
* \param chan The channel that entered the bridge * \param chan The channel that entered the bridge
* \param swap The channel being swapped out of the bridge * \param swap The channel being swapped out of the bridge
@ -228,6 +234,9 @@ void ast_bridge_publish_enter(struct ast_bridge *bridge, struct ast_channel *cha
* \since 12 * \since 12
* \brief Publish a bridge channel leave event * \brief Publish a bridge channel leave event
* *
* \pre bridge is locked.
* \pre No channels are locked.
*
* \param bridge The bridge a channel left * \param bridge The bridge a channel left
* \param chan The channel that left the bridge * \param chan The channel that left the bridge
*/ */
@ -272,6 +281,8 @@ struct stasis_message_type *ast_blind_transfer_type(void);
/*! /*!
* \brief Publish a blind transfer event * \brief Publish a blind transfer event
* *
* \pre No channels or bridges are locked
*
* \param is_external Whether the blind transfer was initiated externally (e.g. via AMI or native protocol) * \param is_external Whether the blind transfer was initiated externally (e.g. via AMI or native protocol)
* \param result The success or failure of the transfer * \param result The success or failure of the transfer
* \param to_transferee The bridge between the transferer and transferee plus the transferer channel * \param to_transferee The bridge between the transferer and transferee plus the transferer channel
@ -335,6 +346,8 @@ struct stasis_message_type *ast_attended_transfer_type(void);
* Publish an \ref ast_attended_transfer_message with the dest_type set to * Publish an \ref ast_attended_transfer_message with the dest_type set to
* \c AST_ATTENDED_TRANSFER_DEST_FAIL. * \c AST_ATTENDED_TRANSFER_DEST_FAIL.
* *
* \pre No channels or bridges are locked
*
* \param is_external Indicates if the transfer was initiated externally * \param is_external Indicates if the transfer was initiated externally
* \param result The result of the transfer. Will always be a type of failure. * \param result The result of the transfer. Will always be a type of failure.
* \param transferee The bridge between the transferer and transferees as well as the transferer channel from that bridge * \param transferee The bridge between the transferer and transferees as well as the transferer channel from that bridge
@ -356,6 +369,8 @@ void ast_bridge_publish_attended_transfer_fail(int is_external, enum ast_transfe
* *
* In either case, two bridges enter, one leaves. * In either case, two bridges enter, one leaves.
* *
* \pre No channels or bridges are locked
*
* \param is_external Indicates if the transfer was initiated externally * \param is_external Indicates if the transfer was initiated externally
* \param result The result of the transfer. * \param result The result of the transfer.
* \param transferee The bridge between the transferer and transferees as well as the transferer channel from that bridge * \param transferee The bridge between the transferer and transferees as well as the transferer channel from that bridge
@ -375,6 +390,8 @@ void ast_bridge_publish_attended_transfer_bridge_merge(int is_external, enum ast
* this results from merging two bridges together. The difference is that a * this results from merging two bridges together. The difference is that a
* transferer channel survives the bridge merge * transferer channel survives the bridge merge
* *
* \pre No channels or bridges are locked
*
* \param is_external Indicates if the transfer was initiated externally * \param is_external Indicates if the transfer was initiated externally
* \param result The result of the transfer. * \param result The result of the transfer.
* \param transferee The bridge between the transferer and transferees as well as the transferer channel from that bridge * \param transferee The bridge between the transferer and transferees as well as the transferer channel from that bridge
@ -396,6 +413,8 @@ void ast_bridge_publish_attended_transfer_threeway(int is_external, enum ast_tra
* \li A transferee channel leaving a bridge to run an app * \li A transferee channel leaving a bridge to run an app
* \li A bridge of transferees running an app (via a local channel) * \li A bridge of transferees running an app (via a local channel)
* *
* \pre No channels or bridges are locked
*
* \param is_external Indicates if the transfer was initiated externally * \param is_external Indicates if the transfer was initiated externally
* \param result The result of the transfer. * \param result The result of the transfer.
* \param transferee The bridge between the transferer and transferees as well as the transferer channel from that bridge * \param transferee The bridge between the transferer and transferees as well as the transferer channel from that bridge
@ -419,6 +438,8 @@ void ast_bridge_publish_attended_transfer_app(int is_external, enum ast_transfer
* When this type of transfer occurs, the two bridges continue to exist after the * When this type of transfer occurs, the two bridges continue to exist after the
* transfer and a local channel is used to link the two bridges together. * transfer and a local channel is used to link the two bridges together.
* *
* \pre No channels or bridges are locked
*
* \param is_external Indicates if the transfer was initiated externally * \param is_external Indicates if the transfer was initiated externally
* \param result The result of the transfer. * \param result The result of the transfer.
* \param transferee The bridge between the transferer and transferees as well as the transferer channel from that bridge * \param transferee The bridge between the transferer and transferees as well as the transferer channel from that bridge

@ -153,6 +153,8 @@ struct stasis_message_type *ast_channel_snapshot_type(void);
* \brief Generate a snapshot of the channel state. This is an ao2 object, so * \brief Generate a snapshot of the channel state. This is an ao2 object, so
* ao2_cleanup() to deallocate. * ao2_cleanup() to deallocate.
* *
* \pre chan is locked
*
* \param chan The channel from which to generate a snapshot * \param chan The channel from which to generate a snapshot
* *
* \retval pointer on success (must be unreffed) * \retval pointer on success (must be unreffed)
@ -192,6 +194,8 @@ struct ast_channel_snapshot *ast_channel_snapshot_get_latest_by_name(const char
* The given \a blob should be treated as immutable and not modified after it is * The given \a blob should be treated as immutable and not modified after it is
* put into the message. * put into the message.
* *
* \pre chan is locked
*
* \param chan Channel blob is associated with, or \c NULL for global/all channels. * \param chan Channel blob is associated with, or \c NULL for global/all channels.
* \param type Message type for this blob. * \param type Message type for this blob.
* \param blob JSON object representing the data, or \c NULL for no data. If * \param blob JSON object representing the data, or \c NULL for no data. If
@ -305,6 +309,8 @@ void ast_multi_channel_blob_add_channel(struct ast_multi_channel_blob *obj,
* \brief Publish a channel blob message. * \brief Publish a channel blob message.
* \since 12.0.0 * \since 12.0.0
* *
* \pre chan is locked
*
* \param chan Channel publishing the blob. * \param chan Channel publishing the blob.
* \param type Type of stasis message. * \param type Type of stasis message.
* \param blob The blob being published. (NULL if no blob) * \param blob The blob being published. (NULL if no blob)
@ -318,6 +324,8 @@ void ast_channel_publish_blob(struct ast_channel *chan, struct stasis_message_ty
* \since 12 * \since 12
* \brief Set flag to indicate channel snapshot is being staged. * \brief Set flag to indicate channel snapshot is being staged.
* *
* \pre chan is locked
*
* \param chan Channel being staged. * \param chan Channel being staged.
*/ */
void ast_channel_stage_snapshot(struct ast_channel *chan); void ast_channel_stage_snapshot(struct ast_channel *chan);
@ -326,6 +334,8 @@ void ast_channel_stage_snapshot(struct ast_channel *chan);
* \since 12 * \since 12
* \brief Clear flag to indicate channel snapshot is being staged, and publish snapshot. * \brief Clear flag to indicate channel snapshot is being staged, and publish snapshot.
* *
* \pre chan is locked
*
* \param chan Channel being staged. * \param chan Channel being staged.
*/ */
void ast_channel_stage_snapshot_done(struct ast_channel *chan); void ast_channel_stage_snapshot_done(struct ast_channel *chan);
@ -334,6 +344,8 @@ void ast_channel_stage_snapshot_done(struct ast_channel *chan);
* \since 12 * \since 12
* \brief Publish a \ref ast_channel_snapshot for a channel. * \brief Publish a \ref ast_channel_snapshot for a channel.
* *
* \pre chan is locked
*
* \param chan Channel to publish. * \param chan Channel to publish.
*/ */
void ast_channel_publish_snapshot(struct ast_channel *chan); void ast_channel_publish_snapshot(struct ast_channel *chan);
@ -342,6 +354,8 @@ void ast_channel_publish_snapshot(struct ast_channel *chan);
* \since 12 * \since 12
* \brief Publish a \ref ast_channel_varset for a channel. * \brief Publish a \ref ast_channel_varset for a channel.
* *
* \pre chan is locked
*
* \param chan Channel to publish the event for, or \c NULL for 'none'. * \param chan Channel to publish the event for, or \c NULL for 'none'.
* \param variable Name of the variable being set * \param variable Name of the variable being set
* \param value Value. * \param value Value.
@ -535,6 +549,8 @@ void ast_channel_publish_dial_forward(struct ast_channel *caller,
* \brief Publish in the \ref ast_channel_topic a \ref ast_channel_snapshot * \brief Publish in the \ref ast_channel_topic a \ref ast_channel_snapshot
* message indicating a change in channel state * message indicating a change in channel state
* *
* \pre chan is locked
*
* \param chan The channel whose state has changed * \param chan The channel whose state has changed
*/ */
void ast_publish_channel_state(struct ast_channel *chan); void ast_publish_channel_state(struct ast_channel *chan);

@ -2524,7 +2524,13 @@ static int try_swap_optimize_out(struct ast_bridge *chan_bridge,
other = ast_bridge_channel_peer(src_bridge_channel); other = ast_bridge_channel_peer(src_bridge_channel);
if (other && other->state == BRIDGE_CHANNEL_STATE_WAIT) { if (other && other->state == BRIDGE_CHANNEL_STATE_WAIT) {
unsigned int id = ast_atomic_fetchadd_int((int *) &optimization_id, +1); unsigned int id;
if (ast_channel_trylock(other->chan)) {
return 1;
}
id = ast_atomic_fetchadd_int((int *) &optimization_id, +1);
ast_verb(3, "Move-swap optimizing %s <-- %s.\n", ast_verb(3, "Move-swap optimizing %s <-- %s.\n",
ast_channel_name(dst_bridge_channel->chan), ast_channel_name(dst_bridge_channel->chan),
@ -2546,6 +2552,7 @@ static int try_swap_optimize_out(struct ast_bridge *chan_bridge,
if (pvt && pvt->callbacks && pvt->callbacks->optimization_finished) { if (pvt && pvt->callbacks && pvt->callbacks->optimization_finished) {
pvt->callbacks->optimization_finished(pvt, res == 1, id); pvt->callbacks->optimization_finished(pvt, res == 1, id);
} }
ast_channel_unlock(other->chan);
} }
return res; return res;
} }

@ -235,12 +235,16 @@ void ast_bridge_channel_update_linkedids(struct ast_bridge_channel *bridge_chann
return; return;
} }
ast_channel_lock(bridge_channel->chan);
ast_channel_linkedid_set(bridge_channel->chan, oldest_linkedid); ast_channel_linkedid_set(bridge_channel->chan, oldest_linkedid);
ast_channel_unlock(bridge_channel->chan);
AST_LIST_TRAVERSE(&bridge->channels, other, entry) { AST_LIST_TRAVERSE(&bridge->channels, other, entry) {
if (other == swap) { if (other == swap) {
continue; continue;
} }
ast_channel_lock(other->chan);
ast_channel_linkedid_set(other->chan, oldest_linkedid); ast_channel_linkedid_set(other->chan, oldest_linkedid);
ast_channel_unlock(other->chan);
} }
} }
@ -253,6 +257,7 @@ void ast_bridge_channel_update_accountcodes(struct ast_bridge_channel *bridge_ch
if (other == swap) { if (other == swap) {
continue; continue;
} }
ast_channel_lock_both(bridge_channel->chan, other->chan);
if (!ast_strlen_zero(ast_channel_accountcode(bridge_channel->chan)) && ast_strlen_zero(ast_channel_peeraccount(other->chan))) { if (!ast_strlen_zero(ast_channel_accountcode(bridge_channel->chan)) && ast_strlen_zero(ast_channel_peeraccount(other->chan))) {
ast_debug(1, "Setting peeraccount to %s for %s from data on channel %s\n", ast_debug(1, "Setting peeraccount to %s for %s from data on channel %s\n",
@ -286,6 +291,8 @@ void ast_bridge_channel_update_accountcodes(struct ast_bridge_channel *bridge_ch
ast_channel_peeraccount_set(bridge_channel->chan, ast_channel_accountcode(other->chan)); ast_channel_peeraccount_set(bridge_channel->chan, ast_channel_accountcode(other->chan));
} }
} }
ast_channel_unlock(bridge_channel->chan);
ast_channel_unlock(other->chan);
} }
} }
@ -624,14 +631,18 @@ int ast_bridge_channel_write_hold(struct ast_bridge_channel *bridge_channel, con
datalen = 0; datalen = 0;
} }
ast_channel_lock(bridge_channel->chan);
ast_channel_publish_blob(bridge_channel->chan, ast_channel_hold_type(), blob); ast_channel_publish_blob(bridge_channel->chan, ast_channel_hold_type(), blob);
ast_channel_unlock(bridge_channel->chan);
return ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_HOLD, return ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_HOLD,
moh_class, datalen); moh_class, datalen);
} }
int ast_bridge_channel_write_unhold(struct ast_bridge_channel *bridge_channel) 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_publish_blob(bridge_channel->chan, ast_channel_unhold_type(), NULL);
ast_channel_unlock(bridge_channel->chan);
return ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_UNHOLD, NULL, 0); return ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_UNHOLD, NULL, 0);
} }

@ -1614,7 +1614,9 @@ void ast_cel_publish_event(struct ast_channel *chan,
"event_type", event_type, "event_type", event_type,
"event_details", blob); "event_details", blob);
ast_channel_lock(chan);
message = ast_channel_blob_create(chan, cel_generic_type(), cel_blob); message = ast_channel_blob_create(chan, cel_generic_type(), cel_blob);
ast_channel_unlock(chan);
if (message) { if (message) {
stasis_publish(ast_cel_topic(), message); stasis_publish(ast_cel_topic(), message);
} }

@ -678,7 +678,9 @@ int ast_str2cause(const char *name)
static struct stasis_message *create_channel_snapshot_message(struct ast_channel *channel) static struct stasis_message *create_channel_snapshot_message(struct ast_channel *channel)
{ {
RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup); RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
ast_channel_lock(channel);
snapshot = ast_channel_snapshot_create(channel); snapshot = ast_channel_snapshot_create(channel);
ast_channel_unlock(channel);
if (!snapshot) { if (!snapshot) {
return NULL; return NULL;
} }
@ -1267,6 +1269,7 @@ int ast_queue_hold(struct ast_channel *chan, const char *musicclass)
struct ast_frame f = { AST_FRAME_CONTROL, .subclass.integer = AST_CONTROL_HOLD }; struct ast_frame f = { AST_FRAME_CONTROL, .subclass.integer = AST_CONTROL_HOLD };
int res; int res;
ast_channel_lock(chan);
if (!ast_strlen_zero(musicclass)) { if (!ast_strlen_zero(musicclass)) {
f.data.ptr = (void *) musicclass; f.data.ptr = (void *) musicclass;
f.datalen = strlen(musicclass) + 1; f.datalen = strlen(musicclass) + 1;
@ -1278,6 +1281,7 @@ int ast_queue_hold(struct ast_channel *chan, const char *musicclass)
ast_channel_publish_blob(chan, ast_channel_hold_type(), blob); ast_channel_publish_blob(chan, ast_channel_hold_type(), blob);
res = ast_queue_frame(chan, &f); res = ast_queue_frame(chan, &f);
ast_channel_unlock(chan);
return res; return res;
} }
@ -1286,9 +1290,11 @@ int ast_queue_unhold(struct ast_channel *chan)
struct ast_frame f = { AST_FRAME_CONTROL, .subclass.integer = AST_CONTROL_UNHOLD }; struct ast_frame f = { AST_FRAME_CONTROL, .subclass.integer = AST_CONTROL_UNHOLD };
int res; int res;
ast_channel_lock(chan);
ast_channel_publish_blob(chan, ast_channel_unhold_type(), NULL); ast_channel_publish_blob(chan, ast_channel_unhold_type(), NULL);
res = ast_queue_frame(chan, &f); res = ast_queue_frame(chan, &f);
ast_channel_unlock(chan);
return res; return res;
} }
@ -2254,7 +2260,9 @@ static void ast_channel_destructor(void *obj)
/* Things that may possibly raise Stasis messages shouldn't occur after this point */ /* Things that may possibly raise Stasis messages shouldn't occur after this point */
ast_set_flag(ast_channel_flags(chan), AST_FLAG_DEAD); ast_set_flag(ast_channel_flags(chan), AST_FLAG_DEAD);
ast_channel_lock(chan);
ast_channel_publish_snapshot(chan); ast_channel_publish_snapshot(chan);
ast_channel_unlock(chan);
publish_cache_clear(chan); publish_cache_clear(chan);
ast_channel_lock(chan); ast_channel_lock(chan);
@ -5324,7 +5332,9 @@ static int set_format(struct ast_channel *chan,
generator_write_format_change(chan); generator_write_format_change(chan);
} }
ast_channel_lock(chan);
ast_channel_publish_snapshot(chan); ast_channel_publish_snapshot(chan);
ast_channel_unlock(chan);
return 0; return 0;
} }
@ -5405,7 +5415,9 @@ static int set_format(struct ast_channel *chan,
generator_write_format_change(chan); generator_write_format_change(chan);
} }
ast_channel_lock(chan);
ast_channel_publish_snapshot(chan); ast_channel_publish_snapshot(chan);
ast_channel_unlock(chan);
return res; return res;
} }
@ -5622,7 +5634,9 @@ struct ast_channel *ast_call_forward(struct ast_channel *caller, struct ast_chan
/* Copy/inherit important information into new channel */ /* Copy/inherit important information into new channel */
if (oh) { if (oh) {
if (oh->vars) { if (oh->vars) {
ast_channel_lock(new_chan);
ast_set_variables(new_chan, oh->vars); ast_set_variables(new_chan, oh->vars);
ast_channel_unlock(new_chan);
} }
if (oh->parent_channel) { if (oh->parent_channel) {
call_forward_inherit(new_chan, oh->parent_channel, orig); call_forward_inherit(new_chan, oh->parent_channel, orig);
@ -5683,7 +5697,9 @@ struct ast_channel *__ast_request_and_dial(const char *type, struct ast_format_c
if (oh) { if (oh) {
if (oh->vars) { if (oh->vars) {
ast_channel_lock(chan);
ast_set_variables(chan, oh->vars); ast_set_variables(chan, oh->vars);
ast_channel_unlock(chan);
} }
if (!ast_strlen_zero(oh->cid_num) && !ast_strlen_zero(oh->cid_name)) { if (!ast_strlen_zero(oh->cid_num) && !ast_strlen_zero(oh->cid_name)) {
/* /*
@ -5955,7 +5971,9 @@ struct ast_channel *ast_request(const char *type, struct ast_format_cap *request
if (requestor) { if (requestor) {
struct ast_callid *callid = ast_channel_callid(requestor); struct ast_callid *callid = ast_channel_callid(requestor);
if (callid) { if (callid) {
ast_channel_lock(c);
ast_channel_callid_set(c, callid); ast_channel_callid_set(c, callid);
ast_channel_unlock(c);
callid = ast_callid_unref(callid); callid = ast_callid_unref(callid);
} }
} }

@ -498,29 +498,32 @@ static void publish_local_bridge_message(struct local_pvt *p)
RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup); RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
RAII_VAR(struct ast_channel_snapshot *, one_snapshot, NULL, ao2_cleanup); RAII_VAR(struct ast_channel_snapshot *, one_snapshot, NULL, ao2_cleanup);
RAII_VAR(struct ast_channel_snapshot *, two_snapshot, NULL, ao2_cleanup); RAII_VAR(struct ast_channel_snapshot *, two_snapshot, NULL, ao2_cleanup);
SCOPED_AO2LOCK(lock, p); struct ast_channel *owner;
struct ast_channel *chan;
ast_unreal_lock_all(&p->base, &chan, &owner);
blob = ast_json_pack("{s: s, s: s, s: b}", blob = ast_json_pack("{s: s, s: s, s: b}",
"context", p->context, "context", p->context,
"exten", p->exten, "exten", p->exten,
"can_optimize", !ast_test_flag(&p->base, AST_UNREAL_NO_OPTIMIZATION)); "can_optimize", !ast_test_flag(&p->base, AST_UNREAL_NO_OPTIMIZATION));
if (!blob) { if (!blob) {
return; goto end;
} }
multi_blob = ast_multi_channel_blob_create(blob); multi_blob = ast_multi_channel_blob_create(blob);
if (!multi_blob) { if (!multi_blob) {
return; goto end;
} }
one_snapshot = ast_channel_snapshot_create(p->base.owner); one_snapshot = ast_channel_snapshot_create(owner);
if (!one_snapshot) { if (!one_snapshot) {
return; goto end;
} }
two_snapshot = ast_channel_snapshot_create(p->base.chan); two_snapshot = ast_channel_snapshot_create(chan);
if (!two_snapshot) { if (!two_snapshot) {
return; goto end;
} }
ast_multi_channel_blob_add_channel(multi_blob, "1", one_snapshot); ast_multi_channel_blob_add_channel(multi_blob, "1", one_snapshot);
@ -528,10 +531,19 @@ static void publish_local_bridge_message(struct local_pvt *p)
msg = stasis_message_create(ast_local_bridge_type(), multi_blob); msg = stasis_message_create(ast_local_bridge_type(), multi_blob);
if (!msg) { if (!msg) {
return; goto end;
} }
stasis_publish(ast_channel_topic(p->base.owner), msg); stasis_publish(ast_channel_topic(owner), msg);
end:
ast_channel_unlock(owner);
ast_channel_unref(owner);
ast_channel_unlock(chan);
ast_channel_unref(chan);
ao2_unlock(&p->base);
} }
int ast_local_setup_bridge(struct ast_channel *ast, struct ast_bridge *bridge, struct ast_channel *swap, struct ast_bridge_features *features) int ast_local_setup_bridge(struct ast_channel *ast, struct ast_bridge *bridge, struct ast_channel *swap, struct ast_bridge_features *features)

@ -303,6 +303,7 @@ static int begin_dial_prerun(struct ast_dial_channel *channel, struct ast_channe
cap_request = NULL; cap_request = NULL;
cap_all_audio = ast_format_cap_destroy(cap_all_audio); cap_all_audio = ast_format_cap_destroy(cap_all_audio);
ast_channel_lock(channel->owner);
ast_channel_stage_snapshot(channel->owner); ast_channel_stage_snapshot(channel->owner);
ast_channel_appl_set(channel->owner, "AppDial2"); ast_channel_appl_set(channel->owner, "AppDial2");
@ -332,6 +333,7 @@ static int begin_dial_prerun(struct ast_dial_channel *channel, struct ast_channe
} }
ast_channel_stage_snapshot_done(channel->owner); ast_channel_stage_snapshot_done(channel->owner);
ast_channel_unlock(channel->owner);
if (!ast_strlen_zero(predial_string)) { if (!ast_strlen_zero(predial_string)) {
const char *predial_callee = ast_app_expand_sub_args(chan, predial_string); const char *predial_callee = ast_app_expand_sub_args(chan, predial_string);

@ -203,7 +203,9 @@ int ast_endpoint_add_channel(struct ast_endpoint *endpoint,
ast_str_container_add(endpoint->channel_ids, ast_channel_uniqueid(chan)); ast_str_container_add(endpoint->channel_ids, ast_channel_uniqueid(chan));
ao2_unlock(endpoint); ao2_unlock(endpoint);
ast_channel_lock(chan);
ast_publish_channel_state(chan); ast_publish_channel_state(chan);
ast_channel_unlock(chan);
endpoint_publish_snapshot(endpoint); endpoint_publish_snapshot(endpoint);
return 0; return 0;

@ -1612,9 +1612,11 @@ int pbx_exec(struct ast_channel *c, /*!< Channel */
saved_c_appl= ast_channel_appl(c); saved_c_appl= ast_channel_appl(c);
saved_c_data= ast_channel_data(c); saved_c_data= ast_channel_data(c);
ast_channel_lock(c);
ast_channel_appl_set(c, app->name); ast_channel_appl_set(c, app->name);
ast_channel_data_set(c, data); ast_channel_data_set(c, data);
ast_channel_publish_snapshot(c); ast_channel_publish_snapshot(c);
ast_channel_unlock(c);
if (app->module) if (app->module)
u = __ast_module_user_add(app->module, c); u = __ast_module_user_add(app->module, c);
@ -6281,7 +6283,9 @@ static enum ast_pbx_result __ast_pbx_run(struct ast_channel *c,
if (!callid) { if (!callid) {
callid = ast_create_callid(); callid = ast_create_callid();
if (callid) { if (callid) {
ast_channel_lock(c);
ast_channel_callid_set(c, callid); ast_channel_callid_set(c, callid);
ast_channel_unlock(c);
} }
} }
ast_callid_threadassoc_add(callid); ast_callid_threadassoc_add(callid);
@ -10249,6 +10253,7 @@ static int pbx_outgoing_attempt(const char *type, struct ast_format_cap *cap, co
return -1; return -1;
} }
ast_channel_lock(dialed);
if (vars) { if (vars) {
ast_set_variables(dialed, vars); ast_set_variables(dialed, vars);
} }
@ -10257,6 +10262,7 @@ static int pbx_outgoing_attempt(const char *type, struct ast_format_cap *cap, co
ast_channel_accountcode_set(dialed, account); ast_channel_accountcode_set(dialed, account);
} }
ast_set_flag(ast_channel_flags(dialed), AST_FLAG_ORIGINATED); ast_set_flag(ast_channel_flags(dialed), AST_FLAG_ORIGINATED);
ast_channel_unlock(dialed);
if (!ast_strlen_zero(cid_num) || !ast_strlen_zero(cid_name)) { if (!ast_strlen_zero(cid_num) || !ast_strlen_zero(cid_name)) {
struct ast_party_connected_line connected; struct ast_party_connected_line connected;
@ -10364,7 +10370,6 @@ static int pbx_outgoing_attempt(const char *type, struct ast_format_cap *cap, co
ast_set_variables(failed, vars); ast_set_variables(failed, vars);
snprintf(failed_reason, sizeof(failed_reason), "%d", ast_dial_reason(outgoing->dial, 0)); snprintf(failed_reason, sizeof(failed_reason), "%d", ast_dial_reason(outgoing->dial, 0));
pbx_builtin_setvar_helper(failed, "REASON", failed_reason); pbx_builtin_setvar_helper(failed, "REASON", failed_reason);
ast_channel_unlock(failed); ast_channel_unlock(failed);
if (ast_pbx_run(failed)) { if (ast_pbx_run(failed)) {
@ -10666,10 +10671,12 @@ static int pbx_builtin_busy(struct ast_channel *chan, const char *data)
ast_indicate(chan, AST_CONTROL_BUSY); ast_indicate(chan, AST_CONTROL_BUSY);
/* Don't change state of an UP channel, just indicate /* Don't change state of an UP channel, just indicate
busy in audio */ busy in audio */
ast_channel_lock(chan);
if (ast_channel_state(chan) != AST_STATE_UP) { if (ast_channel_state(chan) != AST_STATE_UP) {
ast_channel_hangupcause_set(chan, AST_CAUSE_BUSY); ast_channel_hangupcause_set(chan, AST_CAUSE_BUSY);
ast_setstate(chan, AST_STATE_BUSY); ast_setstate(chan, AST_STATE_BUSY);
} }
ast_channel_unlock(chan);
wait_for_hangup(chan, data); wait_for_hangup(chan, data);
return -1; return -1;
} }
@ -10682,10 +10689,12 @@ static int pbx_builtin_congestion(struct ast_channel *chan, const char *data)
ast_indicate(chan, AST_CONTROL_CONGESTION); ast_indicate(chan, AST_CONTROL_CONGESTION);
/* Don't change state of an UP channel, just indicate /* Don't change state of an UP channel, just indicate
congestion in audio */ congestion in audio */
ast_channel_lock(chan);
if (ast_channel_state(chan) != AST_STATE_UP) { if (ast_channel_state(chan) != AST_STATE_UP) {
ast_channel_hangupcause_set(chan, AST_CAUSE_CONGESTION); ast_channel_hangupcause_set(chan, AST_CAUSE_CONGESTION);
ast_setstate(chan, AST_STATE_BUSY); ast_setstate(chan, AST_STATE_BUSY);
} }
ast_channel_unlock(chan);
wait_for_hangup(chan, data); wait_for_hangup(chan, data);
return -1; return -1;
} }

@ -354,11 +354,17 @@ int ast_do_pickup(struct ast_channel *chan, struct ast_channel *target)
/* setting the HANGUPCAUSE so the ringing channel knows this call was not a missed call */ /* setting the HANGUPCAUSE so the ringing channel knows this call was not a missed call */
ast_channel_hangupcause_set(chan, AST_CAUSE_ANSWERED_ELSEWHERE); ast_channel_hangupcause_set(chan, AST_CAUSE_ANSWERED_ELSEWHERE);
if (!(chan_snapshot = ast_channel_snapshot_create(chan))) { ast_channel_lock(chan);
chan_snapshot = ast_channel_snapshot_create(chan);
ast_channel_unlock(chan);
if (!chan_snapshot) {
goto pickup_failed; goto pickup_failed;
} }
if (!(target_snapshot = ast_channel_snapshot_create(target))) { ast_channel_lock(target);
target_snapshot = ast_channel_snapshot_create(target);
ast_channel_unlock(target);
if (!target_snapshot) {
goto pickup_failed; goto pickup_failed;
} }

@ -399,7 +399,9 @@ struct stasis_message *ast_bridge_blob_create(
} }
if (chan) { if (chan) {
ast_channel_lock(chan);
obj->channel = ast_channel_snapshot_create(chan); obj->channel = ast_channel_snapshot_create(chan);
ast_channel_unlock(chan);
if (obj->channel == NULL) { if (obj->channel == NULL) {
return NULL; return NULL;
} }
@ -583,7 +585,9 @@ 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); snapshot_pair->channel_snapshot = ast_channel_snapshot_create(pair->channel);
ast_channel_unlock(pair->channel);
if (!snapshot_pair->channel_snapshot) { if (!snapshot_pair->channel_snapshot) {
return -1; return -1;
} }
@ -919,7 +923,9 @@ void ast_bridge_publish_attended_transfer_link(int is_external, enum ast_transfe
transfer_msg->dest_type = AST_ATTENDED_TRANSFER_DEST_LINK; transfer_msg->dest_type = AST_ATTENDED_TRANSFER_DEST_LINK;
for (i = 0; i < 2; ++i) { for (i = 0; i < 2; ++i) {
ast_channel_lock(locals[i]);
transfer_msg->dest.links[i] = ast_channel_snapshot_create(locals[i]); transfer_msg->dest.links[i] = ast_channel_snapshot_create(locals[i]);
ast_channel_unlock(locals[i]);
if (!transfer_msg->dest.links[i]) { if (!transfer_msg->dest.links[i]) {
return; return;
} }

@ -317,14 +317,18 @@ void ast_channel_publish_dial_forward(struct ast_channel *caller, struct ast_cha
} }
if (caller) { if (caller) {
ast_channel_lock(caller);
caller_snapshot = ast_channel_snapshot_create(caller); caller_snapshot = ast_channel_snapshot_create(caller);
ast_channel_unlock(caller);
if (!caller_snapshot) { if (!caller_snapshot) {
return; return;
} }
ast_multi_channel_blob_add_channel(payload, "caller", caller_snapshot); ast_multi_channel_blob_add_channel(payload, "caller", caller_snapshot);
} }
ast_channel_lock(peer);
peer_snapshot = ast_channel_snapshot_create(peer); peer_snapshot = ast_channel_snapshot_create(peer);
ast_channel_unlock(peer);
if (!peer_snapshot) { if (!peer_snapshot) {
return; return;
} }

@ -357,7 +357,9 @@ static int realtime_exec(struct ast_channel *chan, const char *context, const ch
term_color(tmp1, app, COLOR_BRCYAN, 0, sizeof(tmp1)), term_color(tmp1, app, COLOR_BRCYAN, 0, sizeof(tmp1)),
term_color(tmp2, ast_channel_name(chan), COLOR_BRMAGENTA, 0, sizeof(tmp2)), term_color(tmp2, ast_channel_name(chan), COLOR_BRMAGENTA, 0, sizeof(tmp2)),
term_color(tmp3, S_OR(appdata, ""), COLOR_BRMAGENTA, 0, sizeof(tmp3))); term_color(tmp3, S_OR(appdata, ""), COLOR_BRMAGENTA, 0, sizeof(tmp3)));
ast_channel_lock(chan);
snapshot = ast_channel_snapshot_create(chan); snapshot = ast_channel_snapshot_create(chan);
ast_channel_unlock(chan);
if (snapshot) { if (snapshot) {
/* pbx_exec sets application name and data, but we don't want to log /* pbx_exec sets application name and data, but we don't want to log
* every exec. Just update the snapshot here instead. * every exec. Just update the snapshot here instead.

@ -530,6 +530,7 @@ static int parking_duration_callback(struct ast_bridge_channel *bridge_channel,
/* Set parking timeout channel variables */ /* Set parking timeout channel variables */
snprintf(parking_space, sizeof(parking_space), "%d", user->parking_space); snprintf(parking_space, sizeof(parking_space), "%d", user->parking_space);
ast_channel_lock(chan);
ast_channel_stage_snapshot(chan); ast_channel_stage_snapshot(chan);
pbx_builtin_setvar_helper(chan, "PARKING_SPACE", parking_space); pbx_builtin_setvar_helper(chan, "PARKING_SPACE", parking_space);
pbx_builtin_setvar_helper(chan, "PARKINGSLOT", parking_space); /* Deprecated version of PARKING_SPACE */ pbx_builtin_setvar_helper(chan, "PARKINGSLOT", parking_space); /* Deprecated version of PARKING_SPACE */
@ -538,6 +539,7 @@ static int parking_duration_callback(struct ast_bridge_channel *bridge_channel,
pbx_builtin_setvar_helper(chan, "PARKER_FLAT", dial_string_flat); pbx_builtin_setvar_helper(chan, "PARKER_FLAT", dial_string_flat);
parking_timeout_set_caller_features(chan, user->lot->cfg); parking_timeout_set_caller_features(chan, user->lot->cfg);
ast_channel_stage_snapshot_done(chan); ast_channel_stage_snapshot_done(chan);
ast_channel_unlock(chan);
/* Dialplan generation for park-dial extensions */ /* Dialplan generation for park-dial extensions */

@ -155,7 +155,9 @@ static struct ast_parked_call_payload *parked_call_payload_from_failure(struct a
RAII_VAR(struct ast_parked_call_payload *, payload, NULL, ao2_cleanup); RAII_VAR(struct ast_parked_call_payload *, payload, NULL, ao2_cleanup);
RAII_VAR(struct ast_channel_snapshot *, parkee_snapshot, NULL, ao2_cleanup); RAII_VAR(struct ast_channel_snapshot *, parkee_snapshot, NULL, ao2_cleanup);
ast_channel_lock(chan);
parkee_snapshot = ast_channel_snapshot_create(chan); parkee_snapshot = ast_channel_snapshot_create(chan);
ast_channel_unlock(chan);
if (!parkee_snapshot) { if (!parkee_snapshot) {
return NULL; return NULL;
} }
@ -172,7 +174,9 @@ static struct ast_parked_call_payload *parked_call_payload_from_parked_user(stru
struct timeval now = ast_tvnow(); struct timeval now = ast_tvnow();
const char *lot_name = pu->lot->name; const char *lot_name = pu->lot->name;
ast_channel_lock(pu->chan);
parkee_snapshot = ast_channel_snapshot_create(pu->chan); parkee_snapshot = ast_channel_snapshot_create(pu->chan);
ast_channel_unlock(pu->chan);
if (!parkee_snapshot) { if (!parkee_snapshot) {
return NULL; return NULL;

@ -1481,9 +1481,11 @@ static enum agi_result launch_asyncagi(struct ast_channel *chan, int argc, char
to execute based on the setup info */ to execute based on the setup info */
ast_uri_encode(agi_buffer, ami_buffer, AMI_BUF_SIZE, ast_uri_http); ast_uri_encode(agi_buffer, ami_buffer, AMI_BUF_SIZE, ast_uri_http);
startblob = ast_json_pack("{s: s}", "Env", ami_buffer); startblob = ast_json_pack("{s: s}", "Env", ami_buffer);
ast_channel_lock(chan);
ast_channel_publish_blob(chan, agi_async_start_type(), startblob); ast_channel_publish_blob(chan, agi_async_start_type(), startblob);
hungup = ast_check_hangup(chan); hungup = ast_check_hangup(chan);
ast_channel_unlock(chan);
for (;;) { for (;;) {
/* /*
* Process as many commands as we can. Commands are added via * Process as many commands as we can. Commands are added via
@ -1527,7 +1529,9 @@ static enum agi_result launch_asyncagi(struct ast_channel *chan, int argc, char
if (execblob && !ast_strlen_zero(cmd->cmd_id)) { if (execblob && !ast_strlen_zero(cmd->cmd_id)) {
ast_json_object_set(execblob, "CommandId", ast_json_string_create(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_publish_blob(chan, agi_async_exec_type(), execblob);
ast_channel_unlock(chan);
free_agi_cmd(cmd); free_agi_cmd(cmd);
@ -1587,7 +1591,9 @@ async_agi_done:
ast_speech_destroy(async_agi.speech); ast_speech_destroy(async_agi.speech);
} }
/* notify manager users this channel cannot be controlled anymore by Async AGI */ /* 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_publish_blob(chan, agi_async_end_type(), NULL);
ast_channel_unlock(chan);
async_agi_abort: async_agi_abort:
/* close the pipe */ /* close the pipe */
@ -2716,7 +2722,9 @@ static int handle_autohangup(struct ast_channel *chan, AGI *agi, int argc, const
whentohangup.tv_sec = timeout; whentohangup.tv_sec = timeout;
whentohangup.tv_usec = (timeout - whentohangup.tv_sec) * 1000000.0; whentohangup.tv_usec = (timeout - whentohangup.tv_sec) * 1000000.0;
} }
ast_channel_lock(chan);
ast_channel_setwhentohangup_tv(chan, whentohangup); ast_channel_setwhentohangup_tv(chan, whentohangup);
ast_channel_unlock(chan);
ast_agi_send(agi->fd, chan, "200 result=0\n"); ast_agi_send(agi->fd, chan, "200 result=0\n");
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
@ -3657,7 +3665,9 @@ static void publish_async_exec_end(struct ast_channel *chan, int command_id, con
"Command", command, "Command", command,
"ResultCode", result_code, "ResultCode", result_code,
"Result", result); "Result", result);
ast_channel_lock(chan);
ast_channel_publish_blob(chan, agi_exec_end_type(), blob); ast_channel_publish_blob(chan, agi_exec_end_type(), blob);
ast_channel_unlock(chan);
} }
static enum agi_result agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf, int dead) static enum agi_result agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf, int dead)
@ -3675,7 +3685,9 @@ static enum agi_result agi_handle_command(struct ast_channel *chan, AGI *agi, ch
startblob = ast_json_pack("{s: i, s: s}", startblob = ast_json_pack("{s: i, s: s}",
"CommandId", command_id, "CommandId", command_id,
"Command", ami_cmd); "Command", ami_cmd);
ast_channel_lock(chan);
ast_channel_publish_blob(chan, agi_exec_start_type(), startblob); ast_channel_publish_blob(chan, agi_exec_start_type(), startblob);
ast_channel_unlock(chan);
parse_args(buf, &argc, argv); parse_args(buf, &argc, argv);
c = find_command(argv, 0); c = find_command(argv, 0);

@ -754,7 +754,9 @@ static int refer_incoming_invite_request(struct ast_sip_session *session, struct
goto end; goto end;
} }
ast_channel_lock(session->channel);
ast_setstate(session->channel, AST_STATE_RING); ast_setstate(session->channel, AST_STATE_RING);
ast_channel_unlock(session->channel);
ast_raw_answer(session->channel); ast_raw_answer(session->channel);
if (!invite.bridge) { if (!invite.bridge) {

@ -637,7 +637,9 @@ static int send_start_msg(struct stasis_app *app, struct ast_channel *chan,
ast_assert(chan != NULL); ast_assert(chan != NULL);
/* Set channel info */ /* Set channel info */
ast_channel_lock(chan);
snapshot = ast_channel_snapshot_create(chan); snapshot = ast_channel_snapshot_create(chan);
ast_channel_unlock(chan);
if (!snapshot) { if (!snapshot) {
return -1; return -1;
} }
@ -681,7 +683,9 @@ static int send_end_msg(struct stasis_app *app, struct ast_channel *chan)
ast_assert(chan != NULL); ast_assert(chan != NULL);
/* Set channel info */ /* Set channel info */
ast_channel_lock(chan);
snapshot = ast_channel_snapshot_create(chan); snapshot = ast_channel_snapshot_create(chan);
ast_channel_unlock(chan);
if (snapshot == NULL) { if (snapshot == NULL) {
return -1; return -1;
} }

@ -276,9 +276,11 @@ static void clear_mock_cdr_backend(void)
if ((priority) > 0) { \ if ((priority) > 0) { \
ast_channel_priority_set((channel), (priority)); \ ast_channel_priority_set((channel), (priority)); \
} \ } \
ast_channel_lock((channel)); \
ast_channel_appl_set((channel), (application)); \ ast_channel_appl_set((channel), (application)); \
ast_channel_data_set((channel), (data)); \ ast_channel_data_set((channel), (data)); \
ast_channel_publish_snapshot((channel)); \ ast_channel_publish_snapshot((channel)); \
ast_channel_unlock((channel)); \
} while (0) } while (0)
/*! \brief Hang up a test channel safely */ /*! \brief Hang up a test channel safely */
@ -635,9 +637,11 @@ AST_TEST_DEFINE(test_cdr_single_party)
SWAP_CONFIG(config, debug_cdr_config); SWAP_CONFIG(config, debug_cdr_config);
CREATE_ALICE_CHANNEL(chan, &caller, &expected); CREATE_ALICE_CHANNEL(chan, &caller, &expected);
ast_channel_lock(chan);
EMULATE_APP_DATA(chan, 1, "Answer", ""); EMULATE_APP_DATA(chan, 1, "Answer", "");
ast_setstate(chan, AST_STATE_UP); ast_setstate(chan, AST_STATE_UP);
EMULATE_APP_DATA(chan, 2, "VoiceMailMain", "1"); EMULATE_APP_DATA(chan, 2, "VoiceMailMain", "1");
ast_channel_unlock(chan);
HANGUP_CHANNEL(chan, AST_CAUSE_NORMAL); HANGUP_CHANNEL(chan, AST_CAUSE_NORMAL);
@ -684,9 +688,11 @@ AST_TEST_DEFINE(test_cdr_single_bridge)
SWAP_CONFIG(config, debug_cdr_config); SWAP_CONFIG(config, debug_cdr_config);
CREATE_ALICE_CHANNEL(chan, &caller, &expected); CREATE_ALICE_CHANNEL(chan, &caller, &expected);
ast_channel_lock(chan);
EMULATE_APP_DATA(chan, 1, "Answer", ""); EMULATE_APP_DATA(chan, 1, "Answer", "");
ast_setstate(chan, AST_STATE_UP); ast_setstate(chan, AST_STATE_UP);
EMULATE_APP_DATA(chan, 2, "Bridge", ""); EMULATE_APP_DATA(chan, 2, "Bridge", "");
ast_channel_unlock(chan);
bridge = ast_bridge_basic_new(); bridge = ast_bridge_basic_new();
ast_test_validate(test, bridge != NULL); ast_test_validate(test, bridge != NULL);
@ -759,9 +765,11 @@ AST_TEST_DEFINE(test_cdr_single_bridge_continue)
CREATE_ALICE_CHANNEL(chan, &caller, &expected_one); CREATE_ALICE_CHANNEL(chan, &caller, &expected_one);
COPY_IDS(chan, &expected_two); COPY_IDS(chan, &expected_two);
ast_channel_lock(chan);
EMULATE_APP_DATA(chan, 1, "Answer", ""); EMULATE_APP_DATA(chan, 1, "Answer", "");
ast_setstate(chan, AST_STATE_UP); ast_setstate(chan, AST_STATE_UP);
EMULATE_APP_DATA(chan, 2, "Bridge", ""); EMULATE_APP_DATA(chan, 2, "Bridge", "");
ast_channel_unlock(chan);
bridge_one = ast_bridge_basic_new(); bridge_one = ast_bridge_basic_new();
ast_test_validate(test, bridge_one != NULL); ast_test_validate(test, bridge_one != NULL);
@ -843,9 +851,11 @@ AST_TEST_DEFINE(test_cdr_single_twoparty_bridge_a)
CREATE_BOB_CHANNEL(chan_bob, &caller_bob, &bob_expected); CREATE_BOB_CHANNEL(chan_bob, &caller_bob, &bob_expected);
ast_copy_string(bob_expected.linkedid, ast_channel_linkedid(chan_alice), sizeof(bob_expected.linkedid)); ast_copy_string(bob_expected.linkedid, ast_channel_linkedid(chan_alice), sizeof(bob_expected.linkedid));
ast_channel_lock(chan_alice);
EMULATE_APP_DATA(chan_alice, 1, "Answer", ""); EMULATE_APP_DATA(chan_alice, 1, "Answer", "");
ast_setstate(chan_alice, AST_STATE_UP); ast_setstate(chan_alice, AST_STATE_UP);
EMULATE_APP_DATA(chan_alice, 2, "Bridge", ""); EMULATE_APP_DATA(chan_alice, 2, "Bridge", "");
ast_channel_unlock(chan_alice);
bridge = ast_bridge_basic_new(); bridge = ast_bridge_basic_new();
ast_test_validate(test, bridge != NULL); ast_test_validate(test, bridge != NULL);
@ -853,9 +863,11 @@ AST_TEST_DEFINE(test_cdr_single_twoparty_bridge_a)
ast_test_validate(test, !ast_bridge_impart(bridge, chan_alice, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE)); ast_test_validate(test, !ast_bridge_impart(bridge, chan_alice, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE));
while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR)); while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
ast_channel_lock(chan_bob);
EMULATE_APP_DATA(chan_bob, 1, "Answer", ""); EMULATE_APP_DATA(chan_bob, 1, "Answer", "");
ast_setstate(chan_bob, AST_STATE_UP); ast_setstate(chan_bob, AST_STATE_UP);
EMULATE_APP_DATA(chan_bob, 2, "Bridge", ""); EMULATE_APP_DATA(chan_bob, 2, "Bridge", "");
ast_channel_unlock(chan_bob);
ast_test_validate(test, !ast_bridge_impart(bridge, chan_bob, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE)); ast_test_validate(test, !ast_bridge_impart(bridge, chan_bob, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE));
while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR)); while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
@ -931,16 +943,20 @@ AST_TEST_DEFINE(test_cdr_single_twoparty_bridge_b)
CREATE_BOB_CHANNEL(chan_bob, &caller_bob, &bob_expected); CREATE_BOB_CHANNEL(chan_bob, &caller_bob, &bob_expected);
ast_copy_string(bob_expected.linkedid, ast_channel_linkedid(chan_alice), sizeof(bob_expected.linkedid)); ast_copy_string(bob_expected.linkedid, ast_channel_linkedid(chan_alice), sizeof(bob_expected.linkedid));
ast_channel_unlock(chan_alice);
EMULATE_APP_DATA(chan_alice, 1, "Answer", ""); EMULATE_APP_DATA(chan_alice, 1, "Answer", "");
ast_setstate(chan_alice, AST_STATE_UP); ast_setstate(chan_alice, AST_STATE_UP);
EMULATE_APP_DATA(chan_alice, 2, "Bridge", ""); EMULATE_APP_DATA(chan_alice, 2, "Bridge", "");
ast_channel_unlock(chan_alice);
bridge = ast_bridge_basic_new(); bridge = ast_bridge_basic_new();
ast_test_validate(test, bridge != NULL); ast_test_validate(test, bridge != NULL);
ast_channel_lock(chan_bob);
EMULATE_APP_DATA(chan_bob, 1, "Answer", ""); EMULATE_APP_DATA(chan_bob, 1, "Answer", "");
ast_setstate(chan_bob, AST_STATE_UP); ast_setstate(chan_bob, AST_STATE_UP);
EMULATE_APP_DATA(chan_bob, 2, "Bridge", ""); EMULATE_APP_DATA(chan_bob, 2, "Bridge", "");
ast_channel_unlock(chan_bob);
while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR)); while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
ast_test_validate(test, !ast_bridge_impart(bridge, chan_bob, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE)); ast_test_validate(test, !ast_bridge_impart(bridge, chan_bob, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE));
@ -1054,9 +1070,11 @@ AST_TEST_DEFINE(test_cdr_single_multiparty_bridge)
CREATE_CHARLIE_CHANNEL(chan_charlie, &caller_charlie, &charlie_expected); CREATE_CHARLIE_CHANNEL(chan_charlie, &caller_charlie, &charlie_expected);
ast_copy_string(charlie_expected.linkedid, ast_channel_linkedid(chan_alice), sizeof(charlie_expected.linkedid)); ast_copy_string(charlie_expected.linkedid, ast_channel_linkedid(chan_alice), sizeof(charlie_expected.linkedid));
ast_channel_lock(chan_alice);
EMULATE_APP_DATA(chan_alice, 1, "Answer", ""); EMULATE_APP_DATA(chan_alice, 1, "Answer", "");
ast_setstate(chan_alice, AST_STATE_UP); ast_setstate(chan_alice, AST_STATE_UP);
EMULATE_APP_DATA(chan_alice, 2, "Bridge", ""); EMULATE_APP_DATA(chan_alice, 2, "Bridge", "");
ast_channel_unlock(chan_alice);
bridge = ast_bridge_basic_new(); bridge = ast_bridge_basic_new();
ast_test_validate(test, bridge != NULL); ast_test_validate(test, bridge != NULL);
@ -1064,18 +1082,22 @@ AST_TEST_DEFINE(test_cdr_single_multiparty_bridge)
ast_test_validate(test, !ast_bridge_impart(bridge, chan_alice, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE)); ast_test_validate(test, !ast_bridge_impart(bridge, chan_alice, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE));
ast_channel_lock(chan_bob);
EMULATE_APP_DATA(chan_bob, 1, "Answer", ""); EMULATE_APP_DATA(chan_bob, 1, "Answer", "");
ast_setstate(chan_bob, AST_STATE_UP); ast_setstate(chan_bob, AST_STATE_UP);
EMULATE_APP_DATA(chan_bob, 2, "Bridge", ""); EMULATE_APP_DATA(chan_bob, 2, "Bridge", "");
ast_channel_unlock(chan_bob);
while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR)); while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
ast_test_validate(test, !ast_bridge_impart(bridge, chan_bob, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE)); ast_test_validate(test, !ast_bridge_impart(bridge, chan_bob, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE));
while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR)); while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
ast_channel_lock(chan_charlie);
EMULATE_APP_DATA(chan_charlie, 1, "Answer", ""); EMULATE_APP_DATA(chan_charlie, 1, "Answer", "");
ast_setstate(chan_charlie, AST_STATE_UP); ast_setstate(chan_charlie, AST_STATE_UP);
EMULATE_APP_DATA(chan_charlie, 2, "Bridge", ""); EMULATE_APP_DATA(chan_charlie, 2, "Bridge", "");
ast_channel_unlock(chan_charlie);
ast_test_validate(test, !ast_bridge_impart(bridge, chan_charlie, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE)); ast_test_validate(test, !ast_bridge_impart(bridge, chan_charlie, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE));
while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR)); while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
@ -2018,10 +2040,15 @@ AST_TEST_DEFINE(test_cdr_park)
CREATE_ALICE_CHANNEL(chan_alice, &alice_caller, &alice_expected); CREATE_ALICE_CHANNEL(chan_alice, &alice_caller, &alice_expected);
CREATE_BOB_CHANNEL(chan_bob, &bob_caller, &bob_expected); CREATE_BOB_CHANNEL(chan_bob, &bob_caller, &bob_expected);
ast_channel_lock(chan_alice);
EMULATE_APP_DATA(chan_alice, 1, "Park", "700"); EMULATE_APP_DATA(chan_alice, 1, "Park", "700");
ast_setstate(chan_alice, AST_STATE_UP); ast_setstate(chan_alice, AST_STATE_UP);
ast_channel_unlock(chan_alice);
ast_channel_lock(chan_bob);
EMULATE_APP_DATA(chan_bob, 1, "Park", "701"); EMULATE_APP_DATA(chan_bob, 1, "Park", "701");
ast_setstate(chan_bob, AST_STATE_UP); ast_setstate(chan_bob, AST_STATE_UP);
ast_channel_unlock(chan_bob);
bridge = ast_bridge_base_new(AST_BRIDGE_CAPABILITY_HOLDING, bridge = ast_bridge_base_new(AST_BRIDGE_CAPABILITY_HOLDING,
AST_BRIDGE_FLAG_MERGE_INHIBIT_TO | AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM AST_BRIDGE_FLAG_MERGE_INHIBIT_TO | AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM
@ -2127,6 +2154,7 @@ AST_TEST_DEFINE(test_cdr_fields)
ast_copy_string(fork_expected_two.linkedid, ast_channel_linkedid(chan), sizeof(fork_expected_two.linkedid)); ast_copy_string(fork_expected_two.linkedid, ast_channel_linkedid(chan), sizeof(fork_expected_two.linkedid));
/* Channel enters Wait app */ /* Channel enters Wait app */
ast_channel_lock(chan);
ast_channel_appl_set(chan, "Wait"); ast_channel_appl_set(chan, "Wait");
ast_channel_data_set(chan, "10"); ast_channel_data_set(chan, "10");
ast_channel_priority_set(chan, 1); ast_channel_priority_set(chan, 1);
@ -2135,6 +2163,7 @@ AST_TEST_DEFINE(test_cdr_fields)
/* Set properties on the channel that propagate to the CDR */ /* Set properties on the channel that propagate to the CDR */
ast_channel_amaflags_set(chan, AST_AMA_OMIT); ast_channel_amaflags_set(chan, AST_AMA_OMIT);
ast_channel_accountcode_set(chan, "XXX"); ast_channel_accountcode_set(chan, "XXX");
ast_channel_unlock(chan);
/* Wait one second so we get a duration. */ /* Wait one second so we get a duration. */
while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR)); while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
@ -2227,6 +2256,7 @@ AST_TEST_DEFINE(test_cdr_fields)
ast_test_validate(test, ast_cdr_fork(ast_channel_name(chan), &fork_options) == 0); ast_test_validate(test, ast_cdr_fork(ast_channel_name(chan), &fork_options) == 0);
/* Channel enters Answer app */ /* Channel enters Answer app */
ast_channel_lock(chan);
ast_channel_appl_set(chan, "Answer"); ast_channel_appl_set(chan, "Answer");
ast_channel_data_set(chan, ""); ast_channel_data_set(chan, "");
ast_channel_priority_set(chan, 1); ast_channel_priority_set(chan, 1);
@ -2235,6 +2265,7 @@ AST_TEST_DEFINE(test_cdr_fields)
/* Set properties on the last record */ /* Set properties on the last record */
ast_channel_accountcode_set(chan, "ZZZ"); ast_channel_accountcode_set(chan, "ZZZ");
ast_channel_unlock(chan);
ast_cdr_setuserfield(ast_channel_name(chan), "schmackity"); ast_cdr_setuserfield(ast_channel_name(chan), "schmackity");
ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "test_variable", "record_2") == 0); ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "test_variable", "record_2") == 0);
@ -2404,7 +2435,9 @@ AST_TEST_DEFINE(test_cdr_fork_cdr)
ast_test_validate(test, ast_cdr_fork(ast_channel_name(chan), &fork_options) == 0); ast_test_validate(test, ast_cdr_fork(ast_channel_name(chan), &fork_options) == 0);
/* Test keep variables; setting a new answer time */ /* Test keep variables; setting a new answer time */
ast_channel_lock(chan);
ast_setstate(chan, AST_STATE_UP); ast_setstate(chan, AST_STATE_UP);
ast_channel_unlock(chan);
while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR)); while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "test_variable", "record_2") == 0); ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "test_variable", "record_2") == 0);
ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "test_variable", varbuffer, sizeof(varbuffer)) == 0); ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "test_variable", varbuffer, sizeof(varbuffer)) == 0);

@ -1560,10 +1560,14 @@ AST_TEST_DEFINE(test_cel_local_optimize)
CREATE_ALICE_CHANNEL(chan_alice, &alice_caller); CREATE_ALICE_CHANNEL(chan_alice, &alice_caller);
CREATE_BOB_CHANNEL(chan_bob, &bob_caller); CREATE_BOB_CHANNEL(chan_bob, &bob_caller);
ast_channel_lock(chan_alice);
alice_snapshot = ast_channel_snapshot_create(chan_alice); alice_snapshot = ast_channel_snapshot_create(chan_alice);
ast_channel_unlock(chan_alice);
ast_test_validate(test, alice_snapshot != NULL); ast_test_validate(test, alice_snapshot != NULL);
ast_channel_lock(chan_bob);
bob_snapshot = ast_channel_snapshot_create(chan_bob); bob_snapshot = ast_channel_snapshot_create(chan_bob);
ast_channel_unlock(chan_bob);
ast_test_validate(test, bob_snapshot != NULL); ast_test_validate(test, bob_snapshot != NULL);
ast_multi_channel_blob_add_channel(mc_blob, "1", alice_snapshot); ast_multi_channel_blob_add_channel(mc_blob, "1", alice_snapshot);
@ -1684,7 +1688,9 @@ static int append_expected_event(
const char *peer) const char *peer)
{ {
RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup); RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
ast_channel_lock(chan);
snapshot = ast_channel_snapshot_create(chan); snapshot = ast_channel_snapshot_create(chan);
ast_channel_unlock(chan);
if (!snapshot) { if (!snapshot) {
return -1; return -1;
} }

@ -78,10 +78,12 @@ AST_TEST_DEFINE(channel_blob_create)
"foo", "bar"); "foo", "bar");
/* Off nominal creation */ /* Off nominal creation */
ast_channel_lock(chan);
ast_test_validate(test, NULL == ast_channel_blob_create(chan, NULL, json)); ast_test_validate(test, NULL == ast_channel_blob_create(chan, NULL, json));
/* Test for single channel */ /* Test for single channel */
msg = ast_channel_blob_create(chan, type, json); msg = ast_channel_blob_create(chan, type, json);
ast_channel_unlock(chan);
ast_test_validate(test, NULL != msg); ast_test_validate(test, NULL != msg);
blob = stasis_message_data(msg); blob = stasis_message_data(msg);
ast_test_validate(test, NULL != blob); ast_test_validate(test, NULL != blob);
@ -131,7 +133,9 @@ AST_TEST_DEFINE(null_blob)
"foo", "bar"); "foo", "bar");
/* Test for single channel */ /* Test for single channel */
ast_channel_lock(chan);
msg = ast_channel_blob_create(chan, type, NULL); msg = ast_channel_blob_create(chan, type, NULL);
ast_channel_unlock(chan);
ast_test_validate(test, NULL != msg); ast_test_validate(test, NULL != msg);
blob = stasis_message_data(msg); blob = stasis_message_data(msg);
ast_test_validate(test, NULL != blob); ast_test_validate(test, NULL != blob);
@ -201,9 +205,15 @@ AST_TEST_DEFINE(multi_channel_blob_snapshots)
ast_channel_unlock(chan_charlie); ast_channel_unlock(chan_charlie);
blob = ast_multi_channel_blob_create(json); blob = ast_multi_channel_blob_create(json);
ast_channel_lock(chan_alice);
ast_multi_channel_blob_add_channel(blob, "Caller", ast_channel_snapshot_create(chan_alice)); ast_multi_channel_blob_add_channel(blob, "Caller", ast_channel_snapshot_create(chan_alice));
ast_channel_unlock(chan_alice);
ast_channel_lock(chan_bob);
ast_multi_channel_blob_add_channel(blob, "Peer", ast_channel_snapshot_create(chan_bob)); ast_multi_channel_blob_add_channel(blob, "Peer", ast_channel_snapshot_create(chan_bob));
ast_channel_unlock(chan_bob);
ast_channel_lock(chan_charlie);
ast_multi_channel_blob_add_channel(blob, "Peer", ast_channel_snapshot_create(chan_charlie)); ast_multi_channel_blob_add_channel(blob, "Peer", ast_channel_snapshot_create(chan_charlie));
ast_channel_unlock(chan_charlie);
/* Test for unknown role */ /* Test for unknown role */
ast_test_validate(test, NULL == ast_multi_channel_blob_get_channel(blob, "Foobar")); ast_test_validate(test, NULL == ast_multi_channel_blob_get_channel(blob, "Foobar"));
@ -258,7 +268,9 @@ AST_TEST_DEFINE(channel_snapshot_json)
chan = ast_channel_alloc(0, AST_STATE_DOWN, "cid_num", "cid_name", "acctcode", "exten", "context", NULL, 0, "TEST/name"); chan = ast_channel_alloc(0, AST_STATE_DOWN, "cid_num", "cid_name", "acctcode", "exten", "context", NULL, 0, "TEST/name");
ast_channel_unlock(chan); ast_channel_unlock(chan);
ast_test_validate(test, NULL != chan); ast_test_validate(test, NULL != chan);
ast_channel_lock(chan);
snapshot = ast_channel_snapshot_create(chan); snapshot = ast_channel_snapshot_create(chan);
ast_channel_unlock(chan);
ast_test_validate(test, NULL != snapshot); ast_test_validate(test, NULL != snapshot);
actual = ast_channel_snapshot_to_json(snapshot, NULL); actual = ast_channel_snapshot_to_json(snapshot, NULL);

Loading…
Cancel
Save