diff --git a/dependencies/control_system/CMakeLists.txt b/dependencies/control_system/CMakeLists.txt index 1eafad4..e53fe74 100755 --- a/dependencies/control_system/CMakeLists.txt +++ b/dependencies/control_system/CMakeLists.txt @@ -14,7 +14,7 @@ include(CheckCXXCompilerFlag) set(CMAKE_CXX_FLAGS -fPIC) set(default_build_type "Release") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -O0 -fprofile-arcs -ftest-coverage") set(CMAKE_CXX_FLAGS_RELEASE "-O2 -s -DNDEBUG ") message(${CMAKE_CXX_FLAGS}) diff --git a/src/auth/resources.h b/src/auth/resources.h index 53817f6..9f87144 100644 --- a/src/auth/resources.h +++ b/src/auth/resources.h @@ -98,9 +98,9 @@ namespace http::auth { ~AuthRequiredResource() override; private: - uint32_t perms; - resource::respGenerator generator_; AuthProvider& provider_; + resource::respGenerator generator_; + uint32_t perms; }; } diff --git a/src/server/connection.cpp b/src/server/connection.cpp index 757bba4..3517a40 100644 --- a/src/server/connection.cpp +++ b/src/server/connection.cpp @@ -13,6 +13,8 @@ namespace http::server { } void Connection::start() { + request_parser_.reset(); + request_.reset(); doRead(); } @@ -23,9 +25,6 @@ namespace http::server { Connection::~Connection() = default; void Connection::doRead() { - request_parser_.reset(); - request_.reset(); - auto self(shared_from_this()); socket_.async_read_some(boost::asio::buffer(buffer_), [this, self](boost::system::error_code ec, std::size_t bytes_transferred) { if (!ec) { @@ -38,6 +37,7 @@ namespace http::server { doWrite(); } else if (result == RequestParser::bad) { stockReply(bad_request, reply_); + needClose = true; doWrite(); } else { doRead(); @@ -59,7 +59,7 @@ namespace http::server { auto self(shared_from_this()); async_write(socket_, reply_.to_buffers(), [this, self](boost::system::error_code ec, std::size_t) { - if (!ec) { + if (!ec && !needClose) { // keep alive Connection doRead(); } else { @@ -74,6 +74,8 @@ namespace http::server { void SslConnection::start() { get_lowest_layer(stream_).expires_after(std::chrono::seconds(30)); + request_parser_.reset(); + request_.reset(); // Perform the SSL handshake stream_.async_handshake(boost::asio::ssl::stream_base::server, boost::beast::bind_front_handler([this](auto ec) { @@ -83,6 +85,7 @@ namespace http::server { } void SslConnection::stop() { + stream_.shutdown(); } SslConnection::~SslConnection() = default; @@ -90,9 +93,6 @@ namespace http::server { void SslConnection::doRead() { get_lowest_layer(stream_).expires_after(std::chrono::seconds(30)); - request_parser_.reset(); - request_.reset(); - auto self(shared_from_this()); stream_.async_read_some(boost::asio::buffer(buffer_), [this, self](boost::system::error_code ec, std::size_t bytes_transferred) { if (!ec) { @@ -105,6 +105,7 @@ namespace http::server { doWrite(); } else if (result == RequestParser::bad) { stockReply(bad_request, reply_); + needClose = true; doWrite(); } else { doRead(); @@ -126,8 +127,10 @@ namespace http::server { auto self(shared_from_this()); async_write(stream_, reply_.to_buffers(), [this, self](boost::system::error_code ec, std::size_t) { - if (!ec) { + if (!ec && !needClose) { // keep alive Connection + request_parser_.reset(); + request_.reset(); doRead(); } else { connection_manager_.stop(shared_from_this()); diff --git a/src/server/connection.hpp b/src/server/connection.hpp index 1fbb986..78eed0c 100644 --- a/src/server/connection.hpp +++ b/src/server/connection.hpp @@ -72,6 +72,8 @@ namespace http::server { /// The reply to be sent back to the client. Reply reply_; + + bool needClose = false; }; class SslConnection final : public ConnectionBase, public std::enable_shared_from_this { @@ -114,6 +116,8 @@ namespace http::server { /// The reply to be sent back to the client. Reply reply_; + + bool needClose = false; }; typedef std::shared_ptr connection_ptr; diff --git a/src/server/request_parser.cpp b/src/server/request_parser.cpp index 97b9117..c4643f6 100644 --- a/src/server/request_parser.cpp +++ b/src/server/request_parser.cpp @@ -1,11 +1,31 @@ #include "request_parser.hpp" +#include #include - #include "request.hpp" namespace http::server { + constexpr int HTTP_MAX_HEADERS = 64; + + /** + * Функция, позволяющая или запрещающая выделение размера тела для запросов. + * @return true, если тело удовлетворяет размерам + */ + static bool requestBodySizeResolver(Request& req, size_t reqSize) { + // разрешаем тело только для POST запросов + if (req.method != "POST") { + return false; + } + + // для обновления прошивки разрешаем большое тело + if (req.url->path == "/api/firmwareUpdate") { + return reqSize <= HTTP_MAX_PAYLOAD; + } + + return reqSize < 0x4000; // 16кб на все POST-запросы к API будет более чем достаточно + } + static void parseParams(Url& u, const std::string& query) { std::istringstream iss(query); std::string param; @@ -72,7 +92,7 @@ namespace http::server { switch (state_) { case expecting_payload: req.payload.push_back(input); - if (req.payload.size() <= contentLenghtHeader - 1) { + if (req.payload.size() < contentLenghtHeader) { return indeterminate; } return good; @@ -186,17 +206,23 @@ namespace http::server { if (input == '\r') { state_ = expecting_newline_3; return indeterminate; - } else if (!req.headers.empty() && (input == ' ' || input == '\t')) { + } + if (!req.headers.empty() && (input == ' ' || input == '\t')) { state_ = header_lws; return indeterminate; - } else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) { - return bad; - } else { - req.headers.emplace_back(); - req.headers.back().name.push_back(input); - state_ = header_name; - return indeterminate; } + if (!is_char(input) || is_ctl(input) || is_tspecial(input)) { + return bad; + } + + if (req.headers.size() > HTTP_MAX_HEADERS) { + return bad; + } + req.headers.emplace_back(); + req.headers.back().name.push_back(input); + state_ = header_name; + return indeterminate; + case header_lws: if (input == '\r') { state_ = expecting_newline_2; @@ -255,11 +281,10 @@ namespace http::server { if (contentLenghtHeader == 0) { return good; } - state_ = expecting_payload; - if (contentLenghtHeader > HTTP_MAX_PAYLOAD) { - return bad; + if (requestBodySizeResolver(req, contentLenghtHeader)) { + state_ = expecting_payload; + return indeterminate; } - return indeterminate; } return bad; diff --git a/src/server/resource.cpp b/src/server/resource.cpp index 3573a1e..7fa27e8 100644 --- a/src/server/resource.cpp +++ b/src/server/resource.cpp @@ -25,12 +25,17 @@ static void loadFile(const std::string& path, std::vector& content) { http::resource::BasicResource::BasicResource(std::string path): path(std::move(path)) {} http::resource::StaticFileFactory::StaticFileDef::StaticFileDef(std::string path, server::mime_types::Mime type, bool allowCache): path(std::move(path)), type(type), allowCache(allowCache) { +#ifdef USE_DEBUG if (allowCache) { BOOST_LOG_TRIVIAL(info) << "Load static file " << this->path; loadFile(this->path, this->content); } else { BOOST_LOG_TRIVIAL(info) << "Skip loading static file " << this->path; } +#else + BOOST_LOG_TRIVIAL(info) << "Load static file " << this->path; + loadFile(this->path, this->content); +#endif } http::resource::StaticFileFactory::StaticFileDef::~StaticFileDef() = default; diff --git a/src/terminal_api_driver.cpp b/src/terminal_api_driver.cpp index 08cdfc4..8680259 100644 --- a/src/terminal_api_driver.cpp +++ b/src/terminal_api_driver.cpp @@ -505,17 +505,19 @@ std::string api_driver::ApiDriver::loadSettings() const { result << ",\n\"buc.refClk10M\":" << boolAsStr(bucLnb.is_ref_10MHz_buc); switch (bucLnb.buc) { - case voltage_buc::DISABLE: result << ",\"buc.powering\":0"; break; case voltage_buc::_24V: result << ",\"buc.powering\":24"; break; case voltage_buc::_48V: result << ",\"buc.powering\":48"; break; + case voltage_buc::DISABLE: + default: result << ",\"buc.powering\":0"; } result << ",\n\"lnb.refClk10M\":" << boolAsStr(bucLnb.is_ref_10MHz_lnb); switch (bucLnb.lnb) { - case voltage_lnb::DISABLE: result << ",\"lnb.powering\":0"; break; case voltage_lnb::_13V: result << ",\"lnb.powering\":13"; break; case voltage_lnb::_18V: result << ",\"lnb.powering\":18"; break; case voltage_lnb::_24V: result << ",\"lnb.powering\":24"; break; + case voltage_lnb::DISABLE: + default: result << ",\"lnb.powering\":0"; } result << ",\n\"serviceSettings.refClk10M\":" << boolAsStr(bucLnb.is_ref_10MHz_output);