channels: Return allocated channels locked.

This change makes ast_channel_alloc return allocated channels
locked. By doing so no other thread can acquire, lock, and manipulate
the channel before it is completely set up.

(closes issue AST-1256)

Review: https://reviewboard.asterisk.org/r/3067/
........

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


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@404210 65c4cc65-6c06-0410-ace0-fbb531ad65f3
changes/97/197/1
Joshua Colp 12 years ago
parent e23b8d19a4
commit e2630fcd51

@ -879,6 +879,8 @@ static struct ast_channel *mbl_new(int state, struct mbl_pvt *pvt, char *cid_num
ast_channel_set_fd(chn, 0, pvt->sco_socket);
}
ast_channel_unlock(chn);
return chn;
e_return:

@ -395,7 +395,6 @@ static struct ast_channel *ooh323_new(struct ooh323_pvt *i, int state,
ast_mutex_lock(&i->lock);
if (ch) {
ast_channel_lock(ch);
ast_channel_tech_set(ch, &ooh323_tech);
if (cap)

@ -8140,6 +8140,8 @@ AST_TEST_DEFINE(test_meetme_data_provider)
return AST_TEST_FAIL;
}
ast_channel_unlock(chan);
cnf = build_conf("9898", "", "1234", 1, 1, 1, chan, test);
if (!cnf) {
ast_test_status_update(test, "Build of test conference 9898 failed\n");

@ -13744,6 +13744,8 @@ AST_TEST_DEFINE(test_voicemail_vmsayname)
ast_format_set(ast_channel_rawreadformat(test_channel1), AST_FORMAT_GSM, 0);
ast_channel_tech_set(test_channel1, &fake_tech);
ast_channel_unlock(test_channel1);
ast_test_status_update(test, "Test playing of extension when greeting is not available...\n");
snprintf(dir, sizeof(dir), "%s@%s", TEST_EXTENSION, TEST_CONTEXT); /* not a dir, don't get confused */
if (!(res = vmsayname_exec(test_channel1, dir))) {

@ -66,6 +66,7 @@ static struct ast_channel *rec_request(const char *type, struct ast_format_cap *
return NULL;
}
if (ast_channel_add_bridge_role(chan, "recorder")) {
ast_channel_unlock(chan);
ast_channel_release(chan);
return NULL;
}
@ -76,6 +77,7 @@ static struct ast_channel *rec_request(const char *type, struct ast_format_cap *
ast_format_copy(ast_channel_rawwriteformat(chan), &format);
ast_format_copy(ast_channel_readformat(chan), &format);
ast_format_copy(ast_channel_rawreadformat(chan), &format);
ast_channel_unlock(chan);
return chan;
}

@ -602,6 +602,8 @@ static struct ast_channel *alsa_new(struct chan_alsa_pvt *p, int state, const ch
ast_channel_stage_snapshot_done(tmp);
ast_channel_unlock(tmp);
if (state != AST_STATE_DOWN) {
if (ast_pbx_start(tmp)) {
ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));

@ -445,6 +445,8 @@ static struct ast_channel *console_new(struct console_pvt *pvt, const char *ext,
ast_channel_stage_snapshot_done(chan);
ast_channel_unlock(chan);
if (state != AST_STATE_DOWN) {
if (ast_pbx_start(chan)) {
ast_channel_hangupcause_set(chan, AST_CAUSE_SWITCH_CONGESTION);

@ -9097,6 +9097,8 @@ static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpb
ast_channel_stage_snapshot_done(tmp);
ast_channel_unlock(tmp);
ast_module_ref(ast_module_info->self);
dahdi_ami_channel_event(i, tmp);

@ -1227,6 +1227,8 @@ static struct ast_channel *gtalk_new(struct gtalk *client, struct gtalk_pvt *i,
ast_channel_stage_snapshot_done(tmp);
ast_channel_unlock(tmp);
if (state != AST_STATE_DOWN && ast_pbx_start(tmp)) {
ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
ast_channel_hangupcause_set(tmp, AST_CAUSE_SWITCH_CONGESTION);

@ -1139,6 +1139,7 @@ static struct ast_channel *__oh323_new(struct oh323_pvt *pvt, int state, const c
}
if (pvt->cd.transfer_capability >= 0)
ast_channel_transfercapability_set(ch, pvt->cd.transfer_capability);
ast_channel_unlock(ch);
if (state != AST_STATE_DOWN) {
if (ast_pbx_start(ch)) {
ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(ch));

@ -5694,6 +5694,7 @@ static struct ast_channel *ast_iax2_new(int callno, int state, iax2_format capab
if (tmp) {
/* unlock and relock iaxsl[callno] to preserve locking order */
ast_mutex_unlock(&iaxsl[callno]);
ast_channel_unlock(tmp);
tmp = ast_channel_release(tmp);
ast_mutex_lock(&iaxsl[callno]);
}
@ -5804,6 +5805,8 @@ static struct ast_channel *ast_iax2_new(int callno, int state, iax2_format capab
ast_channel_stage_snapshot_done(tmp);
ast_channel_unlock(tmp);
if (state != AST_STATE_DOWN) {
if (ast_pbx_start(tmp)) {
ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));

@ -942,6 +942,8 @@ static struct ast_channel *jingle_new(struct jingle *client, struct jingle_pvt *
ast_channel_stage_snapshot_done(tmp);
ast_channel_unlock(tmp);
if (state != AST_STATE_DOWN && ast_pbx_start(tmp)) {
ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
ast_channel_hangupcause_set(tmp, AST_CAUSE_SWITCH_CONGESTION);

@ -1571,6 +1571,8 @@ static struct ast_channel *mgcp_new(struct mgcp_subchannel *sub, int state, cons
ast_channel_stage_snapshot_done(tmp);
ast_channel_unlock(tmp);
if (state != AST_STATE_DOWN) {
if (ast_pbx_start(tmp)) {
ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));

@ -8226,6 +8226,8 @@ static struct ast_channel *misdn_new(struct chan_list *chlist, int state, char
ast_channel_rings_set(tmp, (state == AST_STATE_RING) ? 1 : 0);
ast_jb_configure(tmp, misdn_get_global_jbconf());
ast_channel_unlock(tmp);
} else {
chan_misdn_log(-1, 0, "Unable to allocate channel structure\n");
}
@ -8949,6 +8951,8 @@ static void misdn_cc_pbx_notify(long record_id, const struct misdn_cc_notify *no
ast_free(ast_channel_dialed(chan)->number.str);
ast_channel_dialed(chan)->number.str = ast_strdup(notify->exten);
ast_channel_unlock(chan);
if (ast_pbx_start(chan)) {
ast_log(LOG_WARNING, "Unable to start pbx channel %s!\n", ast_channel_name(chan));
ast_channel_release(chan);

@ -853,6 +853,8 @@ static struct ast_channel *jingle_new(struct jingle_endpoint *endpoint, struct j
ast_channel_stage_snapshot_done(chan);
ast_channel_unlock(chan);
return chan;
}

@ -166,6 +166,8 @@ static struct ast_channel *multicast_rtp_request(const char *type, struct ast_fo
ast_channel_tech_pvt_set(chan, instance);
ast_channel_unlock(chan);
return chan;
failure:

@ -239,6 +239,7 @@ static struct ast_channel *nbs_new(struct nbs_pvt *i, int state, const char *lin
ast_channel_language_set(tmp, "");
i->owner = tmp;
i->u = ast_module_user_add(tmp);
ast_channel_unlock(tmp);
if (state != AST_STATE_DOWN) {
if (ast_pbx_start(tmp)) {
ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));

@ -829,6 +829,7 @@ static struct ast_channel *oss_new(struct chan_oss_pvt *o, char *ext, char *ctx,
o->owner = c;
ast_module_ref(ast_module_info->self);
ast_jb_configure(c, &global_jbconf);
ast_channel_unlock(c);
if (state != AST_STATE_DOWN) {
if (ast_pbx_start(c)) {
ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(c));

@ -901,6 +901,7 @@ static struct ast_channel *phone_new(struct phone_pvt *i, int state, char *cntx,
i->owner = tmp;
ast_module_ref(ast_module_info->self);
ast_channel_unlock(tmp);
if (state != AST_STATE_DOWN) {
if (state == AST_STATE_RING) {
ioctl(ast_channel_fd(tmp, 0), PHONE_RINGBACK);

@ -359,24 +359,14 @@ static struct ast_channel *chan_pjsip_new(struct ast_sip_session *session, int s
ast_channel_tech_set(chan, &chan_pjsip_tech);
if (!(channel = ast_sip_channel_pvt_alloc(pvt, session))) {
ast_channel_unlock(chan);
ast_hangup(chan);
return NULL;
}
ast_channel_stage_snapshot(chan);
/* If res_pjsip_session is ever updated to create/destroy ast_sip_session_media
* during a call such as if multiple same-type stream support is introduced,
* these will need to be recaptured as well */
pvt->media[SIP_MEDIA_AUDIO] = ao2_find(session->media, "audio", OBJ_KEY);
pvt->media[SIP_MEDIA_VIDEO] = ao2_find(session->media, "video", OBJ_KEY);
ast_channel_tech_pvt_set(chan, channel);
if (pvt->media[SIP_MEDIA_AUDIO] && pvt->media[SIP_MEDIA_AUDIO]->rtp) {
ast_rtp_instance_set_channel_id(pvt->media[SIP_MEDIA_AUDIO]->rtp, ast_channel_uniqueid(chan));
}
if (pvt->media[SIP_MEDIA_VIDEO] && pvt->media[SIP_MEDIA_VIDEO]->rtp) {
ast_rtp_instance_set_channel_id(pvt->media[SIP_MEDIA_VIDEO]->rtp, ast_channel_uniqueid(chan));
}
if (ast_format_cap_is_empty(session->req_caps) || !ast_format_cap_has_joint(session->req_caps, session->endpoint->media.codecs)) {
ast_format_cap_copy(ast_channel_nativeformats(chan), session->endpoint->media.codecs);
@ -418,9 +408,22 @@ static struct ast_channel *chan_pjsip_new(struct ast_sip_session *session, int s
ast_channel_zone_set(chan, zone);
}
ast_endpoint_add_channel(session->endpoint->persistent, chan);
ast_channel_stage_snapshot_done(chan);
ast_channel_unlock(chan);
/* If res_pjsip_session is ever updated to create/destroy ast_sip_session_media
* during a call such as if multiple same-type stream support is introduced,
* these will need to be recaptured as well */
pvt->media[SIP_MEDIA_AUDIO] = ao2_find(session->media, "audio", OBJ_KEY);
pvt->media[SIP_MEDIA_VIDEO] = ao2_find(session->media, "video", OBJ_KEY);
if (pvt->media[SIP_MEDIA_AUDIO] && pvt->media[SIP_MEDIA_AUDIO]->rtp) {
ast_rtp_instance_set_channel_id(pvt->media[SIP_MEDIA_AUDIO]->rtp, ast_channel_uniqueid(chan));
}
if (pvt->media[SIP_MEDIA_VIDEO] && pvt->media[SIP_MEDIA_VIDEO]->rtp) {
ast_rtp_instance_set_channel_id(pvt->media[SIP_MEDIA_VIDEO]->rtp, ast_channel_uniqueid(chan));
}
ast_endpoint_add_channel(session->endpoint->persistent, chan);
return chan;
}

@ -8100,6 +8100,7 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit
if (i->relatedpeer && i->relatedpeer->endpoint) {
if (ast_endpoint_add_channel(i->relatedpeer->endpoint, tmp)) {
ast_channel_unlock(tmp);
ast_channel_unref(tmp);
sip_pvt_lock(i);
return NULL;
@ -8113,7 +8114,6 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit
ast_channel_callid_set(tmp, callid);
}
ast_channel_lock(tmp);
sip_pvt_lock(i);
ast_channel_cc_params_init(tmp, i->cc_params);
ast_channel_caller(tmp)->id.tag = ast_strdup(i->cid_tag);

@ -5393,6 +5393,8 @@ static struct ast_channel *skinny_new(struct skinny_line *l, struct skinny_subli
sub = ast_calloc(1, sizeof(*sub));
if (!sub) {
ast_log(LOG_WARNING, "Unable to allocate Skinny subchannel\n");
ast_channel_unlock(tmp);
ast_channel_unref(tmp);
return NULL;
} else {
ast_mutex_init(&sub->lock);
@ -5500,6 +5502,8 @@ static struct ast_channel *skinny_new(struct skinny_line *l, struct skinny_subli
ast_channel_stage_snapshot_done(tmp);
ast_channel_unlock(tmp);
if (state != AST_STATE_DOWN) {
if (ast_pbx_start(tmp)) {
ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));

@ -5628,6 +5628,8 @@ static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state
ast_channel_stage_snapshot_done(tmp);
ast_channel_unlock(tmp);
if (state != AST_STATE_DOWN) {
if (unistimdebug) {
ast_verb(0, "Starting pbx in unistim_new\n");

@ -2472,6 +2472,8 @@ static struct ast_channel *vpb_new(struct vpb_pvt *me, enum ast_channel_state st
if (!ast_strlen_zero(me->language))
ast_channel_language_set(tmp, me->language);
ast_channel_unlock(tmp);
me->owner = tmp;
me->bridge = NULL;

@ -791,7 +791,8 @@ typedef int(*ast_timing_func_t)(const void *data);
* active channels in the system. The hash key is based on the channel name. Because
* of this, if you want to change the name, you _must_ use ast_change_name(), not change
* the name field directly. When ast_channel_alloc() returns a channel pointer, you now
* hold a reference to that channel. In most cases this reference is given to ast_pbx_run().
* hold both a reference to that channel and a lock on the channel. Once the channel has
* been set up the lock can be released. In most cases the reference is given to ast_pbx_run().
*
* \par Channel Locking
* There is a lock associated with every ast_channel. It is allocated internally via astobj2.
@ -1122,6 +1123,7 @@ struct ast_datastore *ast_channel_datastore_find(struct ast_channel *chan, const
* \note Absolutely _NO_ channel locks should be held before calling this function.
* \note By default, new channels are set to the "s" extension
* and "default" context.
* \note Since 12.0.0 this function returns with the newly created channel locked.
*/
struct ast_channel * attribute_malloc __attribute__((format(printf, 13, 14)))
__ast_channel_alloc(int needqueue, int state, const char *cid_num,
@ -1140,6 +1142,7 @@ struct ast_channel * attribute_malloc __attribute__((format(printf, 13, 14)))
* \note Absolutely _NO_ channel locks should be held before calling this function.
* \note By default, new channels are set to the "s" extension
* and "default" context.
* \note Since 12.0.0 this function returns with the newly created channel locked.
*/
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, linkedid, amaflag, ...) \
__ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, linkedid, amaflag, \

@ -1017,6 +1017,12 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char
ast_channel_internal_finalize(tmp);
ast_atomic_fetchadd_int(&chancount, +1);
/* You might scream "locking inversion" at seeing this but it is actually perfectly fine.
* Since the channel was just created nothing can know about it yet or even acquire it.
*/
ast_channel_lock(tmp);
ao2_link(channels, tmp);
/*

@ -906,57 +906,72 @@ struct ast_channel *ast_unreal_new_channels(struct ast_unreal_pvt *p,
*/
if (!(owner = ast_channel_alloc(1, semi1_state, NULL, NULL, NULL,
exten, context, linkedid, 0,
"%s/%s-%08x;1", tech->type, p->name, generated_seqno))
|| !(chan = ast_channel_alloc(1, semi2_state, NULL, NULL, NULL,
exten, context, ast_channel_linkedid(owner), 0,
"%s/%s-%08x;2", tech->type, p->name, generated_seqno))) {
if (owner) {
owner = ast_channel_release(owner);
}
ast_log(LOG_WARNING, "Unable to allocate channel structure(s)\n");
"%s/%s-%08x;1", tech->type, p->name, generated_seqno))) {
ast_log(LOG_WARNING, "Unable to allocate owner channel structure\n");
return NULL;
}
if (callid) {
ast_channel_callid_set(owner, callid);
ast_channel_callid_set(chan, callid);
}
ast_channel_tech_set(owner, tech);
ast_channel_tech_set(chan, tech);
ao2_ref(p, +1);
ast_channel_tech_pvt_set(owner, p);
ast_channel_tech_pvt_set(chan, p);
ast_format_cap_copy(ast_channel_nativeformats(owner), p->reqcap);
ast_format_cap_copy(ast_channel_nativeformats(chan), p->reqcap);
/* Determine our read/write format and set it on each channel */
ast_best_codec(p->reqcap, &fmt);
ast_format_copy(ast_channel_writeformat(owner), &fmt);
ast_format_copy(ast_channel_writeformat(chan), &fmt);
ast_format_copy(ast_channel_rawwriteformat(owner), &fmt);
ast_format_copy(ast_channel_rawwriteformat(chan), &fmt);
ast_format_copy(ast_channel_readformat(owner), &fmt);
ast_format_copy(ast_channel_readformat(chan), &fmt);
ast_format_copy(ast_channel_rawreadformat(owner), &fmt);
ast_format_copy(ast_channel_rawreadformat(chan), &fmt);
ast_set_flag(ast_channel_flags(owner), AST_FLAG_DISABLE_DEVSTATE_CACHE);
ast_set_flag(ast_channel_flags(chan), AST_FLAG_DISABLE_DEVSTATE_CACHE);
ast_jb_configure(owner, &p->jb_conf);
if (ast_channel_cc_params_init(owner, requestor
? ast_channel_get_cc_config_params((struct ast_channel *) requestor) : NULL)) {
ao2_ref(p, -1);
ast_channel_unlock(owner);
ast_channel_release(owner);
ast_channel_release(chan);
return NULL;
}
/* Give the private a ref for each channel. */
ao2_ref(p, +2);
p->owner = owner;
ast_channel_unlock(owner);
if (!(chan = ast_channel_alloc(1, semi2_state, NULL, NULL, NULL,
exten, context, ast_channel_linkedid(owner), 0,
"%s/%s-%08x;2", tech->type, p->name, generated_seqno))) {
ast_log(LOG_WARNING, "Unable to allocate chan channel structure\n");
ao2_ref(p, -1);
ast_channel_release(owner);
return NULL;
}
if (callid) {
ast_channel_callid_set(chan, callid);
}
ast_channel_tech_set(chan, tech);
ao2_ref(p, +1);
ast_channel_tech_pvt_set(chan, p);
ast_format_cap_copy(ast_channel_nativeformats(chan), p->reqcap);
/* Format was already determined when setting up owner */
ast_format_copy(ast_channel_writeformat(chan), &fmt);
ast_format_copy(ast_channel_rawwriteformat(chan), &fmt);
ast_format_copy(ast_channel_readformat(chan), &fmt);
ast_format_copy(ast_channel_rawreadformat(chan), &fmt);
ast_set_flag(ast_channel_flags(chan), AST_FLAG_DISABLE_DEVSTATE_CACHE);
p->chan = chan;
ast_channel_unlock(chan);
return owner;
}

@ -678,9 +678,9 @@ static struct ast_channel *create_msg_q_chan(void)
return NULL;
}
ast_channel_unlink(chan);
ast_channel_tech_set(chan, &msg_chan_tech_hack);
ast_channel_unlock(chan);
ast_channel_unlink(chan);
if (!(ds = ast_datastore_alloc(&msg_datastore, NULL))) {
ast_hangup(chan);

@ -10365,6 +10365,8 @@ static int pbx_outgoing_attempt(const char *type, struct ast_format_cap *cap, co
snprintf(failed_reason, sizeof(failed_reason), "%d", ast_dial_reason(outgoing->dial, 0));
pbx_builtin_setvar_helper(failed, "REASON", failed_reason);
ast_channel_unlock(failed);
if (ast_pbx_run(failed)) {
ast_log(LOG_ERROR, "Unable to run PBX on '%s'\n", ast_channel_name(failed));
ast_hangup(failed);

@ -63,6 +63,8 @@ static struct ast_channel *create_alice_channel(void)
ast_channel_set_caller(alice, &alice_callerid, NULL);
ast_channel_unlock(alice);
return alice;
}

@ -766,6 +766,8 @@ static void *do_notify(void *data)
/* clear native formats and set to slinear. write format is signlear so just use that to set it */
ast_format_cap_set(ast_channel_nativeformats(chan), ast_channel_writeformat(chan));
ast_channel_unlock(chan);
if (!(datastore = ast_datastore_alloc(&event_notification_datastore, NULL))) {
ast_log(LOG_ERROR, "Could not allocate datastore, notification not being sent!\n");
goto notify_cleanup;

@ -274,12 +274,21 @@ static int snoop_setup_audiohook(struct ast_channel *chan, enum ast_audiohook_ty
return ast_audiohook_attach(chan, audiohook);
}
/*! \brief Helper function which gets the format for a Snoop channel based on the channel being snooped on */
static void snoop_determine_format(struct ast_channel *chan, struct stasis_app_snoop *snoop)
{
SCOPED_CHANNELLOCK(lock, chan);
unsigned int rate = MAX(ast_format_rate(ast_channel_rawwriteformat(chan)),
ast_format_rate(ast_channel_rawreadformat(chan)));
ast_format_set(&snoop->spy_format, ast_format_slin_by_rate(rate), 0);
}
struct ast_channel *stasis_app_control_snoop(struct ast_channel *chan,
enum stasis_app_snoop_direction spy, enum stasis_app_snoop_direction whisper,
const char *app, const char *app_args)
{
RAII_VAR(struct stasis_app_snoop *, snoop, NULL, ao2_cleanup);
unsigned int rate;
pthread_t thread;
if (spy == STASIS_SNOOP_DIRECTION_NONE &&
@ -310,6 +319,9 @@ struct ast_channel *stasis_app_control_snoop(struct ast_channel *chan,
}
ast_timer_set_rate(snoop->timer, 1000 / SNOOP_INTERVAL);
/* Determine which signed linear format should be used */
snoop_determine_format(chan, snoop);
/* Allocate a Snoop channel and set up various parameters */
snoop->chan = ast_channel_alloc(1, AST_STATE_UP, "", "", "", "", "", "", 0, "Snoop/%s-%08x", ast_channel_uniqueid(chan),
ast_atomic_fetchadd_int((int *)&chan_idx, +1));
@ -327,39 +339,33 @@ struct ast_channel *stasis_app_control_snoop(struct ast_channel *chan,
ast_channel_tech_pvt_set(snoop->chan, snoop);
ast_channel_set_fd(snoop->chan, 0, ast_timer_fd(snoop->timer));
{
SCOPED_CHANNELLOCK(lock, chan);
/* The format on the Snoop channel will be this signed linear format, and it will never change */
ast_format_cap_set(ast_channel_nativeformats(snoop->chan), &snoop->spy_format);
ast_format_copy(ast_channel_writeformat(snoop->chan), &snoop->spy_format);
ast_format_copy(ast_channel_rawwriteformat(snoop->chan), &snoop->spy_format);
ast_format_copy(ast_channel_readformat(snoop->chan), &snoop->spy_format);
ast_format_copy(ast_channel_rawreadformat(snoop->chan), &snoop->spy_format);
/* Determine the "best" signed linear format capable by the channel we are snooping on */
rate = MAX(ast_format_rate(ast_channel_rawwriteformat(chan)), ast_format_rate(ast_channel_rawreadformat(chan)));
ast_format_set(&snoop->spy_format, ast_format_slin_by_rate(rate), 0);
ast_channel_unlock(snoop->chan);
/* The format on the Snoop channel will be this signed linear format, and it will never change */
ast_format_cap_set(ast_channel_nativeformats(snoop->chan), &snoop->spy_format);
ast_format_copy(ast_channel_writeformat(snoop->chan), &snoop->spy_format);
ast_format_copy(ast_channel_rawwriteformat(snoop->chan), &snoop->spy_format);
ast_format_copy(ast_channel_readformat(snoop->chan), &snoop->spy_format);
ast_format_copy(ast_channel_rawreadformat(snoop->chan), &snoop->spy_format);
if (spy != STASIS_SNOOP_DIRECTION_NONE) {
if (snoop_setup_audiohook(chan, AST_AUDIOHOOK_TYPE_SPY, spy, &snoop->spy_direction, &snoop->spy)) {
ast_hangup(snoop->chan);
return NULL;
}
snoop->spy_samples = rate / (1000 / SNOOP_INTERVAL);
snoop->spy_active = 1;
if (spy != STASIS_SNOOP_DIRECTION_NONE) {
if (snoop_setup_audiohook(chan, AST_AUDIOHOOK_TYPE_SPY, spy, &snoop->spy_direction, &snoop->spy)) {
ast_hangup(snoop->chan);
return NULL;
}
/* If whispering is enabled set up the audiohook */
if (whisper != STASIS_SNOOP_DIRECTION_NONE) {
if (snoop_setup_audiohook(chan, AST_AUDIOHOOK_TYPE_WHISPER, whisper, &snoop->whisper_direction, &snoop->whisper)) {
ast_hangup(snoop->chan);
return NULL;
}
snoop->spy_samples = ast_format_rate(&snoop->spy_format) / (1000 / SNOOP_INTERVAL);
snoop->spy_active = 1;
}
snoop->whisper_active = 1;
/* If whispering is enabled set up the audiohook */
if (whisper != STASIS_SNOOP_DIRECTION_NONE) {
if (snoop_setup_audiohook(chan, AST_AUDIOHOOK_TYPE_WHISPER, whisper, &snoop->whisper_direction, &snoop->whisper)) {
ast_hangup(snoop->chan);
return NULL;
}
snoop->whisper_active = 1;
}
/* Create the thread which services the Snoop channel */

@ -175,21 +175,25 @@ AST_TEST_DEFINE(app_group)
"'%s', '%s', '%s', '%s'\n", group1_full, group2_full, category1_full, category2_full);
if (!(test_channel1 = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
NULL, NULL, 0, 0, "TestChannel1"))) {
NULL, NULL, 0, 0, "TestChannel1"))) {
goto exit_group_test;
}
ast_channel_unlock(test_channel1);
if (!(test_channel2 = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
NULL, NULL, 0, 0, "TestChannel2"))) {
NULL, NULL, 0, 0, "TestChannel2"))) {
goto exit_group_test;
}
ast_channel_unlock(test_channel2);
if (!(test_channel3 = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
NULL, NULL, 0, 0, "TestChannel3"))) {
NULL, NULL, 0, 0, "TestChannel3"))) {
goto exit_group_test;
}
ast_channel_unlock(test_channel3);
if (!(test_channel4 = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
NULL, NULL, 0, 0, "TestChannel4"))) {
NULL, NULL, 0, 0, "TestChannel4"))) {
goto exit_group_test;
}
ast_channel_unlock(test_channel4);
ast_app_group_set_channel(test_channel1, group1_full);
ast_app_group_set_channel(test_channel2, group2_full);

@ -238,6 +238,7 @@ static void clear_mock_cdr_backend(void)
ast_channel_set_caller((channel_var), (caller_id), NULL); \
ast_copy_string((expected_record)->uniqueid, ast_channel_uniqueid((channel_var)), sizeof((expected_record)->uniqueid)); \
ast_copy_string((expected_record)->linkedid, ast_channel_linkedid((channel_var)), sizeof((expected_record)->linkedid)); \
ast_channel_unlock((channel_var)); \
} while (0)
/*! \brief Create a \ref test_cdr_chan_tech for Bob, and set the expected
@ -247,6 +248,7 @@ static void clear_mock_cdr_backend(void)
ast_channel_set_caller((channel_var), (caller_id), NULL); \
ast_copy_string((expected_record)->uniqueid, ast_channel_uniqueid((channel_var)), sizeof((expected_record)->uniqueid)); \
ast_copy_string((expected_record)->linkedid, ast_channel_linkedid((channel_var)), sizeof((expected_record)->linkedid)); \
ast_channel_unlock((channel_var)); \
} while (0)
/*! \brief Create a \ref test_cdr_chan_tech for Charlie, and set the expected
@ -256,6 +258,7 @@ static void clear_mock_cdr_backend(void)
ast_channel_set_caller((channel_var), (caller_id), NULL); \
ast_copy_string((expected_record)->uniqueid, ast_channel_uniqueid((channel_var)), sizeof((expected_record)->uniqueid)); \
ast_copy_string((expected_record)->linkedid, ast_channel_linkedid((channel_var)), sizeof((expected_record)->linkedid)); \
ast_channel_unlock((channel_var)); \
} while (0)
/*! \brief Create a \ref test_cdr_chan_tech for Charlie, and set the expected
@ -265,6 +268,7 @@ static void clear_mock_cdr_backend(void)
ast_channel_set_caller((channel_var), (caller_id), NULL); \
ast_copy_string((expected_record)->uniqueid, ast_channel_uniqueid((channel_var)), sizeof((expected_record)->uniqueid)); \
ast_copy_string((expected_record)->linkedid, ast_channel_linkedid((channel_var)), sizeof((expected_record)->linkedid)); \
ast_channel_unlock((channel_var)); \
} while (0)
/*! \brief Emulate a channel entering into an application */
@ -563,6 +567,7 @@ AST_TEST_DEFINE(test_cdr_outbound_bridged_call)
ast_test_validate(test, !ast_bridge_impart(bridge, chan_alice, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE));
chan_bob = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_alice), 0, CHANNEL_TECH_NAME "/Bob");
ast_channel_unlock(chan_bob);
ast_copy_string(bob_expected.linkedid, ast_channel_linkedid(chan_bob), sizeof(bob_expected.linkedid));
ast_copy_string(bob_expected.uniqueid, ast_channel_uniqueid(chan_bob), sizeof(bob_expected.uniqueid));
ast_set_flag(ast_channel_flags(chan_bob), AST_FLAG_OUTGOING);
@ -1133,6 +1138,7 @@ AST_TEST_DEFINE(test_cdr_dial_unanswered)
EMULATE_APP_DATA(chan_caller, 1, "Dial", "CDRTestChannel/Bob");
chan_callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/Bob");
ast_channel_unlock(chan_callee);
ast_set_flag(ast_channel_flags(chan_callee), AST_FLAG_OUTGOING);
EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)");
@ -1194,6 +1200,7 @@ AST_TEST_DEFINE(test_cdr_dial_busy)
EMULATE_APP_DATA(chan_caller, 1, "Dial", CHANNEL_TECH_NAME "/Bob");
chan_callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/Bob");
ast_channel_unlock(chan_callee);
ast_set_flag(ast_channel_flags(chan_callee), AST_FLAG_OUTGOING);
EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)");
@ -1254,6 +1261,7 @@ AST_TEST_DEFINE(test_cdr_dial_congestion)
EMULATE_APP_DATA(chan_caller, 1, "Dial", CHANNEL_TECH_NAME "/Bob");
chan_callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/Bob");
ast_channel_unlock(chan_callee);
ast_set_flag(ast_channel_flags(chan_callee), AST_FLAG_OUTGOING);
EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)");
@ -1314,6 +1322,7 @@ AST_TEST_DEFINE(test_cdr_dial_unavailable)
EMULATE_APP_DATA(chan_caller, 1, "Dial", CHANNEL_TECH_NAME "/Bob");
chan_callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/Bob");
ast_channel_unlock(chan_callee);
ast_set_flag(ast_channel_flags(chan_callee), AST_FLAG_OUTGOING);
EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)");
@ -1375,6 +1384,7 @@ AST_TEST_DEFINE(test_cdr_dial_caller_cancel)
EMULATE_APP_DATA(chan_caller, 1, "Dial", CHANNEL_TECH_NAME "/Bob");
chan_callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/Bob");
ast_channel_unlock(chan_callee);
ast_set_flag(ast_channel_flags(chan_callee), AST_FLAG_OUTGOING);
EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)");
@ -1476,14 +1486,17 @@ AST_TEST_DEFINE(test_cdr_dial_parallel_failed)
/* Outbound channels are created */
chan_bob = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/Bob");
ast_channel_unlock(chan_bob);
ast_set_flag(ast_channel_flags(chan_bob), AST_FLAG_OUTGOING);
EMULATE_APP_DATA(chan_bob, 0, "AppDial", "(Outgoing Line)");
chan_charlie = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "300", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/Charlie");
ast_channel_unlock(chan_charlie);
ast_set_flag(ast_channel_flags(chan_charlie), AST_FLAG_OUTGOING);
EMULATE_APP_DATA(chan_charlie, 0, "AppDial", "(Outgoing Line)");
chan_david = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "400", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/David");
ast_channel_unlock(chan_david);
ast_set_flag(ast_channel_flags(chan_david), AST_FLAG_OUTGOING);
EMULATE_APP_DATA(chan_david, 0, "AppDial", "(Outgoing Line)");
@ -1589,6 +1602,7 @@ AST_TEST_DEFINE(test_cdr_dial_answer_no_bridge)
EMULATE_APP_DATA(chan_caller, 1, "Dial", CHANNEL_TECH_NAME "/Bob");
chan_callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/Bob");
ast_channel_unlock(chan_callee);
ast_set_flag(ast_channel_flags(chan_callee), AST_FLAG_OUTGOING);
COPY_IDS(chan_callee, &bob_expected_one);
@ -1656,6 +1670,7 @@ AST_TEST_DEFINE(test_cdr_dial_answer_twoparty_bridge_a)
EMULATE_APP_DATA(chan_caller, 1, "Dial", CHANNEL_TECH_NAME "/Bob");
chan_callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/Bob");
ast_channel_unlock(chan_callee);
ast_set_flag(ast_channel_flags(chan_callee), AST_FLAG_OUTGOING);
EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)");
@ -1731,6 +1746,7 @@ AST_TEST_DEFINE(test_cdr_dial_answer_twoparty_bridge_b)
EMULATE_APP_DATA(chan_caller, 1, "Dial", CHANNEL_TECH_NAME "/Bob");
chan_callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/Bob");
ast_channel_unlock(chan_callee);
ast_set_flag(ast_channel_flags(chan_callee), AST_FLAG_OUTGOING);
EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)");
@ -1889,6 +1905,7 @@ AST_TEST_DEFINE(test_cdr_dial_answer_multiparty)
EMULATE_APP_DATA(chan_alice, 1, "Dial", CHANNEL_TECH_NAME "/Bob");
chan_bob = ast_channel_alloc(0, AST_STATE_DOWN, "200", "Bob", "200", "200", "default", NULL, 0, CHANNEL_TECH_NAME "/Bob");
ast_channel_unlock(chan_bob);
ast_set_flag(ast_channel_flags(chan_bob), AST_FLAG_OUTGOING);
EMULATE_APP_DATA(chan_bob, 0, "AppDial", "(Outgoing Line)");
ast_copy_string(bob_expected_one.uniqueid, ast_channel_uniqueid(chan_bob), sizeof(bob_expected_one.uniqueid));
@ -1902,6 +1919,7 @@ AST_TEST_DEFINE(test_cdr_dial_answer_multiparty)
ast_copy_string(charlie_expected_two.linkedid, ast_channel_linkedid(chan_alice), sizeof(charlie_expected_two.linkedid));
chan_david = ast_channel_alloc(0, AST_STATE_DOWN, "400", "David", "400", "400", "default", NULL, 0, CHANNEL_TECH_NAME "/David");
ast_channel_unlock(chan_david);
ast_set_flag(ast_channel_flags(chan_david), AST_FLAG_OUTGOING);
EMULATE_APP_DATA(chan_david, 0, "AppDial", "(Outgoing Line)");

@ -201,24 +201,28 @@ static void do_sleep(void)
#define CREATE_ALICE_CHANNEL(channel_var, caller_id) do { \
(channel_var) = ast_channel_alloc(0, AST_STATE_DOWN, (caller_id)->id.number.str, (caller_id)->id.name.str, "100", "100", "default", NULL, 0, CHANNEL_TECH_NAME "/Alice"); \
APPEND_EVENT(channel_var, AST_CEL_CHANNEL_START, NULL, NULL); \
ast_channel_unlock((channel_var)); \
} while (0)
/*! \brief Create a \ref test_cel_chan_tech for Bob. */
#define CREATE_BOB_CHANNEL(channel_var, caller_id) do { \
(channel_var) = ast_channel_alloc(0, AST_STATE_DOWN, (caller_id)->id.number.str, (caller_id)->id.name.str, "200", "200", "default", NULL, 0, CHANNEL_TECH_NAME "/Bob"); \
APPEND_EVENT(channel_var, AST_CEL_CHANNEL_START, NULL, NULL); \
ast_channel_unlock((channel_var)); \
} while (0)
/*! \brief Create a \ref test_cel_chan_tech for Charlie. */
#define CREATE_CHARLIE_CHANNEL(channel_var, caller_id) do { \
(channel_var) = ast_channel_alloc(0, AST_STATE_DOWN, (caller_id)->id.number.str, (caller_id)->id.name.str, "300", "300", "default", NULL, 0, CHANNEL_TECH_NAME "/Charlie"); \
APPEND_EVENT(channel_var, AST_CEL_CHANNEL_START, NULL, NULL); \
ast_channel_unlock((channel_var)); \
} while (0)
/*! \brief Create a \ref test_cel_chan_tech for David. */
#define CREATE_DAVID_CHANNEL(channel_var, caller_id) do { \
(channel_var) = ast_channel_alloc(0, AST_STATE_DOWN, (caller_id)->id.number.str, (caller_id)->id.name.str, "400", "400", "default", NULL, 0, CHANNEL_TECH_NAME "/David"); \
APPEND_EVENT(channel_var, AST_CEL_CHANNEL_START, NULL, NULL); \
ast_channel_unlock((channel_var)); \
} while (0)
/*! \brief Emulate a channel entering into an application */
@ -717,6 +721,7 @@ AST_TEST_DEFINE(test_cel_single_multiparty_bridge)
#define START_DIALED_FULL(caller, callee, number, name) do { \
callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, number, NULL, NULL, ast_channel_linkedid(caller), 0, CHANNEL_TECH_NAME "/" name); \
ast_channel_unlock(callee); \
if (append_expected_event(callee, AST_CEL_CHANNEL_START, NULL, NULL, NULL)) { \
return AST_TEST_FAIL; \
} \

@ -73,6 +73,7 @@ AST_TEST_DEFINE(channel_blob_create)
type = stasis_message_type_create("test-type", NULL);
chan = ast_channel_alloc(0, AST_STATE_DOWN, "100", "Alice", "100", "100", "default", NULL, 0, "TEST/Alice");
ast_channel_unlock(chan);
json = ast_json_pack("{s: s}",
"foo", "bar");
@ -125,6 +126,7 @@ AST_TEST_DEFINE(null_blob)
type = stasis_message_type_create("test-type", NULL);
chan = ast_channel_alloc(0, AST_STATE_DOWN, "100", "Alice", "100", "100", "default", NULL, 0, "TEST/Alice");
ast_channel_unlock(chan);
json = ast_json_pack("{s: s}",
"foo", "bar");
@ -192,8 +194,11 @@ AST_TEST_DEFINE(multi_channel_blob_snapshots)
json = ast_json_pack("{s: s}",
"type", "test");
chan_alice = ast_channel_alloc(0, AST_STATE_DOWN, "100", "Alice", "100", "100", "default", NULL, 0, "TEST/Alice");
ast_channel_unlock(chan_alice);
chan_bob = ast_channel_alloc(0, AST_STATE_DOWN, "200", "Bob", "200", "200", "default", NULL, 0, "TEST/Bob");
ast_channel_unlock(chan_bob);
chan_charlie = ast_channel_alloc(0, AST_STATE_DOWN, "300", "Bob", "300", "300", "default", NULL, 0, "TEST/Charlie");
ast_channel_unlock(chan_charlie);
blob = ast_multi_channel_blob_create(json);
ast_multi_channel_blob_add_channel(blob, "Caller", ast_channel_snapshot_create(chan_alice));
@ -251,6 +256,7 @@ AST_TEST_DEFINE(channel_snapshot_json)
ast_test_validate(test, NULL == ast_channel_snapshot_to_json(NULL, NULL));
chan = ast_channel_alloc(0, AST_STATE_DOWN, "cid_num", "cid_name", "acctcode", "exten", "context", NULL, 0, "TEST/name");
ast_channel_unlock(chan);
ast_test_validate(test, NULL != chan);
snapshot = ast_channel_snapshot_create(chan);
ast_test_validate(test, NULL != snapshot);

@ -244,6 +244,7 @@ AST_TEST_DEFINE(test_substitution)
ast_test_status_update(test, "Testing variable substitution ...\n");
c = ast_channel_alloc(0, 0, "", "", "", "", "", "", 0, "Test/substitution");
ast_channel_unlock(c);
#define TEST(t) if (t == AST_TEST_FAIL) { res = AST_TEST_FAIL; }
#if 0

@ -833,6 +833,8 @@ static struct ast_channel *test_vm_api_create_mock_channel(void)
ast_format_set(ast_channel_rawreadformat(mock_channel), AST_FORMAT_GSM, 0);
ast_channel_tech_set(mock_channel, &mock_channel_tech);
ast_channel_unlock(mock_channel);
return mock_channel;
}

Loading…
Cancel
Save