#pragma once
#include <memory>
#include <utility>
#include <vector>
#include "clock.hpp"
#include "context_allocator.hpp"
#include "evaluation_engine.hpp"
#include "exclusion/common.hpp"
#include "memory_resource.hpp"
#include "object.hpp"
#include "object_store.hpp"
#include "pointer.hpp"
#include "rule.hpp"
#include "ruleset.hpp"
namespace ddwaf {
class context;
class subcontext {
public:
~subcontext()
{
{
const memory::memory_resource_guard guard(mr_.get());
engine_.reset();
store_.reset();
}
{
const memory::memory_resource_guard guard(ctx_mr_.get());
ctx_store_.reset();
}
}
subcontext(subcontext &&) noexcept = delete;
subcontext(const subcontext &) = delete;
subcontext &operator=(subcontext &&) noexcept = delete;
subcontext &operator=(const subcontext &) = delete;
bool insert_batch(owned_object data)
{
const memory::memory_resource_guard guard(mr_.get());
return engine_->insert_batch(std::move(data));
}
bool insert_batch(map_view data)
{
const memory::memory_resource_guard guard(mr_.get());
return engine_->insert_batch(data);
}
bool insert_batches(owned_object data)
{
const memory::memory_resource_guard guard(mr_.get());
return engine_->insert_batches(std::move(data));
}
bool insert_batches(array_view data)
{
const memory::memory_resource_guard guard(mr_.get());
return engine_->insert_batches(data);
}
std::pair<bool, owned_object> eval(timer &deadline)
{
const memory::memory_resource_guard guard(mr_.get());
return engine_->eval(deadline);
}
bool next_batch()
{
const memory::memory_resource_guard guard(mr_.get());
return engine_->next_batch();
}
bool insert_and_apply(owned_object data)
{
const memory::memory_resource_guard guard(mr_.get());
return engine_->insert_and_apply(std::move(data));
}
bool insert_and_apply(map_view data)
{
const memory::memory_resource_guard guard(mr_.get());
return engine_->insert_and_apply(data);
}
void eval_preprocessors(timer &deadline)
{
const memory::memory_resource_guard guard(mr_.get());
engine_->eval_preprocessors(deadline);
}
void eval_postprocessors(timer &deadline)
{
const memory::memory_resource_guard guard(mr_.get());
engine_->eval_postprocessors(deadline);
}
exclusion_policy &eval_filters(timer &deadline)
{
const memory::memory_resource_guard guard(mr_.get());
return engine_->eval_filters(deadline);
}
void eval_rules(
const exclusion_policy &policy, std::vector<rule_result> &results, timer &deadline)
{
const memory::memory_resource_guard guard(mr_.get());
engine_->eval_rules(policy, results, deadline);
}
protected:
explicit subcontext(evaluation_engine &ctx_engine, std::shared_ptr<object_store> ctx_store,
std::shared_ptr<memory::monotonic_buffer_resource> ctx_mr)
: mr_(std::make_unique<memory::monotonic_buffer_resource>()),
ctx_store_(std::move(ctx_store)), ctx_mr_(std::move(ctx_mr))
{
const memory::memory_resource_guard guard(mr_.get());
store_ = std::make_unique<object_store>(object_store::from_upstream_store(*ctx_store_));
engine_ = std::make_unique<evaluation_engine>(
evaluation_engine::subcontext_engine(ctx_engine, *store_));
}
std::unique_ptr<object_store> store_;
std::unique_ptr<evaluation_engine> engine_;
std::unique_ptr<memory::monotonic_buffer_resource> mr_;
std::shared_ptr<object_store> ctx_store_;
std::shared_ptr<memory::monotonic_buffer_resource> ctx_mr_;
friend class context;
};
class context {
public:
explicit context(std::shared_ptr<ruleset> ruleset,
nonnull_ptr<memory::memory_resource> output_alloc = memory::get_default_resource())
: mr_(std::make_shared<memory::monotonic_buffer_resource>())
{
const memory::memory_resource_guard guard(mr_.get());
store_ = std::make_shared<object_store>();
engine_ = std::make_unique<evaluation_engine>(
evaluation_engine::context_engine(std::move(ruleset), *store_, output_alloc));
}
~context()
{
const memory::memory_resource_guard guard(mr_.get());
engine_.reset();
store_.reset();
}
context(context &&) noexcept = delete;
context(const context &) = delete;
context &operator=(context &&) noexcept = delete;
context &operator=(const context &) = delete;
bool insert_batch(owned_object data)
{
const memory::memory_resource_guard guard(mr_.get());
return engine_->insert_batch(std::move(data));
}
bool insert_batch(map_view data)
{
const memory::memory_resource_guard guard(mr_.get());
return engine_->insert_batch(data);
}
bool insert_batches(owned_object data)
{
const memory::memory_resource_guard guard(mr_.get());
return engine_->insert_batches(std::move(data));
}
bool insert_batches(array_view data)
{
const memory::memory_resource_guard guard(mr_.get());
return engine_->insert_batches(data);
}
std::pair<bool, owned_object> eval(timer &deadline)
{
const memory::memory_resource_guard guard(mr_.get());
return engine_->eval(deadline);
}
subcontext create_subcontext() { return subcontext{*engine_, store_, mr_}; }
bool next_batch()
{
const memory::memory_resource_guard guard(mr_.get());
return engine_->next_batch();
}
bool insert_and_apply(owned_object data)
{
const memory::memory_resource_guard guard(mr_.get());
return engine_->insert_and_apply(std::move(data));
}
bool insert_and_apply(map_view data)
{
const memory::memory_resource_guard guard(mr_.get());
return engine_->insert_and_apply(data);
}
void eval_preprocessors(timer &deadline)
{
const memory::memory_resource_guard guard(mr_.get());
engine_->eval_preprocessors(deadline);
}
void eval_postprocessors(timer &deadline)
{
const memory::memory_resource_guard guard(mr_.get());
engine_->eval_postprocessors(deadline);
}
exclusion_policy &eval_filters(timer &deadline)
{
const memory::memory_resource_guard guard(mr_.get());
return engine_->eval_filters(deadline);
}
void eval_rules(
const exclusion_policy &policy, std::vector<rule_result> &results, timer &deadline)
{
const memory::memory_resource_guard guard(mr_.get());
engine_->eval_rules(policy, results, deadline);
}
protected:
std::shared_ptr<object_store> store_;
std::unique_ptr<evaluation_engine> engine_;
std::shared_ptr<memory::monotonic_buffer_resource> mr_;
};
}