This repository has been archived on 2022-02-10. You can view files and clone it, but cannot push or open issues or pull requests.
fortuna/fortuna.cpp
surtur c0933d355d
All checks were successful
continuous-integration/drone/push Build is passing
fortuna: improve mtx handling, introduce accu_mtx
2022-01-14 08:52:51 +01:00

178 lines
4.9 KiB
C++

#ifndef FORTUNA_FORTUNA_CPP
#define FORTUNA_FORTUNA_CPP
#include "fortuna.h"
#include "seed_file_management.h"
#include "util.h"
#include <cryptopp/cryptlib.h>
#include <fmt/chrono.h>
#include <chrono>
#include <exception>
#include <memory>
#include <mutex>
namespace fortuna {
static constexpr const unsigned int min_pool_size{64};
auto now{std::chrono::steady_clock::now()};
Fortuna::Fortuna() {
try {
initialize_prng();
}
catch (CryptoPP::Exception& e) {
fmt::print(stderr, "{}\n", e.what());
}
th_gen = std::thread(&Fortuna::generator_service,
this,
std::make_shared<fortuna::generator::Generator>());
th_accu = std::thread(&Fortuna::accumulator_service, this);
th_sfm = std::thread(&Fortuna::seed_file_manager_service, this);
}
Fortuna::~Fortuna() noexcept {
if (th_gen.joinable()) {
th_gen.join();
}
if (th_gen.joinable()) {
th_accu.join();
}
if (th_sfm.joinable()) {
th_sfm.join();
}
}
auto Fortuna::random_data(unsigned int n_bytes) -> void {
const auto start{std::chrono::system_clock::now()};
fmt::print("random_data starting - {}\n", start);
auto elapsed{std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now().time_since_epoch() -
now.time_since_epoch())};
fmt::print("[i] fortuna: last_reseed: {} ago\n", elapsed);
now = std::chrono::steady_clock::now();
std::string s;
// synchronise reads and writes to the between
// {generator,accumulator,fortuna} service threads -> in member functions
const int pools_to_use{ffsll(static_cast<int>(get_reseed_ctr()))};
fmt::print("[*] fortuna: current p0 length: {}\n",
R.pools[0].get_s_length());
if (R.pools[0].get_s_length() >= min_pool_size &&
elapsed > R.Gen.reseed_interval) {
for (int i = 0; i < static_cast<int>(pools_to_use); ++i) {
if (R.reseed_ctr % static_cast<int>(pow(2, i)) == 0) {
try {
s.append(fortuna::Util::do_sha(R.pools[i].get_s()));
R.pools[i].clear_pool();
}
catch (std::exception& e) {
fmt::print("{}\n", e.what());
}
}
}
incr_reseed_ctr();
R.Gen.reseed(s);
R.last_reseed = std::chrono::steady_clock::now();
s.clear();
}
fmt::print("[i] fortuna: reseed ctr {}\n", R.reseed_ctr);
if (R.reseed_ctr == 0) {
fmt::print("[!] ERROR: reseed ctr is 0, PRNG not seeded!\n");
throw std::runtime_error("illegal state, PRNG not seeded");
}
else {
std::string n{R.Gen.generate_random_data(n_bytes)};
fmt::print("got you {} proper bytes from generate_random_data -> {}\n",
n_bytes,
n);
n.clear();
}
const auto end{std::chrono::system_clock::now()};
std::chrono::duration<float> diff = end - start;
fmt::print("random_data done - {}\n", end);
fmt::print("getting random data took {:.{}f}s\n", diff.count(), 12);
} // random_data
auto Fortuna::generator_service(
std::shared_ptr<fortuna::generator::Generator> Gen) -> void {
int i{0};
std::chrono::milliseconds sleep_time{1000};
std::chrono::system_clock::time_point time_point;
std::unique_lock<std::mutex> p_ul(print_mtx);
fmt::print("[i] fortuna: starting generator service\n");
p_ul.unlock();
while (true) {
p_ul.lock();
fmt::print("[*] g: sleeping [{}]\n", i);
p_ul.unlock();
++i;
time_point = fortuna::Util::current_time();
p_ul.lock();
fmt::print("[*] g: @{}\n", time_point);
p_ul.unlock();
std::this_thread::sleep_until(time_point +
std::chrono::milliseconds(sleep_time));
}
}
auto Fortuna::accumulator_service() -> void {
std::chrono::seconds sleep_time{10};
std::chrono::system_clock::time_point time_point;
std::unique_lock<std::mutex> p_ul(print_mtx);
fmt::print("[i] fortuna: starting accumulator service\n");
p_ul.unlock();
while (true) {
time_point = fortuna::Util::current_time();
p_ul.lock();
fmt::print("[*] accu: @{}\n", time_point);
p_ul.unlock();
std::this_thread::sleep_until(time_point +
std::chrono::seconds(sleep_time));
}
}
auto Fortuna::seed_file_manager_service() -> void {
static constexpr const std::chrono::seconds checkup_interval{10};
std::unique_lock<std::mutex> p_ul(print_mtx);
fmt::print("[i] fortuna: starting seed file manager service\n");
fmt::print("[*] sfm: checkup interval {}\n", checkup_interval);
p_ul.unlock();
auto right_now{fortuna::Util::current_time()};
std::unique_lock<std::mutex> mtx_l(mtx);
std::unique_lock<std::mutex> a_ul(accu_mtx);
SeedFileManager sfm(this->accumulator);
a_ul.unlock();
mtx_l.unlock();
while (true) {
right_now = fortuna::Util::current_time();
p_ul.lock();
fmt::print("[*] sfm: checkup time @{}\n", right_now);
if (!sfm.is_job_running()) {
fmt::print("[*] sfm: job not running, starting\n");
try {
sfm.do_stuff();
}
catch (std::exception& e) {
fmt::print(stderr, "[!] sfm: exception caught: {}\n", e.what());
}
}
else {
fmt::print("[*] sfm: job running\n");
}
p_ul.unlock();
std::this_thread::sleep_until(right_now +
std::chrono::seconds(checkup_interval));
}
}
} // namespace fortuna
#endif // FORTUNA_FORTUNA_CPP