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; }
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); } }
/*! * \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); }
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; }