#include #include #include #include #include #include #include "asibfm700_netserver.h" int main(int argc, char* argv[]) { /* COMMANDLINE OPTS */ cxxopts::Options options(argv[0], "Astrosib (c) BM700 mount server\n"); options.allow_unrecognised_options(); options.add_options()("h,help", "Print usage"); options.add_options()("D,daemon", "Demonize server"); options.add_options()("l,log", "Log filename (use stdout and stderr for standard output and error stream)", cxxopts::value()->default_value("")); options.add_options()("level", "Log level (see SPDLOG package description for valid values)", cxxopts::value()->default_value("info")); options.add_options()("c,config", "Mount configuration filename (by default use of hardcoded one)", cxxopts::value()->default_value("")); options.add_options()("dump", "Dump mount default configuration to file and exit", cxxopts::value()->default_value("")); options.add_options()( "endpoints", "endpoints server will be listening for. For 'local' endpoint the '@' symbol at the beginning of the path " "means " "abstract namespace socket.", cxxopts::value>()->default_value("local://stream/@FM700_SERVER")); options.positional_help("[endpoint0] [enpoint1] ... [endpointN]"); options.parse_positional({"endpoints"}); // asio::io_context ctx(2); asio::io_context ctx; try { auto opt_result = options.parse(argc, argv); if (opt_result["help"].count()) { std::cout << options.help(); std::cout << "\n"; std::cout << "[endpoint0] [enpoint1] ... [endpointN] - endpoints server will be listening for. For 'local' " "endpoint the '@' symbol at the beginning of the path " "means abstract namespace socket (e.g. local://stream/@ASIBFM700_SERVER)." << "\n"; return 0; } asibfm700::Asibfm700MountConfig mount_cfg; std::string fname = opt_result["dump"].as(); if (fname.size()) { bool ok = mount_cfg.dumpDefaultsToFile(fname); if (!ok) { return 255; } return 0; } else { // just ignore } auto logname = opt_result["log"].as(); auto logger = [&logname]() { if (logname == "stdout") { return spdlog::stdout_color_mt("console"); } else if (logname == "stderr") { return spdlog::stderr_color_mt("stderr"); } else if (logname == "") { return spdlog::null_logger_mt("FM700_SERVER_NULL_LOGGER"); } else { return spdlog::basic_logger_mt(logname, logname); } }(); std::string level_str = opt_result["level"].as(); std::ranges::transform(level_str, level_str.begin(), [](const char& c) { return std::tolower(c); }); auto log_level = spdlog::level::from_str(level_str); logger->set_level(log_level); logger->flush_on(spdlog::level::trace); logger->set_pattern("%v"); int w = 90; // const std::string fmt = std::format("{{:*^{}}}", w); constexpr std::string_view fmt = "{:*^90}"; logger->info("\n\n\n"); logger->info(fmt, ""); logger->info(fmt, " ASTROSIB FM700 MOUNT SERVER "); auto zt = std::chrono::zoned_time(std::chrono::current_zone(), std::chrono::floor(std::chrono::system_clock::now())); logger->info(fmt, std::format(" {} ", zt)); logger->info(fmt, ""); logger->info("\n"); std::string mount_cfg_fname = opt_result["config"].as(); if (mount_cfg_fname.size()) { logger->info("Try to load mount configuration from file: {}", mount_cfg_fname); auto err = mount_cfg.load(mount_cfg_fname); if (err) { logger->error("Cannot load mount configuration (err = {})! Use defaults!", err.message()); } else { logger->info("Mount configuration was loaded successfully!"); } } asibfm700::Asibfm700Mount mount(mount_cfg, logger); asibfm700::Asibfm700MountNetServer server(ctx, mount, logger); server.setupSignals(); if (opt_result["daemon"].count()) { server.daemonize(); } // mcc::MccServerEndpoint epn(std::string_view("local://seqpacket/tmp/BM700_SERVER_SOCK")); // mcc::MccServerEndpoint epn(std::string_view("local://stream/tmp/BM700_SERVER_SOCK")); // mcc::MccServerEndpoint epn(std::string_view("local://stream/@tmp/BM700_SERVER_SOCK")); // mcc::MccServerEndpoint epn(std::string_view("tcp://localhost:12345")); // asio::co_spawn(ctx, server.listen(epn), asio::detached); auto epnts = opt_result["endpoints"].as>(); for (auto& epnt : epnts) { mcc::network::MccNetServerEndpoint ep(epnt); if (ep.isValid()) { ep.makeAbstract('@'); asio::co_spawn(ctx, server.listen(ep), asio::detached); } else { std::cerr << "Unrecognized endpoint: '" << epnt << "'! Ignore!\n"; } } asio::thread_pool pool(5); asio::post(pool, [&ctx]() { ctx.run(); }); pool.join(); // ctx.run(); } catch (const std::system_error& ex) { std::cerr << "An error occured: " << ex.code().message() << "\n"; return ex.code().value(); } catch (...) { std::cerr << "Unhandled exceptions!\n"; return 255; } }