Ejemplo n.º 1
0
static void set_config_flags(struct ast_channel *chan, struct ast_bridge_config *config)
{
	ast_clear_flag(config, AST_FLAGS_ALL);

	if (ast_test_flag(&config->features_caller, AST_FEATURE_DTMF_MASK)) {
		ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
	}
	if (ast_test_flag(&config->features_callee, AST_FEATURE_DTMF_MASK)) {
		ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
	}

	if (!(ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_0) && ast_test_flag(config, AST_BRIDGE_DTMF_CHANNEL_1))) {
		RAII_VAR(struct ao2_container *, applicationmap, NULL, ao2_cleanup);

		ast_channel_lock(chan);
		applicationmap = ast_get_chan_applicationmap(chan);
		ast_channel_unlock(chan);

		if (!applicationmap) {
			return;
		}

		/* If an applicationmap exists for this channel at all, then the channel needs the DTMF flag set */
		ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
	}
}
Ejemplo n.º 2
0
const char *comedia_string(struct ast_flags *flags)
{
	if (ast_test_flag(&flags[2], SIP_PAGE3_NAT_AUTO_COMEDIA)) {
		return ast_test_flag(&flags[1], SIP_PAGE2_SYMMETRICRTP) ? "Auto (Yes)" : "Auto (No)";
	}
	return AST_CLI_YESNO(ast_test_flag(&flags[1], SIP_PAGE2_SYMMETRICRTP));
}
Ejemplo n.º 3
0
static void page_state_callback(struct ast_dial *dial)
{
	struct ast_channel *chan;
	struct page_options *options;

	if (ast_dial_state(dial) != AST_DIAL_RESULT_ANSWERED ||
	    !(chan = ast_dial_answered(dial)) ||
	    !(options = ast_dial_get_user_data(dial))) {
		return;
	}

	ast_func_write(chan, "CONFBRIDGE(bridge,template)", "default_bridge");

	if (ast_test_flag(&options->flags, PAGE_RECORD)) {
		ast_func_write(chan, "CONFBRIDGE(bridge,record_conference)", "yes");
	}

	ast_func_write(chan, "CONFBRIDGE(user,quiet)", "yes");
	ast_func_write(chan, "CONFBRIDGE(user,end_marked)", "yes");

	if (!ast_test_flag(&options->flags, PAGE_DUPLEX)) {
		ast_func_write(chan, "CONFBRIDGE(user,startmuted)", "yes");
	}

	if (ast_test_flag(&options->flags, PAGE_ANNOUNCE) && !ast_strlen_zero(options->opts[OPT_ARG_ANNOUNCE])) {
		ast_func_write(chan, "CONFBRIDGE(user,announcement)", options->opts[OPT_ARG_ANNOUNCE]);
	}
}
Ejemplo n.º 4
0
static int resetcdr_exec(struct ast_channel *chan, const char *data)
{
	RAII_VAR(struct app_cdr_message_payload *, payload,
		ao2_alloc(sizeof(*payload), NULL), ao2_cleanup);
	char *args;
	struct ast_flags flags = { 0 };

	if (!payload) {
		return -1;
	}

	if (!ast_strlen_zero(data)) {
		args = ast_strdupa(data);
		ast_app_parse_options(resetcdr_opts, &flags, NULL, args);
	}

	payload->channel_name = ast_channel_name(chan);
	payload->reset = 1;

	if (ast_test_flag(&flags, AST_CDR_FLAG_DISABLE_ALL)) {
		payload->reenable = 1;
	}

	if (ast_test_flag(&flags, AST_CDR_FLAG_KEEP_VARS)) {
		payload->keep_variables = 1;
	}

	return publish_app_cdr_message(chan, payload);
}
Ejemplo n.º 5
0
const char *force_rport_string(struct ast_flags *flags)
{
	if (ast_test_flag(&flags[2], SIP_PAGE3_NAT_AUTO_RPORT)) {
		return ast_test_flag(&flags[0], SIP_NAT_FORCE_RPORT) ? "Auto (Yes)" : "Auto (No)";
	}
	return AST_CLI_YESNO(ast_test_flag(&flags[0], SIP_NAT_FORCE_RPORT));
}
Ejemplo n.º 6
0
const char *ast_sdp_srtp_get_attrib(struct ast_sdp_srtp *srtp, int dtls_enabled, int default_taglen_32)
{
	int taglen = default_taglen_32 ? 32 : 80;

	if (!srtp) {
		return NULL;
	}

	/* Set encryption properties */
	if (!srtp->crypto) {
		srtp->crypto = ast_sdp_crypto_alloc();
	}

	if (dtls_enabled) {
		/* If DTLS-SRTP is enabled the key details will be pulled from TLS */
		return NULL;
	}

	/* set the key length based on INVITE or settings */
	if (ast_test_flag(srtp, AST_SRTP_CRYPTO_TAG_80)) {
		taglen = 80;
	} else if (ast_test_flag(srtp, AST_SRTP_CRYPTO_TAG_32)) {
		taglen = 32;
	}

	if (srtp->crypto && (ast_sdp_crypto_build_offer(srtp->crypto, taglen) >= 0)) {
		return srtp->crypto->a_crypto;
	}

	ast_log(LOG_WARNING, "No SRTP key management enabled\n");
	return NULL;
}
/*!
 * \internal
 * \brief Setup the caller user profile.
 *
 * \param chan Setup user profile on this channel.
 * \param options Options to setup caller user profile.
 *
 * \return Nothing
 */
static void setup_profile_caller(struct ast_channel *chan, struct page_options *options)
{
	/* Use default_user as a starting point if not already setup. */
	ast_func_write(chan, "CONFBRIDGE(user,template)", "");
	ast_func_write(chan, "CONFBRIDGE(user,quiet)", "yes");
	ast_func_write(chan, "CONFBRIDGE(user,marked)", "yes");
	if (!ast_test_flag(&options->flags, PAGE_NOCALLERANNOUNCE)
		&& ast_test_flag(&options->flags, PAGE_ANNOUNCE)
		&& !ast_strlen_zero(options->opts[OPT_ARG_ANNOUNCE])) {
		ast_func_write(chan, "CONFBRIDGE(user,announcement)", options->opts[OPT_ARG_ANNOUNCE]);
	}
}
Ejemplo n.º 8
0
/*!
 * \internal brief Setup limit hook structures on calls that need limits
 *
 * \param config ast_bridge_config which provides the limit data
 * \param caller_limits pointer to an ast_bridge_features_limits struct which will store the caller side limits
 * \param callee_limits pointer to an ast_bridge_features_limits struct which will store the callee side limits
 */
static void bridge_config_set_limits(struct ast_bridge_config *config, struct ast_bridge_features_limits *caller_limits, struct ast_bridge_features_limits *callee_limits)
{
	if (ast_test_flag(&config->features_caller, AST_FEATURE_PLAY_WARNING)) {
		bridge_config_set_limits_warning_values(config, caller_limits);
	}

	if (ast_test_flag(&config->features_callee, AST_FEATURE_PLAY_WARNING)) {
		bridge_config_set_limits_warning_values(config, callee_limits);
	}

	caller_limits->duration = config->timelimit;
	callee_limits->duration = config->timelimit;
}
Ejemplo n.º 9
0
static int app_exec(struct ast_channel *chan, void *data)
{
	int res = 0;
	struct ast_flags flags;
	struct localuser *u;
	char *options=NULL;
	char *dummy = NULL;
	char *args;
	int argc = 0;
	char *opts[2];
	char *argv[2];

	if (ast_strlen_zero(data)) {
		ast_log(LOG_WARNING, "%s requires an argument (dummy|[options])\n",app);
		return -1;
	}

	LOCAL_USER_ADD(u);
	
	/* Do our thing here */

	/* We need to make a copy of the input string if we are going to modify it! */
	args = ast_strdupa(data);	
	if (!args) {
		ast_log(LOG_ERROR, "Out of memory!\n");
		LOCAL_USER_REMOVE(u);
		return -1;
	}
	
	if ((argc = ast_app_separate_args(args, '|', argv, sizeof(argv) / sizeof(argv[0])))) {
		dummy = argv[0];
		options = argv[1];
		ast_app_parse_options(app_opts, &flags, opts, options);
	}

	if (!ast_strlen_zero(dummy)) 
		ast_log(LOG_NOTICE, "Dummy value is : %s\n", dummy);

	if (ast_test_flag(&flags, OPTION_A))
		ast_log(LOG_NOTICE, "Option A is set\n");

	if (ast_test_flag(&flags, OPTION_B))
		ast_log(LOG_NOTICE,"Option B is set with : %s\n", opts[0] ? opts[0] : "<unspecified>");

	if (ast_test_flag(&flags, OPTION_C))
		ast_log(LOG_NOTICE,"Option C is set with : %s\n", opts[1] ? opts[1] : "<unspecified>");

	LOCAL_USER_REMOVE(u);
	
	return res;
}
Ejemplo n.º 10
0
int ast_jb_do_usecheck(struct ast_channel *c0, struct ast_channel *c1)
{
	struct ast_jb *jb0 = ast_channel_jb(c0);
	struct ast_jb *jb1 = ast_channel_jb(c1);
	struct ast_jb_conf *conf0 = &jb0->conf;
	struct ast_jb_conf *conf1 = &jb1->conf;
	int c0_wants_jitter = ast_channel_tech(c0)->properties & AST_CHAN_TP_WANTSJITTER;
	int c0_creates_jitter = ast_channel_tech(c0)->properties & AST_CHAN_TP_CREATESJITTER;
	int c0_jb_enabled = ast_test_flag(conf0, AST_JB_ENABLED);
	int c0_force_jb = ast_test_flag(conf0, AST_JB_FORCED);
	int c0_jb_timebase_initialized = ast_test_flag(jb0, JB_TIMEBASE_INITIALIZED);
	int c0_jb_created = ast_test_flag(jb0, JB_CREATED);
	int c1_wants_jitter = ast_channel_tech(c1)->properties & AST_CHAN_TP_WANTSJITTER;
	int c1_creates_jitter = ast_channel_tech(c1)->properties & AST_CHAN_TP_CREATESJITTER;
	int c1_jb_enabled = ast_test_flag(conf1, AST_JB_ENABLED);
	int c1_force_jb = ast_test_flag(conf1, AST_JB_FORCED);
	int c1_jb_timebase_initialized = ast_test_flag(jb1, JB_TIMEBASE_INITIALIZED);
	int c1_jb_created = ast_test_flag(jb1, JB_CREATED);
	int inuse = 0;

	/* Determine whether audio going to c0 needs a jitter buffer */
	if (((!c0_wants_jitter && c1_creates_jitter) || (c0_force_jb && c1_creates_jitter)) && c0_jb_enabled) {
		ast_set_flag(jb0, JB_USE);
		if (!c0_jb_timebase_initialized) {
			if (c1_jb_timebase_initialized) {
				memcpy(&jb0->timebase, &jb1->timebase, sizeof(struct timeval));
			} else {
				gettimeofday(&jb0->timebase, NULL);
			}
			ast_set_flag(jb0, JB_TIMEBASE_INITIALIZED);
		}

		if (!c0_jb_created) {
			jb_choose_impl(c0);
		}

		inuse = 1;
	}

	/* Determine whether audio going to c1 needs a jitter buffer */
	if (((!c1_wants_jitter && c0_creates_jitter) || (c1_force_jb && c0_creates_jitter)) && c1_jb_enabled) {
		ast_set_flag(jb1, JB_USE);
		if (!c1_jb_timebase_initialized) {
			if (c0_jb_timebase_initialized) {
				memcpy(&jb1->timebase, &jb0->timebase, sizeof(struct timeval));
			} else {
				gettimeofday(&jb1->timebase, NULL);
			}
			ast_set_flag(jb1, JB_TIMEBASE_INITIALIZED);
		}

		if (!c1_jb_created) {
			jb_choose_impl(c1);
		}

		inuse = 1;
	}

	return inuse;
}
/*!
 * \internal
 * \brief Setup the paged user profile.
 *
 * \param chan Setup user profile on this channel.
 * \param options Options to setup paged user profile.
 *
 * \return Nothing
 */
static void setup_profile_paged(struct ast_channel *chan, struct page_options *options)
{
	/* Use default_user as a starting point */
	ast_func_write(chan, "CONFBRIDGE(user,template)", "");
	ast_func_write(chan, "CONFBRIDGE(user,quiet)", "yes");
	ast_func_write(chan, "CONFBRIDGE(user,end_marked)", "yes");
	if (!ast_test_flag(&options->flags, PAGE_DUPLEX)) {
		ast_func_write(chan, "CONFBRIDGE(user,startmuted)", "yes");
	}
	if (ast_test_flag(&options->flags, PAGE_ANNOUNCE)
		&& !ast_strlen_zero(options->opts[OPT_ARG_ANNOUNCE])) {
		ast_func_write(chan, "CONFBRIDGE(user,announcement)", options->opts[OPT_ARG_ANNOUNCE]);
	}
}
Ejemplo n.º 12
0
static int start_spying(struct ast_autochan *autochan, const char *spychan_name, struct ast_audiohook *audiohook, struct ast_flags *flags)
{
	ast_log(LOG_NOTICE, "Attaching %s to %s\n", spychan_name, ast_channel_name(autochan->chan));
	if(ast_test_flag(flags, OPTION_READONLY)) {
		ast_set_flag(audiohook, AST_AUDIOHOOK_MUTE_WRITE);
	} else {
		ast_set_flag(audiohook, AST_AUDIOHOOK_TRIGGER_SYNC);
	}
	if(ast_test_flag(flags, OPTION_LONG_QUEUE)) {
		ast_debug(9, "Using a long queue to store audio frames in spy audiohook\n");
	} else {
		ast_set_flag(audiohook, AST_AUDIOHOOK_SMALL_QUEUE);
	}
	return ast_audiohook_attach(autochan->chan, audiohook);
}
Ejemplo n.º 13
0
void ast_jb_get_and_deliver(struct ast_channel *c0, struct ast_channel *c1)
{
	struct ast_jb *jb0 = ast_channel_jb(c0);
	struct ast_jb *jb1 = ast_channel_jb(c1);
	int c0_use_jb = ast_test_flag(jb0, JB_USE);
	int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED);
	int c1_use_jb = ast_test_flag(jb1, JB_USE);
	int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED);

	if (c0_use_jb && c0_jb_is_created)
		jb_get_and_deliver(c0);

	if (c1_use_jb && c1_jb_is_created)
		jb_get_and_deliver(c1);
}
Ejemplo n.º 14
0
/*!
 * \brief Remove a call file from the outgoing queue optionally moving it in the archive dir
 *
 * \param o the pointer to outgoing struct
 * \param status the exit status of the call. Can be "Completed", "Failed" or "Expired"
 */
static int remove_from_queue(struct outgoing *o, const char *status)
{
	int fd;
	FILE *f;
	char newfn[256];
	const char *bname;

	if (!ast_test_flag(&o->options, SPOOL_FLAG_ALWAYS_DELETE)) {
		struct stat current_file_status;

		if (!stat(o->fn, &current_file_status))
			if (time(NULL) < current_file_status.st_mtime)
				return 0;
	}

	if (!ast_test_flag(&o->options, SPOOL_FLAG_ARCHIVE)) {
		unlink(o->fn);
		return 0;
	}
	if (mkdir(qdonedir, 0700) && (errno != EEXIST)) {
		ast_log(LOG_WARNING, "Unable to create queue directory %s -- outgoing spool archiving disabled\n", qdonedir);
		unlink(o->fn);
		return -1;
	}
	fd = open(o->fn, O_WRONLY|O_APPEND);
	if (fd > -1) {
		f = fdopen(fd, "a");
		if (f) {
			fprintf(f, "Status: %s\n", status);
			fclose(f);
		} else
			close(fd);
	}

	bname = strrchr(o->fn,'/');
	if (bname == NULL) 
		bname = o->fn;
	else 
		bname++;	
	snprintf(newfn, sizeof(newfn), "%s/%s", qdonedir, bname);
	/* a existing call file the archive dir is overwritten */
	unlink(newfn);
	if (rename(o->fn, newfn) != 0) {
		unlink(o->fn);
		return -1;
	} else
		return 0;
}
Ejemplo n.º 15
0
static int local_write(struct ast_channel *ast, struct ast_frame *f)
{
	struct local_pvt *p = ast_channel_tech_pvt(ast);
	int res = -1;
	int isoutbound;

	if (!p) {
		return -1;
	}

	/* Just queue for delivery to the other side */
	ao2_ref(p, 1); /* ref for local_queue_frame */
	ao2_lock(p);
	isoutbound = IS_OUTBOUND(ast, p);

	if (isoutbound
		&& (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO)) {
		check_bridge(ast, p);
	}

	if (!ast_test_flag(p, LOCAL_ALREADY_MASQED)) {
		res = local_queue_frame(p, isoutbound, f, ast, 1);
	} else {
		ast_debug(1, "Not posting to '%s' queue since already masqueraded out\n",
			ast_channel_name(ast));
		res = 0;
	}
	ao2_unlock(p);
	ao2_ref(p, -1);

	return res;
}
Ejemplo n.º 16
0
static void mixmonitor_save_prep(struct mixmonitor *mixmonitor, char *filename, struct ast_filestream **fs, unsigned int *oflags, int *errflag)
{
	/* Initialize the file if not already done so */
	char *ext = NULL;
	char *last_slash = NULL;
	if (!ast_strlen_zero(filename)) {
		if (!*fs && !*errflag && !mixmonitor->mixmonitor_ds->fs_quit) {
			*oflags = O_CREAT | O_WRONLY;
			*oflags |= ast_test_flag(mixmonitor, MUXFLAG_APPEND) ? O_APPEND : O_TRUNC;

			last_slash = strrchr(filename, '/');

			if ((ext = strrchr(filename, '.')) && (ext > last_slash)) {
				*(ext++) = '\0';
			} else {
				ext = "raw";
			}

			if (!(*fs = ast_writefile(filename, ext, NULL, *oflags, 0, 0666))) {
				ast_log(LOG_ERROR, "Cannot open %s.%s\n", filename, ext);
				*errflag = 1;
			} else {
				struct ast_filestream *tmp = *fs;
				mixmonitor->mixmonitor_ds->samp_rate = MAX(mixmonitor->mixmonitor_ds->samp_rate, ast_format_rate(&tmp->fmt->format));
			}
		}
	}
}
Ejemplo n.º 17
0
/*! \brief Return the bridged channel of a Local channel */
static struct ast_channel *local_bridgedchannel(struct ast_channel *chan, struct ast_channel *bridge)
{
	struct local_pvt *p = ast_channel_tech_pvt(bridge);
	struct ast_channel *bridged = bridge;

	if (!p) {
		ast_debug(1, "Asked for bridged channel on '%s'/'%s', returning <none>\n",
			ast_channel_name(chan), ast_channel_name(bridge));
		return NULL;
	}

	ao2_lock(p);

	if (ast_test_flag(p, LOCAL_BRIDGE)) {
		/* Find the opposite channel */
		bridged = (bridge == p->owner ? p->chan : p->owner);

		/* Now see if the opposite channel is bridged to anything */
		if (!bridged) {
			bridged = bridge;
		} else if (ast_channel_internal_bridged_channel(bridged)) {
			bridged = ast_channel_internal_bridged_channel(bridged);
		}
	}

	ao2_unlock(p);

	return bridged;
}
Ejemplo n.º 18
0
int ast_autoservice_stop(struct ast_channel *chan)
{
	int res = -1;
	struct asent *as, *prev;
	ast_mutex_lock(&autolock);
	as = aslist;
	prev = NULL;
	while(as) {
		if (as->chan == chan)
			break;
		prev = as;
		as = as->next;
	}
	if (as) {
		if (prev)
			prev->next = as->next;
		else
			aslist = as->next;
		free(as);
		if (!chan->_softhangup)
			res = 0;
	}
	if (asthread != AST_PTHREADT_NULL) 
		pthread_kill(asthread, SIGURG);
	ast_mutex_unlock(&autolock);
	/* Wait for it to un-block */
	while(ast_test_flag(chan, AST_FLAG_BLOCKING))
		usleep(1000);
	return res;
}
Ejemplo n.º 19
0
void ast_jb_destroy(struct ast_channel *chan)
{
	struct ast_jb *jb = ast_channel_jb(chan);
	const struct ast_jb_impl *jbimpl = jb->impl;
	void *jbobj = jb->jbobj;
	struct ast_frame *f;

	if (jb->logfile) {
		fclose(jb->logfile);
		jb->logfile = NULL;
	}

	if (ast_test_flag(jb, JB_CREATED)) {
		/* Remove and free all frames still queued in jb */
		while (jbimpl->remove(jbobj, &f) == AST_JB_IMPL_OK) {
			ast_frfree(f);
		}

		jbimpl->destroy(jbobj);
		jb->jbobj = NULL;

		ast_clear_flag(jb, JB_CREATED);

		ast_verb(3, "%s jitterbuffer destroyed on channel %s\n", jbimpl->name, ast_channel_name(chan));
	}
}
Ejemplo n.º 20
0
static int load_module(void)
{
	CHECK_PJSIP_MODULE_LOADED();

	if (ast_sip_register_subscription_handler(&mwi_handler)) {
		return AST_MODULE_LOAD_DECLINE;
	}

	unsolicited_mwi = ao2_container_alloc(MWI_BUCKETS, mwi_sub_hash, mwi_sub_cmp);
	if (!unsolicited_mwi) {
		ast_sip_unregister_subscription_handler(&mwi_handler);
		return AST_MODULE_LOAD_DECLINE;
	}

	create_mwi_subscriptions();
	ast_sorcery_observer_add(ast_sip_get_sorcery(), "contact", &mwi_contact_observer);

	if (ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
		ast_sip_push_task(NULL, send_initial_notify_all, NULL);
	} else {
		stasis_subscribe_pool(ast_manager_get_topic(), mwi_startup_event_cb, NULL);
	}

	return AST_MODULE_LOAD_SUCCESS;
}
Ejemplo n.º 21
0
void ast_jb_enable_for_channel(struct ast_channel *chan)
{
	struct ast_jb_conf conf = ast_channel_jb(chan)->conf;
	if (ast_test_flag(&conf, AST_JB_ENABLED)) {
		ast_jb_create_framehook(chan, &conf, 1);
	}
}
Ejemplo n.º 22
0
int ast_local_setup_masquerade(struct ast_channel *ast, struct ast_channel *masq)
{
	struct local_pvt *p;
	struct local_pvt *found;
	int res = -1;

	/* Sanity checks. */
	if (!ast || !masq) {
		return -1;
	}

	ast_channel_lock(ast);
	p = ast_channel_tech_pvt(ast);
	ast_channel_unlock(ast);

	found = p ? ao2_find(locals, p, 0) : NULL;
	if (found) {
		ao2_lock(found);
		if (found->type == LOCAL_CALL_ACTION_DIALPLAN
			&& found->base.owner
			&& found->base.chan
			&& !ast_test_flag(&found->base, AST_UNREAL_CARETAKER_THREAD)) {
			ast_channel_ref(masq);
			found->type = LOCAL_CALL_ACTION_MASQUERADE;
			found->action.masq = masq;
			res = 0;
		}
		ao2_unlock(found);
		ao2_ref(found, -1);
	}

	return res;
}
Ejemplo n.º 23
0
/*!
 * \internal
 * \brief Used to determine what action to take when DTMF is received while recording
 * \since 13.0.0
 *
 * \param chan channel being recorded
 * \param flags option flags in use by the record application
 * \param dtmf_integer the integer value of the DTMF key received
 * \param terminator key currently set to be pressed for normal termination
 *
 * \retval 0 do not exit
 * \retval -1 do exit
 */
static int record_dtmf_response(struct ast_channel *chan, struct ast_flags *flags, int dtmf_integer, int terminator)
{
	if ((dtmf_integer == OPERATOR_KEY) &&
		(ast_test_flag(flags, OPTION_OPERATOR_EXIT))) {
		pbx_builtin_setvar_helper(chan, "RECORD_STATUS", "OPERATOR");
		return -1;
	}

	if ((dtmf_integer == terminator) ||
		(ast_test_flag(flags, OPTION_ANY_TERMINATE))) {
		pbx_builtin_setvar_helper(chan, "RECORD_STATUS", "DTMF");
		return -1;
	}

	return 0;
}
static void ast_cdr_fork(struct ast_channel *chan, struct ast_flags optflags, char *set) 
{
	struct ast_cdr *cdr;
	struct ast_cdr *newcdr;
	struct ast_flags flags = { AST_CDR_FLAG_KEEP_VARS };

	cdr = ast_channel_cdr(chan);

	while (cdr->next)
		cdr = cdr->next;
	
	if (!(newcdr = ast_cdr_dup_unique(cdr)))
		return;
	
	/*
	 * End the original CDR if requested BEFORE appending the new CDR
	 * otherwise we incorrectly end the new CDR also.
	 */
	if (ast_test_flag(&optflags, OPT_ENDCDR)) {
		ast_cdr_end(cdr);
	}

	ast_cdr_append(cdr, newcdr);

	if (!ast_test_flag(&optflags, OPT_NORESET))
		ast_cdr_reset(newcdr, &flags);
		
	if (!ast_test_flag(cdr, AST_CDR_FLAG_KEEP_VARS))
		ast_cdr_free_vars(cdr, 0);
	
	if (!ast_strlen_zero(set)) {
		char *varname = ast_strdupa(set), *varval;
		varval = strchr(varname,'=');
		if (varval) {
			*varval = 0;
			varval++;
			ast_cdr_setvar(cdr, varname, varval, 0);
		}
	}
	
	if (ast_test_flag(&optflags, OPT_SETANS) && !ast_tvzero(cdr->answer))
		newcdr->answer = newcdr->start;

	if (ast_test_flag(&optflags, OPT_SETDISP))
		newcdr->disposition = cdr->disposition;
	
	if (ast_test_flag(&optflags, OPT_RESETDEST))
		newcdr->dstchannel[0] = 0;
	
	if (ast_test_flag(&optflags, OPT_ANSLOCK))
		ast_set_flag(cdr, AST_CDR_FLAG_ANSLOCKED);
	
	if (ast_test_flag(&optflags, OPT_DONTOUCH))
		ast_set_flag(cdr, AST_CDR_FLAG_DONT_TOUCH);
		
	ast_set_flag(cdr, AST_CDR_FLAG_CHILD | AST_CDR_FLAG_LOCKED);
}
Ejemplo n.º 25
0
void ast_jb_empty_and_reset(struct ast_channel *c0, struct ast_channel *c1)
{
	struct ast_jb *jb0 = ast_channel_jb(c0);
	struct ast_jb *jb1 = ast_channel_jb(c1);
	int c0_use_jb = ast_test_flag(jb0, JB_USE);
	int c0_jb_is_created = ast_test_flag(jb0, JB_CREATED);
	int c1_use_jb = ast_test_flag(jb1, JB_USE);
	int c1_jb_is_created = ast_test_flag(jb1, JB_CREATED);

	if (c0_use_jb && c0_jb_is_created && jb0->impl->empty_and_reset) {
		jb0->impl->empty_and_reset(jb0->jbobj);
	}

	if (c1_use_jb && c1_jb_is_created && jb1->impl->empty_and_reset) {
		jb1->impl->empty_and_reset(jb1->jbobj);
	}
}
/*!
 * \internal
 * \brief Setup the page bridge profile.
 *
 * \param chan Setup bridge profile on this channel.
 * \param options Options to setup bridge profile.
 *
 * \return Nothing
 */
static void setup_profile_bridge(struct ast_channel *chan, struct page_options *options)
{
	/* Use default_bridge as a starting point */
	ast_func_write(chan, "CONFBRIDGE(bridge,template)", "");
	if (ast_test_flag(&options->flags, PAGE_RECORD)) {
		ast_func_write(chan, "CONFBRIDGE(bridge,record_conference)", "yes");
	}
}
Ejemplo n.º 27
0
/*!
 * \internal
 * \brief Post the \ref ast_local_bridge_type \ref stasis message
 * \since 12.0.0
 *
 * \param p local_pvt to raise the local bridge message
 *
 * \return Nothing
 */
static void publish_local_bridge_message(struct local_pvt *p)
{
	RAII_VAR(struct ast_multi_channel_blob *, multi_blob, NULL, ao2_cleanup);
	RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
	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 *, two_snapshot, NULL, ao2_cleanup);
	struct ast_channel *owner;
	struct ast_channel *chan;

	if (!ast_local_bridge_type()) {
		return;
	}

	ast_unreal_lock_all(&p->base, &chan, &owner);

	blob = ast_json_pack("{s: s, s: s, s: b}",
		"context", p->context,
		"exten", p->exten,
		"can_optimize", !ast_test_flag(&p->base, AST_UNREAL_NO_OPTIMIZATION));
	if (!blob) {
		goto end;
	}

	multi_blob = ast_multi_channel_blob_create(blob);
	if (!multi_blob) {
		goto end;
	}

	one_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(owner));
	if (!one_snapshot) {
		goto end;
	}

	two_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(chan));
	if (!two_snapshot) {
		goto end;
	}

	ast_multi_channel_blob_add_channel(multi_blob, "1", one_snapshot);
	ast_multi_channel_blob_add_channel(multi_blob, "2", two_snapshot);

	msg = stasis_message_create(ast_local_bridge_type(), multi_blob);
	if (!msg) {
		goto end;
	}

	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);
}
Ejemplo n.º 28
0
/*!
 * \internal
 * \brief Push this channel into the Stasis bridge.
 * \since 12.5.0
 *
 * \param self Bridge to operate upon.
 * \param bridge_channel Bridge channel to push.
 * \param swap Bridge channel to swap places with if not NULL.
 *
 * \note On entry, self is already locked.
 *
 * \retval 0 on success.
 * \retval -1 on failure.  The channel did not get pushed.
 */
static int bridge_stasis_push(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
{
    struct stasis_app_control *control = stasis_app_control_find_by_channel(bridge_channel->chan);

    if (!control && !stasis_app_channel_is_internal(bridge_channel->chan)) {
        /* channel not in Stasis(), get it there */
        ast_debug(1, "Bridge %s: pushing non-stasis %p(%s) setup to come back in under stasis\n",
                  self->uniqueid, bridge_channel, ast_channel_name(bridge_channel->chan));

        /* Attach after-bridge callback and pass ownership of swap_app to it */
        if (ast_bridge_set_after_callback(bridge_channel->chan,
                                          bridge_stasis_run_cb, NULL, NULL)) {
            ast_log(LOG_ERROR,
                    "Failed to set after bridge callback for bridge %s non-stasis push of %s\n",
                    self->uniqueid, ast_channel_name(bridge_channel->chan));
            return -1;
        }

        bridge_stasis_queue_join_action(self, bridge_channel, swap);

        /* Return -1 so the push fails and the after-bridge callback gets called
         * This keeps the bridging framework from putting the channel into the bridge
         * until the Stasis thread gets started, and then the channel is put into the bridge.
         */
        return -1;
    }

    /*
     * If going into a holding bridge, default the role to participant, if
     * it has no compatible role currently
     */
    if ((self->technology->capabilities & AST_BRIDGE_CAPABILITY_HOLDING)
            && !ast_channel_has_role(bridge_channel->chan, "announcer")
            && !ast_channel_has_role(bridge_channel->chan, "holding_participant")) {
        if (ast_channel_add_bridge_role(bridge_channel->chan, "holding_participant")) {
            ast_log(LOG_ERROR, "Failed to set holding participant on %s\n", ast_channel_name(bridge_channel->chan));
            return -1;
        }

        if (ast_channel_set_bridge_role_option(bridge_channel->chan, "holding_participant", "idle_mode", "none")) {
            ast_log(LOG_ERROR, "Failed to set holding participant mode on %s\n", ast_channel_name(bridge_channel->chan));
            return -1;
        }
    }

    ao2_cleanup(control);
    if (self->allowed_capabilities & STASIS_BRIDGE_MIXING_CAPABILITIES) {
        ast_bridge_channel_update_linkedids(bridge_channel, swap);
        if (ast_test_flag(&self->feature_flags, AST_BRIDGE_FLAG_SMART)) {
            ast_bridge_channel_update_accountcodes(bridge_channel, swap);
        }
    }

    return ast_bridge_base_v_table.push(self, bridge_channel, swap);
}
Ejemplo n.º 29
0
static void ast_cdr_fork(struct ast_channel *chan, struct ast_flags optflags, char *set) 
{
	struct ast_cdr *cdr;
	struct ast_cdr *newcdr;
	struct ast_flags flags = { AST_CDR_FLAG_KEEP_VARS };

	cdr = chan->cdr;

	while (cdr->next)
		cdr = cdr->next;
	
	if (!(newcdr = ast_cdr_dup(cdr)))
		return;
	
	ast_cdr_append(cdr, newcdr);

	if (!ast_test_flag(&optflags, OPT_NORESET))
		ast_cdr_reset(newcdr, &flags);
		
	if (!ast_test_flag(cdr, AST_CDR_FLAG_KEEP_VARS))
		ast_cdr_free_vars(cdr, 0);
	
	if (!ast_strlen_zero(set)) {
		char *varname = ast_strdupa(set), *varval;
		varval = strchr(varname,'=');
		if (varval) {
			*varval = 0;
			varval++;
			ast_cdr_setvar(cdr, varname, varval, 0);
		}
	}
	
	if (ast_test_flag(&optflags, OPT_SETANS) && !ast_tvzero(cdr->answer))
		newcdr->answer = newcdr->start;

	if (ast_test_flag(&optflags, OPT_SETDISP))
		newcdr->disposition = cdr->disposition;
	
	if (ast_test_flag(&optflags, OPT_RESETDEST))
		newcdr->dstchannel[0] = 0;
	
	if (ast_test_flag(&optflags, OPT_ENDCDR))
		ast_cdr_end(cdr);

	if (ast_test_flag(&optflags, OPT_ANSLOCK))
		ast_set_flag(cdr, AST_CDR_FLAG_ANSLOCKED);
	
	if (ast_test_flag(&optflags, OPT_DONTOUCH))
		ast_set_flag(cdr, AST_CDR_FLAG_DONT_TOUCH);
		
	ast_set_flag(cdr, AST_CDR_FLAG_CHILD | AST_CDR_FLAG_LOCKED);
}
Ejemplo n.º 30
0
/*! \brief Create a call structure */
static struct local_pvt *local_alloc(const char *data, struct ast_format_cap *cap)
{
	struct local_pvt *pvt;
	char *parse;
	char *context;
	char *opts;

	pvt = (struct local_pvt *) ast_unreal_alloc(sizeof(*pvt), local_pvt_destructor, cap);
	if (!pvt) {
		return NULL;
	}
	pvt->base.callbacks = &local_unreal_callbacks;

	parse = ast_strdupa(data);

	/*
	 * Local channels intercept MOH by default.
	 *
	 * This is a silly default because it represents state held by
	 * the local channels.  Unless local channel optimization is
	 * disabled, the state will dissapear when the local channels
	 * optimize out.
	 */
	ast_set_flag(&pvt->base, AST_UNREAL_MOH_INTERCEPT);

	/* Look for options */
	if ((opts = strchr(parse, '/'))) {
		*opts++ = '\0';
		if (strchr(opts, 'n')) {
			ast_set_flag(&pvt->base, AST_UNREAL_NO_OPTIMIZATION);
		}
		if (strchr(opts, 'j')) {
			if (ast_test_flag(&pvt->base, AST_UNREAL_NO_OPTIMIZATION)) {
				ast_set_flag(&pvt->base.jb_conf, AST_JB_ENABLED);
			} else {
				ast_log(LOG_ERROR, "You must use the 'n' option with the 'j' option to enable the jitter buffer\n");
			}
		}
		if (strchr(opts, 'm')) {
			ast_clear_flag(&pvt->base, AST_UNREAL_MOH_INTERCEPT);
		}
	}

	/* Look for a context */
	if ((context = strchr(parse, '@'))) {
		*context++ = '\0';
	}

	ast_copy_string(pvt->context, S_OR(context, "default"), sizeof(pvt->context));
	ast_copy_string(pvt->exten, parse, sizeof(pvt->exten));
	snprintf(pvt->base.name, sizeof(pvt->base.name), "%s@%s", pvt->exten, pvt->context);

	return pvt; /* this is returned with a ref */
}