From 34fc9ace914bc04ac97af59e064daa1a47969bf3 Mon Sep 17 00:00:00 2001 From: Nicolas Pope <nwpope@utu.fi> Date: Thu, 11 Apr 2019 08:38:10 +0300 Subject: [PATCH] Add json config to net --- .../cpp}/include/nlohmann/json.hpp | 0 net/cpp/include/ftl/net/universe.hpp | 11 ++- net/cpp/src/main.cpp | 92 ++++++++++++++++--- net/cpp/src/universe.cpp | 20 +++- net/cpp/test/net_integration.cpp | 10 +- 5 files changed, 106 insertions(+), 27 deletions(-) rename {cv-node => common/cpp}/include/nlohmann/json.hpp (100%) diff --git a/cv-node/include/nlohmann/json.hpp b/common/cpp/include/nlohmann/json.hpp similarity index 100% rename from cv-node/include/nlohmann/json.hpp rename to common/cpp/include/nlohmann/json.hpp diff --git a/net/cpp/include/ftl/net/universe.hpp b/net/cpp/include/ftl/net/universe.hpp index d34b842fc..8f84287fe 100644 --- a/net/cpp/include/ftl/net/universe.hpp +++ b/net/cpp/include/ftl/net/universe.hpp @@ -5,6 +5,7 @@ #include <ftl/net/listener.hpp> #include <ftl/net/dispatcher.hpp> #include <ftl/uuid.hpp> +#include <nlohmann/json.hpp> #include <vector> #include <string> #include <thread> @@ -23,12 +24,12 @@ namespace net { */ class Universe { public: + Universe(); /** - * Constructor with a URI base. The base uri is used as a base to validate - * resource identifiers. (it may be removed). This creates a new thread - * to monitor network sockets. + * Constructor with json config object. The config allows listening and + * peer connection to be set up automatically. */ - explicit Universe(const std::string &base); + explicit Universe(nlohmann::json &config); /** * The destructor will terminate the network thread before completing. @@ -93,7 +94,7 @@ class Universe { private: bool active_; - std::string base_; + nlohmann::json config_; std::thread thread_; fd_set sfderror_; fd_set sfdread_; diff --git a/net/cpp/src/main.cpp b/net/cpp/src/main.cpp index 76e72fd3a..7999e37b7 100644 --- a/net/cpp/src/main.cpp +++ b/net/cpp/src/main.cpp @@ -1,5 +1,8 @@ #include <string> #include <iostream> +#include <map> +//#include <vector> +#include <fstream> #include <ftl/net.hpp> #ifndef WIN32 @@ -13,27 +16,82 @@ using std::string; using ftl::net::Universe; +using json = nlohmann::json; +using std::ifstream; +using std::map; static Universe *universe; static volatile bool stop = false; -void handle_options(const char ***argv, int *argc) { +// Store loaded configuration +static json config; + +/** + * Find and load a JSON configuration file + */ +static bool findConfiguration(const string &file) { + ifstream i; + + if (file != "") i.open(file); + if (!i.is_open()) i.open("./config.json"); + if (!i.is_open()) i.open(FTL_LOCAL_CONFIG_ROOT "/config.json"); + if (!i.is_open()) i.open(FTL_GLOBAL_CONFIG_ROOT "/config.json"); + if (!i.is_open()) return false; + i >> config; + return true; +} + +/** + * Generate a map from command line option to value + */ +map<string, string> read_options(char ***argv, int *argc) { + map<string, string> opts; + while (*argc > 0) { string cmd((*argv)[0]); if (cmd[0] != '-') break; - - if (cmd.find("--peer=") == 0) { - cmd = cmd.substr(cmd.find("=")+1); - //std::cout << "Peer added " << cmd.substr(cmd.find("=")+1) << std::endl; - universe->connect(cmd); - } else if (cmd.find("--listen=") == 0) { - cmd = cmd.substr(cmd.find("=")+1); - universe->listen(cmd); + + size_t p; + if ((p = cmd.find("=")) == string::npos) { + opts[cmd.substr(2)] = "true"; + } else { + opts[cmd.substr(2, p-2)] = cmd.substr(p+1); } - + (*argc)--; (*argv)++; } + + return opts; +} + +/** + * Put command line options into json config. If config element does not exist + * or is of a different type then report an error. + */ +static void process_options(const map<string, string> &opts) { + for (auto opt : opts) { + if (opt.first == "config") continue; + + if (opt.first == "version") { + std::cout << "FTL Vision Node - v" << FTL_VERSION << std::endl; + std::cout << FTL_VERSION_LONG << std::endl; + exit(0); + } + + try { + auto ptr = json::json_pointer("/"+opt.first); + // TODO(nick) Allow strings without quotes + auto v = json::parse(opt.second); + if (v.type() != config.at(ptr).type()) { + LOG(ERROR) << "Incorrect type for argument " << opt.first; + continue; + } + config.at(ptr) = v; + } catch(...) { + LOG(ERROR) << "Unrecognised option: " << opt.first; + } + } } void handle_command(const char *l) { @@ -53,14 +111,18 @@ void handle_command(const char *l) { } } -int main(int argc, const char **argv) { +int main(int argc, char **argv) { argc--; argv++; - - universe = new Universe("ftl://cli"); - + // Process Arguments - handle_options(&argv, &argc); + auto options = read_options(&argv, &argc); + if (!findConfiguration(options["config"])) { + LOG(FATAL) << "Could not find any configuration!"; + } + process_options(options); + + universe = new Universe(config); while (!stop) { #ifndef WIN32 diff --git a/net/cpp/src/universe.cpp b/net/cpp/src/universe.cpp index ffe195fc8..006131c4e 100644 --- a/net/cpp/src/universe.cpp +++ b/net/cpp/src/universe.cpp @@ -11,9 +11,25 @@ using std::thread; using ftl::net::Peer; using ftl::net::Listener; using ftl::net::Universe; +using nlohmann::json; -Universe::Universe(const string &base) : - active_(true), base_(base), thread_(Universe::__start, this) { +Universe::Universe() : active_(true), thread_(Universe::__start, this) {} + +Universe::Universe(nlohmann::json &config) : + active_(true), config_(config), thread_(Universe::__start, this) { + if (config["listen"].is_array()) { + for (auto &l : config["listen"]) { + listen(l); + } + } else if (config["listen"].is_string()) { + listen(config["listen"]); + } + + if (config["peers"].is_array()) { + for (auto &p : config["peers"]) { + connect(p); + } + } } Universe::~Universe() { diff --git a/net/cpp/test/net_integration.cpp b/net/cpp/test/net_integration.cpp index cc2d581d0..0d33af7c2 100644 --- a/net/cpp/test/net_integration.cpp +++ b/net/cpp/test/net_integration.cpp @@ -13,8 +13,8 @@ using std::chrono::milliseconds; // --- Tests ------------------------------------------------------------------- TEST_CASE("Universe::connect()", "[net]") { - Universe a("ftl://utu.fi"); - Universe b("ftl://utu.fi"); + Universe a; + Universe b; a.listen("tcp://localhost:7077"); @@ -73,8 +73,8 @@ TEST_CASE("Universe::connect()", "[net]") { } TEST_CASE("Universe::broadcast()", "[net]") { - Universe a("ftl://utu.fi"); - Universe b("ftl://utu.fi"); + Universe a; + Universe b; a.listen("tcp://localhost:7077"); @@ -122,7 +122,7 @@ TEST_CASE("Universe::broadcast()", "[net]") { } SECTION("one argument to two peers") { - Universe c("ftl://utu.fi"); + Universe c; b.connect("tcp://localhost:7077"); c.connect("tcp://localhost:7077"); -- GitLab