From 6725e351bf3d63df4b8bf194a9a0064b1a2f446e Mon Sep 17 00:00:00 2001 From: Iker Luengo Date: Tue, 7 Jan 2020 14:18:19 +0100 Subject: [PATCH] size limit on PartitionQosPolicy --- include/fastrtps/qos/QosPolicies.h | 242 +++++++++++++++++- .../RTPSParticipantAllocationAttributes.hpp | 2 + .../fastrtps/rtps/common/SerializedPayload.h | 7 + include/fastrtps/xmlparser/XMLParserCommon.h | 1 + resources/xsd/fastRTPS_profiles.xsd | 1 + src/cpp/qos/QosPolicies.cpp | 67 +++-- src/cpp/rtps/builtin/data/ReaderProxyData.cpp | 3 + src/cpp/rtps/builtin/data/WriterProxyData.cpp | 3 + .../rtps/builtin/discovery/endpoint/EDP.cpp | 48 ++-- src/cpp/xmlparser/XMLElementParser.cpp | 10 + src/cpp/xmlparser/XMLParserCommon.cpp | 1 + 11 files changed, 324 insertions(+), 61 deletions(-) diff --git a/include/fastrtps/qos/QosPolicies.h b/include/fastrtps/qos/QosPolicies.h index 0a47961468d..94cd00c2798 100644 --- a/include/fastrtps/qos/QosPolicies.h +++ b/include/fastrtps/qos/QosPolicies.h @@ -601,7 +601,7 @@ class UserDataQosPolicy : public Parameter_t, public QosPolicy } /** - * @return the maximuim size of the user data + * @return the maximum size of the user data */ size_t max_size () const { @@ -798,6 +798,52 @@ class PresentationQosPolicy : public Parameter_t, public QosPolicy }; + +class Partition_t { + + friend class PartitionQosPolicy; + + +private: + + const char* partition_; + +private: + Partition_t() + { + partition_ = nullptr; + } + +public: + explicit Partition_t(const void* ptr) + { + partition_ = (char*)ptr; + } + + bool operator ==( + const Partition_t& rhs) const + { + return (size() == rhs.size() && + (size() == 0 || strcmp(partition_ + 4, rhs.partition_ + 4))); + } + + bool operator !=( + const Partition_t& rhs) const + { + return !(*this == rhs); + } + + size_t size() const + { + return *(uint32_t*)partition_; + } + + const char* name() const + { + return partition_ + 4; + } +}; + /** * Class PartitionQosPolicy, to indicate the Partition Qos. */ @@ -806,22 +852,104 @@ class PartitionQosPolicy : public Parameter_t, public QosPolicy friend class ParameterList; friend class rtps::EDP; +public: + + class const_iterator + { + public: + typedef const_iterator self_type; + typedef const Partition_t value_type; + typedef const Partition_t reference; + typedef const Partition_t* pointer; + typedef size_t difference_type; + typedef std::forward_iterator_tag iterator_category; + + const_iterator(const rtps::octet* ptr) + : ptr_(ptr) + , value_ (ptr_) + { } + + self_type operator++() + { + self_type tmp = *this; + advance(); + return tmp; + } + + self_type operator++(int) + { + advance(); + return *this; + } + + reference operator*() + { + return value_; + } + + pointer operator->() + { + return &value_; + } + + bool operator==(const self_type& rhs) + { + return ptr_ == rhs.ptr_; + } + + bool operator!=(const self_type& rhs) + { + return ptr_ != rhs.ptr_; + } + + protected: + + void advance() + { + //Size of the element (with alignment) + uint32_t size = *(uint32_t*)ptr_; + ptr_ += (4 + ((size + 3) & ~3)); + value_ = Partition_t(ptr_); + } + + private: + const rtps::octet* ptr_; + Partition_t value_; + + }; + public: RTPS_DllAPI PartitionQosPolicy() : Parameter_t(PID_PARTITION, 0) , QosPolicy(false) - , names{} + , max_size_ (0) + , Npartitions_ (0) { } RTPS_DllAPI PartitionQosPolicy(uint16_t in_length) : Parameter_t(PID_PARTITION, in_length) , QosPolicy(false) - , names{} + , max_size_ (in_length) + , partitions_(in_length) + , Npartitions_ (0) + { + } + + RTPS_DllAPI PartitionQosPolicy(const PartitionQosPolicy& b) + : Parameter_t(b) + , QosPolicy(b) + , max_size_ (b.max_size_) + , partitions_(b.max_size_ != 0 ? + b.partitions_.max_size : + b.partitions_.length) + , Npartitions_ (b.Npartitions_) { + partitions_.copy(&b.partitions_, b.max_size_ != 0); } + virtual RTPS_DllAPI ~PartitionQosPolicy() { } @@ -829,9 +957,57 @@ class PartitionQosPolicy : public Parameter_t, public QosPolicy bool operator ==( const PartitionQosPolicy& b) const { - return (this->names == b.names) && - Parameter_t::operator ==(b) && - QosPolicy::operator ==(b); + return (this->max_size_ == b.max_size_) && + (this->Npartitions_ == b.Npartitions_) && + (this->partitions_ == b.partitions_) && + Parameter_t::operator==(b) && + QosPolicy::operator==(b); + } + + PartitionQosPolicy& operator =( + const PartitionQosPolicy& b) + { + length = b.length; + max_size_ = b.max_size_; + partitions_.reserve(max_size_ != 0 ? + b.partitions_.max_size : + b.partitions_.length); + partitions_.copy(&b.partitions_, b.max_size_ != 0); + Npartitions_ = b.Npartitions_; + hasChanged = true; + + return *this; + } + + const_iterator begin() const + { + return const_iterator(partitions_.data); + } + + const_iterator end() const + { + return const_iterator(partitions_.data + partitions_.length); + } + + size_t size() const + { + return Npartitions_; + } + + size_t empty() const + { + return Npartitions_ == 0; + } + + void max_size (size_t size) + { + partitions_.reserve(size); + max_size_ = size; + } + + size_t max_size () + { + return max_size_; } /** @@ -856,7 +1032,33 @@ class PartitionQosPolicy : public Parameter_t, public QosPolicy RTPS_DllAPI inline void push_back( const char* name) { - names.push_back(std::string(name)); hasChanged = true; + //Realloc if needed; + uint32_t size = strlen(name)+1; + uint32_t alignment = ((size + 3) & ~3) - size; + + if (max_size_ != 0 && (partitions_.max_size < partitions_.length + + size + alignment + 4)) + { + return; + } + + partitions_.reserve(partitions_.length + + size + alignment + 4); + + rtps::octet* o = (rtps::octet*)&size; + memcpy(partitions_.data + partitions_.length, + o, 4); + partitions_.length += 4; + + memcpy(partitions_.data + partitions_.length, + name, size); + partitions_.length += size; + + memset(partitions_.data + partitions_.length, 0, alignment); + partitions_.length += alignment; + + ++Npartitions_; + hasChanged = true; } /** @@ -864,15 +1066,25 @@ class PartitionQosPolicy : public Parameter_t, public QosPolicy */ RTPS_DllAPI inline void clear() { - names.clear(); + partitions_.length = 0; + Npartitions_ = 0; + hasChanged = true; } /** * Returns partition names. * @return Vector of partition name strings. */ - RTPS_DllAPI inline std::vector getNames() const + RTPS_DllAPI inline const std::vector getNames() const { + std::vector names; + if (Npartitions_ > 0) + { + for (auto it = begin(); it != end(); ++it) + { + names.push_back(it->name()); + } + } return names; } @@ -883,12 +1095,18 @@ class PartitionQosPolicy : public Parameter_t, public QosPolicy RTPS_DllAPI inline void setNames( std::vector& nam) { - names = nam; hasChanged = true; + clear(); + for (auto it = nam.begin(); it != nam.end(); ++it) + { + push_back(it->c_str()); + } + hasChanged = true; } private: - - std::vector names; + uint32_t max_size_; + rtps::SerializedPayload_t partitions_; + size_t Npartitions_; }; diff --git a/include/fastrtps/rtps/attributes/RTPSParticipantAllocationAttributes.hpp b/include/fastrtps/rtps/attributes/RTPSParticipantAllocationAttributes.hpp index 2cb173bb7f5..45ae1478eb9 100644 --- a/include/fastrtps/rtps/attributes/RTPSParticipantAllocationAttributes.hpp +++ b/include/fastrtps/rtps/attributes/RTPSParticipantAllocationAttributes.hpp @@ -81,6 +81,8 @@ struct VariableLengthDataLimits size_t max_properties = 0; //! Defines the maximum size (in octets) of user data in the local or remote participant size_t max_user_data = 0; + //! Defines the maximum size (in octets) of partitions data + size_t max_partitions = 0; }; /** diff --git a/include/fastrtps/rtps/common/SerializedPayload.h b/include/fastrtps/rtps/common/SerializedPayload.h index 9a0b71ec11a..a98096ac6e5 100644 --- a/include/fastrtps/rtps/common/SerializedPayload.h +++ b/include/fastrtps/rtps/common/SerializedPayload.h @@ -78,6 +78,13 @@ namespace eprosima{ this->empty(); } + bool operator== (const SerializedPayload_t& other) const + { + return ((encapsulation == other.encapsulation) && + (length == other.length) && + (memcmp(data, other.data, length))); + } + /*! * Copy another structure (including allocating new space for the data.) * @param[in] serData Pointer to the structure to copy diff --git a/include/fastrtps/xmlparser/XMLParserCommon.h b/include/fastrtps/xmlparser/XMLParserCommon.h index fbe2877bd4d..62670acea23 100644 --- a/include/fastrtps/xmlparser/XMLParserCommon.h +++ b/include/fastrtps/xmlparser/XMLParserCommon.h @@ -120,6 +120,7 @@ extern const char* PREALLOCATED_NUMBER; extern const char* DYNAMIC_LC; extern const char* MAX_PROPERTIES; extern const char* MAX_USER_DATA; +extern const char* MAX_PARTITIONS; /// Publisher-subscriber attributes extern const char* TOPIC; diff --git a/resources/xsd/fastRTPS_profiles.xsd b/resources/xsd/fastRTPS_profiles.xsd index 88cd98c0327..18f2e4026ed 100644 --- a/resources/xsd/fastRTPS_profiles.xsd +++ b/resources/xsd/fastRTPS_profiles.xsd @@ -399,6 +399,7 @@ + diff --git a/src/cpp/qos/QosPolicies.cpp b/src/cpp/qos/QosPolicies.cpp index deb13e47cc0..0e1a71398a5 100644 --- a/src/cpp/qos/QosPolicies.cpp +++ b/src/cpp/qos/QosPolicies.cpp @@ -215,59 +215,76 @@ bool PartitionQosPolicy::addToCDRMessage(CDRMessage_t* msg) { bool valid = CDRMessage::addUInt16(msg, this->Pid); //Obtain Length: - this->length = 0; - this->length += 4; - uint16_t rest; - for(std::vector::iterator it = names.begin();it!=names.end();++it) + uint16_t pos_str = (uint16_t)msg->pos; + valid &= CDRMessage::addUInt16(msg, this->length);//this->length); + valid &= CDRMessage::addUInt32(msg,(uint32_t)this->size()); + + for(PartitionQosPolicy::const_iterator it = this->begin(); + it != this->end(); ++it) { - this->length +=4; - this->length += (uint16_t)it->size()+1; - rest = ((uint16_t)it->size() +1 ) % 4; - this->length += rest != 0 ? 4 - rest : 0; + uint32_t size = it->size(); //Already accounts for null char + valid &= CDRMessage::addUInt32(msg,size); + valid &= CDRMessage::addData(msg,(unsigned char*)it->name(),size); + uint32_t align = ((size + 3) & ~3) - size; + for(uint32_t count = 0; count < align; ++count) + { + valid &= CDRMessage::addOctet(msg, 0); + } } + + uint16_t pos_param_end = (uint16_t)msg->pos; + this->length = pos_param_end-pos_str-2; + msg->pos = pos_str; valid &= CDRMessage::addUInt16(msg, this->length); - valid &= CDRMessage::addUInt32(msg,(uint32_t)this->names.size()); - for(std::vector::iterator it = names.begin();it!=names.end();++it) - valid &= CDRMessage::addString(msg,*it); - //valid &= CDRMessage::addOctetVector(msg,&name); + msg->pos = pos_param_end; + msg->length-=2; + return valid; } bool PartitionQosPolicy::readFromCDRMessage(CDRMessage_t* msg, uint32_t size) { - (void) size; - uint32_t namessize = 0; - bool valid = CDRMessage::readUInt32(msg, &namessize); - if (!valid) + if (max_size_ != 0 && partitions_.max_size < size - 4) { return false; } - for (uint32_t i = 1; i <= namessize; ++i) + + uint32_t num_partitions; + bool valid = CDRMessage::readUInt32(msg, &num_partitions); + partitions_.reserve(size - 4); + + for(size_t i = 0; i < num_partitions; ++i) { - std::string auxstr; - valid &= CDRMessage::readString(msg, &auxstr); + uint32_t size, alignment; + + valid &= CDRMessage::readUInt32(msg,&size); if (!valid) { return false; } - names.push_back(auxstr); - } + push_back ((const char*)&msg->buffer[msg->pos]); + alignment = ((size + 3) & ~3) - size; + msg->pos += (size + alignment); + } + Npartitions_ = num_partitions; return valid; } bool UserDataQosPolicy::addToCDRMessage(CDRMessage_t* msg) { bool valid = CDRMessage::addUInt16(msg, this->Pid); - uint32_t align = (4 - (msg->pos + 6 + dataVec_.size()) % 4) & 3; //align - this->length = (uint16_t)(4 + this->dataVec_.size() + align); + uint32_t size = dataVec_.size(); + uint32_t align = ((size + 3) & ~3) - size; + this->length = (uint16_t)(4 + size + align); valid &= CDRMessage::addUInt16(msg, this->length); - valid &= CDRMessage::addUInt32(msg, (uint32_t)this->dataVec_.size()); - valid &= CDRMessage::addData(msg,this->dataVec_.data(),(uint32_t)this->dataVec_.size()); + valid &= CDRMessage::addUInt32(msg, size); + valid &= CDRMessage::addData(msg,this->dataVec_.data(),size); for(uint32_t count = 0; count < align; ++count) { valid &= CDRMessage::addOctet(msg, 0); } + return valid; } diff --git a/src/cpp/rtps/builtin/data/ReaderProxyData.cpp b/src/cpp/rtps/builtin/data/ReaderProxyData.cpp index d695c9cf490..5cac469926e 100644 --- a/src/cpp/rtps/builtin/data/ReaderProxyData.cpp +++ b/src/cpp/rtps/builtin/data/ReaderProxyData.cpp @@ -60,6 +60,7 @@ ReaderProxyData::ReaderProxyData ( : ReaderProxyData(max_unicast_locators, max_multicast_locators) { m_qos.m_userData.max_size(data_limits.max_user_data); + m_qos.m_partition.max_size(data_limits.max_partitions); } ReaderProxyData::~ReaderProxyData() @@ -836,8 +837,10 @@ void ReaderProxyData::clear() m_topicKind = NO_KEY; //clear user data but keep max size on qos size_t max_user_data = m_qos.m_userData.max_size(); + size_t max_partitions = m_qos.m_partition.max_size(); m_qos = ReaderQos(); m_qos.m_userData.max_size(max_user_data); + m_qos.m_partition.max_size(max_partitions); m_topicDiscoveryKind = NO_CHECK; if (m_type_id) { diff --git a/src/cpp/rtps/builtin/data/WriterProxyData.cpp b/src/cpp/rtps/builtin/data/WriterProxyData.cpp index d129425d6cd..3e941ac3086 100644 --- a/src/cpp/rtps/builtin/data/WriterProxyData.cpp +++ b/src/cpp/rtps/builtin/data/WriterProxyData.cpp @@ -64,6 +64,7 @@ WriterProxyData::WriterProxyData( : WriterProxyData(max_unicast_locators, max_multicast_locators) { m_qos.m_userData.max_size(data_limits.max_user_data); + m_qos.m_partition.max_size(data_limits.max_partitions); } WriterProxyData::WriterProxyData( @@ -841,8 +842,10 @@ void WriterProxyData::clear() m_userDefinedId = 0; //clear user data but keep max size on qos size_t max_user_data = m_qos.m_userData.max_size(); + size_t max_partition = m_qos.m_partition.max_size(); m_qos = WriterQos(); m_qos.m_userData.max_size(max_user_data); + m_qos.m_partition.max_size(max_partition); m_typeMaxSerialized = 0; m_topicKind = NO_KEY; persistence_guid_ = c_Guid_Unknown; diff --git a/src/cpp/rtps/builtin/discovery/endpoint/EDP.cpp b/src/cpp/rtps/builtin/discovery/endpoint/EDP.cpp index 93ea1e9647c..f346017d1c5 100644 --- a/src/cpp/rtps/builtin/discovery/endpoint/EDP.cpp +++ b/src/cpp/rtps/builtin/discovery/endpoint/EDP.cpp @@ -536,14 +536,14 @@ bool EDP::validMatching( //Partition check: bool matched = false; - if(wdata->m_qos.m_partition.names.empty() && rdata->m_qos.m_partition.names.empty()) + if(wdata->m_qos.m_partition.empty() && rdata->m_qos.m_partition.empty()) { matched = true; } - else if(wdata->m_qos.m_partition.names.empty() && rdata->m_qos.m_partition.names.size()>0) + else if(wdata->m_qos.m_partition.empty() && rdata->m_qos.m_partition.size()>0) { - for(std::vector::const_iterator rnameit = rdata->m_qos.m_partition.names.begin(); - rnameit!=rdata->m_qos.m_partition.names.end();++rnameit) + for(auto rnameit = rdata->m_qos.m_partition.begin(); + rnameit!=rdata->m_qos.m_partition.end();++rnameit) { if(rnameit->size()==0) { @@ -552,10 +552,10 @@ bool EDP::validMatching( } } } - else if(wdata->m_qos.m_partition.names.size()>0 && rdata->m_qos.m_partition.names.empty() ) + else if(wdata->m_qos.m_partition.size()>0 && rdata->m_qos.m_partition.empty() ) { - for(std::vector::const_iterator wnameit = wdata->m_qos.m_partition.names.begin(); - wnameit != wdata->m_qos.m_partition.names.end();++wnameit) + for(auto wnameit = wdata->m_qos.m_partition.begin(); + wnameit != wdata->m_qos.m_partition.end();++wnameit) { if(wnameit->size()==0) { @@ -566,13 +566,13 @@ bool EDP::validMatching( } else { - for(std::vector::const_iterator wnameit = wdata->m_qos.m_partition.names.begin(); - wnameit != wdata->m_qos.m_partition.names.end();++wnameit) + for(auto wnameit = wdata->m_qos.m_partition.begin(); + wnameit != wdata->m_qos.m_partition.end();++wnameit) { - for(std::vector::const_iterator rnameit = rdata->m_qos.m_partition.names.begin(); - rnameit!=rdata->m_qos.m_partition.names.end();++rnameit) + for(auto rnameit = rdata->m_qos.m_partition.begin(); + rnameit!=rdata->m_qos.m_partition.end();++rnameit) { - if(StringMatching::matchString(wnameit->c_str(),rnameit->c_str())) + if(StringMatching::matchString(wnameit->name(),rnameit->name())) { matched = true; break; @@ -662,14 +662,14 @@ bool EDP::validMatching( //Partition check: bool matched = false; - if(rdata->m_qos.m_partition.names.empty() && wdata->m_qos.m_partition.names.empty()) + if(rdata->m_qos.m_partition.empty() && wdata->m_qos.m_partition.empty()) { matched = true; } - else if(rdata->m_qos.m_partition.names.empty() && wdata->m_qos.m_partition.names.size()>0) + else if(rdata->m_qos.m_partition.empty() && wdata->m_qos.m_partition.size()>0) { - for(std::vector::const_iterator rnameit = wdata->m_qos.m_partition.names.begin(); - rnameit!=wdata->m_qos.m_partition.names.end();++rnameit) + for(auto rnameit = wdata->m_qos.m_partition.begin(); + rnameit!=wdata->m_qos.m_partition.end();++rnameit) { if(rnameit->size()==0) { @@ -678,10 +678,10 @@ bool EDP::validMatching( } } } - else if(rdata->m_qos.m_partition.names.size()>0 && wdata->m_qos.m_partition.names.empty() ) + else if(rdata->m_qos.m_partition.size()>0 && wdata->m_qos.m_partition.empty() ) { - for(std::vector::const_iterator wnameit = rdata->m_qos.m_partition.names.begin(); - wnameit != rdata->m_qos.m_partition.names.end();++wnameit) + for(auto wnameit = rdata->m_qos.m_partition.begin(); + wnameit != rdata->m_qos.m_partition.end();++wnameit) { if(wnameit->size()==0) { @@ -692,13 +692,13 @@ bool EDP::validMatching( } else { - for(std::vector::const_iterator wnameit = rdata->m_qos.m_partition.names.begin(); - wnameit != rdata->m_qos.m_partition.names.end();++wnameit) + for(auto wnameit = rdata->m_qos.m_partition.begin(); + wnameit != rdata->m_qos.m_partition.end();++wnameit) { - for(std::vector::const_iterator rnameit = wdata->m_qos.m_partition.names.begin(); - rnameit!=wdata->m_qos.m_partition.names.end();++rnameit) + for(auto rnameit = wdata->m_qos.m_partition.begin(); + rnameit!=wdata->m_qos.m_partition.end();++rnameit) { - if(StringMatching::matchString(wnameit->c_str(),rnameit->c_str())) + if(StringMatching::matchString(wnameit->name(),rnameit->name())) { matched = true; break; diff --git a/src/cpp/xmlparser/XMLElementParser.cpp b/src/cpp/xmlparser/XMLElementParser.cpp index db65398e3a4..3762eed5704 100644 --- a/src/cpp/xmlparser/XMLElementParser.cpp +++ b/src/cpp/xmlparser/XMLElementParser.cpp @@ -40,6 +40,7 @@ XMLP_ret XMLParser::getXMLParticipantAllocationAttributes( + */ @@ -108,6 +109,15 @@ XMLP_ret XMLParser::getXMLParticipantAllocationAttributes( } allocation.data_limits.max_user_data = tmp; } + else if (strcmp(name, MAX_PARTITIONS) == 0) + { + // max number of user data in incomming message - uint32Type + if (XMLP_ret::XML_OK != getXMLUint(p_aux0, &tmp, ident)) + { + return XMLP_ret::XML_ERROR; + } + allocation.data_limits.max_partitions = tmp; + } else { logError(XMLPARSER, "Invalid element found into 'rtpsParticipantAllocationAttributesType'. Name: " << name); diff --git a/src/cpp/xmlparser/XMLParserCommon.cpp b/src/cpp/xmlparser/XMLParserCommon.cpp index a33bc633fc1..8638a3383f1 100644 --- a/src/cpp/xmlparser/XMLParserCommon.cpp +++ b/src/cpp/xmlparser/XMLParserCommon.cpp @@ -102,6 +102,7 @@ const char* PREALLOCATED_NUMBER = "preallocated_number"; const char* DYNAMIC_LC = "dynamic"; const char* MAX_PROPERTIES = "max_properties"; const char* MAX_USER_DATA = "max_user_data"; +const char* MAX_PARTITIONS = "max_partitions"; /// Publisher-subscriber attributes const char* TOPIC = "topic";