#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 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("\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("{} {}\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("{} {}, 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); // we need the size in bits this->_p_accumulator->call_reseed(str_buff); write_seed_file(); } catch (std::exception& e) { fmt::print("{}\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 * 2); // da_buff is // hex-encoded // account for hex encoding that is returned from get_random_data(), i.e. // the total length is half of the actual number of characters const size_t length{da_buff.length() / 2}; CryptoPP::StringSource src( da_buff.c_str(), true /*pumpAll*/, new CryptoPP::HexDecoder(new CryptoPP::ArraySink(&buff[0], length))); fmt::print("[*] 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("[!] sfm: error writing to seed file!\n"); fmt::print("{}\n", e.what()); fortuna::SeedFileManager::IS_RUNNING = false; throw; } } } // namespace fortuna #endif // FORTUNA_SEED_FILE_MANAGER_CPP