Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed regex for URL parsing. #474

Merged
merged 7 commits into from
Jul 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ jobs:
- name: Build and Test C++ Agent
run: |
set CTEST_OUTPUT_ON_FAILURE=TRUE
conan create . --build=missing -pr conan/profiles/${{ matrix.profile }} -o with_docs=False -o cpack=True -o cpack_destination=${{ env.ZIP_DIR }} -o shared=${{ matrix.shared }}
conan create . --build=missing -pr conan/profiles/${{ matrix.profile }} -o "&:with_docs=False" -o "&:cpack=True" -o "&:cpack_destination=${{ env.ZIP_DIR }}" -o "&:shared=${{ matrix.shared }}"

- name: Release
uses: softprops/action-gh-release@v1
Expand Down Expand Up @@ -149,7 +149,7 @@ jobs:
shell: bash
run: |
export CTEST_OUTPUT_ON_FAILURE=TRUE
conan create . --build=missing -pr conan/profiles/gcc -o shared=${{ matrix.shared }} -o with_docs=False -o cpack=True -o cpack_name=dist -o cpack_destination=${{ github.workspace }}
conan create . --build=missing -pr conan/profiles/gcc -o '&:shared=${{ matrix.shared }}' -o '&:with_docs=False' -o '&:cpack=True' -o '&:cpack_name=dist' -o '&:cpack_destination=${{ github.workspace }}'

- name: Cleanse package version
run: |
Expand Down Expand Up @@ -225,5 +225,5 @@ jobs:
shell: bash
run: |
export CTEST_OUTPUT_ON_FAILURE=TRUE
conan create . --build=missing -pr conan/profiles/macos -o shared=${{ matrix.shared }} -o with_docs=False
conan create . --build=missing -pr conan/profiles/macos -o '&:shared=${{ matrix.shared }}' -o '&:with_docs=False'

2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
set(AGENT_VERSION_MAJOR 2)
set(AGENT_VERSION_MINOR 3)
set(AGENT_VERSION_PATCH 0)
set(AGENT_VERSION_BUILD 15)
set(AGENT_VERSION_BUILD 16)
set(AGENT_VERSION_RC "")

# This minimum version is to support Visual Studio 2019 and C++ feature checking and FetchContent
Expand Down
2 changes: 0 additions & 2 deletions agent_lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,6 @@ set(AGENT_SOURCES
"${SOURCE_DIR}/source/adapter/agent_adapter/https_session.hpp"
"${SOURCE_DIR}/source/adapter/agent_adapter/session.hpp"
"${SOURCE_DIR}/source/adapter/agent_adapter/session_impl.hpp"
"${SOURCE_DIR}/source/adapter/agent_adapter/url_parser.hpp"
"${SOURCE_DIR}/source/adapter/mqtt/mqtt_adapter.hpp"
"${SOURCE_DIR}/source/adapter/shdr/connector.hpp"
"${SOURCE_DIR}/source/adapter/shdr/shdr_adapter.hpp"
Expand All @@ -233,7 +232,6 @@ set(AGENT_SOURCES
"${SOURCE_DIR}/source/loopback_source.cpp"
"${SOURCE_DIR}/source/source.cpp"
"${SOURCE_DIR}/source/adapter/agent_adapter/agent_adapter.cpp"
"${SOURCE_DIR}/source/adapter/agent_adapter/url_parser.cpp"

# src/sink HEADER_FILE_ONLY

Expand Down
9 changes: 4 additions & 5 deletions src/mtconnect/agent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -438,8 +438,7 @@ namespace mtconnect {
}
}

void Agent::loadDevices(list<DevicePtr> devices, const optional<string> source,
bool force)
void Agent::loadDevices(list<DevicePtr> devices, const optional<string> source, bool force)
{
if (!force && !IsOptionSet(m_options, config::EnableSourceDeviceModels))
{
Expand All @@ -460,7 +459,7 @@ namespace mtconnect {
{
oldUuid = *oldDev->getUuid();
}

auto uuid = *device->getUuid();
auto name = *device->getComponentName();

Expand All @@ -475,7 +474,7 @@ namespace mtconnect {
s->setOptions({{config::Device, uuid}});
}
}

for (auto src : m_sources)
{
auto adapter = std::dynamic_pointer_cast<source::adapter::Adapter>(src);
Expand Down Expand Up @@ -514,7 +513,7 @@ namespace mtconnect {
cerr << f.what() << endl;
}
};

// Gets around a race condition in the loading of adapaters and setting of
// UUID.
if (m_context.isRunning() && !m_context.isPauased())
Expand Down
9 changes: 5 additions & 4 deletions src/mtconnect/agent.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -279,8 +279,7 @@ namespace mtconnect {
/// @param[in] deviceXml the device xml as a string
/// @param[in] source the source loading the device
void loadDevices(std::list<DevicePtr> device,
const std::optional<std::string> source = std::nullopt,
bool force = false);
const std::optional<std::string> source = std::nullopt, bool force = false);

/// @brief receive and parse a single device from a source
/// @param[in] deviceXml the device xml as a string
Expand Down Expand Up @@ -591,8 +590,10 @@ namespace mtconnect {
void deliverConnectStatus(entity::EntityPtr, const StringList &devices,
bool autoAvailable) override;
void deliverCommand(entity::EntityPtr) override;
void deliverDevice(DevicePtr device) override { m_agent->loadDevices({device}, std::nullopt,
true); }
void deliverDevice(DevicePtr device) override
{
m_agent->loadDevices({device}, std::nullopt, true);
}
void deliverDevices(std::list<DevicePtr> devices) override { m_agent->loadDevices(devices); }

void sourceFailed(const std::string &identity) override { m_agent->sourceFailed(identity); }
Expand Down
4 changes: 2 additions & 2 deletions src/mtconnect/asset/asset.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,9 +160,9 @@ namespace mtconnect {
/// Override to skip the `hash`, `timestamp`, and `removed` properties.
///
/// @param[in,out] sha1 The boost sha1 accumulator
void hash(boost::uuids::detail::sha1 &sha1) const override
void hash(::boost::uuids::detail::sha1 &sha1) const override
{
static const boost::unordered_set<std::string> skip {"hash", "timestamp", "removed"};
static const ::boost::unordered_set<std::string> skip {"hash", "timestamp", "removed"};
entity::Entity::hash(sha1, skip);
}

Expand Down
36 changes: 13 additions & 23 deletions src/mtconnect/configuration/agent_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -906,31 +906,21 @@ namespace mtconnect::configuration {

void parseUrl(ConfigOptions &options)
{
string host, protocol, path;
using namespace mtconnect::url;
auto url = *GetOption<string>(options, configuration::Url);

boost::regex pat("^([^:]+)://([^:/]+)(:[0-9]+)?(/.+)?");
boost::match_results<string::const_iterator> match;
if (boost::regex_match(url, match, pat))
auto parsed = Url::parse(url);
options[configuration::Protocol] = parsed.m_protocol;
options[configuration::Host] = parsed.getHost();
if (parsed.m_port)
options[configuration::Port] = parsed.getPort();
if (parsed.m_path != "/")
{
if (match[1].matched)
options[configuration::Protocol] = string(match[1].first, match[1].second);
if (match[2].matched)
options[configuration::Host] = string(match[2].first, match[2].second);
if (match[3].matched)
{
try
{
options[configuration::Port] =
boost::lexical_cast<int>(string(match[3].first + 1, match[3].second).c_str());
}
catch (boost::bad_lexical_cast &e)
{
LOG(error) << "Cannot intrepret the port for " << match[3] << ": " << e.what();
}
}
if (match[4].matched)
options[configuration::Topics] = StringList {string(match[4].first, match[4].second)};
StringList list;
string topics = parsed.m_path.substr(1, string::npos);
boost::split(list, topics, boost::is_any_of(":"),
boost::token_compress_on);
options[configuration::Topics] = list;
}
}

Expand Down Expand Up @@ -979,7 +969,7 @@ namespace mtconnect::configuration {
device = getDefaultDevice();
if (device)
{
deviceName = *device->getComponentName();
deviceName = *device->getUuid();
adapterOptions[configuration::Device] = deviceName;
LOG(info) << "Assigning default device " << deviceName << " to adapter";
}
Expand Down
4 changes: 2 additions & 2 deletions src/mtconnect/configuration/async_context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ namespace mtconnect::configuration {
/// @brief removes the copy constructor
AsyncContext(const AsyncContext &) = delete;
~AsyncContext() {}

/// @brief is the context running
/// @returns running status
auto isRunning() { return m_running; }

/// @brief return the paused state
/// @returns the paused state
auto isPauased() { return m_paused; }
Expand Down
5 changes: 2 additions & 3 deletions src/mtconnect/configuration/service.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@
//

/* -- this file needs to be first for the servics to build correctly */
#ifdef _WINDOWS
#include "windows.h"
#endif
#include "mtconnect/utilities.hpp"

/* keep this file first */

#include <boost/program_options.hpp>
Expand Down
29 changes: 16 additions & 13 deletions src/mtconnect/sink/mqtt_sink/mqtt2_service.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,11 @@ namespace mtconnect {
{
m_options[configuration::MqttHost] = m_options[configuration::Host];
}

auto retain = GetOption<bool>(m_options, configuration::MqttRetain);
if (retain)
m_retain = *retain;

auto qoso = GetOption<string>(m_options, configuration::MqttQOS);

if (qoso)
Expand All @@ -133,7 +133,7 @@ namespace mtconnect {
else if (qos == "exactly_once")
m_qos = MqttClient::QOS::exactly_once;
else
LOG(warning) << "Invalid QOS for MQTT Client: " << qos
LOG(warning) << "Invalid QOS for MQTT Client: " << qos
<< ", must be at_most_once, at_least_once, or exactly_once";
}
}
Expand Down Expand Up @@ -269,16 +269,19 @@ namespace mtconnect {
m_sinkContract->getCircularBuffer().getBufferSize(), end,
firstSeq, lastSeq, *observations, false);

m_client->asyncPublish(topic, doc, [sampler, topic](std::error_code ec) {
if (!ec)
{
sampler->handlerCompleted();
}
else
{
LOG(warning) << "Async publish failed for " << topic << ": " << ec.message();
}
}, m_retain, m_qos);
m_client->asyncPublish(
topic, doc,
[sampler, topic](std::error_code ec) {
if (!ec)
{
sampler->handlerCompleted();
}
else
{
LOG(warning) << "Async publish failed for " << topic << ": " << ec.message();
}
},
m_retain, m_qos);

return end;
}
Expand Down
4 changes: 2 additions & 2 deletions src/mtconnect/sink/mqtt_sink/mqtt2_service.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ namespace mtconnect {
/// @brief Mqtt Client is Connected or not
/// @return `true` when the client was connected
bool isConnected() { return m_client && m_client->isConnected(); }

/// @name Retain and QOS flags
///@{
auto getRetain() { return m_retain; }
Expand Down Expand Up @@ -205,7 +205,7 @@ namespace mtconnect {

std::map<std::string, FilterSet> m_filters;
std::map<std::string, std::shared_ptr<AsyncSample>> m_samplers;

bool m_retain {true};
MqttClient::QOS m_qos {MqttClient::QOS::at_least_once};
};
Expand Down
6 changes: 3 additions & 3 deletions src/mtconnect/source/adapter/agent_adapter/agent_adapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
using namespace std;
using namespace mtconnect;
using namespace mtconnect::pipeline;
using namespace mtconnect::url;

namespace mtconnect::source::adapter::agent_adapter {
void AgentAdapterPipeline::build(const ConfigOptions &options)
Expand All @@ -51,9 +52,8 @@ namespace mtconnect::source::adapter::agent_adapter {

TransformPtr next =
bind(make_shared<MTConnectXmlTransform>(m_context, m_feedback, m_device, m_uuid));
std::optional<string> obsMetrics;
obsMetrics = m_identity + "_observation_update_rate";
next->bind(make_shared<DeliverObservation>(m_context, obsMetrics));

buildObservationDelivery(next);
buildDeviceDelivery(next);
buildAssetDelivery(next);

Expand Down
4 changes: 2 additions & 2 deletions src/mtconnect/source/adapter/agent_adapter/agent_adapter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
#include "mtconnect/pipeline/mtconnect_xml_transform.hpp"
#include "mtconnect/source/adapter/adapter.hpp"
#include "mtconnect/source/adapter/adapter_pipeline.hpp"
#include "mtconnect/utilities.hpp"
#include "session.hpp"
#include "url_parser.hpp"

namespace boost::asio::ssl {
class context;
Expand Down Expand Up @@ -127,7 +127,7 @@ namespace mtconnect::source::adapter::agent_adapter {
protected:
pipeline::XmlTransformFeedback m_feedback;
AgentAdapterPipeline m_pipeline;
Url m_url;
url::Url m_url;
int m_count = 1000;
std::chrono::milliseconds m_heartbeat;
bool m_reconnecting = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ namespace mtconnect::source::adapter::agent_adapter {
/// @brief Create a session to connect to the remote agent
/// @param ioc the asio strand to run in
/// @param url URL to connect to
HttpSession(boost::asio::io_context::strand &ioc, const Url &url)
HttpSession(boost::asio::io_context::strand &ioc, const url::Url &url)
: super(ioc, url), m_stream(ioc.context())
{}

Expand Down
3 changes: 2 additions & 1 deletion src/mtconnect/source/adapter/agent_adapter/https_session.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ namespace mtconnect::source::adapter::agent_adapter {
/// @param ex the strand to run in
/// @param url the url to connect to
/// @param ctx the TLS context
explicit HttpsSession(boost::asio::io_context::strand &ex, const Url &url, ssl::context &ctx)
explicit HttpsSession(boost::asio::io_context::strand &ex, const url::Url &url,
ssl::context &ctx)
: super(ex, url), m_stream(ex.context(), ctx)
{}
~HttpsSession()
Expand Down
10 changes: 6 additions & 4 deletions src/mtconnect/source/adapter/agent_adapter/session.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@

#include "mtconnect/config.hpp"
#include "mtconnect/entity/entity.hpp"
#include "url_parser.hpp"

namespace mtconnect::source::adapter {
struct Handler;
Expand Down Expand Up @@ -53,7 +52,7 @@ namespace mtconnect::source::adapter::agent_adapter {
/// @param stream `true` if HTTP x-multipart-replace streaming is desired
/// @param next Function to determine what to do on successful read
Request(const std::optional<std::string> &device, const std::string &operation,
const UrlQuery &query, bool stream, Next next)
const url::UrlQuery &query, bool stream, Next next)
: m_sourceDevice(device),
m_operation(operation),
m_query(query),
Expand All @@ -65,15 +64,18 @@ namespace mtconnect::source::adapter::agent_adapter {

std::optional<std::string> m_sourceDevice; ///< optional source device
std::string m_operation; ///< The REST operation (probe, current, sample, asset)
UrlQuery m_query; ///< URL Query parameters
url::UrlQuery m_query; ///< URL Query parameters
bool m_stream; ///< `true` if using HTTP long pull
Next m_next; ///< function to call on successful read
int32_t m_agentVersion = 0; ///< agent version if required > 0 for asset requests

/// @brief Given a url, get a formatted target for a given operation
/// @param url The base url
/// @return a string with a new URL path and query (for the GET)
auto getTarget(const Url &url) { return url.getTarget(m_sourceDevice, m_operation, m_query); }
auto getTarget(const url::Url &url)
{
return url.getTarget(m_sourceDevice, m_operation, m_query);
}
};

virtual ~Session() {}
Expand Down
4 changes: 2 additions & 2 deletions src/mtconnect/source/adapter/agent_adapter/session_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ namespace mtconnect::source::adapter::agent_adapter {

// Objects are constructed with a strand to
// ensure that handlers do not execute concurrently.
SessionImpl(boost::asio::io_context::strand &strand, const Url &url)
SessionImpl(boost::asio::io_context::strand &strand, const url::Url &url)
: m_resolver(strand.context()), m_strand(strand), m_url(url), m_chunk(1 * 1024 * 1024)
{}

Expand Down Expand Up @@ -595,7 +595,7 @@ namespace mtconnect::source::adapter::agent_adapter {
std::optional<http::response_parser<http::dynamic_body>> m_chunkParser;
std::optional<http::response_parser<http::string_body>> m_textParser;
asio::io_context::strand m_strand;
Url m_url;
url::Url m_url;

std::function<std::uint64_t(std::uint64_t, boost::string_view, boost::system::error_code &)>
m_chunkHandler;
Expand Down
Loading
Loading