static int bridge_builtin_set_limits(struct ast_bridge_features *features,
	struct ast_bridge_features_limits *limits,
	enum ast_bridge_hook_remove_flags remove_flags)
{
	RAII_VAR(struct ast_bridge_features_limits *, feature_limits, NULL, ao2_cleanup);

	if (!limits->duration) {
		return -1;
	}

	/* Create limits hook_pvt data. */
	ast_module_ref(ast_module_info->self);
	feature_limits = ao2_alloc_options(sizeof(*feature_limits),
		bridge_features_limits_dtor, AO2_ALLOC_OPT_LOCK_NOLOCK);
	if (!feature_limits) {
		ast_module_unref(ast_module_info->self);
		return -1;
	}
	if (ast_bridge_features_limits_construct(feature_limits)) {
		return -1;
	}
	bridge_features_limits_copy(feature_limits, limits);
	feature_limits->quitting_time = ast_tvadd(ast_tvnow(),
		ast_samp2tv(feature_limits->duration, 1000));

	/* Install limit hooks. */
	ao2_ref(feature_limits, +1);
	if (ast_bridge_interval_hook(features, AST_BRIDGE_HOOK_TIMER_OPTION_MEDIA,
		feature_limits->duration,
		bridge_features_duration_callback, feature_limits, __ao2_cleanup, remove_flags)) {
		ast_log(LOG_ERROR, "Failed to schedule the duration limiter to the bridge channel.\n");
		ao2_ref(feature_limits, -1);
		return -1;
	}
	if (!ast_strlen_zero(feature_limits->connect_sound)) {
		ao2_ref(feature_limits, +1);
		if (ast_bridge_interval_hook(features, AST_BRIDGE_HOOK_TIMER_OPTION_MEDIA, 1,
			bridge_features_connect_callback, feature_limits, __ao2_cleanup, remove_flags)) {
			ast_log(LOG_WARNING, "Failed to schedule connect sound to the bridge channel.\n");
			ao2_ref(feature_limits, -1);
		}
	}
	if (feature_limits->warning && feature_limits->warning < feature_limits->duration) {
		ao2_ref(feature_limits, +1);
		if (ast_bridge_interval_hook(features, AST_BRIDGE_HOOK_TIMER_OPTION_MEDIA,
			feature_limits->duration - feature_limits->warning,
			bridge_features_warning_callback, feature_limits, __ao2_cleanup, remove_flags)) {
			ast_log(LOG_WARNING, "Failed to schedule warning sound playback to the bridge channel.\n");
			ao2_ref(feature_limits, -1);
		}
	}

	return 0;
}
Ejemplo n.º 2
0
void parking_set_duration(struct ast_bridge_features *features, struct parked_user *user)
{
	unsigned int time_limit;

	time_limit = user->time_limit * 1000;

	if (!time_limit) {
		/* There is no duration limit that we need to apply. */
		return;
	}

	/* If the time limit has already been passed, set a really low time limit so we can kick them out immediately. */
	time_limit = ast_remaining_ms(user->start, time_limit);
	if (time_limit <= 0) {
		time_limit = 1;
	}

	/* The interval hook is going to need a reference to the parked_user */
	ao2_ref(user, +1);

	if (ast_bridge_interval_hook(features, 0, time_limit,
		parking_duration_callback, user, __ao2_cleanup, AST_BRIDGE_HOOK_REMOVE_ON_PULL)) {
		ast_log(LOG_ERROR, "Failed to apply duration limit to the parked call.\n");
		ao2_ref(user, -1);
	}
}
Ejemplo n.º 3
0
/*!
 * \brief Set a dial timeout interval hook on the channel.
 *
 * The absolute time that the timeout should occur is stored on
 * a datastore on the channel. This time is converted into a relative
 * number of milliseconds in the future. Then an interval hook is set
 * to trigger in that number of milliseconds.
 *
 * \pre chan is locked
 *
 * \param chan The channel on which to set the interval hook
 */
static void set_interval_hook(struct ast_channel *chan)
{
	struct ast_datastore *datastore;
	struct timeval *hangup_time;
	int64_t ms;
	struct ast_bridge_channel *bridge_channel;

	datastore = ast_channel_datastore_find(chan, &timeout_datastore, NULL);
	if (!datastore) {
		return;
	}

	hangup_time = datastore->data;

	ms = ast_tvdiff_ms(*hangup_time, ast_tvnow());
	bridge_channel = ast_channel_get_bridge_channel(chan);
	if (!bridge_channel) {
		return;
	}

	if (ast_bridge_interval_hook(bridge_channel->features, 0, ms > 0 ? ms : 1,
			bridge_timeout, NULL, NULL, 0)) {
		return;
	}

	ast_queue_frame(bridge_channel->chan, &ast_null_frame);
}
Ejemplo n.º 4
0
static int apply_option_timeout(struct ast_bridge_features *features, char *duration_arg)
{
    unsigned int duration;

    if (ast_strlen_zero(duration_arg)) {
        ast_log(LOG_ERROR, "Timeout option 'S': No value provided.\n");
        return -1;
    }
    if (sscanf(duration_arg, "%u", &duration) != 1 || duration == 0) {
        ast_log(LOG_ERROR, "Timeout option 'S': Invalid value provided '%s'.\n",
                duration_arg);
        return -1;
    }

    duration *= 1000;
    if (ast_bridge_interval_hook(features, 0, duration, bridgewait_timeout_callback,
                                 NULL, NULL, AST_BRIDGE_HOOK_REMOVE_ON_PULL)) {
        ast_log(LOG_ERROR, "Timeout option 'S': Could not create timer.\n");
        return -1;
    }

    return 0;
}