diff --git a/src/agent/communicator/include/communicator.hpp b/src/agent/communicator/include/communicator.hpp index 67e89f8075..97c95d0afd 100644 --- a/src/agent/communicator/include/communicator.hpp +++ b/src/agent/communicator/include/communicator.hpp @@ -137,5 +137,8 @@ namespace communicator /// @brief The verification mode std::string m_verificationMode; + + /// TODO: + std::time_t m_timeoutCommands; }; } // namespace communicator diff --git a/src/agent/communicator/src/communicator.cpp b/src/agent/communicator/src/communicator.cpp index ccd3ba2b17..e31e7158a1 100644 --- a/src/agent/communicator/src/communicator.cpp +++ b/src/agent/communicator/src/communicator.cpp @@ -101,6 +101,15 @@ namespace communicator config::agent::DEFAULT_VERIFICATION_MODE); m_verificationMode = config::agent::DEFAULT_VERIFICATION_MODE; } + + m_timeoutCommands = configurationParser->GetConfig("agent", "commands_request_timeout") + .value_or(config::agent::DEFAULT_COMMANDS_REQUEST_TIMEOUT); + if (m_timeoutCommands <= 0) + { + LogWarn("Incorrect value for 'commands_request_timeout', should be above 0.", + config::agent::DEFAULT_COMMANDS_REQUEST_TIMEOUT); + m_timeoutCommands = config::agent::DEFAULT_COMMANDS_REQUEST_TIMEOUT; + } } bool Communicator::SendAuthenticationRequest() @@ -264,7 +273,11 @@ namespace communicator m_serverUrl, "/api/v1/commands", m_getHeaderInfo ? m_getHeaderInfo() : "", - m_verificationMode); + m_verificationMode, + "", + "", + "", + m_timeoutCommands); co_await ExecuteRequestLoop(reqParams, {}, onSuccess); } diff --git a/src/agent/communicator/tests/communicator_test.cpp b/src/agent/communicator/tests/communicator_test.cpp index 1cfaec5577..c4070fa40e 100644 --- a/src/agent/communicator/tests/communicator_test.cpp +++ b/src/agent/communicator/tests/communicator_test.cpp @@ -213,8 +213,15 @@ TEST(CommunicatorTest, GetCommandsFromManager_CallsWithValidToken) EXPECT_CALL(*mockHttpClientPtr, PerformHttpRequest(testing::_)) .WillOnce(Invoke([communicatorPtr, &expectedResponse1]() -> intStringTuple { return expectedResponse1; })); - const auto reqParams = http_client::HttpRequestParams( - http_client::MethodType::GET, "https://localhost:27000", "/api/v1/commands", "", "none"); + const auto reqParams = http_client::HttpRequestParams(http_client::MethodType::GET, + "https://localhost:27000", + "/api/v1/commands", + "", + "none", + "", + "", + "", + 60); // TODO: check value // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) intStringTuple expectedResponse2 {200, "Dummy response"}; @@ -265,8 +272,15 @@ TEST(CommunicatorTest, GetCommandsFromManager_Failure) EXPECT_CALL(*mockHttpClientPtr, PerformHttpRequest(testing::_)) .WillOnce(Invoke([communicatorPtr, &expectedResponse1]() -> intStringTuple { return expectedResponse1; })); - const auto reqParams = http_client::HttpRequestParams( - http_client::MethodType::GET, "https://localhost:27000", "/api/v1/commands", "", "none"); + const auto reqParams = http_client::HttpRequestParams(http_client::MethodType::GET, + "https://localhost:27000", + "/api/v1/commands", + "", + "none", + "", + "", + "", + 60); // TODO: check value // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) intStringTuple expectedResponse2 {401, "Dummy response"}; diff --git a/src/agent/http_client/include/http_request_params.hpp b/src/agent/http_client/include/http_request_params.hpp index 3ef4564070..70c6958f04 100644 --- a/src/agent/http_client/include/http_request_params.hpp +++ b/src/agent/http_client/include/http_request_params.hpp @@ -37,6 +37,7 @@ namespace http_client std::string User_pass; std::string Body; bool Use_Https; + time_t RequestTimeout; /// @brief Constructs HttpRequestParams with specified parameters /// @param method The HTTP method to use @@ -47,6 +48,7 @@ namespace http_client /// @param token Optional token for authorization /// @param userPass Optional user credentials for basic authentication /// @param body Optional body for the request + /// @param RequestTimeout Optional request timeout HttpRequestParams(MethodType method, const std::string& serverUrl, std::string endpoint, @@ -54,7 +56,8 @@ namespace http_client std::string verificationMode = "none", std::string token = "", std::string userPass = "", - std::string body = ""); + std::string body = "", + const time_t RequestTimeout = 0); // TODO: reuse constexpr /// @brief Equality operator for comparing two HttpRequestParams objects /// @param other The other HttpRequestParams object to compare with diff --git a/src/agent/http_client/src/http_client.cpp b/src/agent/http_client/src/http_client.cpp index 8d67cb489e..acfb3d1ef3 100644 --- a/src/agent/http_client/src/http_client.cpp +++ b/src/agent/http_client/src/http_client.cpp @@ -140,7 +140,17 @@ namespace http_client const auto req = CreateHttpRequest(params); - co_await socket->AsyncWrite(req, ec); + if (params.RequestTimeout) + { + LogError("/*/*/*/ someTimeOut "); + co_await socket->AsyncWrite(req, ec, params.RequestTimeout); + } + else + { + LogError("/*/*/*/ someTimeOut "); + co_await socket->AsyncWrite(req, ec); + } + LogError("/*/*/*/ resume waiting "); if (ec) { diff --git a/src/agent/http_client/src/http_request_params.cpp b/src/agent/http_client/src/http_request_params.cpp index 659072c3d7..2ed936dc52 100644 --- a/src/agent/http_client/src/http_request_params.cpp +++ b/src/agent/http_client/src/http_request_params.cpp @@ -13,7 +13,8 @@ namespace http_client std::string verificationMode, std::string token, std::string userPass, - std::string body) + std::string body, + const time_t requestTimeout) : Method(method) , Endpoint(std::move(endpoint)) , User_agent(std::move(userAgent)) @@ -21,6 +22,7 @@ namespace http_client , Token(std::move(token)) , User_pass(std::move(userPass)) , Body(std::move(body)) + , RequestTimeout(requestTimeout) { const auto result = boost::urls::parse_uri(serverUrl); @@ -53,6 +55,7 @@ namespace http_client { return Method == other.Method && Host == other.Host && Port == other.Port && Endpoint == other.Endpoint && User_agent == other.User_agent && Verification_Mode == other.Verification_Mode && Token == other.Token && - User_pass == other.User_pass && Body == other.Body && Use_Https == other.Use_Https; + User_pass == other.User_pass && Body == other.Body && Use_Https == other.Use_Https && + RequestTimeout == other.RequestTimeout; } } // namespace http_client diff --git a/src/agent/http_client/src/http_socket.cpp b/src/agent/http_client/src/http_socket.cpp index 2f2a36e002..def0de5783 100644 --- a/src/agent/http_client/src/http_socket.cpp +++ b/src/agent/http_client/src/http_socket.cpp @@ -65,11 +65,13 @@ namespace http_client boost::asio::awaitable HttpSocket::AsyncWrite(const boost::beast::http::request& req, - boost::system::error_code& ec) + boost::system::error_code& ec, + const std::time_t socketTimeout) { try { - m_socket->expires_after(std::chrono::seconds(http_client::SOCKET_TIMEOUT_SECS)); + LogError("/*/*/*/ waiting "); + m_socket->expires_after(std::chrono::seconds(socketTimeout)); co_await m_socket->async_write(req, ec); } catch (const std::exception& e) diff --git a/src/agent/http_client/src/http_socket.hpp b/src/agent/http_client/src/http_socket.hpp index f29adc1c3f..1c63aa3eb7 100644 --- a/src/agent/http_client/src/http_socket.hpp +++ b/src/agent/http_client/src/http_socket.hpp @@ -49,7 +49,8 @@ namespace http_client /// @param req The request to write /// @param ec The error code, if any occurred boost::asio::awaitable AsyncWrite(const boost::beast::http::request& req, - boost::system::error_code& ec) override; + boost::system::error_code& ec, + const time_t socketTimeout = http_client::SOCKET_TIMEOUT_SECS) override; /// @brief Reads a response from the socket /// @param res The response to read diff --git a/src/agent/http_client/src/https_socket.cpp b/src/agent/http_client/src/https_socket.cpp index e2ac9572b7..e91866910b 100644 --- a/src/agent/http_client/src/https_socket.cpp +++ b/src/agent/http_client/src/https_socket.cpp @@ -90,11 +90,12 @@ namespace http_client boost::asio::awaitable HttpsSocket::AsyncWrite(const boost::beast::http::request& req, - boost::system::error_code& ec) + boost::system::error_code& ec, + const time_t socketTimeout) { try { - m_ssl_socket->expires_after(std::chrono::seconds(http_client::SOCKET_TIMEOUT_SECS)); + m_ssl_socket->expires_after(std::chrono::seconds(socketTimeout)); co_await m_ssl_socket->async_write(req, ec); } catch (const std::exception& e) diff --git a/src/agent/http_client/src/https_socket.hpp b/src/agent/http_client/src/https_socket.hpp index c1473bcb90..bdb61e378a 100644 --- a/src/agent/http_client/src/https_socket.hpp +++ b/src/agent/http_client/src/https_socket.hpp @@ -55,7 +55,8 @@ namespace http_client /// @param req The request to write /// @param ec The error code, if any occurred boost::asio::awaitable AsyncWrite(const boost::beast::http::request& req, - boost::system::error_code& ec) override; + boost::system::error_code& ec, + const time_t socketTimeout = http_client::SOCKET_TIMEOUT_SECS) override; /// @brief Reads a response from the socket /// @param res The response to read diff --git a/src/agent/http_client/src/ihttp_socket.hpp b/src/agent/http_client/src/ihttp_socket.hpp index ececc2a944..b51c321279 100644 --- a/src/agent/http_client/src/ihttp_socket.hpp +++ b/src/agent/http_client/src/ihttp_socket.hpp @@ -45,9 +45,11 @@ namespace http_client /// @brief Asynchronous version of Write /// @param req The request to write /// @param ec The error code, if any occurred + /// TODO: doc virtual boost::asio::awaitable AsyncWrite(const boost::beast::http::request& req, - boost::system::error_code& ec) = 0; + boost::system::error_code& ec, + const time_t socketTimeout = http_client::SOCKET_TIMEOUT_SECS) = 0; /// @brief Reads a response from the socket /// @param res The response to read diff --git a/src/agent/http_client/tests/http_client_test.cpp b/src/agent/http_client/tests/http_client_test.cpp index 8185f322ee..e9e695dcdf 100644 --- a/src/agent/http_client/tests/http_client_test.cpp +++ b/src/agent/http_client/tests/http_client_test.cpp @@ -86,10 +86,11 @@ class HttpClientTest : public TestWithParam void SetupMockSocketWriteExpectations(boost::system::error_code writeEc = {}) { - EXPECT_CALL(*mockSocket, AsyncWrite(_, _)) + EXPECT_CALL(*mockSocket, AsyncWrite(_, _, _)) .WillOnce(Invoke( [writeEc](const boost::beast::http::request&, - boost::system::error_code& ec) -> boost::asio::awaitable + boost::system::error_code& ec, + [[maybe_unused]] const time_t timeout) -> boost::asio::awaitable { ec = writeEc; co_return; diff --git a/src/agent/http_client/tests/http_socket_test.cpp b/src/agent/http_client/tests/http_socket_test.cpp index c9a4faddee..30f374bab0 100644 --- a/src/agent/http_client/tests/http_socket_test.cpp +++ b/src/agent/http_client/tests/http_socket_test.cpp @@ -220,7 +220,7 @@ TEST_F(HttpSocketTest, AsyncWriteSuccess) boost::system::error_code ec; boost::asio::co_spawn( *m_ioContext, - [&]() -> boost::asio::awaitable { co_await m_socket->AsyncWrite(req, ec); }, + [&]() -> boost::asio::awaitable { co_await m_socket->AsyncWrite(req, ec, 60); }, boost::asio::detached); m_ioContext->run(); @@ -244,7 +244,7 @@ TEST_F(HttpSocketTest, AsyncWriteFailure) boost::system::error_code ec; boost::asio::co_spawn( *m_ioContext, - [&]() -> boost::asio::awaitable { co_await m_socket->AsyncWrite(req, ec); }, + [&]() -> boost::asio::awaitable { co_await m_socket->AsyncWrite(req, ec, 60); }, boost::asio::detached); m_ioContext->run(); @@ -264,7 +264,7 @@ TEST_F(HttpSocketTest, AsyncWriteException) boost::system::error_code ec; boost::asio::co_spawn( *m_ioContext, - [&]() -> boost::asio::awaitable { co_await m_socket->AsyncWrite(req, ec); }, + [&]() -> boost::asio::awaitable { co_await m_socket->AsyncWrite(req, ec, 60); }, boost::asio::detached); m_ioContext->run(); diff --git a/src/agent/http_client/tests/https_socket_test.cpp b/src/agent/http_client/tests/https_socket_test.cpp index bb13788486..3d0c740ffd 100644 --- a/src/agent/http_client/tests/https_socket_test.cpp +++ b/src/agent/http_client/tests/https_socket_test.cpp @@ -220,7 +220,7 @@ TEST_F(HttpsSocketTest, AsyncWriteSuccess) boost::system::error_code ec; boost::asio::co_spawn( *m_ioContext, - [&]() -> boost::asio::awaitable { co_await m_socket->AsyncWrite(req, ec); }, + [&]() -> boost::asio::awaitable { co_await m_socket->AsyncWrite(req, ec, 60); }, // TODO: Check value boost::asio::detached); m_ioContext->run(); @@ -244,7 +244,7 @@ TEST_F(HttpsSocketTest, AsyncWriteFailure) boost::system::error_code ec; boost::asio::co_spawn( *m_ioContext, - [&]() -> boost::asio::awaitable { co_await m_socket->AsyncWrite(req, ec); }, + [&]() -> boost::asio::awaitable { co_await m_socket->AsyncWrite(req, ec, 60); }, // TODO: Check value boost::asio::detached); m_ioContext->run(); @@ -264,7 +264,7 @@ TEST_F(HttpsSocketTest, AsyncWriteException) boost::system::error_code ec; boost::asio::co_spawn( *m_ioContext, - [&]() -> boost::asio::awaitable { co_await m_socket->AsyncWrite(req, ec); }, + [&]() -> boost::asio::awaitable { co_await m_socket->AsyncWrite(req, ec, 60); }, // TODO: Check value boost::asio::detached); m_ioContext->run(); diff --git a/src/agent/http_client/tests/mocks/mock_http_socket.hpp b/src/agent/http_client/tests/mocks/mock_http_socket.hpp index b290d93853..7186d612d3 100644 --- a/src/agent/http_client/tests/mocks/mock_http_socket.hpp +++ b/src/agent/http_client/tests/mocks/mock_http_socket.hpp @@ -25,7 +25,8 @@ class MockHttpSocket : public http_client::IHttpSocket MOCK_METHOD(boost::asio::awaitable, AsyncWrite, (const boost::beast::http::request& req, - boost::system::error_code& ec), + boost::system::error_code& ec, + const time_t timeout), (override)); MOCK_METHOD(void, diff --git a/src/cmake/config.cmake b/src/cmake/config.cmake index 611695a7d3..110e9ef390 100644 --- a/src/cmake/config.cmake +++ b/src/cmake/config.cmake @@ -61,3 +61,5 @@ set(DEFAULT_HOTFIXES true CACHE BOOL "Default inventory hotfixes") set(QUEUE_STATUS_REFRESH_TIMER 100 CACHE STRING "Default Agent's queue refresh timer (100ms)") set(QUEUE_DEFAULT_SIZE 10000 CACHE STRING "Default Agent's queue size (10000)") + +set(DEFAULT_COMMANDS_REQUEST_TIMEOUT 60 CACHE STRING "Default Agent's command request timeout (60s)") \ No newline at end of file diff --git a/src/common/config/include/config.h.in b/src/common/config/include/config.h.in index a766770f02..626294a30e 100644 --- a/src/common/config/include/config.h.in +++ b/src/common/config/include/config.h.in @@ -23,6 +23,7 @@ namespace config constexpr auto QUEUE_DEFAULT_SIZE = @QUEUE_DEFAULT_SIZE@; constexpr auto DEFAULT_VERIFICATION_MODE = "@DEFAULT_VERIFICATION_MODE@"; constexpr std::array VALID_VERIFICATION_MODES = {"full", "certificate", "none"}; + constexpr auto DEFAULT_COMMANDS_REQUEST_TIMEOUT = @DEFAULT_COMMANDS_REQUEST_TIMEOUT@; } namespace logcollector