diff --git a/.travis.yml b/.travis.yml index e214baa..8ae947d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,7 +22,13 @@ matrix: - os: linux env: _CC=gcc-6 _CXX=g++-6 _BUILD=-DCMAKE_BUILD_TYPE=Release - os: linux - env: _CC=gcc-6 _CXX=g++-6 _BUILD=-DCMAKE_BUILD_TYPE=MinSizeRel + env: _CC=gcc-6 _CXX=g++-6 _BUILD=-DCMAKE_BUILD_TYPE=MinSizeRel + - os: linux + env: _CC=gcc-6 _CXX=g++-6 _BUILD=-DCMAKE_CXX_STANDARD=14 + - os: linux + env: _CC=gcc-6 _CXX=g++-6 _BUILD="-DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=14" + - os: linux + env: _CC=gcc-6 _CXX=g++-6 _BUILD="-DCMAKE_BUILD_TYPE=MinSizeRel -DCMAKE_CXX_STANDARD=14" - os: linux env: _CC=clang-3.9 _CXX=clang++-3.9 _BUILD=-DCMAKE_CXX_STANDARD=14 - os: linux @@ -31,18 +37,18 @@ matrix: env: _CC=clang-3.9 _CXX=clang++-3.9 _BUILD="-DCMAKE_BUILD_TYPE=MinSizeRel -DCMAKE_CXX_STANDARD=14" before_install: - - sudo add-apt-repository ppa:beineri/opt-qt551 -y + - sudo add-apt-repository ppa:beineri/opt-qt562-trusty -y - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y - - sudo add-apt-repository ppa:george-edison55/precise-backports -y + - sudo add-apt-repository ppa:george-edison55/cmake-3.x -y - wget -O - http://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - - sudo apt-add-repository "deb http://apt.llvm.org/precise/ llvm-toolchain-precise-3.9 main" -y - sudo apt-get update -q - - sudo apt-get install g++-5 g++-6 clang-3.9 cmake cmake-data qt55declarative qt55serialport -y + - sudo apt-get install g++-5 g++-6 clang-3.9 cmake cmake-data qt56base qt56serialport -y before_script: - mkdir build - cd build - - source /opt/qt55/bin/qt55-env.sh + - source /opt/qt56/bin/qt56-env.sh - CC=${_CC} CXX=${_CXX} cmake .. -DCC_MQTTSN_FULL_SOLUTION=ON ${_BUILD} script: diff --git a/CMakeLists.txt b/CMakeLists.txt index dfa05e6..1905fd7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -147,7 +147,7 @@ set (CC_MQTT_EXTERNAL_TGT "mqtt_external") macro (externals install_dir build_cc mqtt_headers) include(ExternalProject) - set (cc_tag "v0.18.1") + set (cc_tag "v0.23") set (cc_main_dir "${CMAKE_BINARY_DIR}/comms_champion") set (cc_src_dir "${cc_main_dir}/src") set (cc_bin_dir "${cc_main_dir}/build") @@ -186,7 +186,7 @@ macro (externals install_dir build_cc mqtt_headers) set (CC_COMMS_FOUND TRUE) if (${mqtt_headers}) - set (cc_mqtt_tag "v0.7") + set (cc_mqtt_tag "v0.7.2") ExternalProject_Add( "${CC_MQTT_EXTERNAL_TGT}" PREFIX "${cc_mqtt_bin_dir}" diff --git a/client/src/basic/BasicClient.h b/client/src/basic/BasicClient.h index d72e9ec..ec03d77 100644 --- a/client/src/basic/BasicClient.h +++ b/client/src/basic/BasicClient.h @@ -23,6 +23,7 @@ #include #include #include +#include #include "comms/comms.h" #include "comms/util/ScopeGuard.h" @@ -265,16 +266,18 @@ class BasicClient typedef void (BasicClient::*FinaliseFunc)(MqttsnAsyncOpStatus); + struct NoOrigDataViewProtOpts : TProtOpts + { + static const bool HasOrigDataView = false; + }; + public: typedef typename Message::Field FieldBase; typedef typename mqttsn::protocol::field::GwId::ValueType GwIdValueType; - //typedef typename mqttsn::protocol::field::GwAdd::ValueType GwAddValueType; - typedef typename mqttsn::protocol::field::WillTopic::ValueType WillTopicType; - typedef typename mqttsn::protocol::field::WillMsg::ValueType WillMsgType; - typedef typename mqttsn::protocol::field::TopicName::ValueType TopicNameType; - typedef typename mqttsn::protocol::field::Data::ValueType DataType; + typedef typename mqttsn::protocol::field::TopicName::ValueType TopicNameType; + typedef typename mqttsn::protocol::field::Data::ValueType DataType; typedef typename mqttsn::protocol::field::TopicId::ValueType TopicIdType; - typedef typename mqttsn::protocol::field::ClientId::ValueType ClientIdType; + typedef typename mqttsn::protocol::field::ClientId::ValueType ClientIdType; struct GwInfo { @@ -317,7 +320,7 @@ class BasicClient typedef mqttsn::protocol::message::Willmsgresp WillmsgrespMsg; BasicClient() = default; - virtual ~BasicClient() = default; + ~BasicClient() noexcept = default; typedef typename Message::ReadIterator ReadIterator; @@ -1208,7 +1211,9 @@ class BasicClient WillmsgMsg outMsg; if (op->m_willInfo.msg != nullptr) { - outMsg.field_willMsg().value().assign(op->m_willInfo.msg, op->m_willInfo.msg + op->m_willInfo.msgLen); + auto& dataStorage = outMsg.field_willMsg().value(); + using DataStorage = typename std::decay::type; + dataStorage = DataStorage(op->m_willInfo.msg, op->m_willInfo.msgLen); } op->m_willMsgSent = true; @@ -1217,7 +1222,8 @@ class BasicClient void handle(RegisterMsg& msg) { - updateRegInfo(msg.field_topicName().value().c_str(), msg.field_topicId().value(), true); + auto& topic = msg.field_topicName().value(); + updateRegInfo(topic.data(), topic.size(), msg.field_topicId().value(), true); RegackMsg ackMsg; ackMsg.field_topicId().value() = msg.field_topicId().value(); @@ -1254,7 +1260,7 @@ class BasicClient op->m_topicId = msg.field_topicId().value(); op->m_attempt = 0; - updateRegInfo(op->m_topic, op->m_topicId); + updateRegInfo(op->m_topic, std::strlen(op->m_topic), op->m_topicId); bool result = doPublish(); static_cast(result); GASSERT(result); @@ -1350,7 +1356,8 @@ class BasicClient midFlags.getBitValue(MidFlags::BitIdx_retain); } - m_lastInMsg.m_msgData = msg.field_data().value(); + auto& msgData = msg.field_data().value(); + m_lastInMsg.m_msgData.assign(msgData.begin(), msgData.end()); PubrecMsg recMsg; recMsg.field_msgId().value() = msg.field_msgId().value(); @@ -1534,7 +1541,8 @@ class BasicClient } if ((m_currOp == Op::Subscribe) && (msg.field_topicId().value() != 0U)) { - updateRegInfo(opPtr()->m_topic, msg.field_topicId().value(), true); + auto* topicStr = opPtr()->m_topic; + updateRegInfo(topicStr, std::strlen(topicStr), msg.field_topicId().value(), true); } op->m_qos = qosValue; @@ -1691,13 +1699,16 @@ class BasicClient bool m_reported = false; }; - void updateRegInfo(const char* topic, TopicIdType topicId, bool locked = false) + void updateRegInfo(const char* topic, std::size_t topicLen, TopicIdType topicId, bool locked = false) { auto iter = std::find_if( m_regInfos.begin(), m_regInfos.end(), - [topic, topicId](typename RegInfosList::const_reference elem) -> bool + [topic, topicLen, topicId](typename RegInfosList::const_reference elem) -> bool { - return elem.m_allocated && (elem.m_topic == topic); + return + elem.m_allocated && + elem.m_topic.size() == topicLen && + std::equal(elem.m_topic.begin(), elem.m_topic.end(), topic); }); if (iter != m_regInfos.end()) { @@ -1716,7 +1727,7 @@ class BasicClient if (iter != m_regInfos.end()) { iter->m_timestamp = m_timestamp; - iter->m_topic = topic; + iter->m_topic.assign(topic, topic + topicLen); iter->m_topicId = topicId; iter->m_allocated = true; iter->m_locked = locked; @@ -1725,7 +1736,7 @@ class BasicClient RegInfo info; info.m_timestamp = m_timestamp; - info.m_topic = topic; + info.m_topic.assign(topic, topicLen); info.m_topicId = topicId; info.m_allocated = true; info.m_locked = locked; @@ -2425,8 +2436,9 @@ class BasicClient WillmsgupdMsg msg; auto* msgBodyBeg = op->m_msg; if (msgBodyBeg != nullptr) { - auto* msgBodyEnd = msgBodyBeg + op->m_msgLen; - msg.field_willMsg().value().assign(msgBodyBeg, msgBodyEnd); + auto& dataStorage = msg.field_willMsg().value(); + using DataStorage = typename std::decay::type; + dataStorage = DataStorage(msgBodyBeg, op->m_msgLen); } sendMessage(msg); return true; @@ -2462,7 +2474,9 @@ class BasicClient ++op->m_attempt; PingreqMsg msg; - msg.field_clientId().value() = m_clientId; + auto& clientIdStorage = msg.field_clientId().value(); + using ClientIdStorage = typename std::decay::type; + clientIdStorage = ClientIdStorage(m_clientId.c_str(), m_clientId.size()); sendMessage(msg); return true; } @@ -2535,7 +2549,10 @@ class BasicClient dupFlagsField.setBitValue(DupFlags::BitIdx_bit, duplicate); pubMsg.field_topicId().value() = topicId; pubMsg.field_msgId().value() = msgId; - pubMsg.field_data().value().assign(msg, msg + msgLen); + + auto& dataStorage = pubMsg.field_data().value(); + using DataStorage = typename std::decay::type; + dataStorage = DataStorage(msg, msgLen); sendMessage(pubMsg); } diff --git a/client/templ/client.cpp.templ b/client/templ/client.cpp.templ index 0073746..597717d 100644 --- a/client/templ/client.cpp.templ +++ b/client/templ/client.cpp.templ @@ -33,7 +33,8 @@ typedef std::tuple< typedef mqttsn::protocol::ParsedOptions< ProtocolOptions, - mqttsn::protocol::option::ClientOnlyVariant + mqttsn::protocol::option::ClientOnlyVariant, + mqttsn::protocol::option::UseOrigDataView > ParsedProtocolOptions; typedef std::tuple< diff --git a/client/test/bare_metal_app/test_client_build/CMakeLists.txt b/client/test/bare_metal_app/test_client_build/CMakeLists.txt index 29a1cc3..33fe7aa 100644 --- a/client/test/bare_metal_app/test_client_build/CMakeLists.txt +++ b/client/test/bare_metal_app/test_client_build/CMakeLists.txt @@ -35,7 +35,7 @@ endfunction () ################################################################# if (CMAKE_COMPILER_IS_GNUCC) - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nostdlib") + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nostdlib --std=c++11") endif () bin_client_build() diff --git a/client/test/bare_metal_app/test_client_build/stub.cpp b/client/test/bare_metal_app/test_client_build/stub.cpp index 8231813..050cecd 100644 --- a/client/test/bare_metal_app/test_client_build/stub.cpp +++ b/client/test/bare_metal_app/test_client_build/stub.cpp @@ -75,6 +75,18 @@ void* memcpy( void* dest, const void* src, std::size_t count ) return nullptr; } +extern "C" +int memcmp(const void*, const void*, std::size_t) +{ + return 0; +} + +extern "C" +std::size_t strlen(const char*) +{ + return 0U; +} + extern "C" void __aeabi_uidiv() { diff --git a/gateway/src/lib/SessionImpl.cpp b/gateway/src/lib/SessionImpl.cpp index cd3529c..42abcbd 100644 --- a/gateway/src/lib/SessionImpl.cpp +++ b/gateway/src/lib/SessionImpl.cpp @@ -230,8 +230,9 @@ void SessionImpl::handle(RegisterMsg_SN& msg) auto& respMsgIdField = std::get(respFields); auto& respRetCodeField = std::get(respFields); + auto& topicView = topicField.value(); respTopicIdField.value() = - m_state.m_regMgr.mapTopicNoInfo(topicField.value()); + m_state.m_regMgr.mapTopicNoInfo(std::string(topicView.data(), topicView.size())); respMsgIdField.value() = msgIdField.value(); assert(respRetCodeField.value() == mqttsn::protocol::field::ReturnCodeVal_Accepted); diff --git a/gateway/src/lib/messages.h b/gateway/src/lib/messages.h index bff6310..a14dd56 100644 --- a/gateway/src/lib/messages.h +++ b/gateway/src/lib/messages.h @@ -48,7 +48,8 @@ typedef mqtt::protocol::v311::MessageT< > MqttMessage; typedef protocol::ParsedOptions< - protocol::option::GatewayOnlyVariant + protocol::option::GatewayOnlyVariant, + protocol::option::UseOrigDataView > GwOptions; typedef mqttsn::protocol::message::Advertise AdvertiseMsg_SN; diff --git a/gateway/src/lib/session_op/Connect.cpp b/gateway/src/lib/session_op/Connect.cpp index 928e736..a505564 100644 --- a/gateway/src/lib/session_op/Connect.cpp +++ b/gateway/src/lib/session_op/Connect.cpp @@ -60,13 +60,13 @@ void Connect::handle(ConnectMsg_SN& msg) typedef typename std::decay::type MidFlags; auto& st = state(); - auto* reqClientId = &(msg.field_clientId().value()); - if (reqClientId->empty()) { - reqClientId = &(st.m_defaultClientId); + auto reqClientId = msg.field_clientId().value().substr(); + if (reqClientId.empty()) { + reqClientId = st.m_defaultClientId; } if ((st.m_connStatus != ConnectionStatus::Disconnected) && - (*reqClientId != st.m_clientId)) { + (reqClientId != st.m_clientId)) { sendDisconnectToClient(); state().m_connStatus = ConnectionStatus::Disconnected; termRequest(); @@ -74,14 +74,14 @@ void Connect::handle(ConnectMsg_SN& msg) } - assert(st.m_clientId.empty() || st.m_clientId == *reqClientId); + assert(st.m_clientId.empty() || (st.m_clientId == reqClientId)); if (m_internalState.m_hasClientId) { m_internalState = State(); } m_internalState.m_hasClientId = true; - m_clientId = *reqClientId; + m_clientId = std::move(reqClientId); m_keepAlive = msg.field_duration().value(); m_clean = midFlagsField.getBitValue(MidFlags::BitIdx_cleanSession); @@ -125,7 +125,8 @@ void Connect::handle(WilltopicMsg_SN& msg) auto& midFlagsField = msg.field_flags().field().field_midFlags(); typedef typename std::decay::type MidFlags; - m_will.m_topic = msg.field_willTopic().value(); + auto& topicView = msg.field_willTopic().value(); + m_will.m_topic.assign(topicView.begin(), topicView.end()); m_will.m_qos = translateQos(msg.field_flags().field().field_qos().value()); m_will.m_retain = midFlagsField.getBitValue(MidFlags::BitIdx_retain); @@ -150,7 +151,8 @@ void Connect::handle(WillmsgMsg_SN& msg) m_internalState.m_hasWillMsg = true; m_internalState.m_attempt = 0; - m_will.m_msg = msg.field_willMsg().value(); + auto& data = msg.field_willMsg().value(); + m_will.m_msg.assign(data.begin(), data.end()); doNextStep(); } diff --git a/gateway/src/lib/session_op/Forward.cpp b/gateway/src/lib/session_op/Forward.cpp index 0630763..e1206d1 100644 --- a/gateway/src/lib/session_op/Forward.cpp +++ b/gateway/src/lib/session_op/Forward.cpp @@ -59,7 +59,8 @@ void Forward::handle(PublishMsg_SN& msg) NoGwPubInfo info; info.m_topicId = msg.field_topicId().value(); - info.m_data = msg.field_data().value(); + auto& data = msg.field_data().value(); + info.m_data.assign(data.begin(), data.end()); m_pubs.push_back(std::move(info)); return; } while (false); @@ -102,7 +103,8 @@ void Forward::handle(PublishMsg_SN& msg) fwdFlags.field_dup().setBitValue(0, dup); fwdMsg.field_topic().value() = topic; fwdMsg.field_packetId().field().value() = msg.field_msgId().value(); - fwdMsg.field_payload().value() = msg.field_data().value(); + auto& data = msg.field_data().value(); + fwdMsg.field_payload().value().assign(data.begin(), data.end()); fwdMsg.doRefresh(); sendToBroker(fwdMsg); } @@ -149,22 +151,22 @@ void Forward::handle(SubscribeMsg_SN& msg) return; } - - const std::string* topic = nullptr; + std::string topic; std::uint16_t topicId = 0U; do { if (msg.field_topicName().doesExist()) { assert(msg.field_topicId().isMissing()); - topic = &msg.field_topicName().field().value(); + auto& topicStorage = msg.field_topicName().field().value(); + topic.assign(topicStorage.begin(), topicStorage.end()); - if (topic->empty()) { + if (topic.empty()) { sendSubackFunc(mqttsn::protocol::field::ReturnCodeVal_NotSupported); sendToBroker(PingreqMsg()); return; } bool hasWildcards = - std::any_of(topic->begin(), topic->end(), + std::any_of(topic.begin(), topic.end(), [](char ch) -> bool { return (ch == '#') || (ch == '+'); @@ -174,7 +176,7 @@ void Forward::handle(SubscribeMsg_SN& msg) break; } - topicId = state().m_regMgr.mapTopicNoInfo(*topic); + topicId = state().m_regMgr.mapTopicNoInfo(topic); break; } @@ -183,7 +185,7 @@ void Forward::handle(SubscribeMsg_SN& msg) auto& topicStr = state().m_regMgr.mapTopicId(msg.field_topicId().field().value()); if (!topicStr.empty()) { - topic = &topicStr; + topic = topicStr; topicId = msg.field_topicId().field().value(); break; } @@ -210,8 +212,8 @@ void Forward::handle(SubscribeMsg_SN& msg) auto& subTopicField = std::get<0>(subMembers); auto& subQosField = std::get<1>(subMembers); - assert(topic != nullptr); - subTopicField.value() = *topic; + assert(!topic.empty()); + subTopicField.value() = std::move(topic); subQosField.value() = translateQosForBroker(translateQos(msg.field_flags().field_qos().value())); payloadContainer.push_back(std::move(subElem)); @@ -224,13 +226,14 @@ void Forward::handle(UnsubscribeMsg_SN& msg) return; } - const std::string* topic = nullptr; + std::string topic; do { if (msg.field_topicName().doesExist()) { assert(msg.field_topicId().isMissing()); - topic = &msg.field_topicName().field().value(); + auto& topicStorage = msg.field_topicName().field().value(); + topic.assign(topicStorage.begin(), topicStorage.end()); - if (topic->empty()) { + if (topic.empty()) { return; } @@ -244,7 +247,7 @@ void Forward::handle(UnsubscribeMsg_SN& msg) if (topicStr.empty()) { return; } - topic = &topicStr; + topic = topicStr; } while (false); UnsubscribeMsg fwdMsg; @@ -254,7 +257,7 @@ void Forward::handle(UnsubscribeMsg_SN& msg) typedef ContainerType::value_type UnsubString; UnsubString unsubStr; - unsubStr.value() = *topic; + unsubStr.value() = std::move(topic); payloadContainer.push_back(std::move(unsubStr)); sendToBroker(fwdMsg); } diff --git a/gateway/src/lib/session_op/PubSend.cpp b/gateway/src/lib/session_op/PubSend.cpp index 2337e9a..c2d213a 100644 --- a/gateway/src/lib/session_op/PubSend.cpp +++ b/gateway/src/lib/session_op/PubSend.cpp @@ -225,7 +225,10 @@ void PubSend::doSend() m_currMsgId = allocMsgId(); msg.field_topicId().value() = m_currTopicInfo.m_topicId; msg.field_msgId().value() = m_currMsgId; - msg.field_topicName().value() = m_currPub->m_topic; + + auto& topicStorage = msg.field_topicName().value(); + using TopicStorage = typename std::decay::type; + msg.field_topicName().value() = TopicStorage(m_currPub->m_topic.c_str(), m_currPub->m_topic.size()); sendToClient(msg); nextTickReq(st.m_retryPeriod); return; @@ -251,7 +254,9 @@ void PubSend::doSend() dupFlagsField.setBitValue(DupFlags::BitIdx_bit, dup); msg.field_topicId().value() = m_currTopicInfo.m_topicId; msg.field_msgId().value() = m_currMsgId; - msg.field_data().value() = m_currPub->m_msg; + auto& dataStorage = msg.field_data().value(); + using DataStorage = typename std::decay::type; + msg.field_data().value() = DataStorage(&(*m_currPub->m_msg.begin()), m_currPub->m_msg.size()); sendToClient(msg); if (m_currPub->m_qos == QoS_AtMostOnceDelivery) { diff --git a/gateway/src/lib/session_op/WillUpdate.cpp b/gateway/src/lib/session_op/WillUpdate.cpp index 714bcb4..38ab1e0 100644 --- a/gateway/src/lib/session_op/WillUpdate.cpp +++ b/gateway/src/lib/session_op/WillUpdate.cpp @@ -102,7 +102,8 @@ void WillUpdate::handle(WilltopicupdMsg_SN& msg) bool retain = midFlagsField.getBitValue(MidFlags::BitIdx_retain); auto& st = state(); - if ((st.m_will.m_topic == msg.field_willTopic().value()) && + auto& willTopic = msg.field_willTopic().value(); + if ((st.m_will.m_topic == willTopic) && (st.m_will.m_qos == qos) && (st.m_will.m_retain == retain)) { sendTopicResp(mqttsn::protocol::field::ReturnCodeVal_Accepted); @@ -110,8 +111,7 @@ void WillUpdate::handle(WilltopicupdMsg_SN& msg) return; } - - m_will.m_topic = msg.field_willTopic().value(); + m_will.m_topic.assign(willTopic.begin(), willTopic.end()); m_will.m_msg = st.m_will.m_msg; m_will.m_qos = qos; m_will.m_retain = retain; @@ -137,14 +137,17 @@ void WillUpdate::handle(WillmsgupdMsg_SN& msg) } auto& st = state(); - if (st.m_will.m_msg == msg.field_willMsg().value()) { + auto& willData = msg.field_willMsg().value(); + using WillDataStorage = typename std::decay::type; + WillDataStorage storedDataView(&(*st.m_will.m_msg.begin()), st.m_will.m_msg.size()); + if (storedDataView == willData) { sendMsgResp(mqttsn::protocol::field::ReturnCodeVal_Accepted); sendToBroker(PingreqMsg()); return; } m_will.m_topic = st.m_will.m_topic; - m_will.m_msg = msg.field_willMsg().value(); + m_will.m_msg.assign(willData.begin(), willData.end()); m_will.m_qos = st.m_will.m_qos; m_will.m_retain = st.m_will.m_retain; startOp(Op::MsgUpd); diff --git a/protocol/include/mqttsn/protocol/MsgSizeLayer.h b/protocol/include/mqttsn/protocol/MsgSizeLayer.h index 41e4119..de97d56 100644 --- a/protocol/include/mqttsn/protocol/MsgSizeLayer.h +++ b/protocol/include/mqttsn/protocol/MsgSizeLayer.h @@ -90,9 +90,19 @@ enum LengthFieldIdx }; template -class MsgSizeLayer : public comms::protocol::ProtocolLayerBase +class MsgSizeLayer : public + comms::protocol::ProtocolLayerBase< + LengthField, + TNextLayer, + MsgSizeLayer + > { - typedef comms::protocol::ProtocolLayerBase Base; + typedef + comms::protocol::ProtocolLayerBase< + LengthField, + TNextLayer, + MsgSizeLayer + > Base; public: typedef typename Base::MsgPtr MsgPtr; @@ -100,97 +110,14 @@ class MsgSizeLayer : public comms::protocol::ProtocolLayerBase - comms::ErrorStatus read( - TMsgPtr& msgPtr, - TIter& iter, - std::size_t size, - std::size_t* missingSize = nullptr) - { - Field field; - return - readInternal( - field, - msgPtr, - iter, - size, - missingSize, - Base::createNextLayerReader()); - } - - template - comms::ErrorStatus readFieldsCached( - TAllFields& allFields, - TMsgPtr& msgPtr, - TIter& iter, - std::size_t size, - std::size_t* missingSize = nullptr) - { - auto& field = Base::template getField(allFields); - - return - readInternal( - field, - msgPtr, - iter, - size, - missingSize, - Base::template createNextLayerCachedFieldsReader(allFields)); - } - - template - comms::ErrorStatus write( - const TMsg& msg, - TIter& iter, - std::size_t size) const - { - Field field; - return writeInternal(field, msg, iter, size, Base::createNextLayerWriter()); - } - - template - comms::ErrorStatus writeFieldsCached( - TAllFields& allFields, - const TMsg& msg, - TIter& iter, - std::size_t size) const - { - auto& field = Base::template getField(allFields); - return - writeInternal( - field, - msg, - iter, - size, - Base::template createNextLayerCachedFieldsWriter(allFields)); - } - - constexpr std::size_t length() const - { - return ShortLengthField::minLength() + Base::nextLayer().length(); - } - - template - std::size_t length(const TMsg& msg) const - { - auto minLen = ShortLengthField::minLength() + Base::nextLayer().length(msg); - if (minLen <= std::numeric_limits::max()) { - return minLen; - } - - return minLen + sizeof(std::uint16_t); - } - -private: - - template - comms::ErrorStatus readInternal( + template + comms::ErrorStatus doRead( Field& field, TMsgPtr& msgPtr, TIter& iter, std::size_t size, std::size_t* missingSize, - TReader&& reader) + TNextLayerReader&& nextLayerReader) { typedef typename std::decay::type IterType; typedef typename std::iterator_traits::iterator_category IterTag; @@ -226,7 +153,7 @@ class MsgSizeLayer : public comms::protocol::ProtocolLayerBase - comms::ErrorStatus writeInternal( + template + comms::ErrorStatus doWrite( Field& field, const TMsg& msg, TIter& iter, std::size_t size, - TWriter&& nextLayerWriter) const + TNextLayerWriter&& nextLayerWriter) const { auto writeLength = Base::nextLayer().length(msg); auto& members = field.value(); @@ -279,6 +206,22 @@ class MsgSizeLayer : public comms::protocol::ProtocolLayerBase + std::size_t length(const TMsg& msg) const + { + auto minLen = ShortLengthField::minLength() + Base::nextLayer().length(msg); + if (minLen <= std::numeric_limits::max()) { + return minLen; + } + + return minLen + sizeof(std::uint16_t); + } }; } // namespace protocol diff --git a/protocol/include/mqttsn/protocol/details/OptionsParser.h b/protocol/include/mqttsn/protocol/details/OptionsParser.h index 26445b9..76f4995 100644 --- a/protocol/include/mqttsn/protocol/details/OptionsParser.h +++ b/protocol/include/mqttsn/protocol/details/OptionsParser.h @@ -44,6 +44,7 @@ class OptionsParser<> static const bool HasMessageDataStaticStorageSize = false; static const bool ClientOnlyVariant = false; static const bool GatewayOnlyVariant = false; + static const bool HasOrigDataView = false; }; template @@ -108,6 +109,15 @@ class OptionsParser< static const bool GatewayOnlyVariant = true; }; +template +class OptionsParser< + option::UseOrigDataView, + TOptions...> : public OptionsParser +{ +public: + static const bool HasOrigDataView = true; +}; + template class OptionsParser< std::tuple, diff --git a/protocol/include/mqttsn/protocol/field.h b/protocol/include/mqttsn/protocol/field.h index 51ac0ba..2348f96 100644 --- a/protocol/include/mqttsn/protocol/field.h +++ b/protocol/include/mqttsn/protocol/field.h @@ -41,25 +41,45 @@ using ClientId = >; -template -struct ClientIdExtraOpts; +template +struct ClientIdExtraOptsStaticStorage; -template -struct ClientIdExtraOpts +template <> +struct ClientIdExtraOptsStaticStorage { - typedef comms::option::FixedSizeStorage Type; + template + using Type = comms::option::FixedSizeStorage; }; -template -struct ClientIdExtraOpts +template <> +struct ClientIdExtraOptsStaticStorage +{ + template + using Type = comms::option::EmptyOption; +}; + +template +struct ClientIdExtraOptsDataView; + +template <> +struct ClientIdExtraOptsDataView { - typedef comms::option::EmptyOption Type; + template + using Type = comms::option::OrigDataView; +}; + +template <> +struct ClientIdExtraOptsDataView +{ + template + using Type = + typename ClientIdExtraOptsStaticStorage:: + template Type; }; template using ClientIdExtraOptsT = - typename ClientIdExtraOpts::Type; - + typename ClientIdExtraOptsDataView:: template Type; template using GwAdd = @@ -69,46 +89,88 @@ using GwAdd = TExtraOpt... >; -template -struct GwAddExtraOpts; +template +struct GwAddExtraOptsStaticStorage; -template -struct GwAddExtraOpts +template <> +struct GwAddExtraOptsStaticStorage { - typedef comms::option::FixedSizeStorage Type; + template + using Type = comms::option::FixedSizeStorage; }; -template -struct GwAddExtraOpts +template <> +struct GwAddExtraOptsStaticStorage +{ + template + using Type = comms::option::EmptyOption; +}; + +template +struct GwAddExtraOptsDataView; + +template <> +struct GwAddExtraOptsDataView +{ + template + using Type = comms::option::OrigDataView; +}; + +template <> +struct GwAddExtraOptsDataView { - typedef comms::option::EmptyOption Type; + template + using Type = + typename GwAddExtraOptsStaticStorage:: + template Type; }; template using GwAddExtraOptsT = - typename GwAddExtraOpts::Type; + typename GwAddExtraOptsDataView::template Type; template using TopicName = comms::field::String; -template -struct TopicNameExtraOpts; +template +struct TopicNameExtraOptsStaticStorage; -template -struct TopicNameExtraOpts +template <> +struct TopicNameExtraOptsStaticStorage { - typedef comms::option::FixedSizeStorage Type; + template + using Type = comms::option::FixedSizeStorage; }; -template -struct TopicNameExtraOpts +template <> +struct TopicNameExtraOptsStaticStorage +{ + template + using Type = comms::option::EmptyOption; +}; + +template +struct TopicNameExtraOptsDataView; + +template <> +struct TopicNameExtraOptsDataView { - typedef comms::option::EmptyOption Type; + template + using Type = comms::option::OrigDataView; +}; + +template <> +struct TopicNameExtraOptsDataView +{ + template + using Type = + typename TopicNameExtraOptsStaticStorage:: + template Type; }; template using TopicNameExtraOptsT = - typename TopicNameExtraOpts::Type; + typename TopicNameExtraOptsDataView::template Type; template using WillTopic = comms::field::String; @@ -121,24 +183,46 @@ using Data = TExtraOpt... >; -template -struct DataExtraOpts; +template +struct DataExtraOptsStaticStorage; -template -struct DataExtraOpts +template <> +struct DataExtraOptsStaticStorage { - typedef comms::option::FixedSizeStorage Type; + template + using Type = comms::option::FixedSizeStorage; }; -template -struct DataExtraOpts +template <> +struct DataExtraOptsStaticStorage +{ + template + using Type = comms::option::EmptyOption; +}; + +template +struct DataExtraOptsDataView; + +template <> +struct DataExtraOptsDataView { - typedef comms::option::EmptyOption Type; + template + using Type = comms::option::OrigDataView; }; +template <> +struct DataExtraOptsDataView +{ + template + using Type = + typename DataExtraOptsStaticStorage:: + template Type; +}; + + template using DataExtraOptsT = - typename DataExtraOpts::Type; + typename DataExtraOptsDataView::template Type; template using WillMsg = diff --git a/protocol/include/mqttsn/protocol/message/SubUnsubBase.h b/protocol/include/mqttsn/protocol/message/SubUnsubBase.h index 8e87443..e48b452 100644 --- a/protocol/include/mqttsn/protocol/message/SubUnsubBase.h +++ b/protocol/include/mqttsn/protocol/message/SubUnsubBase.h @@ -145,6 +145,9 @@ class SubUnsubBase : public return refreshed; } + +protected: + ~SubUnsubBase() noexcept = default; }; } // namespace message diff --git a/protocol/include/mqttsn/protocol/message/WilltopicBase.h b/protocol/include/mqttsn/protocol/message/WilltopicBase.h index 8db681e..b31b290 100644 --- a/protocol/include/mqttsn/protocol/message/WilltopicBase.h +++ b/protocol/include/mqttsn/protocol/message/WilltopicBase.h @@ -123,6 +123,9 @@ class WilltopicBase : public return refreshed; } + +protected: + ~WilltopicBase() noexcept = default; }; } // namespace message diff --git a/protocol/include/mqttsn/protocol/option.h b/protocol/include/mqttsn/protocol/option.h index d33b307..7f5af3e 100644 --- a/protocol/include/mqttsn/protocol/option.h +++ b/protocol/include/mqttsn/protocol/option.h @@ -56,6 +56,8 @@ struct ClientOnlyVariant {}; struct GatewayOnlyVariant {}; +struct UseOrigDataView {}; + } // namespace option } // namespace protocol