static void safe_channel_release(struct ast_channel *chan)
{
	if (!chan) {
		return;
	}
	ast_channel_release(chan);
}
Exemple #2
0
static struct ast_channel *rec_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause)
{
	struct ast_channel *chan;
	struct ast_format format;
	const char *conf_name = data;

	chan = ast_channel_alloc(1, AST_STATE_UP, NULL, NULL, NULL, NULL, NULL, NULL, 0,
		"CBRec/conf-%s-uid-%d",
		conf_name, (int) ast_random());
	if (!chan) {
		return NULL;
	}
	if (ast_channel_add_bridge_role(chan, "recorder")) {
		ast_channel_release(chan);
		return NULL;
	}
	ast_format_set(&format, AST_FORMAT_SLINEAR, 0);
	ast_channel_tech_set(chan, conf_record_get_tech());
	ast_format_cap_add_all(ast_channel_nativeformats(chan));
	ast_format_copy(ast_channel_writeformat(chan), &format);
	ast_format_copy(ast_channel_rawwriteformat(chan), &format);
	ast_format_copy(ast_channel_readformat(chan), &format);
	ast_format_copy(ast_channel_rawreadformat(chan), &format);
	return chan;
}
Exemple #3
0
/*! \brief Called when we want to place a call somewhere, but not actually call it... yet */
static struct ast_channel *bridge_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause)
{
	struct bridge_pvt *p = NULL;
	struct ast_format slin;

	/* Try to allocate memory for our very minimal pvt structure */
	if (!(p = ao2_alloc(sizeof(*p), NULL))) {
		return NULL;
	}

	/* Try to grab two Asterisk channels to use as input and output channels */
	if (!(p->input = ast_channel_alloc(1, AST_STATE_UP, 0, 0, "", "", "", requestor ? requestor->linkedid : NULL, 0, "Bridge/%p-input", p))) {
		ao2_ref(p, -1);
		return NULL;
	}
	if (!(p->output = ast_channel_alloc(1, AST_STATE_UP, 0, 0, "", "", "", requestor ? requestor->linkedid : NULL, 0, "Bridge/%p-output", p))) {
		p->input = ast_channel_release(p->input);
		ao2_ref(p, -1);
		return NULL;
	}

	/* Setup parameters on both new channels */
	p->input->tech = p->output->tech = &bridge_tech;

	ao2_ref(p, 2);
	p->input->tech_pvt = p->output->tech_pvt = p;

	ast_format_set(&slin, AST_FORMAT_SLINEAR, 0);

	ast_format_cap_add(p->input->nativeformats, &slin);
	ast_format_cap_add(p->output->nativeformats, &slin);
	ast_format_copy(&p->input->readformat, &slin);
	ast_format_copy(&p->output->readformat, &slin);
	ast_format_copy(&p->input->rawreadformat, &slin);
	ast_format_copy(&p->output->rawreadformat, &slin);
	ast_format_copy(&p->input->writeformat, &slin);
	ast_format_copy(&p->output->writeformat, &slin);
	ast_format_copy(&p->input->rawwriteformat, &slin);
	ast_format_copy(&p->output->rawwriteformat, &slin);

	ast_answer(p->output);
	ast_answer(p->input);

	/* remove the reference from the alloc. The channels now own the pvt. */
	ao2_ref(p, -1);
	return p->input;
}
Exemple #4
0
struct ast_channel *ast_cel_fabricate_channel_from_event(const struct ast_event *event)
{
	struct varshead *headp;
	struct ast_var_t *newvariable;
	char timebuf[30];
	struct ast_channel *tchan;
	struct ast_cel_event_record record = {
		.version = AST_CEL_EVENT_RECORD_VERSION,
	};

	/* do not call ast_channel_alloc because this is not really a real channel */
	if (!(tchan = ast_dummy_channel_alloc())) {
		return NULL;
	}

	headp = &tchan->varshead;

	/* first, get the variables from the event */
	if (ast_cel_fill_record(event, &record)) {
		ast_channel_release(tchan);
		return NULL;
	}

	/* next, fill the channel with their data */
	if ((newvariable = ast_var_assign("eventtype", record.event_name))) {
		AST_LIST_INSERT_HEAD(headp, newvariable, entries);
	}

	if (ast_strlen_zero(cel_dateformat)) {
		snprintf(timebuf, sizeof(timebuf), "%ld.%06ld", (long) record.event_time.tv_sec,
				(long) record.event_time.tv_usec);
	} else {
		struct ast_tm tm;
		ast_localtime(&record.event_time, &tm, NULL);
		ast_strftime(timebuf, sizeof(timebuf), cel_dateformat, &tm);
	}

	if ((newvariable = ast_var_assign("eventtime", timebuf))) {
		AST_LIST_INSERT_HEAD(headp, newvariable, entries);
	}

	if ((newvariable = ast_var_assign("eventextra", record.extra))) {
		AST_LIST_INSERT_HEAD(headp, newvariable, entries);
	}

	tchan->caller.id.name.valid = 1;
	tchan->caller.id.name.str = ast_strdup(record.caller_id_name);
	tchan->caller.id.number.valid = 1;
	tchan->caller.id.number.str = ast_strdup(record.caller_id_num);
	tchan->caller.ani.number.valid = 1;
	tchan->caller.ani.number.str = ast_strdup(record.caller_id_ani);
	tchan->redirecting.from.number.valid = 1;
	tchan->redirecting.from.number.str = ast_strdup(record.caller_id_rdnis);
	tchan->dialed.number.str = ast_strdup(record.caller_id_dnid);

	ast_copy_string(tchan->exten, record.extension, sizeof(tchan->exten));
	ast_copy_string(tchan->context, record.context, sizeof(tchan->context));
	ast_string_field_set(tchan, name, record.channel_name);
	ast_string_field_set(tchan, uniqueid, record.unique_id);
	ast_string_field_set(tchan, linkedid, record.linked_id);
	ast_string_field_set(tchan, accountcode, record.account_code);
	ast_string_field_set(tchan, peeraccount, record.peer_account);
	ast_string_field_set(tchan, userfield, record.user_field);

	pbx_builtin_setvar_helper(tchan, "BRIDGEPEER", record.peer);

	tchan->appl = ast_strdup(record.application_name);
	tchan->data = ast_strdup(record.application_data);
	tchan->amaflags = record.amaflag;

	return tchan;
}
Exemple #5
0
struct ast_unreal_pvt *ast_unreal_alloc(size_t size, ao2_destructor_fn destructor, struct ast_format_cap *cap)
{
	struct ast_unreal_pvt *unreal;

	static const struct ast_jb_conf jb_conf = {
		.flags = 0,
		.max_size = -1,
		.resync_threshold = -1,
		.impl = "",
		.target_extra = -1,
	};

	unreal = ao2_alloc(size, destructor);
	if (!unreal) {
		return NULL;
	}
	unreal->reqcap = ast_format_cap_dup(cap);
	if (!unreal->reqcap) {
		ao2_ref(unreal, -1);
		return NULL;
	}

	memcpy(&unreal->jb_conf, &jb_conf, sizeof(unreal->jb_conf));

	return unreal;
}

struct ast_channel *ast_unreal_new_channels(struct ast_unreal_pvt *p,
	const struct ast_channel_tech *tech, int semi1_state, int semi2_state,
	const char *exten, const char *context, const struct ast_assigned_ids *assignedids,
	const struct ast_channel *requestor, struct ast_callid *callid)
{
	struct ast_channel *owner;
	struct ast_channel *chan;
	struct ast_format fmt;
	struct ast_assigned_ids id1 = {NULL, NULL};
	struct ast_assigned_ids id2 = {NULL, NULL};
	int generated_seqno = ast_atomic_fetchadd_int((int *) &name_sequence, +1);

	/* set unique ids for the two channels */
	if (assignedids && !ast_strlen_zero(assignedids->uniqueid)) {
		id1.uniqueid = assignedids->uniqueid;
		id2.uniqueid = assignedids->uniqueid2;
	}

	/* if id1 given but not id2, use default of id1;2 */
	if (id1.uniqueid && ast_strlen_zero(id2.uniqueid)) {
		char *uniqueid2;

		uniqueid2 = ast_alloca(strlen(id1.uniqueid) + 2);
		strcpy(uniqueid2, id1.uniqueid);/* Safe */
		strcat(uniqueid2, ";2");/* Safe */
		id2.uniqueid = uniqueid2;
	}

	/*
	 * Allocate two new Asterisk channels
	 *
	 * Make sure that the ;2 channel gets the same linkedid as ;1.
	 * You can't pass linkedid to both allocations since if linkedid
	 * isn't set, then each channel will generate its own linkedid.
	 */
	if (!(owner = ast_channel_alloc(1, semi1_state, NULL, NULL, NULL,
			exten, context, &id1, requestor, 0,
			"%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_tech_set(owner, tech);
	ao2_ref(p, +1);
	ast_channel_tech_pvt_set(owner, p);

	ast_format_cap_copy(ast_channel_nativeformats(owner), 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_rawwriteformat(owner), &fmt);
	ast_format_copy(ast_channel_readformat(owner), &fmt);
	ast_format_copy(ast_channel_rawreadformat(owner), &fmt);

	ast_set_flag(ast_channel_flags(owner), 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);
		return NULL;
	}

	p->owner = owner;
	ast_channel_unlock(owner);

	if (!(chan = ast_channel_alloc(1, semi2_state, NULL, NULL, NULL,
			exten, context, &id2, 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;
}