#include "ServerCore.h" #include "Global.h" #include "IPTable.h" #include "ServerLogger.h" #include "CORSProcessor.h" #include #include #include #include "ProcessorAdapter.h" class ServerCore::Impl { public: int port = 0; webcc::Server* ccServer = nullptr; std::thread thServer; IPTable BlockedIPs; public: explicit Impl(int port) { this->port = port; ccServer = new webcc::Server(boost::asio::ip::tcp::v4(), port); ccServer->SetDefaultServerName(G_SERVER_NAME); webcc::utility::SetCustomUA(G_SERVER_NAME); SCLOGF_INFO("ServerCore constructed on port {}, version: <{}>", port, G_SERVER_NAME); } ~Impl() { if(ccServer != nullptr) { if(ccServer->IsRunning()) ccServer->Stop(); delete ccServer; } } public: static void ServerThreadFunction(webcc::Server* server, int worker_thread, int loop_thread) { if (server == nullptr) return; server->set_buffer_size(10240); SCLOGF_INFO("ServerCore thread ready: {} Worker(s), {} Loop(s)", worker_thread, loop_thread); server->Run(worker_thread, loop_thread); return; } static webcc::Strings ConvertMethods(std::uint32_t dwmethod) { webcc::Strings res; if (dwmethod & uns::H_GET) res.push_back("GET"); if (dwmethod & uns::H_PUT) res.push_back("PUT"); if (dwmethod & uns::H_HEAD) res.push_back("HEAD"); if (dwmethod & uns::H_POST) res.push_back("POST"); if (dwmethod & uns::H_TRACE) res.push_back("TRACE"); if (dwmethod & uns::H_PATCH) res.push_back("PATCH"); if (dwmethod & uns::H_DELETE) res.push_back("DELETE"); if (dwmethod & uns::H_OPTIONS) res.push_back("OPTIONS"); if (dwmethod & uns::H_CONNECT) res.push_back("CONNECT"); return res; } }; ServerCore::ServerCore(int port) : pimpl(std::make_unique(port)) { } ServerCore::~ServerCore() = default; void ServerCore::Run(int worker_thread, int loop_thread) { if (pimpl->ccServer == nullptr) return; pimpl->ccServer->set_buffer_size(10240); SCLOGF_INFO("ServerCore ready: {} Worker(s), {} Loop(s)", worker_thread, loop_thread); pimpl->ccServer->Run(worker_thread, loop_thread); return; } void ServerCore::ThreadRun(int worker_thread, int loop_thread) { using namespace std::chrono; if (pimpl->ccServer == nullptr) return; pimpl->thServer = std::thread(Impl::ServerThreadFunction, pimpl->ccServer, worker_thread, loop_thread); pimpl->thServer.detach(); std::this_thread::sleep_for(100ms); if (pimpl->ccServer->IsRunning()) SCLOG_INFO("ServerCore Running"); return; } void ServerCore::Stop() { if (pimpl->ccServer == nullptr) return; pimpl->ccServer->Stop(); SCLOG_INFO("ServerCore Stopped"); return; } bool ServerCore::Running() { return pimpl->ccServer->IsRunning(); } void ServerCore::UpdateProcessor() { for (size_t i = 0; i < pimpl->ccServer->GetViewCount(); i++) { auto updatable_ptr = std::dynamic_pointer_cast(pimpl->ccServer->AccessView(i)); if (updatable_ptr != nullptr) updatable_ptr->ApplyIpUpdate(&pimpl->BlockedIPs); } SCLOG_TRACE("Blocked IP list updated"); return; } bool ServerCore::EnableCORSSupport() { return AppenedProcessor(CORSProcessor::UrlRegex(), CORSProcessor::SharedPtr(), uns::H_OPTIONS); } bool ServerCore::AppenedProcessor(std::string url, ServerProcessorPtr ptr, std::uint32_t methods, bool enable_ip_check) { if (enable_ip_check) { ptr->EnableIPCheck(); ptr->UpdateBlockedIPList(&pimpl->BlockedIPs); } auto adapter = std::make_shared(ptr); bool bret = pimpl->ccServer->Route(webcc::UrlRegex(url), adapter, Impl::ConvertMethods(methods)); if (bret) SCLOG_INFO("ServerProcessor added. URL: [%s], Method code: <%s>", url.c_str(), uns::toBinary(methods, 10).c_str()); else SCLOG_ERROR("ServerProcessor add faliure. URL: [%s], Method code: <%s>", url.c_str(), uns::toBinary(methods, 10).c_str()); return bret; } bool ServerCore::AppenedFileReceiver(std::string url, FileReceiverPtr ptr, std::uint32_t methods, FileProcessorCallback fpcb, bool html_response) { ptr->SetFileCallback(fpcb); ptr->UpdateBlockedIPs(&pimpl->BlockedIPs); ptr->SetResponseMode(html_response); auto adapter = std::make_shared(ptr); bool bret = pimpl->ccServer->Route(webcc::UrlRegex(url), adapter, Impl::ConvertMethods(methods)); if (bret) SCLOG_INFO("FileReceiver added. URL: [%s], Method code: <%s>", url.c_str(), uns::toBinary(methods, 10).c_str()); else SCLOG_ERROR("FileReceiver add faliure. URL: [%s], Method code: <%s>", url.c_str(), uns::toBinary(methods, 10).c_str()); return bret; } bool ServerCore::AppenedFileReceiver(std::string url, SyncFileReceiverPtr ptr, std::uint32_t methods, bool html_response) { ptr->UpdateBlockedIPs(&pimpl->BlockedIPs); ptr->SetResponseMode(html_response); auto adapter = std::make_shared(ptr); bool bret = pimpl->ccServer->Route(webcc::UrlRegex(url), adapter, Impl::ConvertMethods(methods)); if (bret) SCLOG_INFO("SyncFileReceiver added. URL: [%s], Method code: <%s>", url.c_str(), uns::toBinary(methods, 10).c_str()); else SCLOG_ERROR("SyncFileReceiver add faliure. URL: [%s], Method code: <%s>", url.c_str(), uns::toBinary(methods, 10).c_str()); return bret; } void ServerCore::EnableWebCCLog(const std::string& path, int level) { if(path.empty()) { WEBCC_LOG_INIT_2("", webcc::LOG_CONSOLE, level); } else { WEBCC_LOG_INIT_2(path.c_str(), webcc::LOG_CONSOLE | webcc::LOG_CONSOLE_FILE_APPEND, level); } }