diff --git a/client/app/common/AppClient.cpp b/client/app/common/AppClient.cpp index c432df7..02ede10 100644 --- a/client/app/common/AppClient.cpp +++ b/client/app/common/AppClient.cpp @@ -22,6 +22,16 @@ namespace cc_mqttsn_client_app namespace { +const std::uint8_t FwdEncMsgType = 0xfe; + +enum FwdEncOffset : unsigned +{ + FwdEncOffset_Length = 0, + FwdEncOffset_MsgType = 1U, + FwdEncOffset_Ctrl = 2U, + FwdEncOffset_NodeId = 3U, +}; + AppClient* asThis(void* data) { return reinterpret_cast(data); @@ -92,6 +102,16 @@ bool AppClient::start(int argc, const char* argv[]) return true; } + auto fwdEncNodeId = parseBinaryData(m_opts.fwdEncNodeId()); + if (!fwdEncNodeId.empty()) { + auto prefixLen = FwdEncOffset_NodeId + fwdEncNodeId.size(); + m_fwdEncPrefix.resize(prefixLen); + m_fwdEncPrefix[FwdEncOffset_Length] = static_cast(prefixLen); + m_fwdEncPrefix[FwdEncOffset_MsgType] = FwdEncMsgType; + m_fwdEncPrefix[FwdEncOffset_Ctrl] = 0U; + std::copy(fwdEncNodeId.begin(), fwdEncNodeId.end(), &m_fwdEncPrefix[FwdEncOffset_NodeId]); + } + if (!createSession()) { return false; } @@ -445,7 +465,16 @@ unsigned AppClient::cancelNextTickWaitInternal() void AppClient::sendDataInternal(const unsigned char* buf, unsigned bufLen, unsigned broadcastRadius) { assert(m_session); - m_session->sendData(buf, bufLen, broadcastRadius); + if (m_fwdEncPrefix.empty()) { + m_session->sendData(buf, bufLen, broadcastRadius); + return; + } + + std::vector encData; + encData.reserve(m_fwdEncPrefix.size() + bufLen); + encData.insert(encData.end(), m_fwdEncPrefix.begin(), m_fwdEncPrefix.end()); + encData.insert(encData.end(), buf, buf + bufLen); + m_session->sendData(encData.data(), encData.size(), broadcastRadius); } bool AppClient::createSession() @@ -461,7 +490,30 @@ bool AppClient::createSession() { assert(m_client); m_lastAddr = addr; - ::cc_mqttsn_client_process_data(m_client.get(), buf, static_cast(bufLen), origin); + + if (m_fwdEncPrefix.empty()) { + ::cc_mqttsn_client_process_data(m_client.get(), buf, static_cast(bufLen), origin); + return; + } + + do { + if (bufLen <= m_fwdEncPrefix.size()) { + break; + } + + if (!std::equal(m_fwdEncPrefix.begin(), m_fwdEncPrefix.begin() + FwdEncOffset_Ctrl, buf)) { + break; + } + + if (!std::equal(m_fwdEncPrefix.begin() + FwdEncOffset_NodeId, m_fwdEncPrefix.end(), &buf[FwdEncOffset_NodeId])) { + break; + } + + ::cc_mqttsn_client_process_data(m_client.get(), buf + m_fwdEncPrefix.size(), static_cast(bufLen - m_fwdEncPrefix.size()), origin); + return; + } while (false); + + logError() << "Recieved data doesn't have appropriate forwarding encapsulation prefix, ignoring..." << std::endl; }); m_session->setNetworkErrorReportCb( diff --git a/client/app/common/AppClient.h b/client/app/common/AppClient.h index 5883d62..675e64f 100644 --- a/client/app/common/AppClient.h +++ b/client/app/common/AppClient.h @@ -113,6 +113,7 @@ class AppClient ProgramOptions m_opts; ClientPtr m_client; SessionPtr m_session; + std::vector m_fwdEncPrefix; Addr m_lastAddr; }; diff --git a/client/app/common/ProgramOptions.cpp b/client/app/common/ProgramOptions.cpp index ae162c8..f75165c 100644 --- a/client/app/common/ProgramOptions.cpp +++ b/client/app/common/ProgramOptions.cpp @@ -82,6 +82,16 @@ void ProgramOptions::addWill() m_desc.add(opts); } +void ProgramOptions::addEncapsulate() +{ + po::options_description opts("Forwarder Encapsulation"); + opts.add_options() + ("fwd-enc-node-id", po::value()->default_value(std::string()), "Emulate forwarder encapsulation with specified node ID (passed as binary data). Use \"\\x\" prefix before hex value of each byte") + ; + + m_desc.add(opts); +} + void ProgramOptions::addPublish() { po::options_description opts("Publish Options"); @@ -202,6 +212,11 @@ unsigned ProgramOptions::willQos() const return m_vm["will-qos"].as(); } +std::string ProgramOptions::fwdEncNodeId() const +{ + return m_vm["fwd-enc-node-id"].as(); +} + std::string ProgramOptions::pubTopic() const { return m_vm["pub-topic"].as(); diff --git a/client/app/common/ProgramOptions.h b/client/app/common/ProgramOptions.h index 8a19438..f46b2de 100644 --- a/client/app/common/ProgramOptions.h +++ b/client/app/common/ProgramOptions.h @@ -32,6 +32,7 @@ class ProgramOptions void addDiscover(); void addConnect(); void addWill(); + void addEncapsulate(); void addPublish(); void addSubscribe(); @@ -62,7 +63,10 @@ class ProgramOptions // Will Options std::string willTopic() const; std::string willMessage() const; - unsigned willQos() const; + unsigned willQos() const; + + // Forwarder Encapsulation options + std::string fwdEncNodeId() const; // Publish Options std::string pubTopic() const; diff --git a/client/app/pub/Pub.cpp b/client/app/pub/Pub.cpp index 97fc7a9..38b56de 100644 --- a/client/app/pub/Pub.cpp +++ b/client/app/pub/Pub.cpp @@ -35,6 +35,7 @@ Pub::Pub(boost::asio::io_context& io, int& result) : opts().addNetwork(); opts().addConnect(); opts().addWill(); + opts().addEncapsulate(); opts().addPublish(); } diff --git a/client/app/sub/Sub.cpp b/client/app/sub/Sub.cpp index 842045d..f2f5295 100644 --- a/client/app/sub/Sub.cpp +++ b/client/app/sub/Sub.cpp @@ -33,6 +33,7 @@ Sub::Sub(boost::asio::io_context& io, int& result) : opts().addNetwork(); opts().addConnect(); opts().addWill(); + opts().addEncapsulate(); opts().addSubscribe(); } diff --git a/gateway/lib/src/session_op/Encapsulate.cpp b/gateway/lib/src/session_op/Encapsulate.cpp index b26f382..34daf42 100644 --- a/gateway/lib/src/session_op/Encapsulate.cpp +++ b/gateway/lib/src/session_op/Encapsulate.cpp @@ -125,7 +125,7 @@ void Encapsulate::sendDataClientReqFromSession( unsigned broadcastRadius) { FwdMsg_SN fwdMsg; - fwdMsg.field_ctrl().field_radius().setValue(3); // TODO: make it configurable + //fwdMsg.field_ctrl().field_radius().setValue(3); // TODO: make it configurable comms::util::assign(fwdMsg.field_nodeId().value(), nodeId.begin(), nodeId.end()); MqttsnFrame frame;