#ifndef FORTUNA_SEED_FILE_MANAGER_CPP #define FORTUNA_SEED_FILE_MANAGER_CPP #include "seed_file_management.h" #include "accumulator.h" #include "util.h" #include #include #include #include #include #include #include #include #include #include #include #include namespace fortuna { SeedFileManager::SeedFileManager( std::shared_ptr da_accumulator) noexcept { this->_p_accumulator = da_accumulator; } SeedFileManager::~SeedFileManager() noexcept { set_job_running(false); // RIP, well, yeah, not running when the obj dies } auto SeedFileManager::is_job_running() const -> bool { std::lock_guard lg(mtx); return this->IS_RUNNING; } auto SeedFileManager::set_job_running(bool running) -> void { std::lock_guard lg(mtx); this->IS_RUNNING = running; } auto SeedFileManager::do_stuff() -> void { std::unique_lock ul(mtx); update_seed_file(); do_task.thread_pls(config.write_interval, [this] { write_seed_file(); }); } auto SeedFileManager::get_write_interval() const -> std::chrono::seconds { std::unique_lock ul(mtx); return this->config.write_interval; } auto SeedFileManager::seed_file_exists() const -> bool { std::lock_guard lg(mtx); // based on https://stackoverflow.com/a/6296808 struct stat buf; if (stat(config.seed_f_path.c_str(), &buf) != -1) { return true; } return false; } auto SeedFileManager::update_seed_file() -> void { std::lock_guard lg(mtx); fortuna::SeedFileManager::IS_RUNNING = true; CryptoPP::SecByteBlock buff{config.seed_f_length}; try { { if (!seed_file_exists()) { fmt::print(stderr, "\t[i] sfm: SEED FILE NOT PRESENT, creating...\n"); std::fstream f_stream; f_stream.open(config.seed_f_path, std::fstream::out | std::fstream::trunc); f_stream << ""; f_stream.close(); return; } std::ifstream f_stream{config.seed_f_path, std::ios::binary}; if (!f_stream.is_open()) { const std::string msg{"\t[!] sfm: error opening seed file!\n"}; fmt::print(stderr, "{} {}\n", msg, config.seed_f_path); fortuna::SeedFileManager::IS_RUNNING = false; throw std::runtime_error(msg); } f_stream.read(reinterpret_cast(buff.BytePtr()), static_cast(config.seed_f_length)); if (static_cast(f_stream.gcount()) != config.seed_f_length) { const std::string msg{ "\t[!] sfm: error reading seed from file, length mismatch"}; fmt::print(stderr, "{} {}, length: {} vs desired length: {}\n", msg, config.seed_f_path, f_stream.gcount(), config.seed_f_length); fortuna::SeedFileManager::IS_RUNNING = false; throw std::runtime_error(msg); } } std::string str_buff(reinterpret_cast(&buff[0]), buff.SizeInBytes() * 8); this->_p_accumulator->call_reseed(str_buff); write_seed_file(); } catch (std::exception& e) { fmt::print(stderr, "{}\n", e.what()); fortuna::SeedFileManager::IS_RUNNING = false; throw; } } auto SeedFileManager::write_seed_file() -> void { std::lock_guard lg(mtx); fortuna::SeedFileManager::IS_RUNNING = true; CryptoPP::SecByteBlock buff{config.seed_f_length}; const std::string da_buff{this->_p_accumulator->get_random_data( static_cast(config.seed_f_length))}; assert(da_buff.length() % 2 == 0); assert(da_buff.size() == config.seed_f_length); const size_t length{da_buff.length()}; // not hex-encoded anymore std::memmove(&buff[0], da_buff.c_str(), length); fmt::print(stderr, "[*] sfm: writing seed file\n"); try { std::ofstream f_stream{config.seed_f_path, std::ios::binary | std::ios::trunc}; f_stream.write(reinterpret_cast(buff.BytePtr()), static_cast(config.seed_f_length)); } catch (std::exception& e) { fmt::print(stderr, "[!] sfm: error writing to seed file!\n"); fmt::print(stderr, "{}\n", e.what()); fortuna::SeedFileManager::IS_RUNNING = false; throw; } } } // namespace fortuna #endif // FORTUNA_SEED_FILE_MANAGER_CPP