Ejemplo n.º 1
0
/*! Forward a channel's topics to an app */
static struct app_forwards *forwards_create_channel(struct stasis_app *app,
	struct ast_channel *chan)
{
	struct app_forwards *forwards;

	if (!app) {
		return NULL;
	}

	forwards = forwards_create(app, chan ? ast_channel_uniqueid(chan) : CHANNEL_ALL);
	if (!forwards) {
		return NULL;
	}

	forwards->forward_type = FORWARD_CHANNEL;
	forwards->topic_forward = stasis_forward_all(
		chan ? ast_channel_topic(chan) : ast_channel_topic_all(),
		app->topic);

	if (!forwards->topic_forward) {
		ao2_ref(forwards, -1);
		return NULL;
	}

	return forwards;
}
Ejemplo n.º 2
0
/*! Forward a bridge's topics to an app */
static struct app_forwards *forwards_create_bridge(struct stasis_app *app,
	struct ast_bridge *bridge)
{
	struct app_forwards *forwards;

	if (!app) {
		return NULL;
	}

	forwards = forwards_create(app, bridge ? bridge->uniqueid : BRIDGE_ALL);
	if (!forwards) {
		return NULL;
	}

	forwards->forward_type = FORWARD_BRIDGE;
	forwards->topic_forward = stasis_forward_all(ast_bridge_topic(bridge), app->topic);

	if (!forwards->topic_forward && bridge) {
		forwards_unsubscribe(forwards);
		ao2_ref(forwards, -1);
		return NULL;
	}

	return forwards;
}
Ejemplo n.º 3
0
/*! Forward a endpoint's topics to an app */
static struct app_forwards *forwards_create_endpoint(struct stasis_app *app,
	struct ast_endpoint *endpoint)
{
	RAII_VAR(struct app_forwards *, forwards, NULL, ao2_cleanup);

	if (!app || !endpoint) {
		return NULL;
	}

	forwards = forwards_create(app, ast_endpoint_get_id(endpoint));
	if (!forwards) {
		return NULL;
	}

	forwards->forward_type = FORWARD_ENDPOINT;
	forwards->topic_forward = stasis_forward_all(ast_endpoint_topic(endpoint),
		app->topic);
	if (!forwards->topic_forward) {
		return NULL;
	}

	forwards->topic_cached_forward = stasis_forward_all(
		ast_endpoint_topic_cached(endpoint), app->topic);
	if (!forwards->topic_cached_forward) {
		/* Half-subscribed is a bad thing */
		stasis_forward_cancel(forwards->topic_forward);
		forwards->topic_forward = NULL;
		return NULL;
	}

	ao2_ref(forwards, +1);
	return forwards;
}
Ejemplo n.º 4
0
/*! Forward a bridge's topics to an app */
static struct app_forwards *forwards_create_bridge(struct stasis_app *app,
	struct ast_bridge *bridge)
{
	RAII_VAR(struct app_forwards *, forwards, NULL, ao2_cleanup);

	if (!app || !bridge) {
		return NULL;
	}

	forwards = forwards_create(app, bridge->uniqueid);
	if (!forwards) {
		return NULL;
	}

	forwards->forward_type = FORWARD_BRIDGE;
	forwards->topic_forward = stasis_forward_all(ast_bridge_topic(bridge),
		app->topic);
	if (!forwards->topic_forward) {
		return NULL;
	}

	forwards->topic_cached_forward = stasis_forward_all(
		ast_bridge_topic_cached(bridge), app->topic);
	if (!forwards->topic_cached_forward) {
		/* Half-subscribed is a bad thing */
		stasis_forward_cancel(forwards->topic_forward);
		forwards->topic_forward = NULL;
		return NULL;
	}

	ao2_ref(forwards, +1);
	return forwards;
}
Ejemplo n.º 5
0
/*! Forward a channel's topics to an app */
static struct app_forwards *forwards_create_channel(struct stasis_app *app,
	struct ast_channel *chan)
{
	RAII_VAR(struct app_forwards *, forwards, NULL, ao2_cleanup);

	if (!app || !chan) {
		return NULL;
	}

	forwards = forwards_create(app, ast_channel_uniqueid(chan));
	if (!forwards) {
		return NULL;
	}

	forwards->forward_type = FORWARD_CHANNEL;
	forwards->topic_forward = stasis_forward_all(ast_channel_topic(chan),
		app->topic);
	if (!forwards->topic_forward) {
		return NULL;
	}

	forwards->topic_cached_forward = stasis_forward_all(
		ast_channel_topic_cached(chan), app->topic);
	if (!forwards->topic_cached_forward) {
		/* Half-subscribed is a bad thing */
		stasis_forward_cancel(forwards->topic_forward);
		forwards->topic_forward = NULL;
		return NULL;
	}

	ao2_ref(forwards, +1);
	return forwards;
}
Ejemplo n.º 6
0
/*! Forward a bridge's topics to an app */
static struct app_forwards *forwards_create_bridge(struct stasis_app *app,
	struct ast_bridge *bridge)
{
	struct app_forwards *forwards;

	if (!app) {
		return NULL;
	}

	forwards = forwards_create(app, bridge ? bridge->uniqueid : BRIDGE_ALL);
	if (!forwards) {
		return NULL;
	}

	forwards->forward_type = FORWARD_BRIDGE;
	if (bridge) {
		forwards->topic_forward = stasis_forward_all(ast_bridge_topic(bridge),
			app->topic);
	}
	forwards->topic_cached_forward = stasis_forward_all(
		bridge ? ast_bridge_topic_cached(bridge) : ast_bridge_topic_all_cached(),
		app->topic);

	if ((!forwards->topic_forward && bridge) || !forwards->topic_cached_forward) {
		/* Half-subscribed is a bad thing */
		forwards_unsubscribe(forwards);
		ao2_ref(forwards, -1);
		return NULL;
	}

	return forwards;
}
Ejemplo n.º 7
0
/*! Forward a channel's topics to an app */
static struct app_forwards *forwards_create_channel(struct stasis_app *app,
	struct ast_channel *chan)
{
	struct app_forwards *forwards;

	if (!app) {
		return NULL;
	}

	forwards = forwards_create(app, chan ? ast_channel_uniqueid(chan) : CHANNEL_ALL);
	if (!forwards) {
		return NULL;
	}

	forwards->forward_type = FORWARD_CHANNEL;
	if (chan) {
		forwards->topic_forward = stasis_forward_all(ast_channel_topic(chan),
			app->topic);
	}
	forwards->topic_cached_forward = stasis_forward_all(
		chan ? ast_channel_topic_cached(chan) : ast_channel_topic_all_cached(),
		app->topic);

	if ((!forwards->topic_forward && chan) || !forwards->topic_cached_forward) {
		/* Half-subscribed is a bad thing */
		forwards_unsubscribe(forwards);
		ao2_ref(forwards, -1);
		return NULL;
	}

	return forwards;
}
Ejemplo n.º 8
0
/*! Forward a endpoint's topics to an app */
static struct app_forwards *forwards_create_endpoint(struct stasis_app *app,
	struct ast_endpoint *endpoint)
{
	struct app_forwards *forwards;
	int ret = 0;

	if (!app) {
		return NULL;
	}

	forwards = forwards_create(app, endpoint ? ast_endpoint_get_id(endpoint) : ENDPOINT_ALL);
	if (!forwards) {
		return NULL;
	}

	forwards->forward_type = FORWARD_ENDPOINT;
	if (endpoint) {
		forwards->topic_forward = stasis_forward_all(ast_endpoint_topic(endpoint),
			app->topic);
		forwards->topic_cached_forward = stasis_forward_all(
			ast_endpoint_topic_cached(endpoint), app->topic);

		if (!forwards->topic_forward || !forwards->topic_cached_forward) {
			/* Half-subscribed is a bad thing */
			forwards_unsubscribe(forwards);
			ao2_ref(forwards, -1);
			return NULL;
		}
	} else {
		/* Since endpoint subscriptions also subscribe to channels, in the case
		 * of all endpoint subscriptions, we only want messages for the endpoints.
		 * As such, we route those particular messages and then re-publish them
		 * on the app's topic.
		 */
		ast_assert(app->endpoint_router == NULL);
		app->endpoint_router = stasis_message_router_create(ast_endpoint_topic_all_cached());
		if (!app->endpoint_router) {
			forwards_unsubscribe(forwards);
			ao2_ref(forwards, -1);
			return NULL;
		}

		ret |= stasis_message_router_add(app->endpoint_router,
			ast_endpoint_state_type(), endpoint_state_cb, app);
		ret |= stasis_message_router_add(app->endpoint_router,
			ast_endpoint_contact_state_type(), endpoint_state_cb, app);

		if (ret) {
			ao2_ref(app->endpoint_router, -1);
			app->endpoint_router = NULL;
			ao2_ref(forwards, -1);
			return NULL;
		}
	}

	return forwards;
}
Ejemplo n.º 9
0
/** check forwards */
static void
check_fwd(struct config_file* cfg)
{
	struct iter_forwards* fwd = forwards_create();
	if(!fwd || !forwards_apply_cfg(fwd, cfg)) {
		fatal_exit("Could not set forward zones");
	}
	forwards_delete(fwd);
}
Ejemplo n.º 10
0
/** setup fresh libworker struct */
static struct libworker*
libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)
{
	unsigned int seed;
	struct libworker* w = (struct libworker*)calloc(1, sizeof(*w));
	struct config_file* cfg = ctx->env->cfg;
	int* ports;
	int numports;
	if(!w) return NULL;
	w->is_bg = is_bg;
	w->ctx = ctx;
	w->env = (struct module_env*)malloc(sizeof(*w->env));
	if(!w->env) {
		free(w);
		return NULL;
	}
	*w->env = *ctx->env;
	w->env->alloc = context_obtain_alloc(ctx, !w->is_bg || w->is_bg_thread);
	if(!w->env->alloc) {
		libworker_delete(w);
		return NULL;
	}
	w->thread_num = w->env->alloc->thread_num;
	alloc_set_id_cleanup(w->env->alloc, &libworker_alloc_cleanup, w);
	if(!w->is_bg || w->is_bg_thread) {
		lock_basic_lock(&ctx->cfglock);
	}
	w->env->scratch = regional_create_custom(cfg->msg_buffer_size);
	w->env->scratch_buffer = sldns_buffer_new(cfg->msg_buffer_size);
	w->env->fwds = forwards_create();
	if(w->env->fwds && !forwards_apply_cfg(w->env->fwds, cfg)) { 
		forwards_delete(w->env->fwds);
		w->env->fwds = NULL;
	}
	w->env->hints = hints_create();
	if(w->env->hints && !hints_apply_cfg(w->env->hints, cfg)) { 
		hints_delete(w->env->hints);
		w->env->hints = NULL;
	}
	if(cfg->ssl_upstream) {
		w->sslctx = connect_sslctx_create(NULL, NULL,
			cfg->tls_cert_bundle);
		if(!w->sslctx) {
			/* to make the setup fail after unlock */
			hints_delete(w->env->hints);
			w->env->hints = NULL;
		}
	}
	if(!w->is_bg || w->is_bg_thread) {
		lock_basic_unlock(&ctx->cfglock);
	}
	if(!w->env->scratch || !w->env->scratch_buffer || !w->env->fwds ||
		!w->env->hints) {
		libworker_delete(w);
		return NULL;
	}
	w->env->worker = (struct worker*)w;
	w->env->probe_timer = NULL;
	seed = (unsigned int)time(NULL) ^ (unsigned int)getpid() ^
		(((unsigned int)w->thread_num)<<17);
	seed ^= (unsigned int)w->env->alloc->next_id;
	if(!w->is_bg || w->is_bg_thread) {
		lock_basic_lock(&ctx->cfglock);
	}
	if(!(w->env->rnd = ub_initstate(seed, ctx->seed_rnd))) {
		if(!w->is_bg || w->is_bg_thread) {
			lock_basic_unlock(&ctx->cfglock);
		}
		seed = 0;
		libworker_delete(w);
		return NULL;
	}
	if(!w->is_bg || w->is_bg_thread) {
		lock_basic_unlock(&ctx->cfglock);
	}
	if(1) {
		/* primitive lockout for threading: if it overwrites another
		 * thread it is like wiping the cache (which is likely empty
		 * at the start) */
		/* note we are holding the ctx lock in normal threaded
		 * cases so that is solved properly, it is only for many ctx
		 * in different threads that this may clash */
		static int done_raninit = 0;
		if(!done_raninit) {
			done_raninit = 1;
			hash_set_raninit((uint32_t)ub_random(w->env->rnd));
		}
	}
	seed = 0;

	if(eb)
		w->base = comm_base_create_event(eb);
	else	w->base = comm_base_create(0);
	if(!w->base) {
		libworker_delete(w);
		return NULL;
	}
	w->env->worker_base = w->base;
	if(!w->is_bg || w->is_bg_thread) {
		lock_basic_lock(&ctx->cfglock);
	}
	numports = cfg_condense_ports(cfg, &ports);
	if(numports == 0) {
		int locked = !w->is_bg || w->is_bg_thread;
		libworker_delete(w);
		if(locked) {
			lock_basic_unlock(&ctx->cfglock);
		}
		return NULL;
	}
	w->back = outside_network_create(w->base, cfg->msg_buffer_size,
		(size_t)cfg->outgoing_num_ports, cfg->out_ifs,
		cfg->num_out_ifs, cfg->do_ip4, cfg->do_ip6, 
		cfg->do_tcp?cfg->outgoing_num_tcp:0,
		w->env->infra_cache, w->env->rnd, cfg->use_caps_bits_for_id,
		ports, numports, cfg->unwanted_threshold,
		cfg->outgoing_tcp_mss, &libworker_alloc_cleanup, w,
		cfg->do_udp || cfg->udp_upstream_without_downstream, w->sslctx,
		cfg->delay_close, NULL);
	w->env->outnet = w->back;
	if(!w->is_bg || w->is_bg_thread) {
		lock_basic_unlock(&ctx->cfglock);
	}
	free(ports);
	if(!w->back) {
		libworker_delete(w);
		return NULL;
	}
	w->env->mesh = mesh_create(&ctx->mods, w->env);
	if(!w->env->mesh) {
		libworker_delete(w);
		return NULL;
	}
	w->env->send_query = &libworker_send_query;
	w->env->detach_subs = &mesh_detach_subs;
	w->env->attach_sub = &mesh_attach_sub;
	w->env->add_sub = &mesh_add_sub;
	w->env->kill_sub = &mesh_state_delete;
	w->env->detect_cycle = &mesh_detect_cycle;
	comm_base_timept(w->base, &w->env->now, &w->env->now_tv);
	return w;
}