diff --git a/CMakeLists.txt b/CMakeLists.txt index a3fa7944f..91454ceeb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ set(AGENT_VERSION_MAJOR 2) set(AGENT_VERSION_MINOR 7) set(AGENT_VERSION_PATCH 0) -set(AGENT_VERSION_BUILD 4) +set(AGENT_VERSION_BUILD 5) set(AGENT_VERSION_RC "") # This minimum version is to support Visual Studio 2019 and C++ feature checking and FetchContent diff --git a/demo/compose/adapter/Dockerfile b/demo/compose/adapter/Dockerfile index 395749dc7..25307b89a 100644 --- a/demo/compose/adapter/Dockerfile +++ b/demo/compose/adapter/Dockerfile @@ -27,7 +27,7 @@ COPY --chown=adapter:adapter "./demo/agent/${LOG_FILE}" machine.log EXPOSE 7878 -CMD ["ruby", "run_scenario.rb", "-l", "-m", "30", "machine.log"] +CMD ["ruby", "run_scenario.rb", "-l", "-m", "1", "machine.log"] diff --git a/docker/ubuntu/Dockerfile b/docker/ubuntu/Dockerfile index a01755a12..6d5f21e16 100644 --- a/docker/ubuntu/Dockerfile +++ b/docker/ubuntu/Dockerfile @@ -28,7 +28,7 @@ # base image - ubuntu has amd64, arm64 etc. # 22.04 is the current long term support release, maintained until 2025-04. -FROM ubuntu:22.04 AS os +FROM ubuntu:24.04 AS os # tzinfo hangs without this ARG DEBIAN_FRONTEND='noninteractive' @@ -62,7 +62,7 @@ RUN apt clean && apt update \ rake \ ruby \ && rm -rf /var/lib/apt/lists/* \ - && pip install conan + && pip install --break-system-packages --root-user-action ignore conan # make an agent directory and cd into it WORKDIR /root/agent @@ -108,8 +108,8 @@ LABEL author='mtconnect' description='MTConnect C++ Agent' # change to a new non-root user for better security. # this also adds the user to a group with the same name. # --create-home creates a home folder, ie /home/ -ARG UID=1000 -ARG GID=1000 +ARG UID=1001 +ARG GID=1001 RUN groupadd \ --gid $GID \ diff --git a/src/mtconnect/source/adapter/agent_adapter/session_impl.hpp b/src/mtconnect/source/adapter/agent_adapter/session_impl.hpp index 227ab16fb..c0811e129 100644 --- a/src/mtconnect/source/adapter/agent_adapter/session_impl.hpp +++ b/src/mtconnect/source/adapter/agent_adapter/session_impl.hpp @@ -84,6 +84,11 @@ namespace mtconnect::source::adapter::agent_adapter { LOG(error) << "Agent Adapter Target: " << m_request->getTarget(m_url); LOG(error) << "Agent Adapter " << what << ": " << ec.message() << "\n"; m_request.reset(); + + // Clear cached DNS resolution so hostname is re-resolved on reconnect. + // This handles DHCP environments where IP addresses may change. + m_resolution.reset(); + if (m_failed) m_failed(ec); } diff --git a/src/mtconnect/source/adapter/shdr/connector.cpp b/src/mtconnect/source/adapter/shdr/connector.cpp index 8345eab3f..0ef731982 100644 --- a/src/mtconnect/source/adapter/shdr/connector.cpp +++ b/src/mtconnect/source/adapter/shdr/connector.cpp @@ -136,6 +136,8 @@ namespace mtconnect::source::adapter::shdr { return true; } + /// @brief Attempt to reconnect after a delay. If the server is a hostname, re-resolve it to get the current IP + /// address in case it has changed. If the server is a static IP address, just reconnect. inline void Connector::asyncTryConnect() { NAMED_SCOPE("Connector::asyncTryConnect"); @@ -145,7 +147,21 @@ namespace mtconnect::source::adapter::shdr { if (ec != boost::asio::error::operation_aborted) { LOG(info) << "reconnect: retrying connection"; - asio::dispatch(m_strand, boost::bind(&Connector::connect, this)); + // Re-resolve hostname to handle DHCP/dynamic IP environments. + // If the server is a hostname (not a static IP), re-resolve to get + // the current IP address in case it has changed. + boost::system::error_code addrEc; + ip::make_address(m_server, addrEc); + if (addrEc) + { + // m_server is a hostname, re-resolve it + asio::dispatch(m_strand, boost::bind(&Connector::resolve, this)); + } + else + { + // m_server is a static IP address, just reconnect + asio::dispatch(m_strand, boost::bind(&Connector::connect, this)); + } } }); } diff --git a/src/mtconnect/utilities.hpp b/src/mtconnect/utilities.hpp index 0b10cc783..9c3f25eb0 100644 --- a/src/mtconnect/utilities.hpp +++ b/src/mtconnect/utilities.hpp @@ -198,7 +198,7 @@ namespace mtconnect { /// @brief Convert text to upper case /// @param[in,out] text text /// @return upper-case of text as string - constexpr std::string &toUpperCase(std::string &text) + inline std::string &toUpperCase(std::string &text) { std::transform(text.begin(), text.end(), text.begin(), [](unsigned char c) { return std::toupper(c); }); @@ -209,7 +209,7 @@ namespace mtconnect { /// @brief Simple check if a number as a string is negative /// @param s the numbeer /// @return `true` if positive - constexpr bool isNonNegativeInteger(const std::string &s) + inline bool isNonNegativeInteger(const std::string &s) { for (const char c : s) { @@ -223,7 +223,7 @@ namespace mtconnect { /// @brief Checks if a string is a valid integer /// @param s the string /// @return `true` if is `[+-]\d+` - constexpr bool isInteger(const std::string &s) + inline bool isInteger(const std::string &s) { auto iter = s.cbegin(); if (*iter == '-' || *iter == '+')