diff --git a/ChangeLog.md b/ChangeLog.md index 2048a0b..aba397e 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,3 +1,9 @@ +## Version 0.9 (Jun. 23rd, 2020) +- Bug fixes +- Code refactoring\ +\ +[Source Code](https://github.com/r-richter/hyenae-ng/releases/tag/v0.9) + ## Version 0.8 (Jun. 21st, 2020) - Code refactoring - Enhanced user interface\ diff --git a/Makefile b/Makefile index d599102..3eaa79b 100644 --- a/Makefile +++ b/Makefile @@ -35,6 +35,7 @@ endif all :\ common.o\ + io.o\ model.o\ model_data_transformations.o\ model_generators.o\ @@ -48,6 +49,9 @@ all :\ common.o: $(CXX) $(CXXFLAGS) -c ./src/*.cpp +io.o: + $(CXX) $(CXXFLAGS) -c ./src/io/*.cpp + model.o: $(CXX) $(CXXFLAGS) -c ./src/model/*.cpp diff --git a/README.md b/README.md index 1588175..7edb9b1 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Besides switching from C to C++, using modern design concepts, Hyenae NG was (just like the original Hyenae) written with maximum portability in mind. Since the original Hyenae had a very complex command line syntax Hyenae NG comes with a fast and intuitively usable command line menu that will allow -you to effectively set up even complex stress-tests or attacks scenarios +you to effectively set up even complex stress-tests or attack scenarios within seconds. ![Main Menu](msc/main_menu.png "Main Menu") diff --git a/include/common.h b/include/common.h index 91d0d0f..20f8d2a 100644 --- a/include/common.h +++ b/include/common.h @@ -78,7 +78,7 @@ namespace hyenae /* Methods */ - template< class T > + template< class T> void safe_delete(T*& ptr) { if (ptr != NULL) @@ -88,7 +88,25 @@ namespace hyenae } } /* safe_delete */ - + + template< class T> + void safe_delete(vector_t pointers) + { + T* current = NULL; + + while (pointers.size() > 0) + { + current = pointers.front(); + pointers.erase(pointers.begin()); + + if (current != NULL) + { + delete current; + } + } + + } /* free_vector_pointers */ + int64_t to_ms(duration_t duration); string_t to_ms_string(duration_t duration); diff --git a/include/config.h b/include/config.h new file mode 100644 index 0000000..8483b7a --- /dev/null +++ b/include/config.h @@ -0,0 +1,115 @@ +/* + * Hyenae NG + * Advanced Network Packet Generator (NextGen) + * + * Copyright (C) 2020 Robin Richter + * + * Contact : hyenae.tool@googlemail.com + * Homepage : https://github.com/r-richter/hyenae-ng + * + * This file is part of Hyenae NG. + * + * Hyenae NG is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Hyenae NG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Hyenae NG. If not, see . + * + */ + +#ifndef CONFIG_H +#define CONFIG_H + +#include "common.h" + +namespace hyenae +{ + /*---------------------------------------------------------------------- */ + + class config + { + public: + /* Delimiters */ + static const char VALUE_ASSIGNER = '='; + static const char VALUE_DELIMITER = ';'; + static const char SECTION_ASSIGNER = '{'; + static const char SECTION_DELIMITER = '}'; + + class value + { + private: + string_t _name; + string_t _value; + + public: + value(const string_t& name, const string_t& value = ""); + string_t get_name() const; + string_t get_value() const; + void set_value(const string_t& value); + string_t to_string() const; + + }; /* value */ + + class section + { + private: + string_t _name; + vector_t _values; + vector_t _sub_sections; + + public: + section(const string_t& name); + ~section(); + string_t get_name() const; + size_t value_count() const; + size_t sub_section_count() const; + bool has_value(const string_t& name) const; + bool has_sub_section(const string_t& name) const; + value* value_at(const size_t pos) const; + section* sub_section_at(const size_t pos) const; + value* value_by_name(const string_t& name) const; + section* sub_section_by_name(const string_t& name) const; + config::section* add_sub_section(const string_t& name); + void remove_sub_section(const string_t& name); + + config::value* add_value( + const string_t& name, const string_t& value = ""); + + void remove_value(const string_t& name); + string_t to_string() const; + + private: + value* value_by_name( + const string_t& name, bool throw_exception) const; + + section* sub_section_by_name( + const string_t& name, bool throw_exception) const; + + }; /* section */ + + private: + section* _root_section; + + config(section* root_section); + + public: + config(string_t name = "config"); + ~config(); + static config* parse(const string_t& text); + section* get_root_section() const; + string_t to_string(); + + }; /* config */ + + /*---------------------------------------------------------------------- */ + +} /* hyenae */ + +#endif /* CONFIG_H */ diff --git a/include/file_io.h b/include/file_io.h new file mode 100644 index 0000000..64c6679 --- /dev/null +++ b/include/file_io.h @@ -0,0 +1,55 @@ +/* + * Hyenae NG + * Advanced Network Packet Generator (NextGen) + * + * Copyright (C) 2020 Robin Richter + * + * Contact : hyenae.tool@googlemail.com + * Homepage : https://github.com/r-richter/hyenae-ng + * + * This file is part of Hyenae NG. + * + * Hyenae NG is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Hyenae NG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Hyenae NG. If not, see . + * + */ + +#ifndef FILE_IO_H +#define FILE_IO_H + +#include "common.h" + +namespace hyenae +{ + /*---------------------------------------------------------------------- */ + + class file_io + { + public: + using provider = func_t; + + virtual ~file_io() {} + virtual bool is_open() const = 0; + virtual void open(const string_t& filename, bool overwrite) = 0; + virtual void close() noexcept = 0; + virtual void write(const string_t& content) = 0; + virtual void write(byte_t* data, size_t size) = 0; + virtual string_t read_all() = 0; + + }; /* file_io */ + + /*---------------------------------------------------------------------- */ + +} /* hyenae */ + +#endif /* FILE_IO_H */ diff --git a/include/frontend/console/console_app.h b/include/frontend/console/console_app.h index 7bf6468..2e6724c 100644 --- a/include/frontend/console/console_app.h +++ b/include/frontend/console/console_app.h @@ -27,6 +27,7 @@ #ifndef CONSOLE_APP_H #define CONSOLE_APP_H +#include "../../../include/file_io.h" #include "../../../include/frontend/console/console_io.h" #include "../../../include/frontend/console/console_app_state.h" #include "../../../include/frontend/console/console_app_state_context.h" @@ -40,9 +41,13 @@ namespace hyenae::frontend::console { private: console_io* _console_io; + file_io::provider _file_io_provider; public: - console_app(console_io* console_io); + console_app( + console_io* console_io, + file_io::provider file_io_provider); + int run(int argc, char** argv); }; /* console_app */ diff --git a/include/frontend/console/console_io.h b/include/frontend/console/console_io.h index 4fbac5f..8466432 100644 --- a/include/frontend/console/console_io.h +++ b/include/frontend/console/console_io.h @@ -49,7 +49,7 @@ namespace hyenae::frontend::console /* Margins */ static const size_t BASE_MARGIN = 1; static const size_t MENU_ITEM_MARGIN = 2; - static const size_t MENU_ITEM_INFO_MARGIN = 39; + static const size_t MENU_ITEM_INFO_MARGIN = 38; /* ANSI Foregrounds */ static const string_t ANSI_FG_RESET; diff --git a/include/frontend/console/states/main_menu.h b/include/frontend/console/states/main_menu.h index d88494a..ff3ba01 100644 --- a/include/frontend/console/states/main_menu.h +++ b/include/frontend/console/states/main_menu.h @@ -27,6 +27,7 @@ #ifndef MAIN_MENU_H #define MAIN_MENU_H +#include "../../../../include/file_io.h" #include "../../../../include/frontend/console/console_menu.h" #include "../../../../include/frontend/console/console_app_state.h" #include "../../../../include/frontend/console/states/output_setup.h" @@ -56,7 +57,9 @@ namespace hyenae::frontend::console::states public: main_menu( - console_app_state_context* context, console_io* console_io); + console_app_state_context* context, + console_io* console_io, + file_io::provider file_io_provider); ~main_menu(); bool run(); diff --git a/include/frontend/console/states/output_setup.h b/include/frontend/console/states/output_setup.h index 575f769..0ae4537 100644 --- a/include/frontend/console/states/output_setup.h +++ b/include/frontend/console/states/output_setup.h @@ -27,6 +27,7 @@ #ifndef OUTPUT_SETUP_H #define OUTPUT_SETUP_H +#include "../../../../include/file_io.h" #include "../../../../include/model/data_output.h" #include "../../../../include/model/outputs/network_output.h" #include "../../../../include/frontend/console/console_menu.h" @@ -54,6 +55,7 @@ namespace hyenae::frontend::console::states private: static const char* FILE_OUTPUT_PATH; + file_io::provider _file_io_provider; network_device_selector* _network_device_selector = NULL; console_menu* _menu = NULL; unordered_map_t _menu_items; @@ -68,6 +70,7 @@ namespace hyenae::frontend::console::states output_setup( console_app_state_context* context, console_io* console_io, + file_io::provider file_io_provider, console_app_state* parent); ~output_setup(); diff --git a/include/io/std_file_io.h b/include/io/std_file_io.h new file mode 100644 index 0000000..cd3f57c --- /dev/null +++ b/include/io/std_file_io.h @@ -0,0 +1,61 @@ +/* + * Hyenae NG + * Advanced Network Packet Generator (NextGen) + * + * Copyright (C) 2020 Robin Richter + * + * Contact : hyenae.tool@googlemail.com + * Homepage : https://github.com/r-richter/hyenae-ng + * + * This file is part of Hyenae NG. + * + * Hyenae NG is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Hyenae NG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Hyenae NG. If not, see . + * + */ + +#ifndef STD_FILE_IO_H +#define STD_FILE_IO_H + +#include "../file_io.h" + +#include + +namespace hyenae::io +{ + /*---------------------------------------------------------------------- */ + + class std_file_io : + public file_io + { + public: + static const file_io::provider PROVIDER; + + private: + std::fstream _stream; + + public: + bool is_open() const; + void open(const string_t& filename, bool overwrite); + void close() noexcept; + void write(const string_t& content); + void write(byte_t* data, size_t size); + string_t read_all(); + + }; /* std_file_io */ + + /*---------------------------------------------------------------------- */ + +} /* hyenae::io */ + +#endif /* STD_FILE_IO_H */ diff --git a/include/model/outputs/file_output.h b/include/model/outputs/file_output.h index bfe07e6..d0e6585 100644 --- a/include/model/outputs/file_output.h +++ b/include/model/outputs/file_output.h @@ -27,10 +27,9 @@ #ifndef FILE_OUTPUT_H #define FILE_OUTPUT_H +#include "../../file_io.h" #include "../../model/data_output.h" -#include - namespace hyenae::model::outputs { /*---------------------------------------------------------------------- */ @@ -39,11 +38,15 @@ namespace hyenae::model::outputs public data_output { private: + file_io* _file_io = NULL; string_t _path; - std::ofstream _stream; - + public: - file_output(const string_t& path); + file_output( + file_io::provider file_io_provider, + const string_t& path); + + ~file_output(); void open(); void close() noexcept; void send(byte_t* data, size_t size); diff --git a/src/config.cpp b/src/config.cpp new file mode 100644 index 0000000..aa8dda2 --- /dev/null +++ b/src/config.cpp @@ -0,0 +1,207 @@ +/* + * Hyenae NG + * Advanced Network Packet Generator (NextGen) + * + * Copyright (C) 2020 Robin Richter + * + * Contact : hyenae.tool@googlemail.com + * Homepage : https://github.com/r-richter/hyenae-ng + * + * This file is part of Hyenae NG. + * + * Hyenae NG is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Hyenae NG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Hyenae NG. If not, see . + * + */ + +#include "../include/assert.h" +#include "../include/config.h" + +#include + +namespace hyenae +{ + /*---------------------------------------------------------------------- */ + + config::config(section* root_section) + { + assert::argument_not_null(root_section, "root_section"); + + _root_section = root_section; + + } /* config */ + + /*---------------------------------------------------------------------- */ + + config::config(string_t name) : + config(new section(name)) {} + + /*---------------------------------------------------------------------- */ + + config::~config() + { + safe_delete(_root_section); + + } /* ~config */ + + /*---------------------------------------------------------------------- */ + + config* config::parse(const string_t& text) + { + char chr = 0; + string_t tmp = ""; + string_t item_name = ""; + string_t item_value = ""; + size_t section_index = 0; + section* cur_section = NULL; + vector_t sections; + + try + { + tmp = text; + + std::replace(tmp.begin(), tmp.end(), '\t', ' '); + std::replace(tmp.begin(), tmp.end(), '\n', ' '); + + for (int i = 0; i < (int)tmp.size(); i++) + { + chr = tmp[i]; + + if (chr == SECTION_ASSIGNER) + { + // Item is a section + + if (cur_section == NULL) + { + cur_section = new section(item_name); + } + else + { + cur_section = + cur_section->add_sub_section(item_name); + } + + sections.push_back(cur_section); + + section_index = sections.size(); + + item_name = ""; + } + else if (chr == VALUE_ASSIGNER) + { + // Item is a value + + if (cur_section == NULL) + { + assert::valid_format( + false, "", "value outside of section"); + } + + item_value = ""; + + while ((chr = tmp[i]) != VALUE_DELIMITER) + { + chr = tmp[i]; + + if (chr == VALUE_DELIMITER || + chr == SECTION_ASSIGNER || + chr == SECTION_DELIMITER) + { + assert::valid_format( + false, "", "malformed value declaration"); + } + + if (chr != VALUE_ASSIGNER) + { + item_value.append(string_t(1, chr)); + } + + i++; + } + + cur_section->add_value(item_name, item_value); + + item_name = ""; + } + else if (chr == SECTION_DELIMITER) + { + // Current section closed + + if (section_index > 0) + { + section_index--; + } + else + { + assert::valid_format( + false, "", "unexpected end of section"); + } + + cur_section = sections[section_index]; + } + else + { + if (chr == VALUE_DELIMITER) + { + assert::valid_format( + false, "", "unexpected value delimiter"); + } + + // None of the above, must be the name of an item + + item_name.append(string_t(1, chr)); + } + } + + if (section_index != 0) + { + assert::valid_format( + false, "", "unclosed section"); + } + } + catch (const exception_t& exception) + { + if (sections.size() > 0) + { + // It is only required to delete the root section since all + // sub-sections will be delete by it's destructor. + + safe_delete(sections.front()); + } + + throw runtime_error_t(exception.what()); + } + + return new config(cur_section); + + } /* parse */ + + /*---------------------------------------------------------------------- */ + + config::section* config::get_root_section() const + { + return _root_section; + + } /* get_root_section */ + + /*---------------------------------------------------------------------- */ + + string_t config::to_string() + { + return _root_section->to_string(); + + } /* to_string */ + + /*---------------------------------------------------------------------- */ + +} /* hyenae */ diff --git a/src/config_section.cpp b/src/config_section.cpp new file mode 100644 index 0000000..48cc38d --- /dev/null +++ b/src/config_section.cpp @@ -0,0 +1,265 @@ +/* + * Hyenae NG + * Advanced Network Packet Generator (NextGen) + * + * Copyright (C) 2020 Robin Richter + * + * Contact : hyenae.tool@googlemail.com + * Homepage : https://github.com/r-richter/hyenae-ng + * + * This file is part of Hyenae NG. + * + * Hyenae NG is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Hyenae NG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Hyenae NG. If not, see . + * + */ + +#include "../include/assert.h" +#include "../include/config.h" + +namespace hyenae +{ + /*---------------------------------------------------------------------- */ + + config::section::section(const string_t& name) + { + _name = name; + + } /* section */ + + /*---------------------------------------------------------------------- */ + + config::section::~section() + { + safe_delete(_sub_sections); + safe_delete(_values); + + } /* ~section */ + + /*---------------------------------------------------------------------- */ + + string_t config::section::get_name() const + { + return _name; + + } /* section */ + + /*---------------------------------------------------------------------- */ + + size_t config::section::value_count() const + { + return _values.size(); + + } /* value_count */ + + /*---------------------------------------------------------------------- */ + + size_t config::section::sub_section_count() const + { + return _sub_sections.size(); + + } /* sub_section_count */ + + /*---------------------------------------------------------------------- */ + + bool config::section::has_value(const string_t& name) const + { + return value_by_name(name, false) != NULL; + + } /* has_value */ + + /*---------------------------------------------------------------------- */ + + bool config::section::has_sub_section(const string_t& name) const + { + return sub_section_by_name(name, false); + + } /* has_sub_section */ + + /*---------------------------------------------------------------------- */ + + config::value* config::section::value_at(const size_t pos) const + { + return _values.at(pos); + + } /* value_at */ + + /*---------------------------------------------------------------------- */ + + config::section* config::section::sub_section_at(const size_t pos) const + { + return _sub_sections.at(pos); + + } /* sub_section_at */ + + /*---------------------------------------------------------------------- */ + + config::value* config::section::value_by_name(const string_t& name) const + { + return value_by_name(name, true); + } + + /*---------------------------------------------------------------------- */ + + config::section* config::section::sub_section_by_name( + const string_t& name) const + { + return sub_section_by_name(name, true); + } + + /*---------------------------------------------------------------------- */ + + config::section* config::section::add_sub_section(const string_t& name) + { + section* new_section = NULL; + + if (has_sub_section(name)) + { + assert::legal_call(false, "", "section already exists"); + } + + new_section = new section(name); + + _sub_sections.push_back(new_section); + + return new_section; + + } /* add_sub_section */ + + /*---------------------------------------------------------------------- */ + + void config::section::remove_sub_section(const string_t& name) + { + section* sub_section = NULL; + + if ((sub_section == sub_section_by_name(name, false))) + { + assert::legal_call(false, "", "section not found"); + } + + _sub_sections.erase( + std::remove(_sub_sections.begin(), _sub_sections.end(), sub_section), + _sub_sections.end()); + + delete sub_section; + + } /* remove_sub_section */ + + /*---------------------------------------------------------------------- */ + + config::value* config::section::add_value( + const string_t& name, const string_t& value) + { + config::value* new_value = NULL; + + if (has_value(name)) + { + assert::legal_call(false, "", "value already exists"); + } + new_value = new config::value(name, value); + + _values.push_back(new_value); + + return new_value; + + } /* add_sub_section */ + + /*---------------------------------------------------------------------- */ + + void config::section::remove_value(const string_t& name) + { + value* value = NULL; + + if ((value == value_by_name(name, false))) + { + assert::legal_call(false, "", "value not found"); + } + + _values.erase( + std::remove(_values.begin(), _values.end(), value), + _values.end()); + + delete value; + + } /* remove_sub_section */ + + /*---------------------------------------------------------------------- */ + + string_t config::section::to_string() const + { + string_t section = ""; + + section.append(_name); + section.push_back(config::SECTION_ASSIGNER); + + for (auto value : _values) + { + section.append(value->to_string()); + } + + for (auto sub_section : _sub_sections) + { + section.append(sub_section->to_string()); + } + + section.push_back(config::SECTION_DELIMITER); + + return section; + + } /* to_string */ + + /*---------------------------------------------------------------------- */ + + config::value* config::section::value_by_name( + const string_t& name, bool throw_exception) const + { + for (auto value : _values) + { + if (value->get_name() == name) + { + return value; + } + } + + if (throw_exception) + { + assert::legal_call(false, "", "value not found"); + } + + return NULL; + } + + /*---------------------------------------------------------------------- */ + + config::section* config::section::sub_section_by_name( + const string_t& name, bool throw_exception) const + { + for (auto section : _sub_sections) + { + if (section->get_name() == name) + { + return section; + } + } + + if (throw_exception) + { + assert::legal_call(false, "", "section not found"); + } + + return NULL; + } + + /*---------------------------------------------------------------------- */ + +} /* hyenae */ diff --git a/src/config_value.cpp b/src/config_value.cpp new file mode 100644 index 0000000..3e35d37 --- /dev/null +++ b/src/config_value.cpp @@ -0,0 +1,80 @@ +/* + * Hyenae NG + * Advanced Network Packet Generator (NextGen) + * + * Copyright (C) 2020 Robin Richter + * + * Contact : hyenae.tool@googlemail.com + * Homepage : https://github.com/r-richter/hyenae-ng + * + * This file is part of Hyenae NG. + * + * Hyenae NG is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Hyenae NG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Hyenae NG. If not, see . + * + */ + +#include "../include/config.h" + +namespace hyenae +{ + /*---------------------------------------------------------------------- */ + + config::value::value(const string_t& name, const string_t& value) + { + _name = name; + _value = value; + + } /* value */ + + /*---------------------------------------------------------------------- */ + + string_t config::value::get_name() const + { + return _name; + + } /* value */ + + /*---------------------------------------------------------------------- */ + + string_t config::value::get_value() const + { + return _value; + + } /* value */ + + /*---------------------------------------------------------------------- */ + + void config::value::set_value(const string_t& value) + { + _value = value; + + } /* set_value */ + + /*---------------------------------------------------------------------- */ + + string_t config::value::to_string() const + { + string_t value = ""; + value.append(_name); + value.push_back(config::VALUE_ASSIGNER); + value.append(_value); + value.push_back(config::VALUE_DELIMITER); + + return value; + + } /* to_string */ + + /*---------------------------------------------------------------------- */ + +} /* hyenae */ diff --git a/src/constants.cpp b/src/constants.cpp index b916d9c..1ca601d 100644 --- a/src/constants.cpp +++ b/src/constants.cpp @@ -31,7 +31,7 @@ namespace hyenae /*---------------------------------------------------------------------- */ const char* constants::APP_NAME = "Hyenae NG"; - const char* constants::APP_VERSION = "0.8"; + const char* constants::APP_VERSION = "0.9"; /*---------------------------------------------------------------------- */ diff --git a/src/frontend/console/console_app.cpp b/src/frontend/console/console_app.cpp index d67e9f4..6ff52c8 100644 --- a/src/frontend/console/console_app.cpp +++ b/src/frontend/console/console_app.cpp @@ -32,11 +32,14 @@ namespace hyenae::frontend::console { /*---------------------------------------------------------------------- */ - console_app::console_app(console_io* console_io) + console_app::console_app( + console_io* console_io, + file_io::provider file_io_provider) { assert::argument_not_null(console_io, "console_io"); _console_io = console_io; + _file_io_provider = file_io_provider; } /* console_app */ @@ -44,7 +47,7 @@ namespace hyenae::frontend::console int console_app::run(int argc, char** argv) { - states::main_menu main_menu(this, _console_io); + states::main_menu main_menu(this, _console_io, _file_io_provider); console_app_state_context::run(&main_menu); diff --git a/src/frontend/console/main.cpp b/src/frontend/console/main.cpp index 8b603de..d41e099 100644 --- a/src/frontend/console/main.cpp +++ b/src/frontend/console/main.cpp @@ -24,6 +24,7 @@ * */ +#include "../../../include/io/std_file_io.h" #include "../../../include/frontend/console/console_app.h" #include "../../../include/frontend/console/io/std_console_io.h" @@ -35,7 +36,8 @@ int main(int argc, char** argv) return ( new console_app( - io::std_console_io::get_instance()))->run(argc, argv); + io::std_console_io::get_instance(), + hyenae::io::std_file_io::PROVIDER))->run(argc, argv); } /* main */ diff --git a/src/frontend/console/states/generator_selector.cpp b/src/frontend/console/states/generator_selector.cpp index bf67433..04500cb 100644 --- a/src/frontend/console/states/generator_selector.cpp +++ b/src/frontend/console/states/generator_selector.cpp @@ -165,6 +165,7 @@ namespace hyenae::frontend::console::states generator_selector::~generator_selector() { + // TODO: Replace with specific safe_delete method implementation for (auto item : _menu_items) { delete item.first; diff --git a/src/frontend/console/states/main_menu.cpp b/src/frontend/console/states/main_menu.cpp index 9a36876..45226fc 100644 --- a/src/frontend/console/states/main_menu.cpp +++ b/src/frontend/console/states/main_menu.cpp @@ -32,7 +32,9 @@ namespace hyenae::frontend::console::states /*---------------------------------------------------------------------- */ main_menu::main_menu( - console_app_state_context* context, console_io* console_io) : + console_app_state_context* context, + console_io* console_io, + file_io::provider file_io_provider) : console_app_state(context, console_io) { _menu = new console_menu(console_io, "Main Menu", this, NULL); @@ -40,7 +42,7 @@ namespace hyenae::frontend::console::states // Output setup _output_setup_item = new console_menu::item("Output Setup"); _output_setup = new states::output_setup( - get_context(), console_io, this); + get_context(), console_io, file_io_provider, this); _menu->add_item(_output_setup_item); // Generator setup diff --git a/src/frontend/console/states/network_device_selector.cpp b/src/frontend/console/states/network_device_selector.cpp index 0d7bc88..22a6ca1 100644 --- a/src/frontend/console/states/network_device_selector.cpp +++ b/src/frontend/console/states/network_device_selector.cpp @@ -60,6 +60,7 @@ namespace hyenae::frontend::console::states network_device_selector::~network_device_selector() { + // TODO: Replace with specific safe_delete method implementation for (auto item : _menu_items) { delete item.first; diff --git a/src/frontend/console/states/output_setup.cpp b/src/frontend/console/states/output_setup.cpp index 5e62443..6f6d99f 100644 --- a/src/frontend/console/states/output_setup.cpp +++ b/src/frontend/console/states/output_setup.cpp @@ -40,11 +40,13 @@ namespace hyenae::frontend::console::states output_setup::output_setup( console_app_state_context* context, console_io* console_io, + file_io::provider file_io_provider, console_app_state* parent) : console_app_state(context, console_io, parent) { string_t caption; + _file_io_provider = file_io_provider; _menu = new console_menu(console_io, "Output Setup", this, parent); // Default values @@ -76,6 +78,7 @@ namespace hyenae::frontend::console::states output_setup::~output_setup() { + // TODO: Replace with specific safe_delete method implementation for (auto item : _menu_items) { delete item.first; @@ -179,10 +182,14 @@ namespace hyenae::frontend::console::states { if (_network_device_selector != NULL) { - _output = new model::outputs::network_output( - _network_device_selector->get_device()); + _menu_items[_network_output_item] = + new model::outputs::network_output( + _network_device_selector->get_device()); - _menu_items[_network_output_item] = _output; + if (_selected_item == _network_output_item) + { + _output = _menu_items[_network_output_item]; + } } } /* update_network_output */ @@ -224,7 +231,7 @@ namespace hyenae::frontend::console::states } _menu_items[_file_output_item] = - new model::outputs::file_output(_file_path); + new model::outputs::file_output(_file_io_provider, _file_path); return _menu_items[_file_output_item]; diff --git a/src/io/std_file_io.cpp b/src/io/std_file_io.cpp new file mode 100644 index 0000000..f4c5e8f --- /dev/null +++ b/src/io/std_file_io.cpp @@ -0,0 +1,102 @@ +/* + * Hyenae NG + * Advanced Network Packet Generator (NextGen) + * + * Copyright (C) 2020 Robin Richter + * + * Contact : hyenae.tool@googlemail.com + * Homepage : https://github.com/r-richter/hyenae-ng + * + * This file is part of Hyenae NG. + * + * Hyenae NG is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Hyenae NG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Hyenae NG. If not, see . + * + */ + +#include "../../include/assert.h" +#include "../../include/io/std_file_io.h" + +namespace hyenae::io +{ + /*---------------------------------------------------------------------- */ + + const file_io::provider std_file_io::PROVIDER = [] () + { + return new std_file_io(); + }; + + /*---------------------------------------------------------------------- */ + + bool std_file_io::is_open() const + { + return _stream.is_open(); + + } /* is_open */ + + /*---------------------------------------------------------------------- */ + + void std_file_io::open(const string_t& filename, bool overwrite) + { + assert::legal_call(!is_open(), "", "already open"); + + _stream.open( + filename, + std::fstream::in | std::fstream::out | + (overwrite ? std::ios_base::trunc : std::ios_base::app)); + + } /* open */ + + /*---------------------------------------------------------------------- */ + + void std_file_io::close() noexcept + { + _stream.close(); + + } /* close */ + + /*---------------------------------------------------------------------- */ + + void std_file_io::write(const string_t& content) + { + assert::legal_call(is_open(), "", "not open"); + + _stream.write(content.c_str(), content.size()); + + } /* write */ + + /*---------------------------------------------------------------------- */ + + void std_file_io::write(byte_t* data, size_t size) + { + assert::legal_call(is_open(), "", "not open"); + + _stream.write((const char*)data, size); + + } /* write */ + + /*---------------------------------------------------------------------- */ + + string_t std_file_io::read_all() + { + assert::legal_call(is_open(), "", "not open"); + + return string_t( + std::istreambuf_iterator(_stream), + std::istreambuf_iterator()); + + } /* read_all */ + + /*---------------------------------------------------------------------- */ + +} /* hyenae::io */ diff --git a/src/model/outputs/file_output.cpp b/src/model/outputs/file_output.cpp index da81334..7225b8b 100644 --- a/src/model/outputs/file_output.cpp +++ b/src/model/outputs/file_output.cpp @@ -31,19 +31,31 @@ namespace hyenae::model::outputs { /*---------------------------------------------------------------------- */ - file_output::file_output(const string_t& path) + file_output::file_output( + file_io::provider file_io_provider, + const string_t& path) { + _file_io = file_io_provider(); _path = path; } /* file_output */ /*---------------------------------------------------------------------- */ + file_output::~file_output() + { + close(); + + safe_delete(_file_io); + } + + /*---------------------------------------------------------------------- */ + void file_output::open() { - assert::legal_call(!_stream.is_open(), "", "already open"); + assert::legal_call(!_file_io->is_open(), "", "already open"); - _stream.open(_path, std::ios_base::app); + _file_io->open(_path, true); } /* open */ @@ -51,7 +63,7 @@ namespace hyenae::model::outputs void file_output::close() noexcept { - _stream.close(); + _file_io->close(); } /* close */ @@ -59,11 +71,11 @@ namespace hyenae::model::outputs void file_output::send(byte_t* data, size_t size) { - assert::legal_call(_stream.is_open(), "", "not open"); + assert::legal_call(_file_io->is_open(), "", "not open"); assert::argument_not_null(data, "data"); assert::in_range(size > 0, "size"); - _stream.write((const char*)data, size); + _file_io->write(data, size); } /* send */