diff --git a/third-party/realdds/include/realdds/topics/blob-msg.h b/third-party/realdds/include/realdds/topics/blob-msg.h new file mode 100644 index 00000000000..f127a7a85ed --- /dev/null +++ b/third-party/realdds/include/realdds/topics/blob-msg.h @@ -0,0 +1,86 @@ +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright(c) 2023 Intel Corporation. All Rights Reserved. +#pragma once + +#include "blob/blob.h" +#include + +#include +#include +#include + + +namespace eprosima { +namespace fastdds { +namespace dds { +struct SampleInfo; +} +} // namespace fastdds +} // namespace eprosima + + +namespace udds { +class blobPubSubType; +} // namespace raw + + +namespace realdds { + + +class dds_participant; +class dds_topic; +class dds_topic_reader; +class dds_topic_writer; + + +namespace topics { + + +class blob_msg : public udds::blob +{ +public: + using type = udds::blobPubSubType; + + blob_msg() = default; + blob_msg( std::vector< uint8_t > && data_ ) { data( std::move( data_ ) ); } + + bool is_valid() const { return ! data().empty(); } + void invalidate() { data().clear(); } + + static std::shared_ptr< dds_topic > create_topic( std::shared_ptr< dds_participant > const & participant, + char const * topic_name ); + static std::shared_ptr< dds_topic > create_topic( std::shared_ptr< dds_participant > const & participant, + std::string const & topic_name ) + { + return create_topic( participant, topic_name.c_str() ); + } + + // This helper method will take the next sample from a reader. + // + // Returns true if successful. Make sure you still check is_valid() in case the sample info isn't! + // Returns false if no more data is available. + // Will throw if an unexpected error occurs. + // + static bool take_next( dds_topic_reader &, + blob_msg * output, + eprosima::fastdds::dds::SampleInfo * optional_info = nullptr ); + + // Returns some unique (to the writer) identifier for the sample that was sent, or 0 if unsuccessful + dds_sequence_number write_to( dds_topic_writer & ) const; + + // Cast the raw data to the desired type + template< typename T > + T const * custom_data() const + { + return data().size() > 0 ? reinterpret_cast< T const * >( data().data() ) : nullptr; + } + template< typename T > + T * custom_data() + { + return data().size() > 0 ? reinterpret_cast< T * >( data().data() ) : nullptr; + } +}; + + +} // namespace topics +} // namespace realdds diff --git a/third-party/realdds/include/realdds/topics/blob/blob.h b/third-party/realdds/include/realdds/topics/blob/blob.h new file mode 100644 index 00000000000..697f36353d1 --- /dev/null +++ b/third-party/realdds/include/realdds/topics/blob/blob.h @@ -0,0 +1,205 @@ +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright(c) 2023 Intel Corporation. All Rights Reserved. + +/*! + * @file blob.h + * This header file contains the declaration of the described types in the IDL file. + * + * This file was generated by the tool gen. + */ + +#ifndef _FAST_DDS_GENERATED_UDDS_BLOB_H_ +#define _FAST_DDS_GENERATED_UDDS_BLOB_H_ + + +//#include + +#include +#include +#include +#include +#include +#include + +#if defined(_WIN32) +#if defined(EPROSIMA_USER_DLL_EXPORT) +#define eProsima_user_DllExport __declspec( dllexport ) +#else +#define eProsima_user_DllExport +#endif // EPROSIMA_USER_DLL_EXPORT +#else +#define eProsima_user_DllExport +#endif // _WIN32 + +#if defined(_WIN32) +#if defined(EPROSIMA_USER_DLL_EXPORT) +#if defined(blob_SOURCE) +#define blob_DllAPI __declspec( dllexport ) +#else +#define blob_DllAPI __declspec( dllimport ) +#endif // blob_SOURCE +#else +#define blob_DllAPI +#endif // EPROSIMA_USER_DLL_EXPORT +#else +#define blob_DllAPI +#endif // _WIN32 + +namespace eprosima { +namespace fastcdr { +class Cdr; +} // namespace fastcdr +} // namespace eprosima + + +namespace udds { + /*! + * @brief This class represents the structure blob defined by the user in the IDL file. + * @ingroup BLOB + */ + class blob + { + public: + + /*! + * @brief Default constructor. + */ + eProsima_user_DllExport blob(); + + /*! + * @brief Default destructor. + */ + eProsima_user_DllExport ~blob(); + + /*! + * @brief Copy constructor. + * @param x Reference to the object udds::blob that will be copied. + */ + eProsima_user_DllExport blob( + const blob& x); + + /*! + * @brief Move constructor. + * @param x Reference to the object udds::blob that will be copied. + */ + eProsima_user_DllExport blob( + blob&& x) noexcept; + + /*! + * @brief Copy assignment. + * @param x Reference to the object udds::blob that will be copied. + */ + eProsima_user_DllExport blob& operator =( + const blob& x); + + /*! + * @brief Move assignment. + * @param x Reference to the object udds::blob that will be copied. + */ + eProsima_user_DllExport blob& operator =( + blob&& x) noexcept; + + /*! + * @brief Comparison operator. + * @param x udds::blob object to compare. + */ + eProsima_user_DllExport bool operator ==( + const blob& x) const; + + /*! + * @brief Comparison operator. + * @param x udds::blob object to compare. + */ + eProsima_user_DllExport bool operator !=( + const blob& x) const; + + /*! + * @brief This function copies the value in member data + * @param _data New value to be copied in member data + */ + eProsima_user_DllExport void data( + const std::vector& _data); + + /*! + * @brief This function moves the value in member data + * @param _data New value to be moved in member data + */ + eProsima_user_DllExport void data( + std::vector&& _data); + + /*! + * @brief This function returns a constant reference to member data + * @return Constant reference to member data + */ + eProsima_user_DllExport const std::vector& data() const; + + /*! + * @brief This function returns a reference to member data + * @return Reference to member data + */ + eProsima_user_DllExport std::vector& data(); + + /*! + * @brief This function returns the maximum serialized size of an object + * depending on the buffer alignment. + * @param current_alignment Buffer alignment. + * @return Maximum serialized size. + */ + eProsima_user_DllExport static size_t getMaxCdrSerializedSize( + size_t current_alignment = 0); + + /*! + * @brief This function returns the serialized size of a data depending on the buffer alignment. + * @param data Data which is calculated its serialized size. + * @param current_alignment Buffer alignment. + * @return Serialized size. + */ + eProsima_user_DllExport static size_t getCdrSerializedSize( + const udds::blob& data, + size_t current_alignment = 0); + + + /*! + * @brief This function serializes an object using CDR serialization. + * @param cdr CDR serialization object. + */ + eProsima_user_DllExport void serialize( + eprosima::fastcdr::Cdr& cdr) const; + + /*! + * @brief This function deserializes an object using CDR serialization. + * @param cdr CDR serialization object. + */ + eProsima_user_DllExport void deserialize( + eprosima::fastcdr::Cdr& cdr); + + + + /*! + * @brief This function returns the maximum serialized size of the Key of an object + * depending on the buffer alignment. + * @param current_alignment Buffer alignment. + * @return Maximum serialized size. + */ + eProsima_user_DllExport static size_t getKeyMaxCdrSerializedSize( + size_t current_alignment = 0); + + /*! + * @brief This function tells you if the Key has been defined for this type + */ + eProsima_user_DllExport static bool isKeyDefined(); + + /*! + * @brief This function serializes the key members of an object using CDR serialization. + * @param cdr CDR serialization object. + */ + eProsima_user_DllExport void serializeKey( + eprosima::fastcdr::Cdr& cdr) const; + + private: + + std::vector m_data; + }; +} // namespace udds + +#endif // _FAST_DDS_GENERATED_UDDS_BLOB_H_ \ No newline at end of file diff --git a/third-party/realdds/include/realdds/topics/blob/blob.idl b/third-party/realdds/include/realdds/topics/blob/blob.idl new file mode 100644 index 00000000000..0460a0fdacc --- /dev/null +++ b/third-party/realdds/include/realdds/topics/blob/blob.idl @@ -0,0 +1,10 @@ +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright(c) 2023 Intel Corporation. All Rights Reserved. + +module udds +{ + struct blob + { + sequence data; + }; +}; diff --git a/third-party/realdds/include/realdds/topics/blob/blobPubSubTypes.h b/third-party/realdds/include/realdds/topics/blob/blobPubSubTypes.h new file mode 100644 index 00000000000..ae8bd1c0fc5 --- /dev/null +++ b/third-party/realdds/include/realdds/topics/blob/blobPubSubTypes.h @@ -0,0 +1,93 @@ +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright(c) 2023 Intel Corporation. All Rights Reserved. + +/*! + * @file blobPubSubTypes.h + * This header file contains the declaration of the serialization functions. + * + * This file was generated by the tool fastcdrgen. + */ + + +#ifndef _FAST_DDS_GENERATED_UDDS_BLOB_PUBSUBTYPES_H_ +#define _FAST_DDS_GENERATED_UDDS_BLOB_PUBSUBTYPES_H_ + +#include +#include + +#include "blob.h" + +#if !defined(GEN_API_VER) || (GEN_API_VER != 1) +#error \ + Generated blob is not compatible with current installed Fast DDS. Please, regenerate it with fastddsgen. +#endif // GEN_API_VER + +namespace udds +{ + /*! + * @brief This class represents the TopicDataType of the type blob defined by the user in the IDL file. + * @ingroup BLOB + */ + class blobPubSubType : public eprosima::fastdds::dds::TopicDataType + { + public: + + typedef blob type; + + eProsima_user_DllExport blobPubSubType(); + + eProsima_user_DllExport virtual ~blobPubSubType() override; + + eProsima_user_DllExport virtual bool serialize( + void* data, + eprosima::fastrtps::rtps::SerializedPayload_t* payload) override; + + eProsima_user_DllExport virtual bool deserialize( + eprosima::fastrtps::rtps::SerializedPayload_t* payload, + void* data) override; + + eProsima_user_DllExport virtual std::function getSerializedSizeProvider( + void* data) override; + + eProsima_user_DllExport virtual bool getKey( + void* data, + eprosima::fastrtps::rtps::InstanceHandle_t* ihandle, + bool force_md5 = false) override; + + eProsima_user_DllExport virtual void* createData() override; + + eProsima_user_DllExport virtual void deleteData( + void* data) override; + + #ifdef TOPIC_DATA_TYPE_API_HAS_IS_BOUNDED + eProsima_user_DllExport inline bool is_bounded() const override + { + return false; + } + + #endif // TOPIC_DATA_TYPE_API_HAS_IS_BOUNDED + + #ifdef TOPIC_DATA_TYPE_API_HAS_IS_PLAIN + eProsima_user_DllExport inline bool is_plain() const override + { + return false; + } + + #endif // TOPIC_DATA_TYPE_API_HAS_IS_PLAIN + + #ifdef TOPIC_DATA_TYPE_API_HAS_CONSTRUCT_SAMPLE + eProsima_user_DllExport inline bool construct_sample( + void* memory) const override + { + (void)memory; + return false; + } + + #endif // TOPIC_DATA_TYPE_API_HAS_CONSTRUCT_SAMPLE + + MD5 m_md5; + unsigned char* m_keyBuffer; + }; +} + +#endif // _FAST_DDS_GENERATED_UDDS_BLOB_PUBSUBTYPES_H_ \ No newline at end of file diff --git a/third-party/realdds/include/realdds/topics/blob/readme.md b/third-party/realdds/include/realdds/topics/blob/readme.md new file mode 100644 index 00000000000..1659aa7d6aa --- /dev/null +++ b/third-party/realdds/include/realdds/topics/blob/readme.md @@ -0,0 +1,28 @@ + +The files in this directory are, for the most part, automatically generated from the IDL. + +See the [`topics`](../) readme for generation, etc. + + +# blob + +This message format can convey any data in any format: + +```idl +struct blob +{ + sequence< octet > data; +}; +``` + +This can be used for anything, including big data transfers. It is better to use [flexible](../flexible/readme.md) If your data can fit within its limits. + +## Topic type + +The DDS topic type is: +>udds::blob + + +## Quality of Service + +QoS depends on usage. diff --git a/third-party/realdds/include/realdds/topics/flexible/readme.md b/third-party/realdds/include/realdds/topics/flexible/readme.md index 8942a3b13a4..02e9d46dcf5 100644 --- a/third-party/realdds/include/realdds/topics/flexible/readme.md +++ b/third-party/realdds/include/realdds/topics/flexible/readme.md @@ -35,7 +35,7 @@ The DDS topic type is: ## Quality of Service -All flexible topics are usually reliable (as opposed to data streams that are best-effort), unless otherwise stated. +All flexible topics are usually reliable (as opposed to data streams that are best-effort), unless otherwise stated. One notable exception is [metadata](metadata.md). - Reliability: `RELIABLE` - Durability: `VOLATILE` diff --git a/third-party/realdds/src/topics/blob-msg.cpp b/third-party/realdds/src/topics/blob-msg.cpp new file mode 100644 index 00000000000..21d7a5b21b3 --- /dev/null +++ b/third-party/realdds/src/topics/blob-msg.cpp @@ -0,0 +1,76 @@ +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright(c) 2023 Intel Corporation. All Rights Reserved. + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + + +namespace realdds { +namespace topics { + + +/*static*/ std::shared_ptr< dds_topic > +blob_msg::create_topic( std::shared_ptr< dds_participant > const & participant, char const * topic_name ) +{ + return std::make_shared< dds_topic >( participant, + eprosima::fastdds::dds::TypeSupport( new blob_msg::type ), + topic_name ); +} + + +/*static*/ bool +blob_msg::take_next( dds_topic_reader & reader, blob_msg * output, eprosima::fastdds::dds::SampleInfo * info ) +{ + eprosima::fastdds::dds::SampleInfo info_; + if( ! info ) + info = &info_; // use the local copy if the user hasn't provided their own + auto status = reader->take_next_sample( static_cast< udds::blob * >( output ), info ); + if( status == ReturnCode_t::RETCODE_OK ) + { + // We have data + if( output ) + { + // Only samples for which valid_data is true should be accessed + // valid_data indicates that the instance is still ALIVE and the `take` return an + // updated sample + if( ! info->valid_data ) + output->invalidate(); + } + return true; + } + if( status == ReturnCode_t::RETCODE_NO_DATA ) + { + // This is an expected return code and is not an error + return false; + } + DDS_API_CALL_THROW( "blob_msg::take_next", status ); +} + + +dds_sequence_number blob_msg::write_to( dds_topic_writer & writer ) const +{ + eprosima::fastrtps::rtps::WriteParams params; + bool success = DDS_API_CALL( + writer.get()->write( const_cast< udds::blob * >( static_cast< udds::blob const * >( this ) ), params ) ); + if( ! success ) + { + LOG_ERROR( "Error writing message" ); + return 0; + } + // The params will contain, after the write, the sequence number (incremented automatically) for the sample that was + // sent. The source_timestamp is always INVALID for some reason. + return params.sample_identity().sequence_number().to64long(); +} + + +} // namespace topics +} // namespace realdds diff --git a/third-party/realdds/src/topics/blob.cpp b/third-party/realdds/src/topics/blob.cpp new file mode 100644 index 00000000000..2795d510707 --- /dev/null +++ b/third-party/realdds/src/topics/blob.cpp @@ -0,0 +1,187 @@ +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright(c) 2023 Intel Corporation. All Rights Reserved. + +/*! + * @file blob.cpp + * This source file contains the definition of the described types in the IDL file. + * + * This file was generated by the tool gen. + */ + +#ifdef _WIN32 +// Remove linker warning LNK4221 on Visual Studio +namespace { +char dummy; +} // namespace +#endif // _WIN32 + +#include +#include + +#include +using namespace eprosima::fastcdr::exception; + +#include + +udds::blob::blob() +{ + // m_data com.eprosima.idl.parser.typecode.SequenceTypeCode@131276c2 + + +} + +udds::blob::~blob() +{ +} + +udds::blob::blob( + const blob& x) +{ + m_data = x.m_data; +} + +udds::blob::blob( + blob&& x) noexcept +{ + m_data = std::move(x.m_data); +} + +udds::blob& udds::blob::operator =( + const blob& x) +{ + + m_data = x.m_data; + + return *this; +} + +udds::blob& udds::blob::operator =( + blob&& x) noexcept +{ + + m_data = std::move(x.m_data); + + return *this; +} + +bool udds::blob::operator ==( + const blob& x) const +{ + + return (m_data == x.m_data); +} + +bool udds::blob::operator !=( + const blob& x) const +{ + return !(*this == x); +} + +size_t udds::blob::getMaxCdrSerializedSize( + size_t current_alignment) +{ + size_t initial_alignment = current_alignment; + + + current_alignment += 4 + eprosima::fastcdr::Cdr::alignment(current_alignment, 4); + + current_alignment += (100 * 1) + eprosima::fastcdr::Cdr::alignment(current_alignment, 1); + + + + return current_alignment - initial_alignment; +} + +size_t udds::blob::getCdrSerializedSize( + const udds::blob& data, + size_t current_alignment) +{ + (void)data; + size_t initial_alignment = current_alignment; + + + current_alignment += 4 + eprosima::fastcdr::Cdr::alignment(current_alignment, 4); + + if (data.data().size() > 0) + { + current_alignment += (data.data().size() * 1) + eprosima::fastcdr::Cdr::alignment(current_alignment, 1); + } + + + + return current_alignment - initial_alignment; +} + +void udds::blob::serialize( + eprosima::fastcdr::Cdr& scdr) const +{ + + scdr << m_data; +} + +void udds::blob::deserialize( + eprosima::fastcdr::Cdr& dcdr) +{ + + dcdr >> m_data;} + +/*! + * @brief This function copies the value in member data + * @param _data New value to be copied in member data + */ +void udds::blob::data( + const std::vector& _data) +{ + m_data = _data; +} + +/*! + * @brief This function moves the value in member data + * @param _data New value to be moved in member data + */ +void udds::blob::data( + std::vector&& _data) +{ + m_data = std::move(_data); +} + +/*! + * @brief This function returns a constant reference to member data + * @return Constant reference to member data + */ +const std::vector& udds::blob::data() const +{ + return m_data; +} + +/*! + * @brief This function returns a reference to member data + * @return Reference to member data + */ +std::vector& udds::blob::data() +{ + return m_data; +} + +size_t udds::blob::getKeyMaxCdrSerializedSize( + size_t current_alignment) +{ + size_t current_align = current_alignment; + + + + return current_align; +} + +bool udds::blob::isKeyDefined() +{ + return false; +} + +void udds::blob::serializeKey( + eprosima::fastcdr::Cdr& scdr) const +{ + (void) scdr; + +} + diff --git a/third-party/realdds/src/topics/blobPubSubTypes.cpp b/third-party/realdds/src/topics/blobPubSubTypes.cpp new file mode 100644 index 00000000000..751b0647ca1 --- /dev/null +++ b/third-party/realdds/src/topics/blobPubSubTypes.cpp @@ -0,0 +1,162 @@ +// License: Apache 2.0. See LICENSE file in root directory. +// Copyright(c) 2023 Intel Corporation. All Rights Reserved. + +/*! + * @file blobPubSubTypes.cpp + * This header file contains the implementation of the serialization functions. + * + * This file was generated by the tool fastcdrgen. + */ + + +#include +#include + +#include + +using SerializedPayload_t = eprosima::fastrtps::rtps::SerializedPayload_t; +using InstanceHandle_t = eprosima::fastrtps::rtps::InstanceHandle_t; + +namespace udds { + blobPubSubType::blobPubSubType() + { + setName("udds::blob"); + auto type_size = blob::getMaxCdrSerializedSize(); + type_size += eprosima::fastcdr::Cdr::alignment(type_size, 4); /* possible submessage alignment */ + m_typeSize = static_cast(type_size) + 4; /*encapsulation*/ + m_isGetKeyDefined = blob::isKeyDefined(); + size_t keyLength = blob::getKeyMaxCdrSerializedSize() > 16 ? + blob::getKeyMaxCdrSerializedSize() : 16; + m_keyBuffer = reinterpret_cast(malloc(keyLength)); + memset(m_keyBuffer, 0, keyLength); + } + + blobPubSubType::~blobPubSubType() + { + if (m_keyBuffer != nullptr) + { + free(m_keyBuffer); + } + } + + bool blobPubSubType::serialize( + void* data, + SerializedPayload_t* payload) + { + blob* p_type = static_cast(data); + + // Object that manages the raw buffer. + eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast(payload->data), payload->max_size); + // Object that serializes the data. + eprosima::fastcdr::Cdr ser(fastbuffer, eprosima::fastcdr::Cdr::DEFAULT_ENDIAN, eprosima::fastcdr::Cdr::DDS_CDR); + payload->encapsulation = ser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE; + // Serialize encapsulation + ser.serialize_encapsulation(); + + try + { + // Serialize the object. + p_type->serialize(ser); + } + catch (eprosima::fastcdr::exception::NotEnoughMemoryException& /*exception*/) + { + return false; + } + + // Get the serialized length + payload->length = static_cast(ser.getSerializedDataLength()); + return true; + } + + bool blobPubSubType::deserialize( + SerializedPayload_t* payload, + void* data) + { + try + { + //Convert DATA to pointer of your type + blob* p_type = static_cast(data); + + // Object that manages the raw buffer. + eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast(payload->data), payload->length); + + // Object that deserializes the data. + eprosima::fastcdr::Cdr deser(fastbuffer, eprosima::fastcdr::Cdr::DEFAULT_ENDIAN, eprosima::fastcdr::Cdr::DDS_CDR); + + // Deserialize encapsulation. + deser.read_encapsulation(); + payload->encapsulation = deser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE; + + // Deserialize the object. + p_type->deserialize(deser); + } + catch (eprosima::fastcdr::exception::NotEnoughMemoryException& /*exception*/) + { + return false; + } + + return true; + } + + std::function blobPubSubType::getSerializedSizeProvider( + void* data) + { + return [data]() -> uint32_t + { + return static_cast(type::getCdrSerializedSize(*static_cast(data))) + + 4u /*encapsulation*/; + }; + } + + void* blobPubSubType::createData() + { + return reinterpret_cast(new blob()); + } + + void blobPubSubType::deleteData( + void* data) + { + delete(reinterpret_cast(data)); + } + + bool blobPubSubType::getKey( + void* data, + InstanceHandle_t* handle, + bool force_md5) + { + if (!m_isGetKeyDefined) + { + return false; + } + + blob* p_type = static_cast(data); + + // Object that manages the raw buffer. + eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast(m_keyBuffer), + blob::getKeyMaxCdrSerializedSize()); + + // Object that serializes the data. + eprosima::fastcdr::Cdr ser(fastbuffer, eprosima::fastcdr::Cdr::BIG_ENDIANNESS); + p_type->serializeKey(ser); + if (force_md5 || blob::getKeyMaxCdrSerializedSize() > 16) + { + m_md5.init(); + m_md5.update(m_keyBuffer, static_cast(ser.getSerializedDataLength())); + m_md5.finalize(); + for (uint8_t i = 0; i < 16; ++i) + { + handle->value[i] = m_md5.digest[i]; + } + } + else + { + for (uint8_t i = 0; i < 16; ++i) + { + handle->value[i] = m_keyBuffer[i]; + } + } + return true; + } + + +} //End of namespace udds