#include "Application.h" #include "BoostLog.h" #include "Database.h" #include "IoContext.h" #include "Listener.h" #include "ProxyListener.h" #include "ServiceManager.h" #include "UdpServer.h" #include "WeChatContext/CorporationContext.h" #include "WeChatContext/WeChatContext.h" #include #include #include #include int main(int argc, char const *argv[]) { using namespace Amass; boost::log::initialize("logs/HttpServer"); auto manager = Singleton::instance(); boost::program_options::options_description description("Allowed options"); // clang-format off description.add_options() ("help,h", "produce help message.") ("prefix", boost::program_options::value(),"set prefix path (default: ${pwd} )"); // clang-format on boost::program_options::variables_map values; try { boost::program_options::store(boost::program_options::parse_command_line(argc, argv, description), values); boost::program_options::notify(values); } catch (const boost::program_options::invalid_command_line_syntax &e) { LOG(fatal) << e.what(); std::exit(-1); } if (values.count("help")) { std::cout << description << std::endl; std::exit(0); } std::error_code error; auto prefix = std::filesystem::current_path(error); if (error) { LOG(fatal) << "cannot get current path,reason: " << error.message(); return -1; } if (values.count("prefix")) { prefix = values["prefix"].as(); if (prefix.empty() || !std::filesystem::exists(prefix)) { LOG(fatal) << "working directory: " << prefix << " is not exists."; return -1; } std::filesystem::current_path(prefix, error); LOG_IF(fatal, error) << "cannot set current path,reason: " << error.message(); } auto application = Singleton::instance("settings.ini"); auto database = Singleton::instance(); database->open("database.sqlite"); if (!std::filesystem::exists(application->getDocumentRoot())) { LOG(fatal) << "document root: " << application->getDocumentRoot() << " is not exists..."; std::exit(102); } BOOST_ASSERT_MSG(!application->getServer().empty(), "server.empty() == true"); auto address = boost::asio::ip::make_address(application->getServer()); auto listener = std::make_shared(application->ioContext(), boost::asio::ip::tcp::endpoint{address, application->getPort()}); listener->startAccept(); auto wechatContext = Singleton::instance(application->ioContext()); auto corpContext = Singleton::instance(application->ioContext()); LOG(info) << "hardware_concurrency: " << std::thread::hardware_concurrency() << ",threads: " << application->getThreads(); LOG(info) << "working directory: " << prefix.generic_string(); LOG(info) << "server: " << application->getServer() << ",port: " << application->getPort(); LOG(info) << "document root: " << application->getDocumentRoot(); // Capture SIGINT and SIGTERM to perform a clean shutdown #ifndef WIN32 boost::asio::signal_set signals(application->ioContext(), SIGINT, SIGTERM, SIGHUP); #else boost::asio::signal_set signals(application->ioContext(), SIGINT, SIGTERM); #endif signals.async_wait([&application](boost::system::error_code const &, int signal) { // Stop the io_context. This will cause run() // to return immediately, eventually destroying the // io_context and any remaining handlers in it. LOG(info) << "capture " << (signal == SIGINT ? "SIGINT" : "SIGTERM") << ",stop!"; application->ioContext().stop(); }); auto udpServer = std::make_shared(application->ioContext()); using namespace boost::asio::ip; auto proxyAddress = make_address(application->getServer()); uint16_t proxyPort = 41091; auto proxy = std::make_shared(application->ioContext(), tcp::endpoint{proxyAddress, proxyPort}); boost::system::error_code perror; proxy->run(perror); return application->exec(); }