#include "Application.h" #include "Base/Messages.h" #include "Core/IoContext.h" #include "Core/MessageManager.h" #include "Core/Singleton.h" #include "Database.h" #include "HttpSession.h" #include "Nng/Asio.h" #include "Nng/Message.h" #include "Nng/Socket.h" #include "Router/router.hpp" #include "ServiceLogic.h" #include "SessionStore.h" #include "Settings.h" #include "WeChat/Corporation/Context.h" #include "WebRTC/SignalServer.h" #include namespace Older { class ApplicationPrivate { public: void asyncReply() { reply->asyncReceive([this](const std::error_code &error, const Nng::Message &message) { if (error) { LOG(error) << error.message(); return; } LOG(info) << "request: " << message.data(); std::string_view data("i am older server."); reply->send(data.data(), data.size()); asyncReply(); }); } std::shared_ptr> router; std::shared_ptr acceptor; std::unique_ptr reply; }; Application::Application() : m_d{new ApplicationPrivate()} { using namespace boost::urls; using namespace Core; m_d->router = std::make_shared>(); m_messageManager = Singleton::construct(); m_settings = Singleton::construct(); m_ioContext = Singleton::construct(m_settings->threads()); m_database = Singleton::construct(); m_database->open(m_settings->sqlitePath()); m_sessionStore = Singleton::construct(*m_ioContext->ioContext()); m_corporationContext = Singleton::construct(*m_ioContext->ioContext()); m_corporationContext->start(); m_signalServer = std::make_shared(*this); m_d->router->insert("/api/v1/notify", [this](HttpSession &session, const Request &request, const matches &matches) { auto manager = Singleton::instance(); if (manager) { manager->publish(request); } session.reply(ServiceLogic::make_200(request, "notify successed.\n", "text/html")); }); m_d->reply = std::make_unique(*m_ioContext->ioContext(), Nng::Reply); m_d->reply->listen("tcp://127.0.0.1:8985"); m_d->asyncReply(); } Application::~Application() { if (m_d != nullptr) { delete m_d; } } boost::asio::io_context &Application::ioContext() { return *m_ioContext->ioContext(); } void Application::startAcceptHttpConnections(const std::string &address, uint16_t port) { m_d->acceptor = std::make_shared(*m_ioContext->ioContext()); boost::beast::error_code error; boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::make_address(address), port); m_d->acceptor->open(endpoint.protocol(), error); if (error) { LOG(error) << error.message(); return; } m_d->acceptor->set_option(boost::asio::socket_base::reuse_address(true), error); if (error) { LOG(error) << error.message(); return; } m_d->acceptor->bind(endpoint, error); if (error) { LOG(error) << error.message(); return; } m_d->acceptor->listen(boost::asio::socket_base::max_listen_connections, error); if (error) { LOG(error) << error.message(); return; } asyncAcceptHttpConnections(); } void Application::insertUrl(std::string_view url, RequestHandler &&handler) { m_d->router->insert(url, std::move(handler)); } int Application::exec() { using namespace Core; auto settings = Singleton::instance(); ServiceLogic::live2dBackend(); ServiceLogic::visitAnalysis(); ServiceLogic::userAccount(); ServiceLogic::staticFilesDeploy(); startAcceptHttpConnections(settings->server(), settings->port()); m_ioContext->run(); LOG(info) << "app exit, code: " << m_returnCode; return 0; } void Application::exit(int returnCode) { if (m_returnCode != returnCode) { m_returnCode = returnCode; } if (m_ioContext) { m_ioContext->stop(); } } void Application::asyncAcceptHttpConnections() { auto socket = std::make_shared(boost::asio::make_strand(*m_ioContext->ioContext())); m_d->acceptor->async_accept(*socket, [self{shared_from_this()}, socket](const boost::system::error_code &error) { if (error) { if (error == boost::asio::error::operation_aborted) return; LOG(error) << error.message(); } else { auto session = std::make_shared(std::move(*socket), self->m_d->router); session->run(); } self->asyncAcceptHttpConnections(); }); } } // namespace Older