CVE-2023-50257 (published 2024-02-19T20:15Z)

eProsima Fast DDS (formerly Fast RTPS) is a C++ implementation of the Data Distribution Service standard of the Object Management Group. Even with the application of SROS2, due to the issue where the data (`p[UD]`) and `guid` values used to disconnect between nodes are not encrypted, a vulnerability has been discovered where a malicious attacker can forcibly disconnect a Subscriber and can deny a Subscriber attempting to connect. Afterwards, if the attacker sends the packet for disconnecting, which is data (`p[UD]`), to the Global Data Space (`239.255.0.1:7400`) using the said Publisher ID, all the Subscribers (Listeners) connected to the Publisher (Talker) will not receive any data and their connection will be disconnected. Moreover, if this disconnection packet is sent continuously, the Subscribers (Listeners) trying to connect will not be able to do so. Since the initial commit of the `SecurityManager.cpp` code (`init`, `on_process_handshake`) on Nov 8, 2016, the Disconnect Vulnerability in RTPS Packets Used by SROS2 has been present prior to versions 2.13.0, 2.12.2, 2.11.3, 2.10.3, and 2.6.7.


Weakness information:
cwe_id: CWE-284
cwe_name: Improper Access Control
description: The product does not restrict or incorrectly restricts access to a resource from an unauthorized actor.
extended_description: 
            Access control involves the use of several protection mechanisms such as:
            
               Authentication (proving the identity of an actor)
               Authorization (ensuring that a given actor can access a resource), and
               Accountability (tracking of activities that were performed)
            
            When any mechanism is not applied or otherwise fails, attackers can compromise the security of the product by gaining privileges, reading sensitive information, executing commands, evading detection, etc.
            There are two distinct behaviors that can introduce access control weaknesses:
               
                  Specification: incorrect privileges, permissions, ownership, etc. are explicitly specified for either the user or the resource (for example, setting a password file to be world-writable, or giving administrator capabilities to a guest user). This action could be performed by the program or the administrator.
                  Enforcement: the mechanism contains errors that prevent it from properly enforcing the specified access control requirements (e.g., allowing the user to specify their own privileges, or allowing a syntactically-incorrect ACL to produce insecure settings). This problem occurs within the program itself, in that it does not actually enforce the intended security policy that the administrator specifies.
               
         
		 

Fix information:
repo_url: https://github.com/eProsima/Fast-DDS
commit_details: repo_url: https://github.com/eProsima/Fast-DDS
author: Ricardo González Moreno
author_date: 2016-11-16 10:19:59+01:00
msg: Refs #1811. WIP SecurityManager.
repository: repo_url: https://github.com/eProsima/Fast-DDS
repo_name: eProsima/Fast-DDS
description: The most complete DDS - Proven: Plenty of success cases. Looking for commercial support? Contact info@eprosima.com
repo_language: C++
owner: eProsima
file_changes: filename: config.h.in
change_type: ModificationType.MODIFY
diff: @@ -63,4 +63,9 @@
 #endif
 #endif
 
+// Security
+#ifndef SECURITY
+#define SECURITY @HAVE_SECURITY@
+#endif
+
 #endif // _FASTRTPS_CONFIG_H_

programming_language: C
filename: Token.h
change_type: ModificationType.MODIFY
diff: @@ -132,6 +132,14 @@ class DataHolderHelper
         static BinaryProperty* find_binary_property(DataHolder& data_holder, const std::string& name);
 
         static const BinaryProperty* find_binary_property(const DataHolder& data_holder, const std::string& name);
+
+        static size_t serialized_size(const DataHolder& data_holder, size_t current_alignment = 0);
+
+        static size_t serialized_size(const DataHolderSeq& data_holders, size_t current_alignment = 0);
+
+    private:
+
+        inline static size_t alignment(size_t current_alignment, size_t dataSize) { return (dataSize - (current_alignment % dataSize)) & (dataSize-1);}
 };
 
 } //namespace rtps

programming_language: C++
filename: CDRMessage.h
change_type: ModificationType.MODIFY
diff: @@ -26,6 +26,10 @@
 #include "../common/Property.h"
 #include "../common/BinaryProperty.h"
 
+#ifdef SECURITY
+#include "../security/common/ParticipantGenericMessage.h"
+#endif
+
 using namespace eprosima::fastrtps;
 
 namespace eprosima {
@@ -53,6 +57,7 @@ namespace CDRMessage{
 	  inline bool readDataReversed(CDRMessage_t* msg, octet* o, uint32_t length);
 	  inline bool readInt32(CDRMessage_t* msg,int32_t* lo);
 	  inline bool readUInt32(CDRMessage_t* msg, uint32_t* ulo);
+	  inline bool readInt64(CDRMessage_t* msg, int64_t* lolo);
 	  inline bool readSequenceNumber(CDRMessage_t* msg, SequenceNumber_t* sn);
 	  inline bool readInt16(CDRMessage_t* msg,int16_t* i16);
 	  inline bool readUInt16(CDRMessage_t* msg,uint16_t* i16);
@@ -63,6 +68,15 @@ namespace CDRMessage{
 	  inline bool readTimestamp(CDRMessage_t*msg,Time_t* ts);
 	  inline bool readString(CDRMessage_t*msg,std::string* p_str);
 	  inline bool readOctetVector(CDRMessage_t*msg,std::vector<octet>* ocvec);
+
+      inline bool readProperty(CDRMessage_t* msg, Property& property);
+      inline bool readBinaryProperty(CDRMessage_t* msg, BinaryProperty& binary_property);
+      inline bool readPropertySeq(CDRMessage_t* msg, PropertySeq& properties);
+      inline bool readBinaryPropertySeq(CDRMessage_t* msg, BinaryPropertySeq& binary_properties);
+      inline bool readDataHolder(CDRMessage_t* msg, DataHolder& data_holder);
+      inline bool readDataHolderSeq(CDRMessage_t* msg, DataHolderSeq& data_holders);
+      inline bool readMessageIdentity(CDRMessage_t* msg, ::security::MessageIdentity& message_identity);
+      inline bool readParticipantGenericMessage(CDRMessage_t* msg, ::security::ParticipantGenericMessage& message);
 	///@}
 
 
@@ -121,6 +135,10 @@ namespace CDRMessage{
       inline bool addPropertySeq(CDRMessage_t* msg, const PropertySeq& properties);
       inline bool addBinaryPropertySeq(CDRMessage_t* msg, const BinaryPropertySeq& binary_properties);
       inline bool addBinaryPropertySeq(CDRMessage_t* msg, const BinaryPropertySeq& binary_properties, const std::string& property_limit);
+      inline bool addDataHolder(CDRMessage_t* msg, const DataHolder& data_holder);
+      inline bool addDataHolderSeq(CDRMessage_t* msg, const DataHolderSeq& data_holders);
+      inline bool addMessageIdentity(CDRMessage_t* msg, const ::security::MessageIdentity& message_identity);
+      inline bool addParticipantGenericMessage(CDRMessage_t* msg, const ::security::ParticipantGenericMessage& message);
 }
 
 }

programming_language: C++
filename: CDRMessage.hpp
change_type: ModificationType.MODIFY
diff: @@ -121,6 +121,27 @@ inline bool CDRMessage::readUInt32(CDRMessage_t* msg,uint32_t* ulo) {
     return true;
 }
 
+inline bool CDRMessage::readInt64(CDRMessage_t* msg, int64_t* lolo)
+{
+    if(msg->pos+8 > msg->length)
+        return false;
+
+    octet* dest = (octet*)lolo;
+    if(msg->msg_endian == DEFAULT_ENDIAN)
+    {
+        for(uint8_t i = 0; i < 8; ++i)
+            dest[i] = msg->buffer[msg->pos+i];
+
+        msg->pos+=8;
+    }
+    else
+    {
+        readDataReversed(msg, dest, 8);
+    }
+
+    return true;
+}
+
 inline bool CDRMessage::readSequenceNumber(CDRMessage_t* msg,SequenceNumber_t* sn) {
     if(msg->pos+8>msg->length)
         return false;
@@ -651,7 +672,7 @@ inline bool CDRMessage::addString(CDRMessage_t*msg, const std::string& in_str)
 
 inline bool CDRMessage::addParameterSampleIdentity(CDRMessage_t *msg, const SampleIdentity &sample_id)
 {
-    if(msg->pos + 28 >= msg->max_size)
+    if(msg->pos + 28 > msg->max_size)
     {
         return false;
     }
@@ -667,45 +688,107 @@ inline bool CDRMessage::addParameterSampleIdentity(CDRMessage_t *msg, const Samp
 
 inline bool CDRMessage::addProperty(CDRMessage_t* msg, const Property& property)
 {
+    assert(msg);
+
     if(property.propagate())
     {
-        return CDRMessage::addString(msg, property.name()) &&
-            CDRMessage::addString(msg, property.value());
+        if(!CDRMessage::addString(msg, property.name()))
+            return false;
+        if(!CDRMessage::addString(msg, property.value()))
+            return false;
     }
 
     return true;
 }
 
+inline bool CDRMessage::readProperty(CDRMessage_t* msg, Property& property)
+{
+    assert(msg);
+
+    if(!CDRMessage::readString(msg, &property.name()))
+        return false;
+    if(!CDRMessage::readString(msg, &property.value()))
+        return false;
+
+    return true;
+}
+
 inline bool CDRMessage::addBinaryProperty(CDRMessage_t* msg, const BinaryProperty& binary_property)
 {
+    assert(msg);
+
     if(binary_property.propagate())
-        return CDRMessage::addString(msg, binary_property.name()) &&
-            CDRMessage::addOctetVector(msg, &binary_property.value());
+    {
+        if(!CDRMessage::addString(msg, binary_property.name()))
+            return false;
+        if(!CDRMessage::addOctetVector(msg, &binary_property.value()))
+            return false;
+    }
+
+    return true;
+}
+
+inline bool CDRMessage::readBinaryProperty(CDRMessage_t* msg, BinaryProperty& binary_property)
+{
+    assert(msg);
+
+    if(!CDRMessage::readString(msg, &binary_property.name()))
+        return false;
+    if(!CDRMessage::readOctetVector(msg, &binary_property.value()))
+        return false;
 
     return true;
 }
 
 inline bool CDRMessage::addPropertySeq(CDRMessage_t* msg, const PropertySeq& properties)
 {
+    assert(msg);
+
     bool returnedValue = false;
 
-    if(msg->pos + 4 <  msg->max_size)
+    if(msg->pos + 4 <=  msg->max_size)
     {
-        if(CDRMessage::addUInt32(msg, (uint32_t)properties.size()))
+        uint32_t number_to_serialize = 0;
+        for(auto it = properties.begin(); it != properties.end(); ++it)
+            if(it->propagate())
+                ++number_to_serialize;
+
+        if(CDRMessage::addUInt32(msg, number_to_serialize))
         {
+            returnedValue = true;
             for(auto it = properties.begin(); returnedValue && it != properties.end(); ++it)
-                returnedValue = CDRMessage::addProperty(msg, *it);
+                if(it->propagate())
+                    returnedValue = CDRMessage::addProperty(msg, *it);
         }
     }
 
     return returnedValue;
 }
 
+inline bool CDRMessage::readPropertySeq(CDRMessage_t* msg, PropertySeq& properties)
+{
+    assert(msg);
+
+    uint32_t length = 0;
+    if(!CDRMessage::readUInt32(msg, &length))
+        return false;
+
+    properties.resize(length);
+    bool returnedValue = true;
+    for(uint32_t i = 0; returnedValue && i < length; ++i)
+        returnedValue = CDRMessage::readProperty(msg, properties.at(i));
+
+    return returnedValue;
+
+}
+
 inline bool CDRMessage::addBinaryPropertySeq(CDRMessage_t* msg, const BinaryPropertySeq& binary_properties)
 {
+    assert(msg);
+
     bool returnedValue = false;
 
-    if(msg->pos + 4 <  msg->max_size)
+    if(msg->pos + 4 <=  msg->max_size)
     {
         uint32_t number_to_serialize = 0;
         for(auto it = binary_properties.begin(); it != binary_properties.end(); ++it)
@@ -726,9 +809,11 @@ inline bool CDRMessage::addBinaryPropertySeq(CDRMessage_t* msg, const BinaryProp
 
 inline bool CDRMessage::addBinaryPropertySeq(CDRMessage_t* msg, const BinaryPropertySeq& binary_properties, const std::string& property_limit)
 {
+    assert(msg);
+
     bool returnedValue = false;
 
-    if(msg->pos + 4 <  msg->max_size)
+    if(msg->pos + 4 <=  msg->max_size)
     {
         uint32_t position = 0;
         uint32_t number_to_serialize = 0;
@@ -752,6 +837,170 @@ inline bool CDRMessage::addBinaryPropertySeq(CDRMessage_t* msg, const BinaryProp
     return returnedValue;
 }
 
+inline bool CDRMessage::readBinaryPropertySeq(CDRMessage_t* msg, BinaryPropertySeq& binary_properties)
+{
+    assert(msg);
+
+    uint32_t length = 0;
+    if(!CDRMessage::readUInt32(msg, &length))
+        return false;
+
+    binary_properties.resize(length);
+    bool returnedValue = true;
+    for(uint32_t i = 0; returnedValue && i < length; ++i)
+        returnedValue = CDRMessage::readBinaryProperty(msg, binary_properties.at(i));
+
+    return returnedValue;
+}
+
+inline bool CDRMessage::addDataHolder(CDRMessage_t* msg, const DataHolder& data_holder)
+{
+    assert(msg);
+
+    if(!CDRMessage::addString(msg, data_holder.class_id()))
+        return false;
+    if(!CDRMessage::addPropertySeq(msg, data_holder.properties()))
+        return false;
+    if(!CDRMessage::addBinaryPropertySeq(msg, data_holder.binary_properties()))
+        return false;
+
+    return true;
+}
+
+inline bool CDRMessage::readDataHolder(CDRMessage_t* msg, DataHolder& data_holder)
+{
+    assert(msg);
+
+    if(!CDRMessage::readString(msg, &data_holder.class_id()))
+        return false;
+    if(!CDRMessage::readPropertySeq(msg, data_holder.properties()))
+        return false;
+    if(!CDRMessage::readBinaryPropertySeq(msg, data_holder.binary_properties()))
+        return false;
+
+    return true;
+
+}
+
+inline bool CDRMessage::addDataHolderSeq(CDRMessage_t* msg, const DataHolderSeq& data_holders)
+{
+    assert(msg);
+
+    bool returnedValue = false;
+
+    if(msg->pos + 4 <=  msg->max_size)
+    {
+        if(CDRMessage::addUInt32(msg, data_holders.size()))
+        {
+            returnedValue = true;
+            for(auto data_holder = data_holders.begin(); returnedValue && data_holder != data_holders.end(); ++data_holder)
+                returnedValue = CDRMessage::addDataHolder(msg, *data_holder);
+        }
+    }
+
+    return returnedValue;
+}
+
+inline bool CDRMessage::readDataHolderSeq(CDRMessage_t* msg, DataHolderSeq& data_holders)
+{
+    assert(msg);
+
+    uint32_t length = 0;
+    if(!CDRMessage::readUInt32(msg, &length))
+        return false;
+
+    data_holders.resize(length);
+    bool returnedValue = true;
+    for(uint32_t i = 0; returnedValue && i < length; ++i)
+        returnedValue = CDRMessage::readDataHolder(msg, data_holders.at(i));
+
+    return returnedValue;
+}
+
+inline bool CDRMessage::addMessageIdentity(CDRMessage_t* msg, const ::security::MessageIdentity& message_identity)
+{
+    assert(msg);
+
+    if(!CDRMessage::addData(msg, message_identity.source_guid().guidPrefix.value, GuidPrefix_t::size))
+        return false;
+    if(!CDRMessage::addData(msg, message_identity.source_guid().entityId.value, EntityId_t::size))
+        return false;
+    if(!CDRMessage::addInt64(msg, message_identity.sequence_number()))
+        return false;
+
+    return true;
+}
+
+inline bool CDRMessage::readMessageIdentity(CDRMessage_t* msg, ::security::MessageIdentity& message_identity)
+{
+    assert(msg);
+
+    if(!CDRMessage::readData(msg, message_identity.source_guid().guidPrefix.value, GuidPrefix_t::size))
+        return false;
+    if(!CDRMessage::readData(msg, message_identity.source_guid().entityId.value, EntityId_t::size))
+        return false;
+    if(!CDRMessage::readInt64(msg, &message_identity.sequence_number()))
+        return false;
+
+    return true;
+}
+
+inline bool CDRMessage::addParticipantGenericMessage(CDRMessage_t* msg, const ::security::ParticipantGenericMessage& message)
+{
+    assert(msg);
+
+    if(!CDRMessage::addMessageIdentity(msg, message.message_identity()))
+        return false;
+    if(!CDRMessage::addMessageIdentity(msg, message.related_message_identity()))
+        return false;
+    if(!CDRMessage::addData(msg, message.destination_participant_key().guidPrefix.value, GuidPrefix_t::size))
+        return false;
+    if(!CDRMessage::addData(msg, message.destination_participant_key().entityId.value, EntityId_t::size))
+        return false;
+    if(!CDRMessage::addData(msg, message.destination_endpoint_key().guidPrefix.value, GuidPrefix_t::size))
+        return false;
+    if(!CDRMessage::addData(msg, message.destination_endpoint_key().entityId.value, EntityId_t::size))
+        return false;
+    if(!CDRMessage::addData(msg, message.source_endpoint_key().guidPrefix.value, GuidPrefix_t::size))
+        return false;
+    if(!CDRMessage::addData(msg, message.source_endpoint_key().entityId.value, EntityId_t::size))
+        return false;
+    if(!CDRMessage::addString(msg, message.message_class_id()))
+        return false;
+    if(!CDRMessage::addDataHolderSeq(msg, message.message_data()))
+        return false;
+
+    return true;
+}
+
+inline bool CDRMessage::readParticipantGenericMessage(CDRMessage_t* msg, ::security::ParticipantGenericMessage& message)
+{
+    assert(msg);
+
+    if(!CDRMessage::readMessageIdentity(msg, message.message_identity()))
+        return false;
+    if(!CDRMessage::readMessageIdentity(msg, message.related_message_identity()))
+        return false;
+    if(!CDRMessage::readData(msg, message.destination_participant_key().guidPrefix.value, GuidPrefix_t::size))
+        return false;
+    if(!CDRMessage::readData(msg, message.destination_participant_key().entityId.value, EntityId_t::size))
+        return false;
+    if(!CDRMessage::readData(msg, message.destination_endpoint_key().guidPrefix.value, GuidPrefix_t::size))
+        return false;
+    if(!CDRMessage::readData(msg, message.destination_endpoint_key().entityId.value, EntityId_t::size))
+        return false;
+    if(!CDRMessage::readData(msg, message.source_endpoint_key().guidPrefix.value, GuidPrefix_t::size))
+        return false;
+    if(!CDRMessage::readData(msg, message.source_endpoint_key().entityId.value, EntityId_t::size))
+        return false;
+    if(!CDRMessage::readString(msg, &message.message_class_id()))
+        return false;
+    if(!CDRMessage::readDataHolderSeq(msg, message.message_data()))
+        return false;
+
+    return true;
+}
+
 }
 } /* namespace rtps */
 } /* namespace eprosima */

programming_language: C++
filename: ParticipantGenericMessage.h
change_type: ModificationType.ADD
diff: @@ -0,0 +1,346 @@
+// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef _RTPS_SECURITY_COMMON_PARTICIPANTGENERICMESSAGE_H_
+#define _RTPS_SECURITY_COMMON_PARTICIPANTGENERICMESSAGE_H_
+
+#include "../../common/Guid.h"
+#include "../../common/Token.h"
+
+namespace eprosima {
+namespace fastrtps {
+namespace rtps {
+namespace security {
+
+class MessageIdentity
+{
+    public:
+
+        MessageIdentity() : sequence_number_(0) {}
+
+        MessageIdentity(const MessageIdentity& mi) :
+            source_guid_(mi.source_guid_),
+            sequence_number_(mi.sequence_number_)
+        {
+        }
+
+        MessageIdentity(MessageIdentity&& mi) :
+            source_guid_(std::move(mi.source_guid_)),
+            sequence_number_(mi.sequence_number_)
+        {
+        }
+
+        MessageIdentity& operator=(const MessageIdentity& mi)
+        {
+            source_guid_ = mi.source_guid_;
+            sequence_number_ = mi.sequence_number_;
+            return *this;
+        }
+
+        MessageIdentity& operator=(MessageIdentity&& mi)
+        {
+            source_guid_ = std::move(mi.source_guid_);
+            sequence_number_ = mi.sequence_number_;
+            return *this;
+        }
+
+        void source_guid(const GUID_t& source_guid)
+        {
+            source_guid_ = source_guid;
+        }
+
+        void source_guid(GUID_t&& source_guid)
+        {
+            source_guid_ = std::move(source_guid);
+        }
+
+        const GUID_t& source_guid() const
+        {
+            return source_guid_;
+        }
+
+        GUID_t& source_guid()
+        {
+            return source_guid_;
+        }
+
+        void sequence_number(int64_t sequence_number)
+        {
+            sequence_number_ = sequence_number;
+        }
+
+        int64_t sequence_number() const
+        {
+            return sequence_number_;
+        }
+
+        int64_t& sequence_number()
+        {
+            return sequence_number_;
+        }
+
+    private:
+
+        GUID_t source_guid_;
+        int64_t sequence_number_;
+};
+
+class MessageIdentityHelper
+{
+    public:
+
+        static size_t serialized_size(const MessageIdentity& /*message*/, size_t current_alignment = 0)
+        {
+            size_t initial_alignment = current_alignment;
+
+            current_alignment += 16;
+            current_alignment +=  alignment(current_alignment, 8) + 8;
+
+            return current_alignment - initial_alignment;
+        }
+
+    private:
+
+        inline static size_t alignment(size_t current_alignment, size_t dataSize) { return (dataSize - (current_alignment % dataSize)) & (dataSize-1);}
+};
+
+class ParticipantGenericMessage
+{
+    public:
+
+        ParticipantGenericMessage() {}
+
+        ParticipantGenericMessage(const ParticipantGenericMessage& message) :
+            message_identity_(message.message_identity_),
+            related_message_identity_(message.related_message_identity_),
+            destination_participant_key_(message.destination_participant_key_),
+            destination_endpoint_key_(message.destination_endpoint_key_),
+            source_endpoint_key_(message.source_endpoint_key_),
+            message_class_id_(message.message_class_id_),
+            message_data_(message.message_data_)
+        {}
+
+        ParticipantGenericMessage(ParticipantGenericMessage&& message) :
+            message_identity_(std::move(message.message_identity_)),
+            related_message_identity_(std::move(message.related_message_identity_)),
+            destination_participant_key_(std::move(message.destination_participant_key_)),
+            destination_endpoint_key_(std::move(message.destination_endpoint_key_)),
+            source_endpoint_key_(std::move(message.source_endpoint_key_)),
+            message_class_id_(std::move(message.message_class_id_)),
+            message_data_(std::move(message.message_data_))
+        {}
+
+        ParticipantGenericMessage& operator=(const ParticipantGenericMessage& message)
+        {
+            message_identity_ = message.message_identity_;
+            related_message_identity_ = message.related_message_identity_;
+            destination_participant_key_ = message.destination_participant_key_;
+            destination_endpoint_key_ = message.destination_endpoint_key_;
+            source_endpoint_key_ = message.source_endpoint_key_;
+            message_class_id_ = message.message_class_id_;
+            message_data_ = message.message_data_;
+            return *this;
+        }
+
+        ParticipantGenericMessage& operator=(ParticipantGenericMessage&& message)
+        {
+            message_identity_ = std::move(message.message_identity_);
+            related_message_identity_ = std::move(message.related_message_identity_);
+            destination_participant_key_ = std::move(message.destination_participant_key_);
+            destination_endpoint_key_ = std::move(message.destination_endpoint_key_);
+            source_endpoint_key_ = std::move(message.source_endpoint_key_);
+            message_class_id_ = std::move(message.message_class_id_);
+            message_data_ = std::move(message.message_data_);
+            return *this;
+        }
+
+        void message_identity(const MessageIdentity& message_identity)
+        {
+            message_identity_ = message_identity;
+        }
+
+        void message_identity(MessageIdentity&& message_identity)
+        {
+            message_identity_ = std::move(message_identity);
+        }
+
+        const MessageIdentity& message_identity() const
+        {
+            return message_identity_;
+        }
+
+        MessageIdentity& message_identity()
+        {
+            return message_identity_;
+        }
+
+        void related_message_identity(const MessageIdentity& related_message_identity)
+        {
+            related_message_identity_ = related_message_identity;
+        }
+
+        void related_message_identity(MessageIdentity&& related_message_identity)
+        {
+            related_message_identity_ = std::move(related_message_identity);
+        }
+
+        const MessageIdentity& related_message_identity() const
+        {
+            return related_message_identity_;
+        }
+
+        MessageIdentity& related_message_identity()
+        {
+            return related_message_identity_;
+        }
+
+        void destination_participant_key(const GUID_t& destination_participant_key)
+        {
+            destination_participant_key_ = destination_participant_key;
+        }
+
+        void destination_participant_key(GUID_t&& destination_participant_key)
+        {
+            destination_participant_key_ = std::move(destination_participant_key);
+        }
+
+        const GUID_t& destination_participant_key() const
+        {
+            return destination_participant_key_;
+        }
+
+        GUID_t& destination_participant_key()
+        {
+            return destination_participant_key_;
+        }
+
+        void destination_endpoint_key(const GUID_t& destination_endpoint_key)
+        {
+            destination_endpoint_key_ = destination_endpoint_key;
+        }
+
+        void destination_endpoint_key(GUID_t&& destination_endpoint_key)
+        {
+            destination_endpoint_key_ = std::move(destination_endpoint_key);
+        }
+
+        const GUID_t& destination_endpoint_key() const
+        {
+            return destination_endpoint_key_;
+        }
+
+        GUID_t& destination_endpoint_key()
+        {
+            return destination_endpoint_key_;
+        }
+
+        void source_endpoint_key(const GUID_t& source_endpoint_key)
+        {
+            source_endpoint_key_ = source_endpoint_key;
+        }
+
+        void source_endpoint_key(GUID_t&& source_endpoint_key)
+        {
+            source_endpoint_key_ = std::move(source_endpoint_key);
+        }
+
+        const GUID_t& source_endpoint_key() const
+        {
+            return source_endpoint_key_;
+        }
+
+        GUID_t& source_endpoint_key()
+        {
+            return source_endpoint_key_;
+        }
+
+        void message_class_id(const std::string& message_class_id)
+        {
+            message_class_id_ = message_class_id;
+        }
+
+        void message_class_id(std::string&& message_class_id)
+        {
+            message_class_id_ = std::move(message_class_id);
+        }
+
+        const std::string& message_class_id() const
+        {
+            return message_class_id_;
+        }
+
+        std::string& message_class_id()
+        {
+            return message_class_id_;
+        }
+
+        void message_data(const DataHolderSeq& message_data)
+        {
+            message_data_ = message_data;
+        }
+
+        void message_data(DataHolderSeq&& message_data)
+        {
+            message_data_ = std::move(message_data);
+        }
+
+        const DataHolderSeq& message_data() const
+        {
+            return message_data_;
+        }
+
+        DataHolderSeq& message_data()
+        {
+            return message_data_;
+        }
+
+    private:
+
+        MessageIdentity message_identity_;
+        MessageIdentity related_message_identity_;
+        GUID_t destination_participant_key_;
+        GUID_t destination_endpoint_key_;
+        GUID_t source_endpoint_key_;
+        std::string message_class_id_;
+        DataHolderSeq message_data_;
+};
+
+class ParticipantGenericMessageHelper
+{
+    public:
+
+        static size_t serialized_size(const ParticipantGenericMessage& message, size_t current_alignment = 0)
+        {
+            size_t initial_alignment = current_alignment;
+
+            current_alignment += MessageIdentityHelper::serialized_size(message.message_identity(), current_alignment);
+            current_alignment += MessageIdentityHelper::serialized_size(message.related_message_identity(), current_alignment);
+            current_alignment += 16 * 3;
+            current_alignment += 4 + alignment(current_alignment, 4) + message.message_class_id().size() + 1;
+            current_alignment += DataHolderHelper::serialized_size(message.message_data(), current_alignment);
+
+            return current_alignment - initial_alignment;
+        }
+
+    private:
+
+        inline static size_t alignment(size_t current_alignment, size_t dataSize) { return (dataSize - (current_alignment % dataSize)) & (dataSize-1);}
+};
+
+} //namespace security
+} //namespace rtps
+} //namespace fastrtps
+} //namespace eprosima
+
+#endif // _RTPS_SECURITY_COMMON_PARTICIPANTGENERICMESSAGE_H_

programming_language: C++
filename: CMakeLists.txt
change_type: ModificationType.MODIFY
diff: @@ -121,6 +121,10 @@ if(SECURITY)
 
     include_directories(${OPENSSL_INCLUDE_DIR})
     set(EXTRA_LIBRARIES ${EXTRA_LIBRARIES} ${OPENSSL_LIBRARIES})
+
+    set(HAVE_SECURITY 1)
+else()
+    set(HAVE_SECURITY 0)
 endif()
 
 # Set version

programming_language: Shell
filename: Token.cpp
change_type: ModificationType.MODIFY
diff: @@ -147,3 +147,25 @@ const BinaryProperty* DataHolderHelper::find_binary_property(const DataHolder& d
 
     return returnedValue;
 }
+
+size_t DataHolderHelper::serialized_size(const DataHolder& data_holder, size_t current_alignment)
+{
+    size_t initial_alignment = current_alignment;
+
+    current_alignment += 4 + alignment(current_alignment, 4) + data_holder.class_id().size() + 1;
+    current_alignment += PropertyHelper::serialized_size(data_holder.properties(), current_alignment);
+    current_alignment += BinaryPropertyHelper::serialized_size(data_holder.binary_properties(), current_alignment);
+
+    return current_alignment - initial_alignment;
+}
+
+size_t DataHolderHelper::serialized_size(const DataHolderSeq& data_holders, size_t current_alignment)
+{
+    size_t initial_alignment = current_alignment;
+
+    current_alignment += 4 + alignment(current_alignment, 4);
+    for(auto data_holder = data_holders.begin(); data_holder != data_holders.end(); ++data_holder)
+        current_alignment += serialized_size(*data_holder, current_alignment);
+
+    return current_alignment - initial_alignment;
+}

programming_language: C++
filename: SecurityManager.cpp
change_type: ModificationType.MODIFY
diff: @@ -16,6 +16,11 @@
 #define ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_WRITER  0x000201C2
 #define ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_READER  0x000201C7
 
+#define AUTHENTICATION_PARTICIPANT_STATELESS_MESSAGE "dds.sec.auth"
+
+// TODO(Ricardo) Add event because stateless messages can be not received.
+// TODO(Ricardo) Add following of sequence in stateless messages.
+
 const EntityId_t participant_stateless_message_writer_entity_id = ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_WRITER;
 const EntityId_t participant_stateless_message_reader_entity_id = ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_READER;
 
@@ -29,7 +34,9 @@ bool usleep_bool()
     return true;
 }
 
-SecurityManager::SecurityManager(RTPSParticipantImpl *participant) : participant_(participant),
+SecurityManager::SecurityManager(RTPSParticipantImpl *participant) : 
+    participant_stateless_message_listener_(*this),
+    participant_(participant),
     participant_stateless_message_writer_(nullptr),
     participant_stateless_message_writer_history_(nullptr),
     participant_stateless_message_reader_(nullptr),
@@ -42,7 +49,31 @@ SecurityManager::SecurityManager(RTPSParticipantImpl *participant) : participant
 SecurityManager::~SecurityManager()
 {
     if(authentication_plugin_ != nullptr)
+    {
+        SecurityException exception;
+
+        for(auto& dp_it : discovered_participants_)
+        {
+            if(!dp_it.second.is_handshake_handle_null())
+            {
+                HandshakeHandle* handle = dp_it.second.get_handshake_handle();
+                authentication_plugin_->return_handshake_handle(handle, exception);
+            }
+
+            if(!dp_it.second.is_identity_handle_null())
+            {
+                IdentityHandle* handle = dp_it.second.get_identity_handle();
+                authentication_plugin_->return_identity_handle(handle, exception);
+            }
+        }
+
+        if(local_identity_handle_ != nullptr)
+            authentication_plugin_->return_identity_handle(local_identity_handle_, exception);
+
+        delete_entities();
+
         delete authentication_plugin_;
+    }
 }
 
 bool SecurityManager::init()
@@ -109,7 +140,8 @@ void SecurityManager::remove_discovered_participant_info(const GUID_t remote_par
 }
 
 void SecurityManager::restore_remote_identity_handle(const GUID_t& remote_participant_key,
-        IdentityHandle* remote_identity_handle)
+        IdentityHandle* remote_identity_handle,
+        HandshakeHandle* handshake_handle)
 {
     SecurityException exception;
 
@@ -120,14 +152,24 @@ void SecurityManager::restore_remote_identity_handle(const GUID_t& remote_partic
     {
         assert(dp_it->second.is_identity_handle_null());
         dp_it->second.set_identity_handle(remote_identity_handle);
+        assert(dp_it->second.is_handshake_handle_null());
+        dp_it->second.set_handshake_handle(handshake_handle);
     }
     else
+    {
         authentication_plugin_->return_identity_handle(remote_identity_handle, exception);
+
+        if(handshake_handle)
+            authentication_plugin_->return_handshake_handle(handshake_handle, exception);
+    }
 }
 
 bool SecurityManager::discovered_participant(IdentityToken&& remote_identity_token,
         const GUID_t& remote_participant_key)
 {
+    if(authentication_plugin_ == nullptr)
+        return true;
+
     IdentityHandle* remote_identity_handle = nullptr;
     SecurityException exception;
     AuthenticationStatus auth_status = AUTHENTICATION_INIT;
@@ -193,10 +235,14 @@ bool SecurityManager::discovered_participant(IdentityToken&& remote_identity_tok
             return false;
     }
 
+    int64_t last_sequence_number = 0;
+
     if(auth_status == AUTHENTICATION_REQUEST_NOT_SEND)
     {
         remote_identity_handle = dp_it->second.get_identity_handle();
         assert(remote_identity_handle);
+        last_sequence_number = dp_it->second.get_last_sequence_number();
+
     }
     mutex_.unlock();
 
@@ -205,82 +251,188 @@ bool SecurityManager::discovered_participant(IdentityToken&& remote_identity_tok
     // Maybe send request.
     if(remote_identity_handle != nullptr)
     {
-        returnedValue = on_request_not_send(remote_participant_key, remote_identity_handle);
+        returnedValue = on_process_handshake(remote_participant_key, AUTHENTICATION_REQUEST_NOT_SEND,
+                MessageIdentity(), HandshakeMessageToken(),
+                remote_identity_handle, nullptr, last_sequence_number);
     }
 
     return returnedValue;
 }
 
-bool SecurityManager::on_request_not_send(const GUID_t& remote_participant_key,
-        IdentityHandle* remote_identity_handle)
+bool SecurityManager::on_process_handshake(const GUID_t& remote_participant_key,
+        AuthenticationStatus pre_auth_status,
+        MessageIdentity&& message_identity,
+        HandshakeMessageToken&& message_in,
+        IdentityHandle* remote_identity_handle,
+        HandshakeHandle* handshake_handle, int64_t last_sequence_number)
 {
     assert(remote_identity_handle);
 
-    HandshakeHandle* handshake_handle = nullptr;
     HandshakeMessageToken* handshake_message = nullptr;
     SecurityException exception;
     
-    ValidationResult_t ret = authentication_plugin_->begin_handshake_request(&handshake_handle,
+    ValidationResult_t ret = VALIDATION_FAILED;
+    
+    if(pre_auth_status == AUTHENTICATION_REQUEST_NOT_SEND)
+    {
+        ret = authentication_plugin_->begin_handshake_request(&handshake_handle,
                 &handshake_message,
                 *local_identity_handle_,
                 *remote_identity_handle,
                 exception);
+    }
+    else if(pre_auth_status == AUTHENTICATION_WAITING_REQUEST)
+    {
+        assert(!handshake_handle);
+        ret = authentication_plugin_->begin_handshake_reply(&handshake_handle,
+                &handshake_message,
+                std::move(message_in),
+                *remote_identity_handle,
+                *local_identity_handle_,
+                exception);
+    }
+    else if(pre_auth_status == AUTHENTICATION_WAITING_REPLY ||
+            pre_auth_status == AUTHENTICATION_WAITING_FINAL)
+    {
+        assert(handshake_handle);
+        ret = authentication_plugin_->process_handshake(&handshake_message,
+                std::move(message_in),
+                *handshake_handle, 
+                exception);
+    }
 
     if(ret == VALIDATION_FAILED)
     {
-        restore_remote_identity_handle(remote_participant_key, remote_identity_handle);
+        restore_remote_identity_handle(remote_participant_key, remote_identity_handle, handshake_handle);
         return false;
     }
 
     assert(handshake_handle);
-    assert(handshake_message);
 
-    // Send hanshake message
-    // 
-    delete handshake_message;
+    bool handshake_message_send = true;
 
-    AuthenticationStatus auth_status = AUTHENTICATION_FAILED;
-
-    switch(ret)
+    if(ret == VALIDATION_PENDING_HANDSHAKE_MESSAGE ||
+            ret == VALIDATION_OK_WITH_FINAL_MESSAGE)
     {
-        case VALIDATION_OK:
-            auth_status = AUTHENTICATION_OK;
-            break;
-        case VALIDATION_PENDING_HANDSHAKE_MESSAGE:
-            auth_status = AUTHENTICATION_WAITING_REPLY;
-            break;
-        case VALIDATION_OK_WITH_FINAL_MESSAGE:
-            auth_status = AUTHENTICATION_OK;
-            break;
-        case VALIDATION_PENDING_RETRY:
-            // TODO(Ricardo) Send event.
-        default:
-            restore_remote_identity_handle(remote_participant_key, remote_identity_handle);
-            return false;
-    };
+        handshake_message_send = false;
 
-    // Store status
-    std::unique_lock<std::mutex> lock(mutex_);
+        assert(handshake_message);
 
-    auto dp_it = discovered_participants_.find(remote_participant_key);
+        // Send hanshake message
 
-    if(dp_it != discovered_participants_.end())
+        // Create message
+        ParticipantGenericMessage message = generate_authentication_message(last_sequence_number,
+                std::move(message_identity), remote_participant_key, std::move(*handshake_message));
+
+        CacheChange_t* change = participant_stateless_message_writer_->new_change([&message]() -> uint32_t
+                {
+                return ParticipantGenericMessageHelper::serialized_size(message);
+                }
+                , ALIVE, c_InstanceHandle_Unknown);
+
+        if(change != nullptr)
+        {
+            // Serialize message
+            CDRMessage_t aux_msg(0);
+            aux_msg.wraps = true;
+            aux_msg.buffer = change->serializedPayload.data;
+            aux_msg.length = change->serializedPayload.length;
+            aux_msg.max_size = change->serializedPayload.max_size;
+            aux_msg.msg_endian = change->serializedPayload.encapsulation == PL_CDR_BE ? BIGEND : LITTLEEND;
+
+            if(CDRMessage::addParticipantGenericMessage(&aux_msg, message))
+            {
+                // Send
+                if(participant_stateless_message_writer_history_->add_change(change))
+                {
+                    handshake_message_send = true;
+                }
+                else
+                {
+                    logError(SECURITY, "WriterHistory cannot add the CacheChange_t");
+                }
+            }
+            else
+            {
+                logError(SECURITY, "Cannot serialize ParticipantGenericMessage");
+            }
+        }
+        else
+        {
+            logError(SECURITY, "WriterHistory cannot retrieve a CacheChange_t");
+        }
+    }
+
+    bool returnedValue = false;
+
+    if(handshake_message_send)
     {
-        assert(dp_it->second.get_auth_status() == AUTHENTICATION_REQUEST_NOT_SEND);
-        dp_it->second.set_auth_status(auth_status);
-        assert(dp_it->second.is_identity_handle_null());
-        dp_it->second.set_identity_handle(remote_identity_handle);
-        assert(dp_it->second.is_handshake_handle_null());
-        dp_it->second.set_handshake_handle(handshake_handle);
+        AuthenticationStatus auth_status = AUTHENTICATION_FAILED;
+
+        switch(ret)
+        {
+            case VALIDATION_OK:
+            case VALIDATION_PENDING_HANDSHAKE_MESSAGE:
+            case VALIDATION_OK_WITH_FINAL_MESSAGE:
+                {
+                    auth_status = AUTHENTICATION_OK;
+                    if(ret == VALIDATION_PENDING_HANDSHAKE_MESSAGE)
+                    {
+                        if(pre_auth_status == AUTHENTICATION_REQUEST_NOT_SEND)
+                            auth_status = AUTHENTICATION_WAITING_REPLY;
+                        else if(pre_auth_status == AUTHENTICATION_WAITING_REQUEST)
+                            auth_status = AUTHENTICATION_WAITING_FINAL;
+                    }
+
+                    // Store status
+                    std::unique_lock<std::mutex> lock(mutex_);
+
+                    auto dp_it = discovered_participants_.find(remote_participant_key);
+
+                    if(dp_it != discovered_participants_.end())
+                    {
+                        assert(dp_it->second.get_auth_status() == pre_auth_status);
+                        dp_it->second.set_auth_status(auth_status);
+                        assert(dp_it->second.is_identity_handle_null());
+                        dp_it->second.set_identity_handle(remote_identity_handle);
+                        remote_identity_handle = nullptr;
+                        assert(dp_it->second.is_handshake_handle_null());
+                        dp_it->second.set_handshake_handle(handshake_handle);
+                        handshake_handle = nullptr;
+                        if(ret == VALIDATION_PENDING_HANDSHAKE_MESSAGE ||
+                                ret == VALIDATION_OK_WITH_FINAL_MESSAGE)
+                            dp_it->second.set_last_sequence_number(++last_sequence_number);
+
+                        returnedValue = true;
+                    }
+                    else
+                    {
+                        authentication_plugin_->return_handshake_handle(handshake_handle, exception);
+                        handshake_handle = nullptr;
+                        authentication_plugin_->return_identity_handle(remote_identity_handle, exception);
+                        remote_identity_handle = nullptr;
+                    }
+                }
+                break;
+            case VALIDATION_PENDING_RETRY:
+                // TODO(Ricardo) Send event.
+            default:
+                break;
+        };
     }
-    else
+
+    if(handshake_handle != nullptr && (pre_auth_status == AUTHENTICATION_REQUEST_NOT_SEND ||
+                pre_auth_status == AUTHENTICATION_WAITING_REQUEST))
     {
         authentication_plugin_->return_handshake_handle(handshake_handle, exception);
-        authentication_plugin_->return_identity_handle(remote_identity_handle, exception);
-        return false;
+        handshake_handle = nullptr;
     }
+    if(remote_identity_handle != nullptr)
+        restore_remote_identity_handle(remote_participant_key, remote_identity_handle, handshake_handle);
 
-    return true;
+    delete handshake_message;
+
+    return returnedValue;
 }
 
 bool SecurityManager::create_entities()
@@ -293,6 +445,11 @@ bool SecurityManager::create_entities()
     return false; 
 }
 
+void SecurityManager::delete_entities()
+{
+    delete_participant_stateless_message_entities();
+}
+
 bool SecurityManager::create_participant_stateless_message_entities()
 {
     if(create_participant_stateless_message_writer())
@@ -334,6 +491,7 @@ bool SecurityManager::create_participant_stateless_message_writer()
     if(participant_->createWriter(&wout, watt, participant_stateless_message_writer_history_, nullptr, participant_stateless_message_writer_entity_id, true))
     {
         participant_stateless_message_writer_ = dynamic_cast<StatelessWriter*>(wout);
+        auth_source_guid = participant_stateless_message_writer_->getGuid();
 
         return true;
     }
@@ -348,10 +506,16 @@ bool SecurityManager::create_participant_stateless_message_writer()
 void SecurityManager::delete_participant_stateless_message_writer()
 {
     if(participant_stateless_message_writer_ != nullptr)
+    {
         delete participant_stateless_message_writer_;
+        participant_stateless_message_writer_ = nullptr;
+    }
 
     if(participant_stateless_message_writer_history_ != nullptr)
+    {
         delete participant_stateless_message_writer_history_;
+        participant_stateless_message_writer_history_ = nullptr;
+    }
 }
 
 bool SecurityManager::create_participant_stateless_message_reader()
@@ -364,10 +528,10 @@ bool SecurityManager::create_participant_stateless_message_reader()
     ReaderAttributes ratt;
     ratt.endpoint.topicKind = NO_KEY;
     ratt.endpoint.reliabilityKind = BEST_EFFORT;
-    //mp_listener = new PDPSimpleListener(this);
 
     RTPSReader* rout = nullptr;
-    if(participant_->createReader(&rout, ratt, participant_stateless_message_reader_history_, nullptr, participant_stateless_message_reader_entity_id, true, false))
+    if(participant_->createReader(&rout, ratt, participant_stateless_message_reader_history_, &participant_stateless_message_listener_,
+                participant_stateless_message_reader_entity_id, true, false))
     {
         participant_stateless_message_reader_ = dynamic_cast<StatelessReader*>(rout);
 
@@ -377,16 +541,165 @@ bool SecurityManager::create_participant_stateless_message_reader()
     logError(SECURITY,"Participant Stateless Message Reader creation failed");
     delete(participant_stateless_message_reader_history_);
     participant_stateless_message_reader_history_ = nullptr;
-    //delete(mp_listener);
-    //mp_listener = nullptr;
     return false;
 }
 
 void SecurityManager::delete_participant_stateless_message_reader()
 {
     if(participant_stateless_message_reader_ != nullptr)
+    {
         delete participant_stateless_message_reader_;
+        participant_stateless_message_reader_ = nullptr;
+    }
 
     if(participant_stateless_message_reader_history_ != nullptr)
+    {
         delete participant_stateless_message_reader_history_;
+        participant_stateless_message_reader_history_ = nullptr;
+    }
+}
+
+ParticipantGenericMessage SecurityManager::generate_authentication_message(int64_t sequence_number,
+        const MessageIdentity& related_message_identity,
+        const GUID_t& destination_participant_key,
+        HandshakeMessageToken&& handshake_message)
+{
+    ParticipantGenericMessage message;
+
+    message.message_identity().source_guid(auth_source_guid);
+    message.message_identity().sequence_number(sequence_number);
+    message.related_message_identity(related_message_identity);
+    message.destination_participant_key(destination_participant_key);
+    message.message_class_id(AUTHENTICATION_PARTICIPANT_STATELESS_MESSAGE);
+    message.message_data().push_back(std::move(handshake_message));
+
+    return message;
+}
+
+void SecurityManager::process_participant_stateless_message(const CacheChange_t* const change)
+{
+    assert(change);
+
+    // Deserialize message
+    ParticipantGenericMessage message;
+    CDRMessage_t aux_msg(0);
+    aux_msg.wraps = true;
+    aux_msg.buffer = change->serializedPayload.data;
+    aux_msg.length = change->serializedPayload.length;
+    aux_msg.max_size = change->serializedPayload.max_size;
+    aux_msg.msg_endian = change->serializedPayload.encapsulation == PL_CDR_BE ? BIGEND : LITTLEEND;
+
+    CDRMessage::readParticipantGenericMessage(&aux_msg, message);
+
+    if(message.message_class_id().compare(AUTHENTICATION_PARTICIPANT_STATELESS_MESSAGE) == 0)
+    {
+        if(message.destination_endpoint_key() != GUID_t::unknown())
+        {
+            logInfo(SECURITY, "Bad ParticipantGenericMessage. destination_endpoint_key is not GUID_t::unknown()");
+            return;
+        }
+        if(message.source_endpoint_key() != GUID_t::unknown())
+        {
+            logInfo(SECURITY, "Bad ParticipantGenericMessage. source_endpoint_key is not GUID_t::unknown()");
+            return;
+        }
+
+        const GUID_t& remote_participant_key = message.destination_participant_key();
+        AuthenticationStatus auth_status;
+        IdentityHandle* remote_identity_handle = nullptr;
+        HandshakeHandle* handshake_handle = nullptr;
+        int64_t last_sequence_number = 0;
+
+        mutex_.lock();
+        auto dp_it = discovered_participants_.find(remote_participant_key);
+
+        if(dp_it != discovered_participants_.end())
+        {
+            auth_status = dp_it->second.get_auth_status();
+            remote_identity_handle = dp_it->second.get_identity_handle();
+            handshake_handle = dp_it->second.get_handshake_handle();
+            last_sequence_number = dp_it->second.get_last_sequence_number();
+        }
+        else
+        {
+            logInfo(SECURITY, "Received Authentication message but not found related remote_participant_key");
+        }
+        mutex_.unlock();
+
+        if(remote_identity_handle != nullptr)
+        {
+            if(auth_status == AUTHENTICATION_WAITING_REQUEST)
+            {
+                assert(!handshake_handle);
+
+                // Preconditions
+                if(message.message_identity().source_guid() == GUID_t::unknown())
+                {
+                    logInfo(SECURITY, "Bad ParticipantGenericMessage. message_identity.source_guid is GUID_t::unknown()");
+                    restore_remote_identity_handle(remote_participant_key, remote_identity_handle);
+                    return;
+                }
+                if(message.related_message_identity().source_guid() != GUID_t::unknown())
+                {
+                    logInfo(SECURITY, "Bad ParticipantGenericMessage. related_message_identity.source_guid is not GUID_t::unknown()");
+                    restore_remote_identity_handle(remote_participant_key, remote_identity_handle);
+                    return;
+                }
+                if(message.message_data().size() != 1)
+                {
+                    logInfo(SECURITY, "Bad ParticipantGenericMessage. message_data size is not 1");
+                    restore_remote_identity_handle(remote_participant_key, remote_identity_handle);
+                    return;
+                }
+            }
+            else if(auth_status == AUTHENTICATION_WAITING_REPLY ||
+                    auth_status == AUTHENTICATION_WAITING_FINAL)
+            {
+                assert(handshake_handle);
+
+                // Preconditions
+                if(message.message_identity().source_guid() == GUID_t::unknown())
+                {
+                    logInfo(SECURITY, "Bad ParticipantGenericMessage. message_identity.source_guid is GUID_t::unknown()");
+                    restore_remote_identity_handle(remote_participant_key, remote_identity_handle, handshake_handle);
+                    return;
+                }
+                if(message.related_message_identity().source_guid() == GUID_t::unknown())
+                {
+                    logInfo(SECURITY, "Bad ParticipantGenericMessage. related_message_identity.source_guid is GUID_t::unknown()");
+                    restore_remote_identity_handle(remote_participant_key, remote_identity_handle, handshake_handle);
+                    return;
+                }
+                if(message.message_data().size() != 1)
+                {
+                    logInfo(SECURITY, "Bad ParticipantGenericMessage. message_data size is not 1");
+                    restore_remote_identity_handle(remote_participant_key, remote_identity_handle, handshake_handle);
+                    return;
+                }
+            }
+            else
+            {
+                restore_remote_identity_handle(remote_participant_key, remote_identity_handle, handshake_handle);
+                return;
+            }
+
+            on_process_handshake(remote_participant_key, auth_status, std::move(message.related_message_identity()),
+                    std::move(message.message_data().at(0)), remote_identity_handle,
+                    handshake_handle, last_sequence_number);
+        }
+    }
+    else
+    {
+        logInfo(SECURITY, "Discarted ParticipantGenericMessage with class id " << message.message_class_id());
+    }
+}
+
+void SecurityManager::ParticipantStatelessMessageListener::onNewCacheChangeAdded(RTPSReader* reader,
+        const CacheChange_t* const change)
+{
+    manager_.process_participant_stateless_message(change);
+
+    ReaderHistory *history = reader->getHistory();
+    assert(history);
+    history->remove_change((CacheChange_t*)change);
 }

programming_language: C++
filename: SecurityManager.h
change_type: ModificationType.MODIFY
diff: @@ -21,6 +21,8 @@
 #include "SecurityPluginFactory.h"
 
 #include <fastrtps/rtps/security/authentication/Handshake.h>
+#include <fastrtps/rtps/security/common/ParticipantGenericMessage.h>
+#include <fastrtps/rtps/reader/ReaderListener.h>
 
 #include <map>
 #include <mutex>
@@ -71,7 +73,8 @@ class SecurityManager
 
                 DiscoveredParticipantInfo(AuthenticationStatus auth_status) :
                     identity_handle_(nullptr), handshake_handle_(nullptr),
-                    auth_status_(auth_status){}
+                    auth_status_(auth_status), last_sequence_number_(1)
+                {}
 
                 bool is_identity_handle_null()
                 {
@@ -129,6 +132,16 @@ class SecurityManager
                     auth_status_ = auth_status;
                 }
 
+                void set_last_sequence_number(int64_t sequence_number)
+                {
+                    last_sequence_number_ = sequence_number;
+                }
+
+                int64_t get_last_sequence_number()
+                {
+                    return last_sequence_number_;
+                }
+
             private:
 
                 DiscoveredParticipantInfo(const DiscoveredParticipantInfo& info) = delete;
@@ -138,11 +151,30 @@ class SecurityManager
                 HandshakeHandle* handshake_handle_;
 
                 AuthenticationStatus auth_status_;
+
+                int64_t last_sequence_number_;
         };
 
+        class ParticipantStatelessMessageListener: public eprosima::fastrtps::rtps::ReaderListener
+        {
+            public:
+                ParticipantStatelessMessageListener(SecurityManager &manager) : manager_(manager) {};
+
+                ~ParticipantStatelessMessageListener(){};
+
+                void onNewCacheChangeAdded(RTPSReader* reader, const CacheChange_t* const change);
+
+            private:
+
+                ParticipantStatelessMessageListener& operator=(const ParticipantStatelessMessageListener&) NON_COPYABLE_CXX11;
+
+                SecurityManager &manager_;
+        } participant_stateless_message_listener_;
+
         void remove_discovered_participant_info(const GUID_t remote_participant_key);
         void restore_remote_identity_handle(const GUID_t& remote_participant_key,
-                IdentityHandle* remote_identity_handle);
+                IdentityHandle* remote_identity_handle,
+                HandshakeHandle* handshake_handle = nullptr);
 
         bool create_entities();
         void delete_entities();
@@ -153,7 +185,20 @@ class SecurityManager
         bool create_participant_stateless_message_reader();
         void delete_participant_stateless_message_reader();
 
-        bool on_request_not_send(const GUID_t& remote_participant_key, IdentityHandle* remote_identity_handle);
+        void process_participant_stateless_message(const CacheChange_t* const change);
+
+        bool on_process_handshake(const GUID_t& remote_participant_key,
+                AuthenticationStatus pre_auth_status,
+                MessageIdentity&& message_identity,
+                HandshakeMessageToken&& message,
+                IdentityHandle* remote_identity_handle,
+                HandshakeHandle* handshake_handle,
+                int64_t last_sequence_number);
+
+        ParticipantGenericMessage generate_authentication_message(int64_t sequence_number,
+                const MessageIdentity& related_message_identity,
+                const GUID_t& destination_participant_key,
+                HandshakeMessageToken&& handshake_message);
 
         RTPSParticipantImpl* participant_;
         StatelessWriter* participant_stateless_message_writer_;
@@ -168,6 +213,8 @@ class SecurityManager
 
         std::map<GUID_t, DiscoveredParticipantInfo> discovered_participants_;
 
+        GUID_t auth_source_guid;
+
         std::mutex mutex_;
 };
 

programming_language: C++
filename: RTPSParticipantImpl.h
change_type: ModificationType.MODIFY
diff: @@ -21,6 +21,8 @@
 
 #include <fastrtps/rtps/attributes/WriterAttributes.h>
 #include <fastrtps/rtps/attributes/ReaderAttributes.h>
+#include <fastrtps/rtps/writer/RTPSWriter.h>
+#include <fastrtps/rtps/reader/RTPSReader.h>
 
 #include <gmock/gmock.h>
 
@@ -28,8 +30,6 @@ namespace eprosima {
 namespace fastrtps {
 namespace rtps {
 
-class RTPSWriter;
-class RTPSReader;
 class WriterHistory;
 class ReaderHistory;
 class WriterListener;
@@ -44,11 +44,32 @@ class RTPSParticipantImpl
 
         MOCK_CONST_METHOD0(getGuid, const GUID_t&());
 
-        MOCK_METHOD6(createWriter, bool (RTPSWriter** Writer, WriterAttributes& param, WriterHistory* hist,WriterListener* listen,
+        MOCK_METHOD6(createWriter_mock, bool (RTPSWriter** writer, WriterAttributes& param, WriterHistory* hist,WriterListener* listen,
                 const EntityId_t& entityId, bool isBuiltin));
 
-        MOCK_METHOD7(createReader, bool (RTPSReader** Reader, ReaderAttributes& param, ReaderHistory* hist,ReaderListener* listen,
+        MOCK_METHOD7(createReader_mock, bool (RTPSReader** reader, ReaderAttributes& param, ReaderHistory* hist,ReaderListener* listen,
                 const EntityId_t& entityId, bool isBuiltin, bool enable));
+
+        bool createWriter(RTPSWriter** writer, WriterAttributes& param, WriterHistory* hist, WriterListener* listen,
+                const EntityId_t& entityId, bool isBuiltin)
+        {
+            bool ret = createWriter_mock(writer, param , hist, listen, entityId, isBuiltin);
+            if(*writer != nullptr)
+                (*writer)->history_ = hist;
+            return ret;
+        }
+
+        bool createReader(RTPSReader** reader, ReaderAttributes& param, ReaderHistory* hist,ReaderListener* listen,
+                const EntityId_t& entityId, bool isBuiltin, bool enable)
+        {
+            bool ret = createReader_mock(reader, param, hist, listen, entityId, isBuiltin, enable);
+            if(*reader != nullptr)
+            {
+                (*reader)->history_ = hist;
+                (*reader)->listener_ = listen;
+            }
+            return ret;
+        }
 };
 
 } // namespace rtps

programming_language: C++
filename: RTPSReader.h
change_type: ModificationType.MODIFY
diff: @@ -19,6 +19,11 @@
 #ifndef _RTPS_READER_RTPSREADER_H_
 #define _RTPS_READER_RTPSREADER_H_
 
+#include <fastrtps/rtps/history/ReaderHistory.h>
+#include <fastrtps/rtps/reader/ReaderListener.h>
+
+#include <gmock/gmock.h>
+
 namespace eprosima {
 namespace fastrtps {
 namespace rtps {
@@ -30,6 +35,18 @@ class RTPSReader
         virtual bool matched_writer_add(RemoteWriterAttributes& wdata) = 0;
 
         virtual bool matched_writer_remove(RemoteWriterAttributes& wdata) = 0;
+
+        MOCK_METHOD0(getHistory_mock, ReaderHistory*());
+
+        ReaderHistory* getHistory()
+        {
+            getHistory_mock();
+            return history_;
+        }
+
+        ReaderHistory* history_;
+
+        ReaderListener* listener_;
 };
 
 } // namespace rtps

programming_language: C++
filename: RTPSWriter.h
change_type: ModificationType.MODIFY
diff: @@ -19,10 +19,14 @@
 #ifndef _RTPS_WRITER_RTPSWRITER_H_
 #define _RTPS_WRITER_RTPSWRITER_H_
 
+#include <gmock/gmock.h>
+
 namespace eprosima {
 namespace fastrtps {
 namespace rtps {
 
+class WriterHistory;
+
 class RTPSWriter
 {
     public:
@@ -30,6 +34,11 @@ class RTPSWriter
         virtual bool matched_reader_add(RemoteReaderAttributes& ratt) = 0;
 
         virtual bool matched_reader_remove(RemoteReaderAttributes& ratt) = 0;
+
+        MOCK_METHOD3(new_change, CacheChange_t*(const std::function<uint32_t()>&,
+            ChangeKind_t, InstanceHandle_t));
+
+        WriterHistory* history_;
 };
 
 } // namespace rtps

programming_language: C++
filename: ReaderHistory.h
change_type: ModificationType.MODIFY
diff: @@ -21,6 +21,8 @@
 
 #include <fastrtps/rtps/attributes/HistoryAttributes.h>
 
+#include <gmock/gmock.h>
+
 namespace eprosima {
 namespace fastrtps {
 namespace rtps {
@@ -30,6 +32,8 @@ class ReaderHistory
     public:
 
         ReaderHistory(const HistoryAttributes& /*att*/){}
+
+        MOCK_METHOD1(remove_change, bool(CacheChange_t*));
 };
 
 } // namespace rtps

programming_language: C++
filename: SecurityPluginFactory.cpp
change_type: ModificationType.MODIFY
diff: @@ -25,7 +25,9 @@ Authentication* SecurityPluginFactory::auth_plugin_ = nullptr;
 
 Authentication* SecurityPluginFactory::create_authentication_plugin(const PropertyPolicy& /*property_policy*/)
 {
-    return auth_plugin_;
+    Authentication* ret =  auth_plugin_;
+    auth_plugin_ = nullptr;
+    return ret;
 }
 
 void SecurityPluginFactory::set_auth_plugin(Authentication* plugin)
@@ -35,5 +37,9 @@ void SecurityPluginFactory::set_auth_plugin(Authentication* plugin)
 
 void SecurityPluginFactory::release_auth_plugin()
 {
-    auth_plugin_ = nullptr;
+    if(auth_plugin_ != nullptr)
+    {
+        delete auth_plugin_;
+        auth_plugin_ = nullptr;
+    }
 }

programming_language: C++
filename: StatelessWriter.h
change_type: ModificationType.MODIFY
diff: @@ -32,6 +32,8 @@ class StatelessWriter : public RTPSWriter
         MOCK_METHOD1(matched_reader_add, bool(RemoteReaderAttributes&));
 
         MOCK_METHOD1(matched_reader_remove, bool(RemoteReaderAttributes&));
+
+        MOCK_METHOD0(getGuid, const GUID_t&());
 };
 
 } // namespace rtps

programming_language: C#
filename: WriterHistory.h
change_type: ModificationType.MODIFY
diff: @@ -31,6 +31,8 @@ class WriterHistory
 
 
         WriterHistory(const HistoryAttributes& /*att*/){}
+
+        MOCK_METHOD1(add_change, bool(CacheChange_t*));
 };
 
 } // namespace rtps

programming_language: C++
filename: CMakeLists.txt
change_type: ModificationType.MODIFY
diff: @@ -26,10 +26,11 @@ if(NOT ((MSVC OR MSVC_IDE) AND EPROSIMA_INSTALLER))
             ${PROJECT_SOURCE_DIR}/src/cpp/log/Log.cpp
             ${PROJECT_SOURCE_DIR}/src/cpp/log/StdoutConsumer.cpp
             ${PROJECT_SOURCE_DIR}/src/cpp/rtps/attributes/PropertyPolicy.cpp
-            ${PROJECT_SOURCE_DIR}/test/mock/rtps/SecurityPluginFactory/SecurityPluginFactory.cpp
-            ${PROJECT_SOURCE_DIR}/src/cpp/rtps/security/SecurityManager.cpp
+            ${PROJECT_SOURCE_DIR}/src/cpp/rtps/common/Token.cpp
             ${PROJECT_SOURCE_DIR}/src/cpp/rtps/exceptions/Exception.cpp
+            ${PROJECT_SOURCE_DIR}/src/cpp/rtps/security/SecurityManager.cpp
             ${PROJECT_SOURCE_DIR}/src/cpp/rtps/security/exceptions/SecurityException.cpp
+            ${PROJECT_SOURCE_DIR}/test/mock/rtps/SecurityPluginFactory/SecurityPluginFactory.cpp
             )
 
         add_executable(SecurityAuthentication ${SOURCES_SECURITY_TEST_SOURCE}

programming_language: Shell
filename: SecurityAuthenticationTests.cpp
change_type: ModificationType.MODIFY
diff: @@ -15,6 +15,10 @@
 #include <fastrtps/rtps/security/common/Handle.h>
 #include <MockAuthenticationPlugin.h>
 #include <rtps/participant/RTPSParticipantImpl.h>
+#include <fastrtps/rtps/writer/StatelessWriter.h>
+#include <fastrtps/rtps/history/WriterHistory.h>
+#include <fastrtps/rtps/reader/StatelessReader.h>
+#include <fastrtps/rtps/history/ReaderHistory.h>
 #include <SecurityPluginFactory.h>
 #include <SecurityManager.h>
 
@@ -52,6 +56,26 @@ typedef HandleImpl<MockHandshake> MockHandshakeHandle;
 RTPSParticipantAttributes pattr;
 GUID_t guid;
 
+void fill_participant_key(GUID_t& participant_key)
+{
+    participant_key.guidPrefix.value[0] = 1;
+    participant_key.guidPrefix.value[1] = 2;
+    participant_key.guidPrefix.value[2] = 3;
+    participant_key.guidPrefix.value[3] = 4;
+    participant_key.guidPrefix.value[4] = 5;
+    participant_key.guidPrefix.value[5] = 6;
+    participant_key.guidPrefix.value[6] = 7;
+    participant_key.guidPrefix.value[7] = 8;
+    participant_key.guidPrefix.value[8] = 9;
+    participant_key.guidPrefix.value[9] = 10;
+    participant_key.guidPrefix.value[10] = 11;
+    participant_key.guidPrefix.value[11] = 12;
+    participant_key.entityId.value[0] = 13;
+    participant_key.entityId.value[1] = 14;
+    participant_key.entityId.value[2] = 15;
+    participant_key.entityId.value[3] = 16;
+}
+
 class SecurityAuthenticationTest : public ::testing::Test
 {
     protected:
@@ -59,6 +83,7 @@ class SecurityAuthenticationTest : public ::testing::Test
         virtual void SetUp()
         {
             SecurityPluginFactory::set_auth_plugin(auth_plugin_);
+            fill_participant_key(guid);
         }
 
         virtual void TearDown()
@@ -70,25 +95,111 @@ class SecurityAuthenticationTest : public ::testing::Test
         {
             DefaultValue<const RTPSParticipantAttributes&>::Set(pattr);
             DefaultValue<const GUID_t&>::Set(guid);
+            stateless_writer_ = new NiceMock<StatelessWriter>();
+            stateless_reader_ = new NiceMock<StatelessReader>();
             MockIdentityHandle identity_handle;
             MockIdentityHandle* p_identity_handle = &identity_handle;
 
             EXPECT_CALL(*auth_plugin_, validate_local_identity(_,_,_,_,_,_)).Times(1).
                 WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_OK)));
-            EXPECT_CALL(participant_, createWriter(_,_,_,_,_,_)).Times(1).
-                WillOnce(Return(true));
-            EXPECT_CALL(participant_, createReader(_,_,_,_,_,_,_)).Times(1).
-                WillOnce(Return(true));
+            EXPECT_CALL(participant_, createWriter_mock(_,_,_,_,_,_)).Times(1).
+                WillOnce(DoAll(SetArgPointee<0>(stateless_writer_), Return(true)));
+            EXPECT_CALL(participant_, createReader_mock(_,_,_,_,_,_,_)).Times(1).
+                WillOnce(DoAll(SetArgPointee<0>(stateless_reader_), Return(true)));
 
             ASSERT_TRUE(manager_.init());
         }
 
+        void request_process_ok()
+        {
+            initialization_ok();
+
+            MockIdentityHandle identity_handle;
+            MockIdentityHandle* p_identity_handle = &identity_handle;
+            MockHandshakeHandle handshake_handle;
+            MockHandshakeHandle* p_handshake_handle = &handshake_handle;
+            HandshakeMessageToken* p_handshake_message = new HandshakeMessageToken();
+            CacheChange_t* change = new CacheChange_t(200);
+
+            EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
+                WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_REQUEST)));
+            EXPECT_CALL(*auth_plugin_, begin_handshake_request(_,_,_,_,_)).Times(1).
+                WillOnce(DoAll(SetArgPointee<0>(p_handshake_handle), 
+                            SetArgPointee<1>(p_handshake_message), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_MESSAGE)));
+            EXPECT_CALL(*stateless_writer_, new_change(_,_,_)).Times(1).
+                WillOnce(Return(change));
+            EXPECT_CALL(*stateless_writer_->history_, add_change(change)).Times(1).
+                WillOnce(Return(true));
+
+            GUID_t remote_participant_key;
+            fill_participant_key(remote_participant_key);
+            ASSERT_TRUE(manager_.discovered_participant(IdentityToken(), remote_participant_key));
+
+            delete change;
+        }
+
+        void reply_process_ok()
+        {
+            initialization_ok();
+
+            MockIdentityHandle identity_handle;
+            MockIdentityHandle* p_identity_handle = &identity_handle;
+
+            EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
+                WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_MESSAGE)));
+
+            GUID_t remote_participant_key;
+            fill_participant_key(remote_participant_key);
+            ASSERT_TRUE(manager_.discovered_participant(IdentityToken(), remote_participant_key));
+
+            ParticipantGenericMessage message;
+            message.message_identity().source_guid(remote_participant_key);
+            message.destination_participant_key(remote_participant_key);
+            message.message_class_id("dds.sec.auth");
+            HandshakeMessageToken token;
+            message.message_data().push_back(token);
+            CacheChange_t* change = new CacheChange_t(ParticipantGenericMessageHelper::serialized_size(message));
+            CDRMessage_t aux_msg(0);
+            aux_msg.wraps = true;
+            aux_msg.buffer = change->serializedPayload.data;
+            aux_msg.max_size = change->serializedPayload.max_size;
+            aux_msg.msg_endian = change->serializedPayload.encapsulation == PL_CDR_BE ? BIGEND : LITTLEEND;
+            ASSERT_TRUE(CDRMessage::addParticipantGenericMessage(&aux_msg, message));
+            change->serializedPayload.length = aux_msg.length;
+
+            MockHandshakeHandle handshake_handle;
+            MockHandshakeHandle* p_handshake_handle = &handshake_handle;
+            HandshakeMessageToken* p_handshake_message = new HandshakeMessageToken();
+            CacheChange_t* change2 = new CacheChange_t(200);
+
+            EXPECT_CALL(*auth_plugin_, begin_handshake_reply_rvr(_,_,_,_,_,_)).Times(1).
+                WillOnce(DoAll(SetArgPointee<0>(p_handshake_handle), 
+                            SetArgPointee<1>(p_handshake_message), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_MESSAGE)));
+            EXPECT_CALL(*stateless_writer_, new_change(_,_,_)).Times(1).
+                WillOnce(Return(change2));
+            EXPECT_CALL(*stateless_writer_->history_, add_change(change2)).Times(1).
+                WillOnce(Return(true));
+            EXPECT_CALL(*stateless_reader_->history_, remove_change(change)).Times(1).
+                WillOnce(Return(true));
+
+            stateless_reader_->listener_->onNewCacheChangeAdded(stateless_reader_, change);
+
+            delete change2;
+        }
 
     public:
 
-        SecurityAuthenticationTest() : auth_plugin_(new MockAuthenticationPlugin()), manager_(&participant_) {}
+        SecurityAuthenticationTest() : auth_plugin_(new MockAuthenticationPlugin()),
+        stateless_writer_(nullptr), stateless_reader_(nullptr), manager_(&participant_) {}
+
+        ~SecurityAuthenticationTest()
+        {
+        }
+
         MockAuthenticationPlugin* auth_plugin_;
         NiceMock<RTPSParticipantImpl> participant_;
+        NiceMock<StatelessWriter>* stateless_writer_;
+        NiceMock<StatelessReader>* stateless_reader_;
         SecurityManager manager_;
 };
 
@@ -121,7 +232,7 @@ TEST_F(SecurityAuthenticationTest, initialization_fail_participant_stateless_mes
 
     EXPECT_CALL(*auth_plugin_, validate_local_identity(_,_,_,_,_,_)).Times(1).
         WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_OK)));
-    EXPECT_CALL(participant_, createWriter(_,_,_,_,_,_)).Times(1).
+    EXPECT_CALL(participant_, createWriter_mock(_,_,_,_,_,_)).Times(1).
         WillOnce(Return(false));
 
     ASSERT_FALSE(manager_.init());
@@ -131,14 +242,15 @@ TEST_F(SecurityAuthenticationTest, initialization_fail_participant_stateless_mes
 {
     DefaultValue<const RTPSParticipantAttributes&>::Set(pattr);
     DefaultValue<const GUID_t&>::Set(guid);
+    NiceMock<StatelessWriter>* stateless_writer = new NiceMock<StatelessWriter>();
     MockIdentityHandle identity_handle;
     MockIdentityHandle* p_identity_handle = &identity_handle;
 
     EXPECT_CALL(*auth_plugin_, validate_local_identity(_,_,_,_,_,_)).Times(1).
         WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_OK)));
-    EXPECT_CALL(participant_, createWriter(_,_,_,_,_,_)).Times(1).
-        WillOnce(Return(true));
-    EXPECT_CALL(participant_, createReader(_,_,_,_,_,_,_)).Times(1).
+    EXPECT_CALL(participant_, createWriter_mock(_,_,_,_,_,_)).Times(1).
+        WillOnce(DoAll(SetArgPointee<0>(stateless_writer), Return(true)));
+    EXPECT_CALL(participant_, createReader_mock(_,_,_,_,_,_,_)).Times(1).
         WillOnce(Return(false));
 
     ASSERT_FALSE(manager_.init());
@@ -148,16 +260,20 @@ TEST_F(SecurityAuthenticationTest, initialization_auth_retry)
 {
     DefaultValue<const RTPSParticipantAttributes&>::Set(pattr);
     DefaultValue<const GUID_t&>::Set(guid);
+    NiceMock<StatelessWriter>* stateless_writer = new NiceMock<StatelessWriter>();
+    NiceMock<StatelessReader>* stateless_reader = new NiceMock<StatelessReader>();
     MockIdentityHandle identity_handle;
     MockIdentityHandle* p_identity_handle = &identity_handle;
 
     EXPECT_CALL(*auth_plugin_, validate_local_identity(_,_,_,_,_,_)).Times(2).
         WillOnce(Return(ValidationResult_t::VALIDATION_PENDING_RETRY)).
         WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_OK)));
-    EXPECT_CALL(participant_, createWriter(_,_,_,_,_,_)).Times(1).
-        WillOnce(Return(true));
-    EXPECT_CALL(participant_, createReader(_,_,_,_,_,_,_)).Times(1).
-        WillOnce(Return(true));
+    EXPECT_CALL(participant_, createWriter_mock(_,_,_,_,_,_)).Times(1).
+        WillOnce(DoAll(SetArgPointee<0>(stateless_writer), Return(true)));
+    EXPECT_CALL(participant_, createReader_mock(_,_,_,_,_,_,_)).Times(1).
+        WillOnce(DoAll(SetArgPointee<0>(stateless_reader), Return(true)));
+    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(1).
+        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
 
     ASSERT_TRUE(manager_.init());
 }
@@ -165,6 +281,9 @@ TEST_F(SecurityAuthenticationTest, initialization_auth_retry)
 
 TEST_F(SecurityAuthenticationTest, initialization_ok)
 {
+    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(1).
+        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
+
     initialization_ok();
 }
 
@@ -174,8 +293,11 @@ TEST_F(SecurityAuthenticationTest, discovered_participant_validation_remote_iden
 
     EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
         WillOnce(Return(ValidationResult_t::VALIDATION_FAILED));
+    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(1).
+        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
 
     GUID_t remote_participant_key;
+    fill_participant_key(remote_participant_key);
     ASSERT_FALSE(manager_.discovered_participant(IdentityToken(), remote_participant_key));
 }
 
@@ -188,8 +310,11 @@ TEST_F(SecurityAuthenticationTest, discovered_participant_validation_remote_iden
 
     EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
         WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_OK)));
+    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
+        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
 
     GUID_t remote_participant_key;
+    fill_participant_key(remote_participant_key);
     ASSERT_TRUE(manager_.discovered_participant(IdentityToken(), remote_participant_key));
 }
 
@@ -202,8 +327,11 @@ TEST_F(SecurityAuthenticationTest, discovered_participant_validation_remote_iden
 
     EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
         WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_MESSAGE)));
+    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
+        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
 
     GUID_t remote_participant_key;
+    fill_participant_key(remote_participant_key);
     ASSERT_TRUE(manager_.discovered_participant(IdentityToken(), remote_participant_key));
 }
 
@@ -218,8 +346,11 @@ TEST_F(SecurityAuthenticationTest, discovered_participant_validation_remote_iden
         WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_REQUEST)));
     EXPECT_CALL(*auth_plugin_, begin_handshake_request(_,_,_,_,_)).Times(1).
         WillOnce(Return(ValidationResult_t::VALIDATION_FAILED));
+    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
+        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
 
     GUID_t remote_participant_key;
+    fill_participant_key(remote_participant_key);
     ASSERT_FALSE(manager_.discovered_participant(IdentityToken(), remote_participant_key));
 }
 
@@ -231,18 +362,91 @@ TEST_F(SecurityAuthenticationTest, discovered_participant_validation_remote_iden
     MockIdentityHandle* p_identity_handle = &identity_handle;
     MockHandshakeHandle handshake_handle;
     MockHandshakeHandle* p_handshake_handle = &handshake_handle;
-    HandshakeMessageToken* p_handshake_message = new HandshakeMessageToken();
 
     EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
         WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_REQUEST)));
     EXPECT_CALL(*auth_plugin_, begin_handshake_request(_,_,_,_,_)).Times(1).
         WillOnce(DoAll(SetArgPointee<0>(p_handshake_handle), 
-                    SetArgPointee<1>(p_handshake_message), Return(ValidationResult_t::VALIDATION_OK)));
+                    Return(ValidationResult_t::VALIDATION_OK)));
+    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
+        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
+    EXPECT_CALL(*auth_plugin_, return_handshake_handle(_,_)).Times(1).
+        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
 
     GUID_t remote_participant_key;
+    fill_participant_key(remote_participant_key);
     ASSERT_TRUE(manager_.discovered_participant(IdentityToken(), remote_participant_key));
 }
 
+TEST_F(SecurityAuthenticationTest, discovered_participant_validation_remote_identity_new_change_fail)
+{
+    initialization_ok();
+
+    MockIdentityHandle identity_handle;
+    MockIdentityHandle* p_identity_handle = &identity_handle;
+    MockHandshakeHandle handshake_handle;
+    MockHandshakeHandle* p_handshake_handle = &handshake_handle;
+    HandshakeMessageToken* p_handshake_message = new HandshakeMessageToken();
+
+    EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
+        WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_REQUEST)));
+    EXPECT_CALL(*auth_plugin_, begin_handshake_request(_,_,_,_,_)).Times(1).
+        WillOnce(DoAll(SetArgPointee<0>(p_handshake_handle), 
+                    SetArgPointee<1>(p_handshake_message), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_MESSAGE)));
+    EXPECT_CALL(*stateless_writer_, new_change(_,_,_)).Times(1).
+        WillOnce(Return(nullptr));
+    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
+        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
+    EXPECT_CALL(*auth_plugin_, return_handshake_handle(_,_)).Times(1).
+        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
+
+    GUID_t remote_participant_key;
+    fill_participant_key(remote_participant_key);
+    ASSERT_FALSE(manager_.discovered_participant(IdentityToken(), remote_participant_key));
+}
+
+TEST_F(SecurityAuthenticationTest, discovered_participant_validation_remote_identity_add_change_fail)
+{
+    initialization_ok();
+
+    MockIdentityHandle identity_handle;
+    MockIdentityHandle* p_identity_handle = &identity_handle;
+    MockHandshakeHandle handshake_handle;
+    MockHandshakeHandle* p_handshake_handle = &handshake_handle;
+    HandshakeMessageToken* p_handshake_message = new HandshakeMessageToken();
+    CacheChange_t* change = new CacheChange_t(200);
+
+    EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
+        WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_REQUEST)));
+    EXPECT_CALL(*auth_plugin_, begin_handshake_request(_,_,_,_,_)).Times(1).
+        WillOnce(DoAll(SetArgPointee<0>(p_handshake_handle), 
+                    SetArgPointee<1>(p_handshake_message), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_MESSAGE)));
+    EXPECT_CALL(*stateless_writer_, new_change(_,_,_)).Times(1).
+        WillOnce(Return(change));
+    EXPECT_CALL(*stateless_writer_->history_, add_change(change)).Times(1).
+        WillOnce(Return(false));
+    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
+        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
+    EXPECT_CALL(*auth_plugin_, return_handshake_handle(_,_)).Times(1).
+        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
+
+    GUID_t remote_participant_key;
+    fill_participant_key(remote_participant_key);
+    ASSERT_FALSE(manager_.discovered_participant(IdentityToken(), remote_participant_key));
+
+    delete change;
+}
+
+TEST_F(SecurityAuthenticationTest, discovered_participant_validation_remote_identity_pending_handshake_request_pending_message)
+{
+    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
+        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
+    EXPECT_CALL(*auth_plugin_, return_handshake_handle(_,_)).Times(1).
+        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
+
+    request_process_ok();
+}
+
 TEST_F(SecurityAuthenticationTest, discovered_participant_validation_remote_identity_pending_handshake_request_ok_with_final_message)
 {
     initialization_ok();
@@ -252,15 +456,27 @@ TEST_F(SecurityAuthenticationTest, discovered_participant_validation_remote_iden
     MockHandshakeHandle handshake_handle;
     MockHandshakeHandle* p_handshake_handle = &handshake_handle;
     HandshakeMessageToken* p_handshake_message = new HandshakeMessageToken();
+    CacheChange_t* change = new CacheChange_t(200);
 
     EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
         WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_REQUEST)));
     EXPECT_CALL(*auth_plugin_, begin_handshake_request(_,_,_,_,_)).Times(1).
         WillOnce(DoAll(SetArgPointee<0>(p_handshake_handle), 
                     SetArgPointee<1>(p_handshake_message), Return(ValidationResult_t::VALIDATION_OK_WITH_FINAL_MESSAGE)));
+    EXPECT_CALL(*stateless_writer_, new_change(_,_,_)).Times(1).
+        WillOnce(Return(change));
+    EXPECT_CALL(*stateless_writer_->history_, add_change(change)).Times(1).
+        WillOnce(Return(true));
+    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
+        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
+    EXPECT_CALL(*auth_plugin_, return_handshake_handle(_,_)).Times(1).
+        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
 
     GUID_t remote_participant_key;
+    fill_participant_key(remote_participant_key);
     ASSERT_TRUE(manager_.discovered_participant(IdentityToken(), remote_participant_key));
+
+    delete change;
 }
 
 TEST_F(SecurityAuthenticationTest, discovered_participant_ok)
@@ -272,15 +488,27 @@ TEST_F(SecurityAuthenticationTest, discovered_participant_ok)
     MockHandshakeHandle handshake_handle;
     MockHandshakeHandle* p_handshake_handle = &handshake_handle;
     HandshakeMessageToken* p_handshake_message = new HandshakeMessageToken();
+    CacheChange_t* change = new CacheChange_t(200);
 
     EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
         WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_REQUEST)));
     EXPECT_CALL(*auth_plugin_, begin_handshake_request(_,_,_,_,_)).Times(1).
         WillOnce(DoAll(SetArgPointee<0>(p_handshake_handle), 
                     SetArgPointee<1>(p_handshake_message), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_MESSAGE)));
+    EXPECT_CALL(*stateless_writer_, new_change(_,_,_)).Times(1).
+        WillOnce(Return(change));
+    EXPECT_CALL(*stateless_writer_->history_, add_change(change)).Times(1).
+        WillOnce(Return(true));
+    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
+        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
+    EXPECT_CALL(*auth_plugin_, return_handshake_handle(_,_)).Times(1).
+        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
 
     GUID_t remote_participant_key;
+    fill_participant_key(remote_participant_key);
     ASSERT_TRUE(manager_.discovered_participant(IdentityToken(), remote_participant_key));
+
+    delete change;
 }
 
 TEST_F(SecurityAuthenticationTest, discovered_participant_validate_remote_fail_and_then_ok)
@@ -292,11 +520,13 @@ TEST_F(SecurityAuthenticationTest, discovered_participant_validate_remote_fail_a
     MockHandshakeHandle handshake_handle;
     MockHandshakeHandle* p_handshake_handle = &handshake_handle;
     HandshakeMessageToken* p_handshake_message = new HandshakeMessageToken();
+    CacheChange_t* change = new CacheChange_t(200);
 
     EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
         WillOnce(Return(ValidationResult_t::VALIDATION_FAILED));
 
     GUID_t remote_participant_key;
+    fill_participant_key(remote_participant_key);
     ASSERT_FALSE(manager_.discovered_participant(IdentityToken(), remote_participant_key));
 
     EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
@@ -304,8 +534,18 @@ TEST_F(SecurityAuthenticationTest, discovered_participant_validate_remote_fail_a
     EXPECT_CALL(*auth_plugin_, begin_handshake_request(_,_,_,_,_)).Times(1).
         WillOnce(DoAll(SetArgPointee<0>(p_handshake_handle), 
                     SetArgPointee<1>(p_handshake_message), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_MESSAGE)));
+    EXPECT_CALL(*stateless_writer_, new_change(_,_,_)).Times(1).
+        WillOnce(Return(change));
+    EXPECT_CALL(*stateless_writer_->history_, add_change(change)).Times(1).
+        WillOnce(Return(true));
+    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
+        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
+    EXPECT_CALL(*auth_plugin_, return_handshake_handle(_,_)).Times(1).
+        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
 
     ASSERT_TRUE(manager_.discovered_participant(IdentityToken(), remote_participant_key));
+
+    delete change;
 }
 
 TEST_F(SecurityAuthenticationTest, discovered_participant_begin_handshake_request_fail_and_then_ok)
@@ -317,6 +557,7 @@ TEST_F(SecurityAuthenticationTest, discovered_participant_begin_handshake_reques
     MockHandshakeHandle handshake_handle;
     MockHandshakeHandle* p_handshake_handle = &handshake_handle;
     HandshakeMessageToken* p_handshake_message = new HandshakeMessageToken();
+    CacheChange_t* change = new CacheChange_t(200);
 
     EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
         WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_REQUEST)));
@@ -324,14 +565,636 @@ TEST_F(SecurityAuthenticationTest, discovered_participant_begin_handshake_reques
         WillOnce(Return(ValidationResult_t::VALIDATION_FAILED));
 
     GUID_t remote_participant_key;
+    fill_participant_key(remote_participant_key);
     ASSERT_FALSE(manager_.discovered_participant(IdentityToken(), remote_participant_key));
 
     EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(0);
     EXPECT_CALL(*auth_plugin_, begin_handshake_request(_,_,_,_,_)).Times(1).
         WillOnce(DoAll(SetArgPointee<0>(p_handshake_handle), 
                     SetArgPointee<1>(p_handshake_message), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_MESSAGE)));
+    EXPECT_CALL(*stateless_writer_, new_change(_,_,_)).Times(1).
+        WillOnce(Return(change));
+    EXPECT_CALL(*stateless_writer_->history_, add_change(change)).Times(1).
+        WillOnce(Return(true));
+    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
+        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
+    EXPECT_CALL(*auth_plugin_, return_handshake_handle(_,_)).Times(1).
+        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
+
+    ASSERT_TRUE(manager_.discovered_participant(IdentityToken(), remote_participant_key));
+
+    delete change;
+}
+
+TEST_F(SecurityAuthenticationTest, discovered_participant_process_message_not_remote_participant_key)
+{
+    initialization_ok();
+
+    ParticipantGenericMessage message;
+    message.message_class_id("dds.sec.auth");
+    CacheChange_t* change = new CacheChange_t(ParticipantGenericMessageHelper::serialized_size(message));
+    CDRMessage_t aux_msg(0);
+    aux_msg.wraps = true;
+    aux_msg.buffer = change->serializedPayload.data;
+    aux_msg.max_size = change->serializedPayload.max_size;
+    aux_msg.msg_endian = change->serializedPayload.encapsulation == PL_CDR_BE ? BIGEND : LITTLEEND;
+    ASSERT_TRUE(CDRMessage::addParticipantGenericMessage(&aux_msg, message));
+    change->serializedPayload.length = aux_msg.length;
+
+    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(1).
+        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
+    EXPECT_CALL(*stateless_reader_->history_, remove_change(change)).Times(1).
+        WillOnce(Return(true));
+
+    stateless_reader_->listener_->onNewCacheChangeAdded(stateless_reader_, change);
+}
+
+TEST_F(SecurityAuthenticationTest, discovered_participant_process_message_bad_message_class_id)
+{
+    initialization_ok();
+
+    MockIdentityHandle identity_handle;
+    MockIdentityHandle* p_identity_handle = &identity_handle;
+
+    EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
+        WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_MESSAGE)));
+
+    GUID_t remote_participant_key;
+    fill_participant_key(remote_participant_key);
+    ASSERT_TRUE(manager_.discovered_participant(IdentityToken(), remote_participant_key));
+
+    ParticipantGenericMessage message;
+    CacheChange_t* change = new CacheChange_t(ParticipantGenericMessageHelper::serialized_size(message));
+    CDRMessage_t aux_msg(0);
+    aux_msg.wraps = true;
+    aux_msg.buffer = change->serializedPayload.data;
+    aux_msg.max_size = change->serializedPayload.max_size;
+    aux_msg.msg_endian = change->serializedPayload.encapsulation == PL_CDR_BE ? BIGEND : LITTLEEND;
+    ASSERT_TRUE(CDRMessage::addParticipantGenericMessage(&aux_msg, message));
+    change->serializedPayload.length = aux_msg.length;
+
+    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
+        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
+    EXPECT_CALL(*stateless_reader_->history_, remove_change(change)).Times(1).
+        WillOnce(Return(true));
+
+    stateless_reader_->listener_->onNewCacheChangeAdded(stateless_reader_, change);
+}
+
+TEST_F(SecurityAuthenticationTest, discovered_participant_process_message_not_expecting_request)
+{
+    initialization_ok();
 
+    MockIdentityHandle identity_handle;
+    MockIdentityHandle* p_identity_handle = &identity_handle;
+
+    EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
+        WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_OK)));
+
+    GUID_t remote_participant_key;
+    fill_participant_key(remote_participant_key);
+    ASSERT_TRUE(manager_.discovered_participant(IdentityToken(), remote_participant_key));
+
+    ParticipantGenericMessage message;
+    message.message_identity().source_guid(remote_participant_key);
+    message.destination_participant_key(remote_participant_key);
+    message.message_class_id("dds.sec.auth");
+    HandshakeMessageToken token;
+    message.message_data().push_back(token);
+    CacheChange_t* change = new CacheChange_t(ParticipantGenericMessageHelper::serialized_size(message));
+    CDRMessage_t aux_msg(0);
+    aux_msg.wraps = true;
+    aux_msg.buffer = change->serializedPayload.data;
+    aux_msg.max_size = change->serializedPayload.max_size;
+    aux_msg.msg_endian = change->serializedPayload.encapsulation == PL_CDR_BE ? BIGEND : LITTLEEND;
+    ASSERT_TRUE(CDRMessage::addParticipantGenericMessage(&aux_msg, message));
+    change->serializedPayload.length = aux_msg.length;
+
+    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
+        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
+    EXPECT_CALL(*stateless_reader_->history_, remove_change(change)).Times(1).
+        WillOnce(Return(true));
+
+    stateless_reader_->listener_->onNewCacheChangeAdded(stateless_reader_, change);
+}
+
+TEST_F(SecurityAuthenticationTest, discovered_participant_process_message_fail_begin_handshake_reply)
+{
+    initialization_ok();
+
+    MockIdentityHandle identity_handle;
+    MockIdentityHandle* p_identity_handle = &identity_handle;
+
+    EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
+        WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_MESSAGE)));
+
+    GUID_t remote_participant_key;
+    fill_participant_key(remote_participant_key);
     ASSERT_TRUE(manager_.discovered_participant(IdentityToken(), remote_participant_key));
+
+    ParticipantGenericMessage message;
+    message.message_identity().source_guid(remote_participant_key);
+    message.destination_participant_key(remote_participant_key);
+    message.message_class_id("dds.sec.auth");
+    HandshakeMessageToken token;
+    message.message_data().push_back(token);
+    CacheChange_t* change = new CacheChange_t(ParticipantGenericMessageHelper::serialized_size(message));
+    CDRMessage_t aux_msg(0);
+    aux_msg.wraps = true;
+    aux_msg.buffer = change->serializedPayload.data;
+    aux_msg.max_size = change->serializedPayload.max_size;
+    aux_msg.msg_endian = change->serializedPayload.encapsulation == PL_CDR_BE ? BIGEND : LITTLEEND;
+    ASSERT_TRUE(CDRMessage::addParticipantGenericMessage(&aux_msg, message));
+    change->serializedPayload.length = aux_msg.length;
+
+    EXPECT_CALL(*auth_plugin_, begin_handshake_reply_rvr(_,_,_,_,_,_)).Times(1).
+        WillOnce(Return(ValidationResult_t::VALIDATION_FAILED));
+    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
+        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
+    EXPECT_CALL(*stateless_reader_->history_, remove_change(change)).Times(1).
+        WillOnce(Return(true));
+
+    stateless_reader_->listener_->onNewCacheChangeAdded(stateless_reader_, change);
+}
+
+TEST_F(SecurityAuthenticationTest, discovered_participant_process_message_ok_begin_handshake_reply)
+{
+    initialization_ok();
+
+    MockIdentityHandle identity_handle;
+    MockIdentityHandle* p_identity_handle = &identity_handle;
+
+    EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
+        WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_MESSAGE)));
+
+    GUID_t remote_participant_key;
+    fill_participant_key(remote_participant_key);
+    ASSERT_TRUE(manager_.discovered_participant(IdentityToken(), remote_participant_key));
+
+    ParticipantGenericMessage message;
+    message.message_identity().source_guid(remote_participant_key);
+    message.destination_participant_key(remote_participant_key);
+    message.message_class_id("dds.sec.auth");
+    HandshakeMessageToken token;
+    message.message_data().push_back(token);
+    CacheChange_t* change = new CacheChange_t(ParticipantGenericMessageHelper::serialized_size(message));
+    CDRMessage_t aux_msg(0);
+    aux_msg.wraps = true;
+    aux_msg.buffer = change->serializedPayload.data;
+    aux_msg.max_size = change->serializedPayload.max_size;
+    aux_msg.msg_endian = change->serializedPayload.encapsulation == PL_CDR_BE ? BIGEND : LITTLEEND;
+    ASSERT_TRUE(CDRMessage::addParticipantGenericMessage(&aux_msg, message));
+    change->serializedPayload.length = aux_msg.length;
+
+    MockHandshakeHandle handshake_handle;
+    MockHandshakeHandle* p_handshake_handle = &handshake_handle;
+
+    EXPECT_CALL(*auth_plugin_, begin_handshake_reply_rvr(_,_,_,_,_,_)).Times(1).
+        WillOnce(DoAll(SetArgPointee<0>(p_handshake_handle), 
+                    Return(ValidationResult_t::VALIDATION_OK)));
+    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
+        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
+    EXPECT_CALL(*auth_plugin_, return_handshake_handle(_,_)).Times(1).
+        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
+    EXPECT_CALL(*stateless_reader_->history_, remove_change(change)).Times(1).
+        WillOnce(Return(true));
+
+    stateless_reader_->listener_->onNewCacheChangeAdded(stateless_reader_, change);
+}
+
+TEST_F(SecurityAuthenticationTest, discovered_participant_process_message_new_change_fail)
+{
+    initialization_ok();
+
+    MockIdentityHandle identity_handle;
+    MockIdentityHandle* p_identity_handle = &identity_handle;
+
+    EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
+        WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_MESSAGE)));
+
+    GUID_t remote_participant_key;
+    fill_participant_key(remote_participant_key);
+    ASSERT_TRUE(manager_.discovered_participant(IdentityToken(), remote_participant_key));
+
+    ParticipantGenericMessage message;
+    message.message_identity().source_guid(remote_participant_key);
+    message.destination_participant_key(remote_participant_key);
+    message.message_class_id("dds.sec.auth");
+    HandshakeMessageToken token;
+    message.message_data().push_back(token);
+    CacheChange_t* change = new CacheChange_t(ParticipantGenericMessageHelper::serialized_size(message));
+    CDRMessage_t aux_msg(0);
+    aux_msg.wraps = true;
+    aux_msg.buffer = change->serializedPayload.data;
+    aux_msg.max_size = change->serializedPayload.max_size;
+    aux_msg.msg_endian = change->serializedPayload.encapsulation == PL_CDR_BE ? BIGEND : LITTLEEND;
+    ASSERT_TRUE(CDRMessage::addParticipantGenericMessage(&aux_msg, message));
+    change->serializedPayload.length = aux_msg.length;
+
+    MockHandshakeHandle handshake_handle;
+    MockHandshakeHandle* p_handshake_handle = &handshake_handle;
+    HandshakeMessageToken* p_handshake_message = new HandshakeMessageToken();
+
+    EXPECT_CALL(*auth_plugin_, begin_handshake_reply_rvr(_,_,_,_,_,_)).Times(1).
+        WillOnce(DoAll(SetArgPointee<0>(p_handshake_handle), 
+                    SetArgPointee<1>(p_handshake_message), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_MESSAGE)));
+    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
+        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
+    EXPECT_CALL(*stateless_writer_, new_change(_,_,_)).Times(1).
+        WillOnce(Return(nullptr));
+    EXPECT_CALL(*auth_plugin_, return_handshake_handle(_,_)).Times(1).
+        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
+    EXPECT_CALL(*stateless_reader_->history_, remove_change(change)).Times(1).
+        WillOnce(Return(true));
+
+    stateless_reader_->listener_->onNewCacheChangeAdded(stateless_reader_, change);
+}
+
+TEST_F(SecurityAuthenticationTest, discovered_participant_process_message_add_change_fail)
+{
+    initialization_ok();
+
+    MockIdentityHandle identity_handle;
+    MockIdentityHandle* p_identity_handle = &identity_handle;
+
+    EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
+        WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_MESSAGE)));
+
+    GUID_t remote_participant_key;
+    fill_participant_key(remote_participant_key);
+    ASSERT_TRUE(manager_.discovered_participant(IdentityToken(), remote_participant_key));
+
+    ParticipantGenericMessage message;
+    message.message_identity().source_guid(remote_participant_key);
+    message.destination_participant_key(remote_participant_key);
+    message.message_class_id("dds.sec.auth");
+    HandshakeMessageToken token;
+    message.message_data().push_back(token);
+    CacheChange_t* change = new CacheChange_t(ParticipantGenericMessageHelper::serialized_size(message));
+    CDRMessage_t aux_msg(0);
+    aux_msg.wraps = true;
+    aux_msg.buffer = change->serializedPayload.data;
+    aux_msg.max_size = change->serializedPayload.max_size;
+    aux_msg.msg_endian = change->serializedPayload.encapsulation == PL_CDR_BE ? BIGEND : LITTLEEND;
+    ASSERT_TRUE(CDRMessage::addParticipantGenericMessage(&aux_msg, message));
+    change->serializedPayload.length = aux_msg.length;
+
+    MockHandshakeHandle handshake_handle;
+    MockHandshakeHandle* p_handshake_handle = &handshake_handle;
+    HandshakeMessageToken* p_handshake_message = new HandshakeMessageToken();
+    CacheChange_t* change2 = new CacheChange_t(200);
+
+    EXPECT_CALL(*auth_plugin_, begin_handshake_reply_rvr(_,_,_,_,_,_)).Times(1).
+        WillOnce(DoAll(SetArgPointee<0>(p_handshake_handle), 
+                    SetArgPointee<1>(p_handshake_message), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_MESSAGE)));
+    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
+        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
+    EXPECT_CALL(*stateless_writer_, new_change(_,_,_)).Times(1).
+        WillOnce(Return(change2));
+    EXPECT_CALL(*stateless_writer_->history_, add_change(change2)).Times(1).
+        WillOnce(Return(false));
+    EXPECT_CALL(*auth_plugin_, return_handshake_handle(_,_)).Times(1).
+        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
+    EXPECT_CALL(*stateless_reader_->history_, remove_change(change)).Times(1).
+        WillOnce(Return(true));
+
+    stateless_reader_->listener_->onNewCacheChangeAdded(stateless_reader_, change);
+
+    delete change2;
+}
+
+TEST_F(SecurityAuthenticationTest, discovered_participant_process_message_pending_handshake_reply_pending_message)
+{
+    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
+        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
+    EXPECT_CALL(*auth_plugin_, return_handshake_handle(_,_)).Times(1).
+        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
+
+    reply_process_ok();
+}
+
+TEST_F(SecurityAuthenticationTest, discovered_participant_process_message_pending_handshake_reply_ok_with_final_message)
+{
+    initialization_ok();
+
+    MockIdentityHandle identity_handle;
+    MockIdentityHandle* p_identity_handle = &identity_handle;
+
+    EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
+        WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_MESSAGE)));
+
+    GUID_t remote_participant_key;
+    fill_participant_key(remote_participant_key);
+    ASSERT_TRUE(manager_.discovered_participant(IdentityToken(), remote_participant_key));
+
+    ParticipantGenericMessage message;
+    message.message_identity().source_guid(remote_participant_key);
+    message.destination_participant_key(remote_participant_key);
+    message.message_class_id("dds.sec.auth");
+    HandshakeMessageToken token;
+    message.message_data().push_back(token);
+    CacheChange_t* change = new CacheChange_t(ParticipantGenericMessageHelper::serialized_size(message));
+    CDRMessage_t aux_msg(0);
+    aux_msg.wraps = true;
+    aux_msg.buffer = change->serializedPayload.data;
+    aux_msg.max_size = change->serializedPayload.max_size;
+    aux_msg.msg_endian = change->serializedPayload.encapsulation == PL_CDR_BE ? BIGEND : LITTLEEND;
+    ASSERT_TRUE(CDRMessage::addParticipantGenericMessage(&aux_msg, message));
+    change->serializedPayload.length = aux_msg.length;
+
+    MockHandshakeHandle handshake_handle;
+    MockHandshakeHandle* p_handshake_handle = &handshake_handle;
+    HandshakeMessageToken* p_handshake_message = new HandshakeMessageToken();
+    CacheChange_t* change2 = new CacheChange_t(200);
+
+    EXPECT_CALL(*auth_plugin_, begin_handshake_reply_rvr(_,_,_,_,_,_)).Times(1).
+        WillOnce(DoAll(SetArgPointee<0>(p_handshake_handle), 
+                    SetArgPointee<1>(p_handshake_message), Return(ValidationResult_t::VALIDATION_OK_WITH_FINAL_MESSAGE)));
+    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
+        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
+    EXPECT_CALL(*stateless_writer_, new_change(_,_,_)).Times(1).
+        WillOnce(Return(change2));
+    EXPECT_CALL(*stateless_writer_->history_, add_change(change2)).Times(1).
+        WillOnce(Return(true));
+    EXPECT_CALL(*auth_plugin_, return_handshake_handle(_,_)).Times(1).
+        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
+    EXPECT_CALL(*stateless_reader_->history_, remove_change(change)).Times(1).
+        WillOnce(Return(true));
+
+    stateless_reader_->listener_->onNewCacheChangeAdded(stateless_reader_, change);
+
+    delete change2;
+}
+
+TEST_F(SecurityAuthenticationTest, discovered_participant_process_message_fail_process_handshake_reply)
+{
+    request_process_ok();
+
+    GUID_t remote_participant_key;
+    fill_participant_key(remote_participant_key);
+
+    ParticipantGenericMessage message;
+    message.message_identity().source_guid(remote_participant_key);
+    message.related_message_identity().source_guid(remote_participant_key);
+    message.destination_participant_key(remote_participant_key);
+    message.message_class_id("dds.sec.auth");
+    HandshakeMessageToken token;
+    message.message_data().push_back(token);
+    CacheChange_t* change = new CacheChange_t(ParticipantGenericMessageHelper::serialized_size(message));
+    CDRMessage_t aux_msg(0);
+    aux_msg.wraps = true;
+    aux_msg.buffer = change->serializedPayload.data;
+    aux_msg.max_size = change->serializedPayload.max_size;
+    aux_msg.msg_endian = change->serializedPayload.encapsulation == PL_CDR_BE ? BIGEND : LITTLEEND;
+    ASSERT_TRUE(CDRMessage::addParticipantGenericMessage(&aux_msg, message));
+    change->serializedPayload.length = aux_msg.length;
+
+    EXPECT_CALL(*auth_plugin_, process_handshake_rvr(_,_,_,_)).Times(1).
+        WillOnce(Return(ValidationResult_t::VALIDATION_FAILED));
+    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
+        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
+    EXPECT_CALL(*auth_plugin_, return_handshake_handle(_,_)).Times(1).
+        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
+    EXPECT_CALL(*stateless_reader_->history_, remove_change(change)).Times(1).
+        WillOnce(Return(true));
+
+    stateless_reader_->listener_->onNewCacheChangeAdded(stateless_reader_, change);
+
+    delete change;
+}
+
+TEST_F(SecurityAuthenticationTest, discovered_participant_process_message_ok_process_handshake_reply)
+{
+    request_process_ok();
+
+    GUID_t remote_participant_key;
+    fill_participant_key(remote_participant_key);
+
+    ParticipantGenericMessage message;
+    message.message_identity().source_guid(remote_participant_key);
+    message.related_message_identity().source_guid(remote_participant_key);
+    message.destination_participant_key(remote_participant_key);
+    message.message_class_id("dds.sec.auth");
+    HandshakeMessageToken token;
+    message.message_data().push_back(token);
+    CacheChange_t* change = new CacheChange_t(ParticipantGenericMessageHelper::serialized_size(message));
+    CDRMessage_t aux_msg(0);
+    aux_msg.wraps = true;
+    aux_msg.buffer = change->serializedPayload.data;
+    aux_msg.max_size = change->serializedPayload.max_size;
+    aux_msg.msg_endian = change->serializedPayload.encapsulation == PL_CDR_BE ? BIGEND : LITTLEEND;
+    ASSERT_TRUE(CDRMessage::addParticipantGenericMessage(&aux_msg, message));
+    change->serializedPayload.length = aux_msg.length;
+
+    EXPECT_CALL(*auth_plugin_, process_handshake_rvr(_,_,_,_)).Times(1).
+        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
+    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
+        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
+    EXPECT_CALL(*auth_plugin_, return_handshake_handle(_,_)).Times(1).
+        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
+    EXPECT_CALL(*stateless_reader_->history_, remove_change(change)).Times(1).
+        WillOnce(Return(true));
+
+    stateless_reader_->listener_->onNewCacheChangeAdded(stateless_reader_, change);
+}
+
+TEST_F(SecurityAuthenticationTest, discovered_participant_process_message_process_handshake_reply_new_change_fail)
+{
+    request_process_ok();
+
+    GUID_t remote_participant_key;
+    fill_participant_key(remote_participant_key);
+
+    ParticipantGenericMessage message;
+    message.message_identity().source_guid(remote_participant_key);
+    message.related_message_identity().source_guid(remote_participant_key);
+    message.destination_participant_key(remote_participant_key);
+    message.message_class_id("dds.sec.auth");
+    HandshakeMessageToken token;
+    message.message_data().push_back(token);
+    CacheChange_t* change = new CacheChange_t(ParticipantGenericMessageHelper::serialized_size(message));
+    CDRMessage_t aux_msg(0);
+    aux_msg.wraps = true;
+    aux_msg.buffer = change->serializedPayload.data;
+    aux_msg.max_size = change->serializedPayload.max_size;
+    aux_msg.msg_endian = change->serializedPayload.encapsulation == PL_CDR_BE ? BIGEND : LITTLEEND;
+    ASSERT_TRUE(CDRMessage::addParticipantGenericMessage(&aux_msg, message));
+    change->serializedPayload.length = aux_msg.length;
+
+    HandshakeMessageToken* p_handshake_message = new HandshakeMessageToken();
+
+    EXPECT_CALL(*auth_plugin_, process_handshake_rvr(_,_,_,_)).Times(1).
+        WillOnce(DoAll(SetArgPointee<0>(p_handshake_message), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_MESSAGE)));
+    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
+        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
+    EXPECT_CALL(*stateless_writer_, new_change(_,_,_)).Times(1).
+        WillOnce(Return(nullptr));
+    EXPECT_CALL(*auth_plugin_, return_handshake_handle(_,_)).Times(1).
+        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
+    EXPECT_CALL(*stateless_reader_->history_, remove_change(change)).Times(1).
+        WillOnce(Return(true));
+
+    stateless_reader_->listener_->onNewCacheChangeAdded(stateless_reader_, change);
+}
+
+TEST_F(SecurityAuthenticationTest, discovered_participant_process_message_process_handshake_reply_add_change_fail)
+{
+    request_process_ok();
+
+    GUID_t remote_participant_key;
+    fill_participant_key(remote_participant_key);
+
+    ParticipantGenericMessage message;
+    message.message_identity().source_guid(remote_participant_key);
+    message.related_message_identity().source_guid(remote_participant_key);
+    message.destination_participant_key(remote_participant_key);
+    message.message_class_id("dds.sec.auth");
+    HandshakeMessageToken token;
+    message.message_data().push_back(token);
+    CacheChange_t* change = new CacheChange_t(ParticipantGenericMessageHelper::serialized_size(message));
+    CDRMessage_t aux_msg(0);
+    aux_msg.wraps = true;
+    aux_msg.buffer = change->serializedPayload.data;
+    aux_msg.max_size = change->serializedPayload.max_size;
+    aux_msg.msg_endian = change->serializedPayload.encapsulation == PL_CDR_BE ? BIGEND : LITTLEEND;
+    ASSERT_TRUE(CDRMessage::addParticipantGenericMessage(&aux_msg, message));
+    change->serializedPayload.length = aux_msg.length;
+
+    HandshakeMessageToken* p_handshake_message = new HandshakeMessageToken();
+    CacheChange_t* change2 = new CacheChange_t(200);
+
+    EXPECT_CALL(*auth_plugin_, process_handshake_rvr(_,_,_,_)).Times(1).
+        WillOnce(DoAll(SetArgPointee<0>(p_handshake_message), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_MESSAGE)));
+    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
+        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
+    EXPECT_CALL(*stateless_writer_, new_change(_,_,_)).Times(1).
+        WillOnce(Return(change2));
+    EXPECT_CALL(*stateless_writer_->history_, add_change(change2)).Times(1).
+        WillOnce(Return(false));
+    EXPECT_CALL(*auth_plugin_, return_handshake_handle(_,_)).Times(1).
+        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
+    EXPECT_CALL(*stateless_reader_->history_, remove_change(change)).Times(1).
+        WillOnce(Return(true));
+
+    stateless_reader_->listener_->onNewCacheChangeAdded(stateless_reader_, change);
+
+    delete change2;
+}
+
+TEST_F(SecurityAuthenticationTest, discovered_participant_process_message_process_handshake_reply_ok_with_final_message)
+{
+    request_process_ok();
+
+    GUID_t remote_participant_key;
+    fill_participant_key(remote_participant_key);
+
+    ParticipantGenericMessage message;
+    message.message_identity().source_guid(remote_participant_key);
+    message.related_message_identity().source_guid(remote_participant_key);
+    message.destination_participant_key(remote_participant_key);
+    message.message_class_id("dds.sec.auth");
+    HandshakeMessageToken token;
+    message.message_data().push_back(token);
+    CacheChange_t* change = new CacheChange_t(ParticipantGenericMessageHelper::serialized_size(message));
+    CDRMessage_t aux_msg(0);
+    aux_msg.wraps = true;
+    aux_msg.buffer = change->serializedPayload.data;
+    aux_msg.max_size = change->serializedPayload.max_size;
+    aux_msg.msg_endian = change->serializedPayload.encapsulation == PL_CDR_BE ? BIGEND : LITTLEEND;
+    ASSERT_TRUE(CDRMessage::addParticipantGenericMessage(&aux_msg, message));
+    change->serializedPayload.length = aux_msg.length;
+
+    HandshakeMessageToken* p_handshake_message = new HandshakeMessageToken();
+    CacheChange_t* change2 = new CacheChange_t(200);
+
+    EXPECT_CALL(*auth_plugin_, process_handshake_rvr(_,_,_,_)).Times(1).
+        WillOnce(DoAll(SetArgPointee<0>(p_handshake_message), Return(ValidationResult_t::VALIDATION_OK_WITH_FINAL_MESSAGE)));
+    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
+        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
+    EXPECT_CALL(*stateless_writer_, new_change(_,_,_)).Times(1).
+        WillOnce(Return(change2));
+    EXPECT_CALL(*stateless_writer_->history_, add_change(change2)).Times(1).
+        WillOnce(Return(true));
+    EXPECT_CALL(*auth_plugin_, return_handshake_handle(_,_)).Times(1).
+        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
+    EXPECT_CALL(*stateless_reader_->history_, remove_change(change)).Times(1).
+        WillOnce(Return(true));
+
+    stateless_reader_->listener_->onNewCacheChangeAdded(stateless_reader_, change);
+
+    delete change2;
+}
+
+TEST_F(SecurityAuthenticationTest, discovered_participant_process_message_fail_process_handshake_final)
+{
+    reply_process_ok();
+
+    GUID_t remote_participant_key;
+    fill_participant_key(remote_participant_key);
+
+    ParticipantGenericMessage message;
+    message.message_identity().source_guid(remote_participant_key);
+    message.related_message_identity().source_guid(remote_participant_key);
+    message.destination_participant_key(remote_participant_key);
+    message.message_class_id("dds.sec.auth");
+    HandshakeMessageToken token;
+    message.message_data().push_back(token);
+    CacheChange_t* change = new CacheChange_t(ParticipantGenericMessageHelper::serialized_size(message));
+    CDRMessage_t aux_msg(0);
+    aux_msg.wraps = true;
+    aux_msg.buffer = change->serializedPayload.data;
+    aux_msg.max_size = change->serializedPayload.max_size;
+    aux_msg.msg_endian = change->serializedPayload.encapsulation == PL_CDR_BE ? BIGEND : LITTLEEND;
+    ASSERT_TRUE(CDRMessage::addParticipantGenericMessage(&aux_msg, message));
+    change->serializedPayload.length = aux_msg.length;
+
+    EXPECT_CALL(*auth_plugin_, process_handshake_rvr(_,_,_,_)).Times(1).
+        WillOnce(Return(ValidationResult_t::VALIDATION_FAILED));
+    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
+        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
+    EXPECT_CALL(*auth_plugin_, return_handshake_handle(_,_)).Times(1).
+        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
+    EXPECT_CALL(*stateless_reader_->history_, remove_change(change)).Times(1).
+        WillOnce(Return(true));
+
+    stateless_reader_->listener_->onNewCacheChangeAdded(stateless_reader_, change);
+
+    delete change;
+}
+
+TEST_F(SecurityAuthenticationTest, discovered_participant_process_message_ok_process_handshake_final)
+{
+    reply_process_ok();
+
+    GUID_t remote_participant_key;
+    fill_participant_key(remote_participant_key);
+
+    ParticipantGenericMessage message;
+    message.message_identity().source_guid(remote_participant_key);
+    message.related_message_identity().source_guid(remote_participant_key);
+    message.destination_participant_key(remote_participant_key);
+    message.message_class_id("dds.sec.auth");
+    HandshakeMessageToken token;
+    message.message_data().push_back(token);
+    CacheChange_t* change = new CacheChange_t(ParticipantGenericMessageHelper::serialized_size(message));
+    CDRMessage_t aux_msg(0);
+    aux_msg.wraps = true;
+    aux_msg.buffer = change->serializedPayload.data;
+    aux_msg.max_size = change->serializedPayload.max_size;
+    aux_msg.msg_endian = change->serializedPayload.encapsulation == PL_CDR_BE ? BIGEND : LITTLEEND;
+    ASSERT_TRUE(CDRMessage::addParticipantGenericMessage(&aux_msg, message));
+    change->serializedPayload.length = aux_msg.length;
+
+    EXPECT_CALL(*auth_plugin_, process_handshake_rvr(_,_,_,_)).Times(1).
+        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
+    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
+        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
+    EXPECT_CALL(*auth_plugin_, return_handshake_handle(_,_)).Times(1).
+        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
+    EXPECT_CALL(*stateless_reader_->history_, remove_change(change)).Times(1).
+        WillOnce(Return(true));
+
+    stateless_reader_->listener_->onNewCacheChangeAdded(stateless_reader_, change);
 }
 
 int main(int argc, char **argv)

programming_language: C++
repo_url: https://github.com/eProsima/Fast-DDS
commit_details: repo_url: https://github.com/eProsima/Fast-DDS
author: Ricardo González Moreno
author_date: 2016-11-08 15:32:00+01:00
msg: Refs #1811. WIP SecurityManager.
repository: repo_url: https://github.com/eProsima/Fast-DDS
repo_name: eProsima/Fast-DDS
description: The most complete DDS - Proven: Plenty of success cases. Looking for commercial support? Contact info@eprosima.com
repo_language: C++
owner: eProsima
file_changes: filename: Authentication.h
change_type: ModificationType.MODIFY
diff: @@ -94,7 +94,7 @@ class Authentication
         virtual ValidationResult_t validate_remote_identity(IdentityHandle** remote_identity_handle,
                 const IdentityHandle& local_identity_handle,
                 IdentityToken&& remote_identity_token,
-                const GUID_t remote_participant_key,
+                const GUID_t& remote_participant_key,
                 SecurityException& exception) = 0;
 
         /*!

programming_language: Objective-C
filename: ReaderProxy.h
change_type: ModificationType.MODIFY
diff: @@ -28,7 +28,6 @@
 #include "../attributes/WriterAttributes.h"
 
 #include <set>
-#include <unordered_map>
 
 namespace boost
 {

programming_language: Objective-C
filename: CMakeLists.txt
change_type: ModificationType.MODIFY
diff: @@ -170,12 +170,14 @@ if(MSVC OR MSVC_IDE)
         # Define public headers
         target_include_directories(${PROJECT_NAME} PUBLIC
             $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include> $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include/${PROJECT_NAME}>
+            $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src/cpp>
             $<INSTALL_INTERFACE:include>
             )
 
         # Define public headers for static library
         target_include_directories(${PROJECT_NAME}_static PUBLIC
             $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include> $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include/${PROJECT_NAME}>
+            $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src/cpp>
             $<INSTALL_INTERFACE:include>
             )
 
@@ -201,6 +203,7 @@ else()
     # Define public headers
     target_include_directories(${PROJECT_NAME} PUBLIC
         $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include> $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include/${PROJECT_NAME}>
+        $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src/cpp>
         $<INSTALL_INTERFACE:include>
         )
 

programming_language: Shell
filename: RTPSParticipantImpl.cpp
change_type: ModificationType.MODIFY
diff: @@ -87,7 +87,7 @@ Locator_t RTPSParticipantImpl::applyLocatorAdaptRule(Locator_t loc)
 RTPSParticipantImpl::RTPSParticipantImpl(const RTPSParticipantAttributes& PParam,
         const GuidPrefix_t& guidP,
         RTPSParticipant* par,
-        RTPSParticipantListener* plisten):	m_att(PParam), m_guid(guidP,c_EntityId_RTPSParticipant),
+        RTPSParticipantListener* plisten):	m_att(PParam), m_guid(guidP ,c_EntityId_RTPSParticipant),
     mp_event_thr(nullptr),
     mp_builtinProtocols(nullptr),
     mp_ResourceSemaphore(new boost::interprocess::interprocess_semaphore(0)),
@@ -859,11 +859,6 @@ void RTPSParticipantImpl::assertRemoteRTPSParticipantLiveliness(const GuidPrefix
     this->mp_builtinProtocols->mp_PDP->assertRemoteParticipantLiveliness(guidP);
 }
 
-const RTPSParticipantAttributes& RTPSParticipantImpl::getRTPSParticipantAttributes() const
-{
-    return this->m_att;
-}
-
 uint32_t RTPSParticipantImpl::getMaxMessageSize() const
 {
     uint32_t minMaxMessageSize = UINT32_MAX;

programming_language: C++
filename: RTPSParticipantImpl.h
change_type: ModificationType.MODIFY
diff: @@ -13,7 +13,7 @@
 // limitations under the License.
 
 /**
- * @file RTPSParticipant.h
+ * @file RTPSParticipantImpl.h
  */
 
 #ifndef RTPSParticipantIMPL_H_
@@ -131,7 +131,9 @@ class RTPSParticipantImpl
          * Get associated GUID
          * @return Associated GUID
          */
-        inline const GUID_t& getGuid() const {return m_guid;};
+        inline const GUID_t& getGuid() const { return m_guid; }
+
+        void setGuid(GUID_t& guid) { m_guid = guid; }
 
         //! Announce RTPSParticipantState (force the sending of a DPD message.)
         void announceRTPSParticipantState();
@@ -208,7 +210,7 @@ class RTPSParticipantImpl
         //!Attributes of the RTPSParticipant
         RTPSParticipantAttributes m_att;
         //!Guid of the RTPSParticipant.
-        const GUID_t m_guid;
+        GUID_t m_guid;
         //! Sending resources. - DEPRECATED -Stays commented for reference purposes
         // ResourceSend* mp_send_thr;
         //! Event Resource
@@ -304,7 +306,10 @@ class RTPSParticipantImpl
 
     public:
 
-        const RTPSParticipantAttributes& getRTPSParticipantAttributes() const;
+        const RTPSParticipantAttributes& getRTPSParticipantAttributes() const
+        {
+            return this->m_att;
+        }
 
         /**
          * Create a Writer in this RTPSParticipant.

programming_language: C++
filename: SecurityManager.cpp
change_type: ModificationType.MODIFY
diff: @@ -1,9 +1,392 @@
 #include "SecurityManager.h"
 
 #include <fastrtps/rtps/security/authentication/Authentication.h>
+#include <fastrtps/log/Log.h>
+#include <rtps/participant/RTPSParticipantImpl.h>
 
-using namespace eprosima::fastrtps::rtps::security;
+#include <fastrtps/rtps/writer/StatelessWriter.h>
+#include <fastrtps/rtps/reader/StatelessReader.h>
+#include <fastrtps/rtps/history/WriterHistory.h>
+#include <fastrtps/rtps/history/ReaderHistory.h>
+#include <fastrtps/rtps/attributes/HistoryAttributes.h>
 
-SecurityManager::SecurityManager()
+#include <cassert>
+#include <thread>
+
+#define ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_WRITER  0x000201C2
+#define ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_READER  0x000201C7
+
+const EntityId_t participant_stateless_message_writer_entity_id = ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_WRITER;
+const EntityId_t participant_stateless_message_reader_entity_id = ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_READER;
+
+using namespace eprosima::fastrtps;
+using namespace ::rtps;
+using namespace ::security;
+
+bool usleep_bool()
+{
+    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+    return true;
+}
+
+SecurityManager::SecurityManager(RTPSParticipantImpl *participant) : participant_(participant),
+    participant_stateless_message_writer_(nullptr),
+    participant_stateless_message_writer_history_(nullptr),
+    participant_stateless_message_reader_(nullptr),
+    participant_stateless_message_reader_history_(nullptr),
+    authentication_plugin_(nullptr)
+{
+    assert(participant != nullptr);
+}
+
+SecurityManager::~SecurityManager()
+{
+    if(authentication_plugin_ != nullptr)
+        delete authentication_plugin_;
+}
+
+bool SecurityManager::init()
+{
+    SecurityException exception;
+
+    authentication_plugin_ = factory_.create_authentication_plugin(participant_->getRTPSParticipantAttributes().properties);
+
+    if(authentication_plugin_ != nullptr)
+    {
+        // Validate local participant
+        GUID_t adjusted_participant_key;
+        ValidationResult_t ret = VALIDATION_FAILED;
+        
+        do
+        {
+            ret = authentication_plugin_->validate_local_identity(&local_identity_handle_,
+                adjusted_participant_key,
+                participant_->getRTPSParticipantAttributes().builtin.domainId,
+                participant_->getRTPSParticipantAttributes(),
+                participant_->getGuid(),
+                exception);
+        } while(ret == VALIDATION_PENDING_RETRY && usleep_bool());
+
+        if(ret == VALIDATION_OK)
+        {
+            assert(local_identity_handle_ != nullptr);
+
+            // Create RTPS entities
+            if(create_entities())
+            {
+                return true;
+            }
+        }
+
+        delete authentication_plugin_;
+        authentication_plugin_ = nullptr;
+    }
+    else
+    {
+        logInfo(SECURITY, "Authentication plugin not configured. Security will be disable");
+    }
+
+    return false;
+}
+
+void SecurityManager::remove_discovered_participant_info(const GUID_t remote_participant_key)
+{
+    std::unique_lock<std::mutex> lock(mutex_);
+    auto dp_it = discovered_participants_.find(remote_participant_key);
+
+    if(dp_it != discovered_participants_.end())
+    {
+        IdentityHandle* identity_handle = dp_it->second.get_identity_handle();
+
+        if(identity_handle != nullptr)
+        {
+            SecurityException exception;
+            authentication_plugin_->return_identity_handle(identity_handle, exception);
+        }
+
+        discovered_participants_.erase(dp_it);
+    }
+}
+
+void SecurityManager::restore_remote_identity_handle(const GUID_t& remote_participant_key,
+        IdentityHandle* remote_identity_handle)
+{
+    SecurityException exception;
+
+    std::unique_lock<std::mutex> lock(mutex_);
+    auto dp_it = discovered_participants_.find(remote_participant_key);
+
+    if(dp_it != discovered_participants_.end())
+    {
+        assert(dp_it->second.is_identity_handle_null());
+        dp_it->second.set_identity_handle(remote_identity_handle);
+    }
+    else
+        authentication_plugin_->return_identity_handle(remote_identity_handle, exception);
+}
+
+bool SecurityManager::discovered_participant(IdentityToken&& remote_identity_token,
+        const GUID_t& remote_participant_key)
 {
+    IdentityHandle* remote_identity_handle = nullptr;
+    SecurityException exception;
+    AuthenticationStatus auth_status = AUTHENTICATION_INIT;
+
+    // Find information
+    mutex_.lock();
+    auto dp_it = discovered_participants_.find(remote_participant_key);
+
+    if(dp_it == discovered_participants_.end())
+    {
+        discovered_participants_.emplace(remote_participant_key, auth_status);
+
+        mutex_.unlock();
+
+        // Validate remote participant.
+        ValidationResult_t validation_ret = authentication_plugin_->validate_remote_identity(&remote_identity_handle,
+                *local_identity_handle_, std::move(remote_identity_token),
+                remote_participant_key, exception);
+
+        switch(validation_ret)
+        {
+            case VALIDATION_OK:
+                assert(remote_identity_handle != nullptr);
+                auth_status = AUTHENTICATION_OK;
+                break;
+            case VALIDATION_PENDING_HANDSHAKE_REQUEST:
+                assert(remote_identity_handle != nullptr);
+                auth_status = AUTHENTICATION_REQUEST_NOT_SEND;
+                break;
+            case VALIDATION_PENDING_HANDSHAKE_MESSAGE:
+                assert(remote_identity_handle != nullptr);
+                auth_status = AUTHENTICATION_WAITING_REQUEST;
+                break;
+            case VALIDATION_PENDING_RETRY:
+                // TODO(Ricardo) Send event.
+            default:
+                remove_discovered_participant_info(remote_participant_key);
+                return false;
+        };
+
+        // Store remote handle.
+        mutex_.lock();
+        dp_it = discovered_participants_.find(remote_participant_key);
+        if(dp_it != discovered_participants_.end())
+        {
+            dp_it->second.set_auth_status(auth_status);
+            bool ret = dp_it->second.set_identity_handle(remote_identity_handle);
+            (void)ret; assert(ret);
+            remote_identity_handle = nullptr;
+        }
+        else
+        {
+            mutex_.unlock();
+            authentication_plugin_->return_identity_handle(remote_identity_handle, exception); // TODO(Ricardo) Check error.
+            return false;
+        }
+    }
+    else
+    {
+        auth_status = dp_it->second.get_auth_status();
+
+        if(auth_status == AUTHENTICATION_INIT)
+            return false;
+    }
+
+    if(auth_status == AUTHENTICATION_REQUEST_NOT_SEND)
+    {
+        remote_identity_handle = dp_it->second.get_identity_handle();
+        assert(remote_identity_handle);
+    }
+    mutex_.unlock();
+
+    bool returnedValue = true;
+
+    // Maybe send request.
+    if(remote_identity_handle != nullptr)
+    {
+        returnedValue = on_request_not_send(remote_participant_key, remote_identity_handle);
+    }
+
+    return returnedValue;
+}
+
+bool SecurityManager::on_request_not_send(const GUID_t& remote_participant_key,
+        IdentityHandle* remote_identity_handle)
+{
+    assert(remote_identity_handle);
+
+    HandshakeHandle* handshake_handle = nullptr;
+    HandshakeMessageToken* handshake_message = nullptr;
+    SecurityException exception;
+    
+    ValidationResult_t ret = authentication_plugin_->begin_handshake_request(&handshake_handle,
+                &handshake_message,
+                *local_identity_handle_,
+                *remote_identity_handle,
+                exception);
+
+    if(ret == VALIDATION_FAILED)
+    {
+        restore_remote_identity_handle(remote_participant_key, remote_identity_handle);
+        return false;
+    }
+
+    assert(handshake_handle);
+    assert(handshake_message);
+
+    // Send hanshake message
+    // 
+    delete handshake_message;
+
+    AuthenticationStatus auth_status = AUTHENTICATION_FAILED;
+
+    switch(ret)
+    {
+        case VALIDATION_OK:
+            auth_status = AUTHENTICATION_OK;
+            break;
+        case VALIDATION_PENDING_HANDSHAKE_MESSAGE:
+            auth_status = AUTHENTICATION_WAITING_REPLY;
+            break;
+        case VALIDATION_OK_WITH_FINAL_MESSAGE:
+            auth_status = AUTHENTICATION_OK;
+            break;
+        case VALIDATION_PENDING_RETRY:
+            // TODO(Ricardo) Send event.
+        default:
+            restore_remote_identity_handle(remote_participant_key, remote_identity_handle);
+            return false;
+    };
+
+    // Store status
+    std::unique_lock<std::mutex> lock(mutex_);
+
+    auto dp_it = discovered_participants_.find(remote_participant_key);
+
+    if(dp_it != discovered_participants_.end())
+    {
+        assert(dp_it->second.get_auth_status() == AUTHENTICATION_REQUEST_NOT_SEND);
+        dp_it->second.set_auth_status(auth_status);
+        assert(dp_it->second.is_identity_handle_null());
+        dp_it->second.set_identity_handle(remote_identity_handle);
+        assert(dp_it->second.is_handshake_handle_null());
+        dp_it->second.set_handshake_handle(handshake_handle);
+    }
+    else
+    {
+        authentication_plugin_->return_handshake_handle(handshake_handle, exception);
+        authentication_plugin_->return_identity_handle(remote_identity_handle, exception);
+        return false;
+    }
+
+    return true;
+}
+
+bool SecurityManager::create_entities()
+{
+    if(create_participant_stateless_message_entities())
+    {
+        return true;
+    }
+
+    return false; 
+}
+
+bool SecurityManager::create_participant_stateless_message_entities()
+{
+    if(create_participant_stateless_message_writer())
+    {
+        if(create_participant_stateless_message_reader())
+        {
+            return true;
+        }
+
+        delete_participant_stateless_message_writer();
+    }
+
+    return false;
+}
+
+void SecurityManager::delete_participant_stateless_message_entities()
+{
+    delete_participant_stateless_message_reader();
+    delete_participant_stateless_message_writer();
+}
+
+bool SecurityManager::create_participant_stateless_message_writer()
+{
+    HistoryAttributes hatt;
+    hatt.payloadMaxSize = 5000;
+    hatt.initialReservedCaches = 20;
+    hatt.maximumReservedCaches = 100;
+    participant_stateless_message_writer_history_ = new WriterHistory(hatt);
+    WriterAttributes watt;
+    watt.endpoint.endpointKind = WRITER;
+    watt.endpoint.reliabilityKind = BEST_EFFORT;
+    watt.endpoint.topicKind = NO_KEY;
+
+    if(participant_->getRTPSParticipantAttributes().throughputController.bytesPerPeriod != UINT32_MAX &&
+            participant_->getRTPSParticipantAttributes().throughputController.periodMillisecs != 0)
+        watt.mode = ASYNCHRONOUS_WRITER;
+
+    RTPSWriter* wout = nullptr;
+    if(participant_->createWriter(&wout, watt, participant_stateless_message_writer_history_, nullptr, participant_stateless_message_writer_entity_id, true))
+    {
+        participant_stateless_message_writer_ = dynamic_cast<StatelessWriter*>(wout);
+
+        return true;
+    }
+
+    logError(SECURITY,"Participant Stateless Message Writer creation failed");
+    delete(participant_stateless_message_writer_history_);
+    participant_stateless_message_writer_history_ = nullptr;
+
+    return false;
+}
+
+void SecurityManager::delete_participant_stateless_message_writer()
+{
+    if(participant_stateless_message_writer_ != nullptr)
+        delete participant_stateless_message_writer_;
+
+    if(participant_stateless_message_writer_history_ != nullptr)
+        delete participant_stateless_message_writer_history_;
+}
+
+bool SecurityManager::create_participant_stateless_message_reader()
+{
+    HistoryAttributes hatt;
+    hatt.payloadMaxSize = 5000;
+    hatt.initialReservedCaches = 250;
+    hatt.maximumReservedCaches = 5000;
+    participant_stateless_message_reader_history_ = new ReaderHistory(hatt);
+    ReaderAttributes ratt;
+    ratt.endpoint.topicKind = NO_KEY;
+    ratt.endpoint.reliabilityKind = BEST_EFFORT;
+    //mp_listener = new PDPSimpleListener(this);
+
+    RTPSReader* rout = nullptr;
+    if(participant_->createReader(&rout, ratt, participant_stateless_message_reader_history_, nullptr, participant_stateless_message_reader_entity_id, true, false))
+    {
+        participant_stateless_message_reader_ = dynamic_cast<StatelessReader*>(rout);
+
+        return true;
+    }
+
+    logError(SECURITY,"Participant Stateless Message Reader creation failed");
+    delete(participant_stateless_message_reader_history_);
+    participant_stateless_message_reader_history_ = nullptr;
+    //delete(mp_listener);
+    //mp_listener = nullptr;
+    return false;
+}
+
+void SecurityManager::delete_participant_stateless_message_reader()
+{
+    if(participant_stateless_message_reader_ != nullptr)
+        delete participant_stateless_message_reader_;
+
+    if(participant_stateless_message_reader_history_ != nullptr)
+        delete participant_stateless_message_reader_history_;
 }

programming_language: C++
filename: SecurityManager.h
change_type: ModificationType.MODIFY
diff: @@ -18,17 +18,157 @@
 #ifndef _RTPS_SECURITY_SECURITYMANAGER_H_
 #define _RTPS_SECURITY_SECURITYMANAGER_H_
 
+#include "SecurityPluginFactory.h"
+
+#include <fastrtps/rtps/security/authentication/Handshake.h>
+
+#include <map>
+#include <mutex>
+
 namespace eprosima {
 namespace fastrtps {
 namespace rtps {
+
+class RTPSParticipantImpl;
+class StatelessWriter;
+class StatelessReader;
+class WriterHistory;
+class ReaderHistory;
+
 namespace security {
 
+class Authentication;
 
 class SecurityManager
 {
     public:
 
-        SecurityManager();
+        SecurityManager(RTPSParticipantImpl* participant);
+
+        ~SecurityManager();
+
+        bool init();
+
+        bool discovered_participant(IdentityToken&& remote_identity_token,
+                const GUID_t& remote_participant_key);
+
+    private:
+
+        enum AuthenticationStatus : uint32_t
+        {
+            AUTHENTICATION_OK = 0,
+            AUTHENTICATION_FAILED,
+            AUTHENTICATION_INIT,
+            AUTHENTICATION_REQUEST_NOT_SEND,
+            AUTHENTICATION_WAITING_REQUEST,
+            AUTHENTICATION_WAITING_REPLY,
+            AUTHENTICATION_WAITING_FINAL
+        };
+
+        class DiscoveredParticipantInfo
+        {
+            public:
+
+                DiscoveredParticipantInfo(AuthenticationStatus auth_status) :
+                    identity_handle_(nullptr), handshake_handle_(nullptr),
+                    auth_status_(auth_status){}
+
+                bool is_identity_handle_null()
+                {
+                    return identity_handle_ == nullptr;
+                }
+
+                bool set_identity_handle(IdentityHandle* identity_handle)
+                {
+                    if(identity_handle_ == nullptr)
+                    {
+                        identity_handle_ = identity_handle;
+                        return true;
+                    }
+
+                    return false;
+                }
+
+                IdentityHandle* get_identity_handle()
+                {
+                    IdentityHandle* handle = identity_handle_;
+                    identity_handle_ = nullptr;
+                    return handle;
+                }
+
+                bool is_handshake_handle_null()
+                {
+                    return handshake_handle_ == nullptr;
+                }
+
+                bool set_handshake_handle(HandshakeHandle* handshake_handle)
+                {
+                    if(handshake_handle_ == nullptr)
+                    {
+                        handshake_handle_ = handshake_handle;
+                        return true;
+                    }
+
+                    return false;
+                }
+
+                HandshakeHandle* get_handshake_handle()
+                {
+                    HandshakeHandle* handle = handshake_handle_;
+                    handshake_handle_ = nullptr;
+                    return handle;
+                }
+
+                AuthenticationStatus get_auth_status()
+                {
+                    return auth_status_;
+                }
+
+                void set_auth_status(AuthenticationStatus auth_status)
+                {
+                    auth_status_ = auth_status;
+                }
+
+            private:
+
+                DiscoveredParticipantInfo(const DiscoveredParticipantInfo& info) = delete;
+
+                IdentityHandle* identity_handle_;
+
+                HandshakeHandle* handshake_handle_;
+
+                AuthenticationStatus auth_status_;
+        };
+
+        void remove_discovered_participant_info(const GUID_t remote_participant_key);
+        void restore_remote_identity_handle(const GUID_t& remote_participant_key,
+                IdentityHandle* remote_identity_handle);
+
+        bool create_entities();
+        void delete_entities();
+        bool create_participant_stateless_message_entities();
+        void delete_participant_stateless_message_entities();
+        bool create_participant_stateless_message_writer();
+        void delete_participant_stateless_message_writer();
+        bool create_participant_stateless_message_reader();
+        void delete_participant_stateless_message_reader();
+
+        bool on_request_not_send(const GUID_t& remote_participant_key, IdentityHandle* remote_identity_handle);
+
+        RTPSParticipantImpl* participant_;
+        StatelessWriter* participant_stateless_message_writer_;
+        WriterHistory* participant_stateless_message_writer_history_;
+        StatelessReader* participant_stateless_message_reader_;
+        ReaderHistory* participant_stateless_message_reader_history_;
+        SecurityPluginFactory factory_;
+
+        Authentication* authentication_plugin_;
+
+        IdentityHandle* local_identity_handle_;
+
+        std::map<GUID_t, DiscoveredParticipantInfo> discovered_participants_;
+
+        std::mutex mutex_;
 };
 
 } //namespace security

programming_language: C++
filename: PKIDH.cpp
change_type: ModificationType.MODIFY
diff: @@ -998,7 +998,7 @@ ValidationResult_t PKIDH::validate_local_identity(IdentityHandle** local_identit
 ValidationResult_t PKIDH::validate_remote_identity(IdentityHandle** remote_identity_handle,
         const IdentityHandle& local_identity_handle,
         IdentityToken&& remote_identity_token,
-        const GUID_t remote_participant_key,
+        const GUID_t& remote_participant_key,
         SecurityException& exception)
 {
     assert(remote_identity_handle);

programming_language: C++
filename: PKIDH.h
change_type: ModificationType.MODIFY
diff: @@ -42,7 +42,7 @@ class PKIDH : public Authentication
         ValidationResult_t validate_remote_identity(IdentityHandle** remote_identity_handle,
                 const IdentityHandle& local_identity_handle,
                 IdentityToken&& remote_identity_token,
-                const GUID_t remote_participant_key,
+                const GUID_t& remote_participant_key,
                 SecurityException& exception);
 
         ValidationResult_t begin_handshake_request(HandshakeHandle** handshake_handle,

programming_language: Objective-C
filename: CMakeLists.txt
change_type: ModificationType.MODIFY
diff: @@ -29,3 +29,4 @@ add_subdirectory(unittest/rtps/flowcontrol)
 add_subdirectory(unittest/transport)
 add_subdirectory(unittest/logging)
 add_subdirectory(unittest/security/authentication)
+add_subdirectory(unittest/rtps/security)

programming_language: Shell
filename: RTPSParticipantImpl.h
change_type: ModificationType.ADD
diff: @@ -0,0 +1,59 @@
+// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @file RTPSParticipantImpl.h
+ */
+
+#ifndef RTPS_PARTICIPANT_RTPSPARTICIPANTIMPL_H_
+#define RTPS_PARTICIPANT_RTPSPARTICIPANTIMPL_H_
+
+#include <fastrtps/rtps/attributes/WriterAttributes.h>
+#include <fastrtps/rtps/attributes/ReaderAttributes.h>
+
+#include <gmock/gmock.h>
+
+namespace eprosima {
+namespace fastrtps {
+namespace rtps {
+
+class RTPSWriter;
+class RTPSReader;
+class WriterHistory;
+class ReaderHistory;
+class WriterListener;
+class ReaderListener;
+class EntityId_t;
+
+class RTPSParticipantImpl
+{
+    public:
+
+        MOCK_CONST_METHOD0(getRTPSParticipantAttributes, const RTPSParticipantAttributes&());
+
+        MOCK_CONST_METHOD0(getGuid, const GUID_t&());
+
+        MOCK_METHOD6(createWriter, bool (RTPSWriter** Writer, WriterAttributes& param, WriterHistory* hist,WriterListener* listen,
+                const EntityId_t& entityId, bool isBuiltin));
+
+        MOCK_METHOD7(createReader, bool (RTPSReader** Reader, ReaderAttributes& param, ReaderHistory* hist,ReaderListener* listen,
+                const EntityId_t& entityId, bool isBuiltin, bool enable));
+};
+
+} // namespace rtps
+} // namespace fastrtps
+} // namespace eprosima
+
+#endif // RTPS_PARTICIPANT_RTPSPARTICIPANTIMPL_H_
+

programming_language: C++
filename: RTPSReader.h
change_type: ModificationType.ADD
diff: @@ -0,0 +1,39 @@
+// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @file RTPSReader.h
+ */
+
+#ifndef _RTPS_READER_RTPSREADER_H_
+#define _RTPS_READER_RTPSREADER_H_
+
+namespace eprosima {
+namespace fastrtps {
+namespace rtps {
+
+class RTPSReader
+{
+    public:
+
+        virtual bool matched_writer_add(RemoteWriterAttributes& wdata) = 0;
+
+        virtual bool matched_writer_remove(RemoteWriterAttributes& wdata) = 0;
+};
+
+} // namespace rtps
+} // namespace fastrtps
+} // namespace eprosima
+
+#endif // _RTPS_READER_RTPSREADER_H_

programming_language: Go
filename: RTPSWriter.h
change_type: ModificationType.ADD
diff: @@ -0,0 +1,39 @@
+// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @file RTPSWriter.h
+ */
+
+#ifndef _RTPS_WRITER_RTPSWRITER_H_
+#define _RTPS_WRITER_RTPSWRITER_H_
+
+namespace eprosima {
+namespace fastrtps {
+namespace rtps {
+
+class RTPSWriter
+{
+    public:
+
+        virtual bool matched_reader_add(RemoteReaderAttributes& ratt) = 0;
+
+        virtual bool matched_reader_remove(RemoteReaderAttributes& ratt) = 0;
+};
+
+} // namespace rtps
+} // namespace fastrtps
+} // namespace eprosima
+
+#endif // _RTPS_WRITER_RTPSWRITER_H_

programming_language: C#
filename: ReaderHistory.h
change_type: ModificationType.ADD
diff: @@ -0,0 +1,39 @@
+// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @file ReaderHistory.h
+ */
+
+#ifndef _RTPS_HISTORY_READERHISTORY_H_
+#define _RTPS_HISTORY_READERHISTORY_H_
+
+#include <fastrtps/rtps/attributes/HistoryAttributes.h>
+
+namespace eprosima {
+namespace fastrtps {
+namespace rtps {
+
+class ReaderHistory
+{
+    public:
+
+        ReaderHistory(const HistoryAttributes& /*att*/){}
+};
+
+} // namespace rtps
+} // namespace fastrtps
+} // namespace eprosima
+
+#endif // _RTPS_HISTORY_READERHISTORY_H_

programming_language: Go
filename: MockAuthenticationPlugin.h
change_type: ModificationType.ADD
diff: @@ -0,0 +1,125 @@
+// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/*!
+ * @file MockAuthenticationPlugin.h
+ */
+
+#ifndef _SECURITY_MOCKAUTHENTICATIONPLUGIN_H_
+#define _SECURITY_MOCKAUTHENTICATIONPLUGIN_H_
+
+// TODO(Ricardo) Change when GMock supports r-values.
+
+#include <fastrtps/rtps/security/authentication/Authentication.h>
+#include <gmock/gmock.h>
+
+namespace eprosima {
+namespace fastrtps {
+namespace rtps {
+namespace security {
+
+class MockAuthenticationPlugin : public Authentication
+{
+    public:
+
+        MOCK_METHOD6(validate_local_identity, ValidationResult_t(IdentityHandle** local_identity_handle,
+                GUID_t& adjusted_participant_key,
+                const uint32_t domain_id,
+                const RTPSParticipantAttributes& participant_attr,
+                const GUID_t& candidate_participant_key,
+                SecurityException& exception));
+
+        MOCK_METHOD5(validate_remote_identity_rvr, ValidationResult_t(IdentityHandle** remote_identity_handle,
+                const IdentityHandle& local_identity_handle,
+                IdentityToken remote_identity_token,
+                const GUID_t& remote_participant_key,
+                SecurityException& exception));
+
+        MOCK_METHOD5(begin_handshake_request, ValidationResult_t(HandshakeHandle** handshake_handle,
+                HandshakeMessageToken** handshake_message,
+                const IdentityHandle& initiator_identity_handle,
+                IdentityHandle& replier_identity_handle,
+                SecurityException& exception));
+
+        MOCK_METHOD6(begin_handshake_reply_rvr, ValidationResult_t(HandshakeHandle** handshake_handle,
+                HandshakeMessageToken** handshake_message_out,
+                HandshakeMessageToken handshake_message_in,
+                IdentityHandle& initiator_identity_handle,
+                const IdentityHandle& replier_identity_handle,
+                SecurityException& exception));
+
+        MOCK_METHOD4(process_handshake_rvr, ValidationResult_t(HandshakeMessageToken** handshake_message_out,
+                HandshakeMessageToken handshake_message_in,
+                HandshakeHandle& handshake_handle,
+                SecurityException& exception));
+
+        MOCK_METHOD2(get_shared_secret, SharedSecretHandle*(const HandshakeHandle& handshake_handle,
+                SecurityException& exception));
+
+        MOCK_METHOD2(set_listener, bool(AuthenticationListener* listener,
+                SecurityException& exception));
+
+        MOCK_METHOD3(get_identity_token, bool(IdentityToken** identity_token,
+                const IdentityHandle& handle,
+                SecurityException& exception));
+
+        MOCK_METHOD2(return_identity_token, bool(IdentityToken* token,
+                SecurityException& exception));
+
+        MOCK_METHOD2(return_handshake_handle, bool(HandshakeHandle* handshake_handle,
+                SecurityException& exception));
+
+        MOCK_METHOD2(return_identity_handle, bool(IdentityHandle* identity_handle,
+                SecurityException& exception));
+
+        MOCK_METHOD2(return_sharedsecret_handle, bool(SharedSecretHandle* sharedsecret_handle,
+                SecurityException& exception));
+
+        ValidationResult_t validate_remote_identity(IdentityHandle** remote_identity_handle,
+                const IdentityHandle& local_identity_handle,
+                IdentityToken&& remote_identity_token,
+                const GUID_t& remote_participant_key,
+                SecurityException& exception)
+        {
+            return validate_remote_identity_rvr(remote_identity_handle, local_identity_handle,
+                    remote_identity_token, remote_participant_key, exception);
+        }
+
+        ValidationResult_t begin_handshake_reply(HandshakeHandle** handshake_handle,
+                HandshakeMessageToken** handshake_message_out,
+                HandshakeMessageToken&& handshake_message_in,
+                IdentityHandle& initiator_identity_handle,
+                const IdentityHandle& replier_identity_handle,
+                SecurityException& exception)
+        {
+            return begin_handshake_reply_rvr(handshake_handle, handshake_message_out, handshake_message_in,
+                    initiator_identity_handle, replier_identity_handle, exception);
+        }
+
+        ValidationResult_t process_handshake(HandshakeMessageToken** handshake_message_out,
+                HandshakeMessageToken&& handshake_message_in,
+                HandshakeHandle& handshake_handle,
+                SecurityException& exception)
+        {
+            return process_handshake_rvr(handshake_message_out, handshake_message_in,
+                    handshake_handle, exception);
+        }
+};
+
+} // namespace security
+} // namespace rtps
+} // namespace fastrtps
+} // namespace eprosima
+
+#endif // _SECURITY_MOCKAUTHENTICATIONPLUGIN_H_

programming_language: Objective-C
filename: SecurityPluginFactory.cpp
change_type: ModificationType.ADD
diff: @@ -0,0 +1,39 @@
+// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/*!
+ * @file SecurityPluginFactory.cpp
+ */
+
+#include "SecurityPluginFactory.h"
+
+using namespace eprosima::fastrtps::rtps;
+using namespace ::security;
+
+Authentication* SecurityPluginFactory::auth_plugin_ = nullptr;
+
+Authentication* SecurityPluginFactory::create_authentication_plugin(const PropertyPolicy& /*property_policy*/)
+{
+    return auth_plugin_;
+}
+
+void SecurityPluginFactory::set_auth_plugin(Authentication* plugin)
+{
+    auth_plugin_ = plugin;
+}
+
+void SecurityPluginFactory::release_auth_plugin()
+{
+    auth_plugin_ = nullptr;
+}

programming_language: C++
filename: SecurityPluginFactory.h
change_type: ModificationType.ADD
diff: @@ -0,0 +1,55 @@
+// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/*!
+ * @file SecurityPluginFactory.h
+ */
+#ifndef _RTPS_SECURITY_SECURITYPLUGINFACTORY_H_
+#define _RTPS_SECURITY_SECURITYPLUGINFACTORY_H_
+
+#include <fastrtps/rtps/security/authentication/Authentication.h>
+#include <fastrtps/rtps/attributes/PropertyPolicy.h>
+
+namespace eprosima {
+namespace fastrtps {
+namespace rtps {
+namespace security {
+
+class SecurityPluginFactory
+{
+    public:
+
+        /*!
+         * @brief Create an Authentication plugin  described in the PropertyPolicy.
+         * @param property_policy PropertyPolicy containing the definition of the Authentication
+         * plugin that has to be created.
+         * @param Pointer to the new Authentication plugin. In case of error nullptr will be returned.
+         */
+        Authentication* create_authentication_plugin(const PropertyPolicy& property_policy);
+
+        static void set_auth_plugin(Authentication* plugin);
+
+        static void release_auth_plugin();
+
+    private:
+
+        static Authentication* auth_plugin_;
+};
+
+} //namespace security
+} //namespace rtps
+} //namespace fastrtps
+} //namespace eprosima
+
+#endif // _RTPS_SECURITY_SECURITYPLUGINFACTORY_H_

programming_language: Objective-C
filename: StatelessReader.h
change_type: ModificationType.ADD
diff: @@ -0,0 +1,41 @@
+// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @file StatelessReader.h
+ */
+
+#ifndef _RTPS_READER_STATELESSREADER_H_
+#define _RTPS_READER_STATELESSREADER_H_
+
+#include <fastrtps/rtps/reader/RTPSReader.h>
+
+namespace eprosima {
+namespace fastrtps {
+namespace rtps {
+
+class StatelessReader : public RTPSReader
+{
+    public:
+
+        MOCK_METHOD1(matched_writer_add, bool(RemoteWriterAttributes&));
+
+        MOCK_METHOD1(matched_writer_remove, bool(RemoteWriterAttributes&));
+};
+
+} // namespace rtps
+} // namespace fastrtps
+} // namespace eprosima
+
+#endif // _RTPS_READER_STATELESSREADER_H_

programming_language: C#
filename: StatelessWriter.h
change_type: ModificationType.ADD
diff: @@ -0,0 +1,41 @@
+// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @file StatelessWriter.h
+ */
+
+#ifndef _RTPS_WRITER_STATELESSWRITER_H_
+#define _RTPS_WRITER_STATELESSWRITER_H_
+
+#include <fastrtps/rtps/writer/RTPSWriter.h>
+
+namespace eprosima {
+namespace fastrtps {
+namespace rtps {
+
+class StatelessWriter : public RTPSWriter
+{
+    public:
+
+        MOCK_METHOD1(matched_reader_add, bool(RemoteReaderAttributes&));
+
+        MOCK_METHOD1(matched_reader_remove, bool(RemoteReaderAttributes&));
+};
+
+} // namespace rtps
+} // namespace fastrtps
+} // namespace eprosima
+
+#endif // _RTPS_WRITER_STATELESSWRITER_H_

programming_language: C#
filename: WriterHistory.h
change_type: ModificationType.ADD
diff: @@ -0,0 +1,40 @@
+// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @file WriterHistory.h
+ */
+
+#ifndef _RTPS_HISTORY_WRITERHISTORY_H_
+#define _RTPS_HISTORY_WRITERHISTORY_H_
+
+#include <fastrtps/rtps/attributes/HistoryAttributes.h>
+
+namespace eprosima {
+namespace fastrtps {
+namespace rtps {
+
+class WriterHistory
+{
+    public:
+
+
+        WriterHistory(const HistoryAttributes& /*att*/){}
+};
+
+} // namespace rtps
+} // namespace fastrtps
+} // namespace eprosima
+
+#endif // _RTPS_HISTORY_WRITERHISTORY_H_

programming_language: Go
filename: CMakeLists.txt
change_type: ModificationType.ADD
diff: @@ -0,0 +1,53 @@
+# Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+if(NOT ((MSVC OR MSVC_IDE) AND EPROSIMA_INSTALLER))
+    include(${PROJECT_SOURCE_DIR}/cmake/dev/gtest.cmake)
+    check_gtest()
+    check_gmock()
+
+    if(GTEST_FOUND AND GMOCK_FOUND)
+        if(WIN32)
+            add_definitions(-D_WIN32_WINNT=0x0601)
+        endif()
+
+        set(SOURCES_SECURITY_TEST_SOURCE
+            ${PROJECT_SOURCE_DIR}/src/cpp/log/Log.cpp
+            ${PROJECT_SOURCE_DIR}/src/cpp/log/StdoutConsumer.cpp
+            ${PROJECT_SOURCE_DIR}/src/cpp/rtps/attributes/PropertyPolicy.cpp
+            ${PROJECT_SOURCE_DIR}/test/mock/rtps/SecurityPluginFactory/SecurityPluginFactory.cpp
+            ${PROJECT_SOURCE_DIR}/src/cpp/rtps/security/SecurityManager.cpp
+            ${PROJECT_SOURCE_DIR}/src/cpp/rtps/exceptions/Exception.cpp
+            ${PROJECT_SOURCE_DIR}/src/cpp/rtps/security/exceptions/SecurityException.cpp
+            )
+
+        add_executable(SecurityAuthentication ${SOURCES_SECURITY_TEST_SOURCE}
+            ${CMAKE_CURRENT_SOURCE_DIR}/SecurityAuthenticationTests.cpp)
+        add_gtest(SecurityAuthentication 
+            ${CMAKE_CURRENT_SOURCE_DIR}/SecurityAuthenticationTests.cpp)
+        target_include_directories(SecurityAuthentication PRIVATE
+            ${GTEST_INCLUDE_DIRS} ${GMOCK_INCLUDE_DIRS}
+            ${PROJECT_SOURCE_DIR}/test/mock/rtps/SecurityPluginFactory
+            ${PROJECT_SOURCE_DIR}/test/mock/rtps/RTPSParticipantImpl
+            ${PROJECT_SOURCE_DIR}/test/mock/rtps/RTPSWriter
+            ${PROJECT_SOURCE_DIR}/test/mock/rtps/StatelessWriter
+            ${PROJECT_SOURCE_DIR}/test/mock/rtps/WriterHistory
+            ${PROJECT_SOURCE_DIR}/test/mock/rtps/RTPSReader
+            ${PROJECT_SOURCE_DIR}/test/mock/rtps/StatelessReader
+            ${PROJECT_SOURCE_DIR}/test/mock/rtps/ReaderHistory
+            ${PROJECT_SOURCE_DIR}/src/cpp/rtps/security
+            ${PROJECT_SOURCE_DIR}/include ${PROJECT_BINARY_DIR}/include/${PROJECT_NAME})
+        target_link_libraries(SecurityAuthentication ${Boost_LIBRARIES} ${GMOCK_LIBRARIES})
+    endif()
+endif()

programming_language: Shell
filename: SecurityAuthenticationTests.cpp
change_type: ModificationType.ADD
diff: @@ -0,0 +1,341 @@
+// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <fastrtps/rtps/security/common/Handle.h>
+#include <MockAuthenticationPlugin.h>
+#include <rtps/participant/RTPSParticipantImpl.h>
+#include <SecurityPluginFactory.h>
+#include <SecurityManager.h>
+
+#include <gtest/gtest.h>
+
+using namespace eprosima::fastrtps::rtps;
+using namespace ::security;
+using namespace ::testing;
+
+using ::testing::DefaultValue;
+
+class MockIdentity
+{
+    public:
+
+        static const char* const class_id_;
+};
+
+const char* const MockIdentity::class_id_ = "MockIdentityHandle";
+
+typedef HandleImpl<MockIdentity> MockIdentityHandle;
+
+class MockHandshake
+{
+    public:
+
+        static const char* const class_id_;
+};
+
+const char* const MockHandshake::class_id_ = "MockHandshakeHandle";
+
+typedef HandleImpl<MockHandshake> MockHandshakeHandle;
+
+// Default Values
+RTPSParticipantAttributes pattr;
+GUID_t guid;
+
+class SecurityAuthenticationTest : public ::testing::Test
+{
+    protected:
+
+        virtual void SetUp()
+        {
+            SecurityPluginFactory::set_auth_plugin(auth_plugin_);
+        }
+
+        virtual void TearDown()
+        {
+            SecurityPluginFactory::release_auth_plugin();
+        }
+
+        void initialization_ok()
+        {
+            DefaultValue<const RTPSParticipantAttributes&>::Set(pattr);
+            DefaultValue<const GUID_t&>::Set(guid);
+            MockIdentityHandle identity_handle;
+            MockIdentityHandle* p_identity_handle = &identity_handle;
+
+            EXPECT_CALL(*auth_plugin_, validate_local_identity(_,_,_,_,_,_)).Times(1).
+                WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_OK)));
+            EXPECT_CALL(participant_, createWriter(_,_,_,_,_,_)).Times(1).
+                WillOnce(Return(true));
+            EXPECT_CALL(participant_, createReader(_,_,_,_,_,_,_)).Times(1).
+                WillOnce(Return(true));
+
+            ASSERT_TRUE(manager_.init());
+        }
+
+
+    public:
+
+        SecurityAuthenticationTest() : auth_plugin_(new MockAuthenticationPlugin()), manager_(&participant_) {}
+        MockAuthenticationPlugin* auth_plugin_;
+        NiceMock<RTPSParticipantImpl> participant_;
+        SecurityManager manager_;
+};
+
+TEST_F(SecurityAuthenticationTest, initialization_auth_nullptr)
+{
+    SecurityPluginFactory::release_auth_plugin();
+    DefaultValue<const RTPSParticipantAttributes&>::Set(pattr);
+    DefaultValue<const GUID_t&>::Set(guid);
+
+    ASSERT_FALSE(manager_.init());
+}
+
+TEST_F(SecurityAuthenticationTest, initialization_auth_failed)
+{
+    DefaultValue<const RTPSParticipantAttributes&>::Set(pattr);
+    DefaultValue<const GUID_t&>::Set(guid);
+
+    EXPECT_CALL(*auth_plugin_, validate_local_identity(_,_,_,_,_,_)).Times(1).
+        WillOnce(Return(ValidationResult_t::VALIDATION_FAILED));
+
+    ASSERT_FALSE(manager_.init());
+}
+
+TEST_F(SecurityAuthenticationTest, initialization_fail_participant_stateless_message_writer)
+{
+    DefaultValue<const RTPSParticipantAttributes&>::Set(pattr);
+    DefaultValue<const GUID_t&>::Set(guid);
+    MockIdentityHandle identity_handle;
+    MockIdentityHandle* p_identity_handle = &identity_handle;
+
+    EXPECT_CALL(*auth_plugin_, validate_local_identity(_,_,_,_,_,_)).Times(1).
+        WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_OK)));
+    EXPECT_CALL(participant_, createWriter(_,_,_,_,_,_)).Times(1).
+        WillOnce(Return(false));
+
+    ASSERT_FALSE(manager_.init());
+}
+
+TEST_F(SecurityAuthenticationTest, initialization_fail_participant_stateless_message_reader)
+{
+    DefaultValue<const RTPSParticipantAttributes&>::Set(pattr);
+    DefaultValue<const GUID_t&>::Set(guid);
+    MockIdentityHandle identity_handle;
+    MockIdentityHandle* p_identity_handle = &identity_handle;
+
+    EXPECT_CALL(*auth_plugin_, validate_local_identity(_,_,_,_,_,_)).Times(1).
+        WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_OK)));
+    EXPECT_CALL(participant_, createWriter(_,_,_,_,_,_)).Times(1).
+        WillOnce(Return(true));
+    EXPECT_CALL(participant_, createReader(_,_,_,_,_,_,_)).Times(1).
+        WillOnce(Return(false));
+
+    ASSERT_FALSE(manager_.init());
+}
+
+TEST_F(SecurityAuthenticationTest, initialization_auth_retry)
+{
+    DefaultValue<const RTPSParticipantAttributes&>::Set(pattr);
+    DefaultValue<const GUID_t&>::Set(guid);
+    MockIdentityHandle identity_handle;
+    MockIdentityHandle* p_identity_handle = &identity_handle;
+
+    EXPECT_CALL(*auth_plugin_, validate_local_identity(_,_,_,_,_,_)).Times(2).
+        WillOnce(Return(ValidationResult_t::VALIDATION_PENDING_RETRY)).
+        WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_OK)));
+    EXPECT_CALL(participant_, createWriter(_,_,_,_,_,_)).Times(1).
+        WillOnce(Return(true));
+    EXPECT_CALL(participant_, createReader(_,_,_,_,_,_,_)).Times(1).
+        WillOnce(Return(true));
+
+    ASSERT_TRUE(manager_.init());
+}
+
+
+TEST_F(SecurityAuthenticationTest, initialization_ok)
+{
+    initialization_ok();
+}
+
+TEST_F(SecurityAuthenticationTest, discovered_participant_validation_remote_identity_fail)
+{
+    initialization_ok();
+
+    EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
+        WillOnce(Return(ValidationResult_t::VALIDATION_FAILED));
+
+    GUID_t remote_participant_key;
+    ASSERT_FALSE(manager_.discovered_participant(IdentityToken(), remote_participant_key));
+}
+
+TEST_F(SecurityAuthenticationTest, discovered_participant_validation_remote_identity_ok)
+{
+    initialization_ok();
+
+    MockIdentityHandle identity_handle;
+    MockIdentityHandle* p_identity_handle = &identity_handle;
+
+    EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
+        WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_OK)));
+
+    GUID_t remote_participant_key;
+    ASSERT_TRUE(manager_.discovered_participant(IdentityToken(), remote_participant_key));
+}
+
+TEST_F(SecurityAuthenticationTest, discovered_participant_validation_remote_identity_pending_handshake_message)
+{
+    initialization_ok();
+
+    MockIdentityHandle identity_handle;
+    MockIdentityHandle* p_identity_handle = &identity_handle;
+
+    EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
+        WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_MESSAGE)));
+
+    GUID_t remote_participant_key;
+    ASSERT_TRUE(manager_.discovered_participant(IdentityToken(), remote_participant_key));
+}
+
+TEST_F(SecurityAuthenticationTest, discovered_participant_validation_remote_identity_pending_handshake_request_fail)
+{
+    initialization_ok();
+
+    MockIdentityHandle identity_handle;
+    MockIdentityHandle* p_identity_handle = &identity_handle;
+
+    EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
+        WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_REQUEST)));
+    EXPECT_CALL(*auth_plugin_, begin_handshake_request(_,_,_,_,_)).Times(1).
+        WillOnce(Return(ValidationResult_t::VALIDATION_FAILED));
+
+    GUID_t remote_participant_key;
+    ASSERT_FALSE(manager_.discovered_participant(IdentityToken(), remote_participant_key));
+}
+
+TEST_F(SecurityAuthenticationTest, discovered_participant_validation_remote_identity_pending_handshake_request_ok)
+{
+    initialization_ok();
+
+    MockIdentityHandle identity_handle;
+    MockIdentityHandle* p_identity_handle = &identity_handle;
+    MockHandshakeHandle handshake_handle;
+    MockHandshakeHandle* p_handshake_handle = &handshake_handle;
+    HandshakeMessageToken* p_handshake_message = new HandshakeMessageToken();
+
+    EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
+        WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_REQUEST)));
+    EXPECT_CALL(*auth_plugin_, begin_handshake_request(_,_,_,_,_)).Times(1).
+        WillOnce(DoAll(SetArgPointee<0>(p_handshake_handle), 
+                    SetArgPointee<1>(p_handshake_message), Return(ValidationResult_t::VALIDATION_OK)));
+
+    GUID_t remote_participant_key;
+    ASSERT_TRUE(manager_.discovered_participant(IdentityToken(), remote_participant_key));
+}
+
+TEST_F(SecurityAuthenticationTest, discovered_participant_validation_remote_identity_pending_handshake_request_ok_with_final_message)
+{
+    initialization_ok();
+
+    MockIdentityHandle identity_handle;
+    MockIdentityHandle* p_identity_handle = &identity_handle;
+    MockHandshakeHandle handshake_handle;
+    MockHandshakeHandle* p_handshake_handle = &handshake_handle;
+    HandshakeMessageToken* p_handshake_message = new HandshakeMessageToken();
+
+    EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
+        WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_REQUEST)));
+    EXPECT_CALL(*auth_plugin_, begin_handshake_request(_,_,_,_,_)).Times(1).
+        WillOnce(DoAll(SetArgPointee<0>(p_handshake_handle), 
+                    SetArgPointee<1>(p_handshake_message), Return(ValidationResult_t::VALIDATION_OK_WITH_FINAL_MESSAGE)));
+
+    GUID_t remote_participant_key;
+    ASSERT_TRUE(manager_.discovered_participant(IdentityToken(), remote_participant_key));
+}
+
+TEST_F(SecurityAuthenticationTest, discovered_participant_ok)
+{
+    initialization_ok();
+
+    MockIdentityHandle identity_handle;
+    MockIdentityHandle* p_identity_handle = &identity_handle;
+    MockHandshakeHandle handshake_handle;
+    MockHandshakeHandle* p_handshake_handle = &handshake_handle;
+    HandshakeMessageToken* p_handshake_message = new HandshakeMessageToken();
+
+    EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
+        WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_REQUEST)));
+    EXPECT_CALL(*auth_plugin_, begin_handshake_request(_,_,_,_,_)).Times(1).
+        WillOnce(DoAll(SetArgPointee<0>(p_handshake_handle), 
+                    SetArgPointee<1>(p_handshake_message), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_MESSAGE)));
+
+    GUID_t remote_participant_key;
+    ASSERT_TRUE(manager_.discovered_participant(IdentityToken(), remote_participant_key));
+}
+
+TEST_F(SecurityAuthenticationTest, discovered_participant_validate_remote_fail_and_then_ok)
+{
+    initialization_ok();
+
+    MockIdentityHandle identity_handle;
+    MockIdentityHandle* p_identity_handle = &identity_handle;
+    MockHandshakeHandle handshake_handle;
+    MockHandshakeHandle* p_handshake_handle = &handshake_handle;
+    HandshakeMessageToken* p_handshake_message = new HandshakeMessageToken();
+
+    EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
+        WillOnce(Return(ValidationResult_t::VALIDATION_FAILED));
+
+    GUID_t remote_participant_key;
+    ASSERT_FALSE(manager_.discovered_participant(IdentityToken(), remote_participant_key));
+
+    EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
+        WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_REQUEST)));
+    EXPECT_CALL(*auth_plugin_, begin_handshake_request(_,_,_,_,_)).Times(1).
+        WillOnce(DoAll(SetArgPointee<0>(p_handshake_handle), 
+                    SetArgPointee<1>(p_handshake_message), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_MESSAGE)));
+
+    ASSERT_TRUE(manager_.discovered_participant(IdentityToken(), remote_participant_key));
+}
+
+TEST_F(SecurityAuthenticationTest, discovered_participant_begin_handshake_request_fail_and_then_ok)
+{
+    initialization_ok();
+
+    MockIdentityHandle identity_handle;
+    MockIdentityHandle* p_identity_handle = &identity_handle;
+    MockHandshakeHandle handshake_handle;
+    MockHandshakeHandle* p_handshake_handle = &handshake_handle;
+    HandshakeMessageToken* p_handshake_message = new HandshakeMessageToken();
+
+    EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(1).
+        WillOnce(DoAll(SetArgPointee<0>(p_identity_handle), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_REQUEST)));
+    EXPECT_CALL(*auth_plugin_, begin_handshake_request(_,_,_,_,_)).Times(1).
+        WillOnce(Return(ValidationResult_t::VALIDATION_FAILED));
+
+    GUID_t remote_participant_key;
+    ASSERT_FALSE(manager_.discovered_participant(IdentityToken(), remote_participant_key));
+
+    EXPECT_CALL(*auth_plugin_, validate_remote_identity_rvr(_,_,_,_,_)).Times(0);
+    EXPECT_CALL(*auth_plugin_, begin_handshake_request(_,_,_,_,_)).Times(1).
+        WillOnce(DoAll(SetArgPointee<0>(p_handshake_handle), 
+                    SetArgPointee<1>(p_handshake_message), Return(ValidationResult_t::VALIDATION_PENDING_HANDSHAKE_MESSAGE)));
+
+    ASSERT_TRUE(manager_.discovered_participant(IdentityToken(), remote_participant_key));
+}
+
+int main(int argc, char **argv)
+{
+    testing::InitGoogleMock(&argc, argv);
+    return RUN_ALL_TESTS();
+}

programming_language: C++
filename: BuiltinPKIDHTests.cpp
change_type: ModificationType.MODIFY
diff: @@ -694,4 +694,3 @@ int main(int argc, char **argv)
 
     return RUN_ALL_TESTS();
 }
-

programming_language: C++
repo_url: https://github.com/eProsima/Fast-DDS
commit_details: repo_url: https://github.com/eProsima/Fast-DDS
author: Miguel Company
author_date: 2023-12-18 07:29:30+01:00
msg: Fix CVE-2023-50257

Signed-off-by: Miguel Company <miguelcompany@eprosima.com>
Co-authored-by: Mario Dominguez <mariodominguez@eprosima.com>

commit f2bcd264798ebd0d45241e57f7d522c68920b26f
Author: Miguel Company <miguelcompany@eprosima.com>
Date:   Thu Dec 14 10:52:32 2023 +0100

    Refs #19770. Improve BuiltinAuthenticationPlugin_second_participant_creation_loop.

    Signed-off-by: Miguel Company <miguelcompany@eprosima.com>

commit 07380f840422f8ea2a6ae62ec901fe94687f3b3c
Author: Miguel Company <miguelcompany@eprosima.com>
Date:   Wed Dec 13 08:21:34 2023 +0100

    Refs #19770. Fix PDPTests.

    Signed-off-by: Miguel Company <miguelcompany@eprosima.com>

commit 4c2c21e5f2be63c1f4e0766cc8bc5a59a857b106
Author: Miguel Company <miguelcompany@eprosima.com>
Date:   Wed Dec 13 07:26:51 2023 +0100

    Refs #19770. Adding override keyword.

    Signed-off-by: Miguel Company <miguelcompany@eprosima.com>

commit d185a85b937a1fd64f86a40b9db2d0b994e39a7f
Author: Miguel Company <miguelcompany@eprosima.com>
Date:   Tue Dec 12 16:05:00 2023 +0100

    Refs #19770. Uncrustify.

    Signed-off-by: Miguel Company <miguelcompany@eprosima.com>

commit 54a01ab0eff0e326c868d1a32bd44203bf184b4d
Author: Miguel Company <miguelcompany@eprosima.com>
Date:   Tue Dec 12 10:29:42 2023 +0100

    Refs #19770. PDPSecurityInitiatorListener relies on PDPListener::onNewCacheChangeAdded.

    Signed-off-by: Miguel Company <miguelcompany@eprosima.com>

commit 202bc52a4584025c897e06a40f50d5d7d6be8ce6
Author: Miguel Company <miguelcompany@eprosima.com>
Date:   Tue Dec 12 09:49:20 2023 +0100

    Refs #19770. Only process removals when reader is matched.

    Signed-off-by: Miguel Company <miguelcompany@eprosima.com>

commit a4a30779c0ae3b410b8cce4aa56f47490995d20d
Author: Miguel Company <miguelcompany@eprosima.com>
Date:   Tue Dec 12 09:46:03 2023 +0100

    Refs #19770. Added PDPSecurityInitiatorListener::process_alive_data.

    Signed-off-by: Miguel Company <miguelcompany@eprosima.com>

commit 3c7547e0b125ab7156aaf3f72b1a431a9d77672f
Author: Miguel Company <miguelcompany@eprosima.com>
Date:   Tue Dec 12 09:32:55 2023 +0100

    Refs #19770. Refactor with PDPListener::process_alive_data.

    Signed-off-by: Miguel Company <miguelcompany@eprosima.com>

commit 4571178679af32902a5ba6719807b75eabafc296
Author: Miguel Company <MiguelCompany@eprosima.com>
Date:   Wed Nov 15 12:28:14 2023 +0100

    Refs #19770. StatelessReader does not call update_last_notified for not matched writers.

    Signed-off-by: Miguel Company <MiguelCompany@eprosima.com>

commit 8294ca3b0bae320f066779dfa1d9a8690b16ebfc
Author: Miguel Company <MiguelCompany@eprosima.com>
Date:   Wed Nov 29 13:30:14 2023 +0100

    Refs #19770. Avoid dynamic_cast when participant is not secure.

    Signed-off-by: Miguel Company <MiguelCompany@eprosima.com>

commit 83820e84c6cc3dcaf53e6ffe784ed03b2fac9bfa
Author: Miguel Company <MiguelCompany@eprosima.com>
Date:   Wed Nov 29 13:24:59 2023 +0100

    Refs #19770. Avoid warning when built without security.

    Signed-off-by: Miguel Company <MiguelCompany@eprosima.com>

commit 8ce1216f6af4758f4cb8dc1ea63c770a5ff86e1a
Author: Miguel Company <MiguelCompany@eprosima.com>
Date:   Wed Nov 29 12:55:28 2023 +0100

    Refs #19770. Fixed typo in comments.

    Signed-off-by: Miguel Company <MiguelCompany@eprosima.com>

commit 7bb64eb4a0b899b8055beb8a8b0b279db80e20d6
Author: Miguel Company <MiguelCompany@eprosima.com>
Date:   Wed Nov 29 12:52:07 2023 +0100

    Refs #19770. Use constexpr for topic names.

    Signed-off-by: Miguel Company <MiguelCompany@eprosima.com>

commit eef95273d5464210c50a01cb22cc4a3989233f2f
Author: Miguel Company <MiguelCompany@eprosima.com>
Date:   Wed Nov 29 12:50:56 2023 +0100

    Refs #19770. Send participant dispose messages through both writers.

    Signed-off-by: Miguel Company <MiguelCompany@eprosima.com>

commit c3c831f5f047c4a02a3ddd9944ce3015644f3e27
Author: Miguel Company <MiguelCompany@eprosima.com>
Date:   Tue Nov 28 10:07:17 2023 +0100

    Refs #19770. Move to `AUTHENTICATION_FAILED` when authentication fails.

    Signed-off-by: Miguel Company <MiguelCompany@eprosima.com>

commit 11f98a4d0132d630b76c68ed4157a8624dcffaa5
Author: Miguel Company <MiguelCompany@eprosima.com>
Date:   Tue Nov 28 10:05:47 2023 +0100

    Refs #19770. Simulate DATA(p) reception on non secure `notifyAboveRemoteEndpoints`.

    Signed-off-by: Miguel Company <MiguelCompany@eprosima.com>

commit 5097288e5f4816e653a7c5a4c4839d2a077f3d19
Author: Miguel Company <MiguelCompany@eprosima.com>
Date:   Wed Nov 22 09:36:14 2023 +0100

    Refs #19770. Common factor method `notify_and_maybe_ignore_new_participant`.

    Signed-off-by: Miguel Company <MiguelCompany@eprosima.com>

commit 9364310c5c3cf47b586470b90f9511b0be11fbc4
Author: Miguel Company <MiguelCompany@eprosima.com>
Date:   Tue Nov 21 07:56:17 2023 +0100

    Refs #19770. Improve AllowUnauthenticatedParticipants blackbox tests.

    Signed-off-by: Miguel Company <MiguelCompany@eprosima.com>

commit bb8af40be3c8c138e48acfced5835f2066d864dd
Author: Miguel Company <MiguelCompany@eprosima.com>
Date:   Mon Nov 20 09:53:10 2023 +0100

    Refs #19770. Change builtin endpoints matching workflow.

    Signed-off-by: Miguel Company <MiguelCompany@eprosima.com>

commit 4fc685f75949637ee07ede7a72dd43ed4ab351f3
Author: Miguel Company <MiguelCompany@eprosima.com>
Date:   Fri Nov 17 12:34:40 2023 +0100

    Refs #19770. Chages in announceParticipantState.

    Signed-off-by: Miguel Company <MiguelCompany@eprosima.com>

commit fb26bbccf6400123d2cb0d89d34f8c907e301d1a
Author: Miguel Company <MiguelCompany@eprosima.com>
Date:   Fri Nov 17 12:23:48 2023 +0100

    Refs #19770. Chages in removeRemoteEndpoints.

    Signed-off-by: Miguel Company <MiguelCompany@eprosima.com>

commit 96442d58fa0b16984289bbe16a132769e9cbcd81
Author: Miguel Company <MiguelCompany@eprosima.com>
Date:   Fri Nov 17 12:15:35 2023 +0100

    Refs #19770. Chages in notifyAboveRemoteEndpoints.

    Signed-off-by: Miguel Company <MiguelCompany@eprosima.com>

commit cea35be6c84e633a500bd4565119d1a7ec6066da
Author: Miguel Company <MiguelCompany@eprosima.com>
Date:   Fri Nov 17 11:52:15 2023 +0100

    Refs #19770. Additional work on endpoints creation.

    Signed-off-by: Miguel Company <MiguelCompany@eprosima.com>

commit 02f95cf90b8acdf84c0c6dd357b8a7a26816db93
Author: Miguel Company <MiguelCompany@eprosima.com>
Date:   Fri Nov 17 10:46:48 2023 +0100

    Refs #19770. Methods in PDP to setup builtin endpoints security attributes.

    Signed-off-by: Miguel Company <MiguelCompany@eprosima.com>

commit 1f5c43734dfc6d420103e16132034e7e85ba0c3a
Author: Miguel Company <MiguelCompany@eprosima.com>
Date:   Fri Nov 17 10:38:57 2023 +0100

    Refs #19770. Methods in PDP to create builtin endpoints attributes.

    Signed-off-by: Miguel Company <MiguelCompany@eprosima.com>

commit 49624e88746389b44384f007dc17610ba929731a
Author: Miguel Company <MiguelCompany@eprosima.com>
Date:   Thu Nov 16 16:56:25 2023 +0100

    Refs #19770. Endpoints creation refactor.

    Signed-off-by: Miguel Company <MiguelCompany@eprosima.com>

commit 4ab8d1e1e24819da5d27009ec3e80051329dfbb0
Author: Miguel Company <MiguelCompany@eprosima.com>
Date:   Thu Nov 16 16:28:15 2023 +0100

    Refs #19770. Fix unprotected access to local participant data.

    Signed-off-by: Miguel Company <MiguelCompany@eprosima.com>

commit 57b99075eae290412b4d08798e1df27fc9972e1c
Author: Miguel Company <MiguelCompany@eprosima.com>
Date:   Thu Nov 16 15:38:24 2023 +0100

    Refs #19770. Added SimplePDPEndpointsSecure.

    Signed-off-by: Miguel Company <MiguelCompany@eprosima.com>

commit e67c703db6956e15e187868f90f1f99b25e37627
Author: Miguel Company <MiguelCompany@eprosima.com>
Date:   Thu Nov 16 15:28:38 2023 +0100

    Refs #19770. Listeners moved into BuiltinReader.

    Signed-off-by: Miguel Company <MiguelCompany@eprosima.com>

commit b2fe97e1e0001b24b18d4b145143139a084dc37d
Author: Mario Dominguez <mariodominguez@eprosima.com>
Date:   Wed Nov 8 15:42:34 2023 +0100

    Refs #19770. PDP listener moved into PDPEndpoints.

    Signed-off-by: Miguel Company <MiguelCompany@eprosima.com>

commit 1af9da00af27591be14a1abe1d9928ccff83048d
Author: Miguel Company <MiguelCompany@eprosima.com>
Date:   Thu Nov 16 13:33:37 2023 +0100

    Refs #19770. Test improvements.

    Signed-off-by: Miguel Company <MiguelCompany@eprosima.com>

commit 03eeda5f6b305768cc876056ff6584c153c947d1
Author: Miguel Company <MiguelCompany@eprosima.com>
Date:   Thu Nov 16 13:21:45 2023 +0100

    Refs #19770. Regression test for vulnerability.

    Signed-off-by: Miguel Company <MiguelCompany@eprosima.com>

commit 6cd538753fb8be550f9b3a58c508021d2bdf6ccd
Author: Miguel Company <MiguelCompany@eprosima.com>
Date:   Thu Nov 16 12:30:36 2023 +0100

    Refs #19770. Refactor on BlackboxTestsSecurity.

    Signed-off-by: Miguel Company <MiguelCompany@eprosima.com>

Signed-off-by: Miguel Company <miguelcompany@eprosima.com>
repository: repo_url: https://github.com/eProsima/Fast-DDS
repo_name: eProsima/Fast-DDS
description: The most complete DDS - Proven: Plenty of success cases. Looking for commercial support? Contact info@eprosima.com
repo_language: C++
owner: eProsima
file_changes: filename: PDP.h
change_type: ModificationType.MODIFY
diff: @@ -330,9 +330,9 @@ public:
      * Get a pointer to the local RTPSParticipant ParticipantProxyData object.
      * @return Pointer to the local RTPSParticipant ParticipantProxyData object.
      */
-    ParticipantProxyData* getLocalParticipantProxyData()
+    ParticipantProxyData* getLocalParticipantProxyData() const
     {
-        return participant_proxies_.front();
+        return participant_proxies_.empty() ? nullptr : participant_proxies_.front();
     }
 
     /**
@@ -431,7 +431,15 @@ public:
         return temp_writer_proxies_;
     }
 
+    ReaderAttributes create_builtin_reader_attributes() const;
+
+    WriterAttributes create_builtin_writer_attributes() const;
+
 #if HAVE_SECURITY
+    void add_builtin_security_attributes(
+            ReaderAttributes& ratt,
+            WriterAttributes& watt) const;
+
     virtual bool pairing_remote_writer_with_local_reader_after_security(
             const GUID_t& local_reader,
             const WriterProxyData& remote_writer_data);
@@ -501,8 +509,6 @@ protected:
     ResourceLimitedVector<WriterProxyData*> writer_proxies_pool_;
     //!Variable to indicate if any parameter has changed.
     std::atomic_bool m_hasChangedLocalPDP;
-    //!Listener for the SPDP messages.
-    ReaderListener* mp_listener;
     //! ProxyPool for temporary reader proxies
     ProxyPool<ReaderProxyData> temp_reader_proxies_;
     //! ProxyPool for temporary writer proxies
@@ -574,6 +580,10 @@ protected:
      */
     virtual void update_builtin_locators() = 0;
 
+    void notify_and_maybe_ignore_new_participant(
+            ParticipantProxyData* pdata,
+            bool& should_be_ignored);
+
 #ifdef FASTDDS_STATISTICS
 
     std::atomic<const fastdds::statistics::rtps::IProxyObserver*> proxy_observer_;

programming_language: C++
filename: PDPListener.h
change_type: ModificationType.MODIFY
diff: @@ -37,34 +37,56 @@ class PDP;
  * This class is implemented in order to use the same structure than with any other RTPSReader.
  * @ingroup DISCOVERY_MODULE
  */
-class PDPListener: public ReaderListener
+class PDPListener : public ReaderListener
 {
 
 public:
+
     /**
      * @param parent Pointer to object creating this object
      */
-    PDPListener(PDP* parent);
+    PDPListener(
+            PDP* parent);
 
     virtual ~PDPListener() override = default;
 
     /**
-    * New added cache
-    * @param reader
-    * @param change
-    */
+     * New added cache
+     * @param reader
+     * @param change
+     */
     void onNewCacheChangeAdded(
             RTPSReader* reader,
             const CacheChange_t* const change) override;
 
 protected:
 
+    /**
+     * Process an incoming DATA(p).
+     * This method is called from PDPListener::onNewCacheChangeAdded() when an alive DATA(p) is received.
+     * Both the reader lock and the PDP lock are held when this method is called.
+     *
+     * @param  old_data     Pointer to the ParticipantProxyData currently stored in the database. May be nullptr, for a
+     *                      recently discovered participant.
+     * @param  new_data     ParticipantProxyData from the DATA(p) message.
+     * @param  writer_guid  GUID of the writer that sent the DATA(p) message.
+     * @param  reader       RTPSReader that received the DATA(p) message.
+     * @param  lock         Lock on the PDP database. Passed so it can be released before invoking callbacks.
+     */
+    virtual void process_alive_data(
+            ParticipantProxyData* old_data,
+            ParticipantProxyData& new_data,
+            GUID_t& writer_guid,
+            RTPSReader* reader,
+            std::unique_lock<std::recursive_mutex>& lock);
+
     /**
      * Get the key of a CacheChange_t
      * @param change Pointer to the CacheChange_t
      * @return True on success
      */
-    bool get_key(CacheChange_t* change);
+    bool get_key(
+            CacheChange_t* change);
 
     //!Pointer to the associated mp_SPDP;
     PDP* parent_pdp_;
@@ -82,5 +104,5 @@ protected:
 } /* namespace fastrtps */
 } /* namespace eprosima */
 
-#endif
+#endif // ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC
 #endif /* _FASTDDS_RTPS_PDPLISTENER_H_ */

programming_language: C++
filename: PDPSimple.h
change_type: ModificationType.MODIFY
diff: @@ -139,6 +139,28 @@ private:
      */
     bool createPDPEndpoints() override;
 
+    bool create_dcps_participant_endpoints();
+
+    void match_pdp_remote_endpoints(
+            const ParticipantProxyData& pdata,
+            bool notify_secure_endpoints);
+
+    void assign_low_level_remote_endpoints(
+            const ParticipantProxyData& pdata,
+            bool notify_secure_endpoints);
+
+#if HAVE_SECURITY
+    bool create_dcps_participant_secure_endpoints();
+
+    bool pairing_remote_writer_with_local_reader_after_security(
+            const GUID_t& local_reader,
+            const WriterProxyData& remote_writer_data) override;
+
+    bool pairing_remote_reader_with_local_writer_after_security(
+            const GUID_t& local_reader,
+            const ReaderProxyData& remote_reader_data) override;
+#endif // HAVE_SECURITY
+
 };
 
 } /* namespace rtps */

programming_language: C
filename: BuiltinReader.hpp
change_type: ModificationType.MODIFY
diff: @@ -22,6 +22,7 @@
 #include <memory>
 
 #include <fastdds/rtps/history/ReaderHistory.h>
+#include <fastdds/rtps/reader/ReaderListener.h>
 
 #include <rtps/history/ITopicPayloadPool.h>
 #include <rtps/history/PoolConfig.h>
@@ -52,6 +53,8 @@ struct BuiltinReader
                 payload_pool_->release_history(cfg, true);
             }
         }
+
+        listener_.reset();
     }
 
     void remove_from_history(
@@ -75,6 +78,8 @@ struct BuiltinReader
     std::unique_ptr<fastrtps::rtps::ReaderHistory> history_;
     //! Builtin RTPS reader
     TReader* reader_ = nullptr;
+    //! Listener for the builtin RTPS reader
+    std::unique_ptr<fastrtps::rtps::ReaderListener> listener_;
 };
 
 } // namespace rtps

programming_language: C++
filename: EDPSimple.cpp
change_type: ModificationType.MODIFY
diff: @@ -382,90 +382,21 @@ void EDPSimple::set_builtin_writer_history_attributes(
 void EDPSimple::set_builtin_reader_attributes(
         ReaderAttributes& attributes)
 {
-    const RTPSParticipantAttributes& pattr = mp_PDP->getRTPSParticipant()->getRTPSParticipantAttributes();
-
-    // Matched writers will depend on total number of participants
-    attributes.matched_writers_allocation = pattr.allocation.participants;
-
-    // As participants allocation policy includes the local participant, one has to be substracted
-    if (attributes.matched_writers_allocation.initial > 1)
-    {
-        attributes.matched_writers_allocation.initial--;
-    }
-    if ((attributes.matched_writers_allocation.maximum > 1) &&
-            (attributes.matched_writers_allocation.maximum < std::numeric_limits<size_t>::max()))
-    {
-        attributes.matched_writers_allocation.maximum--;
-    }
-
-    // Locators are copied from the local participant metatraffic locators
-    attributes.endpoint.unicastLocatorList.clear();
-    for (const Locator_t& loc : mp_PDP->getLocalParticipantProxyData()->metatraffic_locators.unicast)
-    {
-        attributes.endpoint.unicastLocatorList.push_back(loc);
-    }
-    attributes.endpoint.multicastLocatorList.clear();
-    for (const Locator_t& loc : mp_PDP->getLocalParticipantProxyData()->metatraffic_locators.multicast)
-    {
-        attributes.endpoint.multicastLocatorList.push_back(loc);
-    }
-    attributes.endpoint.external_unicast_locators = mp_PDP->builtin_attributes().metatraffic_external_unicast_locators;
-    attributes.endpoint.ignore_non_matching_locators = pattr.ignore_non_matching_locators;
+    attributes = mp_PDP->create_builtin_reader_attributes();
 
     // Timings are configured using EDP default values
     attributes.times.heartbeatResponseDelay = edp_heartbeat_response_delay;
-
-    // EDP endpoints are always reliable, transsient local, keyed topics
-    attributes.endpoint.reliabilityKind = RELIABLE;
-    attributes.endpoint.durabilityKind = TRANSIENT_LOCAL;
-    attributes.endpoint.topicKind = WITH_KEY;
-
-    // Built-in EDP readers never expect inline qos
-    attributes.expectsInlineQos = false;
 }
 
 void EDPSimple::set_builtin_writer_attributes(
         WriterAttributes& attributes)
 {
-    const RTPSParticipantAttributes& pattr = mp_PDP->getRTPSParticipant()->getRTPSParticipantAttributes();
-
-    // Matched readers will depend on total number of participants
-    attributes.matched_readers_allocation = pattr.allocation.participants;
-
-    // As participants allocation policy includes the local participant, one has to be substracted
-    if (attributes.matched_readers_allocation.initial > 1)
-    {
-        attributes.matched_readers_allocation.initial--;
-    }
-    if ((attributes.matched_readers_allocation.maximum > 1) &&
-            (attributes.matched_readers_allocation.maximum < std::numeric_limits<size_t>::max()))
-    {
-        attributes.matched_readers_allocation.maximum--;
-    }
-
-    // Locators are copied from the local participant metatraffic locators
-    attributes.endpoint.unicastLocatorList.clear();
-    for (const Locator_t& loc : mp_PDP->getLocalParticipantProxyData()->metatraffic_locators.unicast)
-    {
-        attributes.endpoint.unicastLocatorList.push_back(loc);
-    }
-    attributes.endpoint.multicastLocatorList.clear();
-    for (const Locator_t& loc : mp_PDP->getLocalParticipantProxyData()->metatraffic_locators.multicast)
-    {
-        attributes.endpoint.multicastLocatorList.push_back(loc);
-    }
-    attributes.endpoint.external_unicast_locators = mp_PDP->builtin_attributes().metatraffic_external_unicast_locators;
-    attributes.endpoint.ignore_non_matching_locators = pattr.ignore_non_matching_locators;
+    attributes = mp_PDP->create_builtin_writer_attributes();
 
     // Timings are configured using EDP default values
     attributes.times.heartbeatPeriod = edp_heartbeat_period;
     attributes.times.nackResponseDelay = edp_nack_response_delay;
     attributes.times.nackSupressionDuration = edp_nack_supression_duration;
-
-    // EDP endpoints are always reliable, transsient local, keyed topics
-    attributes.endpoint.reliabilityKind = RELIABLE;
-    attributes.endpoint.durabilityKind = TRANSIENT_LOCAL;
-    attributes.endpoint.topicKind = WITH_KEY;
 }
 
 bool EDPSimple::createSEDPEndpoints()
@@ -537,34 +468,7 @@ bool EDPSimple::create_sedp_secure_endpoints()
     set_builtin_writer_history_attributes(writer_history_att);
     set_builtin_reader_attributes(ratt);
     set_builtin_writer_attributes(watt);
-
-    const security::ParticipantSecurityAttributes& part_attr = mp_RTPSParticipant->security_attributes();
-
-    ratt.endpoint.security_attributes().is_submessage_protected = part_attr.is_discovery_protected;
-    ratt.endpoint.security_attributes().plugin_endpoint_attributes = PLUGIN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_VALID;
-
-    watt.endpoint.security_attributes().is_submessage_protected = part_attr.is_discovery_protected;
-    watt.endpoint.security_attributes().plugin_endpoint_attributes = PLUGIN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_VALID;
-
-    if (part_attr.is_discovery_protected)
-    {
-        security::PluginParticipantSecurityAttributes plugin_part_attr(part_attr.plugin_participant_attributes);
-
-        if (plugin_part_attr.is_discovery_encrypted)
-        {
-            ratt.endpoint.security_attributes().plugin_endpoint_attributes |=
-                    PLUGIN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_SUBMESSAGE_ENCRYPTED;
-            watt.endpoint.security_attributes().plugin_endpoint_attributes |=
-                    PLUGIN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_SUBMESSAGE_ENCRYPTED;
-        }
-        if (plugin_part_attr.is_discovery_origin_authenticated)
-        {
-            ratt.endpoint.security_attributes().plugin_endpoint_attributes |=
-                    PLUGIN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_SUBMESSAGE_ORIGIN_AUTHENTICATED;
-            watt.endpoint.security_attributes().plugin_endpoint_attributes |=
-                    PLUGIN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_SUBMESSAGE_ORIGIN_AUTHENTICATED;
-        }
-    }
+    mp_PDP->add_builtin_security_attributes(ratt, watt);
 
     if (m_discovery.discovery_config.m_simpleEDP.enable_builtin_secure_publications_writer_and_subscriptions_reader)
     {

programming_language: C++
filename: DiscoveryServerPDPEndpoints.hpp
change_type: ModificationType.MODIFY
diff: @@ -46,6 +46,11 @@ struct DiscoveryServerPDPEndpoints : public PDPEndpoints
         return DISC_BUILTIN_ENDPOINT_PARTICIPANT_ANNOUNCER | DISC_BUILTIN_ENDPOINT_PARTICIPANT_DETECTOR;
     }
 
+    const std::unique_ptr<fastrtps::rtps::ReaderListener>& main_listener() const override
+    {
+        return reader.listener_;
+    }
+
     bool enable_pdp_readers(
             fastrtps::rtps::RTPSParticipantImpl* participant) override
     {

programming_language: C++
filename: DiscoveryServerPDPEndpointsSecure.hpp
change_type: ModificationType.MODIFY
diff: @@ -89,8 +89,6 @@ struct DiscoveryServerPDPEndpointsSecure : public DiscoveryServerPDPEndpoints
 
     //! Builtin Simple PDP reader
     BuiltinReader<fastrtps::rtps::StatelessReader> stateless_reader;
-    //! Listener for stateless_reader
-    std::unique_ptr<fastrtps::rtps::ReaderListener> stateless_listener;
 };
 
 } // namespace rtps

programming_language: C++
filename: PDPSecurityInitiatorListener.cpp
change_type: ModificationType.MODIFY
diff: @@ -23,6 +23,7 @@
 
 #include <fastdds/rtps/builtin/discovery/endpoint/EDP.h>
 #include <fastdds/rtps/builtin/discovery/participant/PDP.h>
+#include <fastdds/rtps/builtin/discovery/participant/PDPListener.h>
 #include <fastdds/rtps/history/ReaderHistory.h>
 #include <fastdds/rtps/participant/ParticipantDiscoveryInfo.h>
 #include <fastdds/rtps/participant/RTPSParticipantListener.h>
@@ -47,121 +48,44 @@ namespace rtps {
 PDPSecurityInitiatorListener::PDPSecurityInitiatorListener(
         PDP* parent,
         SecurityInitiatedCallback response_cb)
-    : parent_pdp_(parent)
-    , temp_participant_data_(parent->getRTPSParticipant()->getRTPSParticipantAttributes().allocation)
+    : PDPListener(parent)
     , response_cb_(response_cb)
 {
 }
 
-void PDPSecurityInitiatorListener::onNewCacheChangeAdded(
+void PDPSecurityInitiatorListener::process_alive_data(
+        ParticipantProxyData* old_data,
+        ParticipantProxyData& new_data,
+        GUID_t& writer_guid,
         RTPSReader* reader,
-        const CacheChange_t* const change_in)
+        std::unique_lock<std::recursive_mutex>& lock)
 {
-    CacheChange_t* change = const_cast<CacheChange_t*>(change_in);
-    GUID_t writer_guid = change->writerGUID;
-    EPROSIMA_LOG_INFO(RTPS_PDP, "SPDP Message received from: " << change_in->writerGUID);
-
-    // Make sure we have an instance handle (i.e GUID)
-    if (change->instanceHandle == c_InstanceHandle_Unknown)
+    if (reader->matched_writer_is_matched(writer_guid))
     {
-        if (!this->get_key(change))
-        {
-            EPROSIMA_LOG_WARNING(RTPS_PDP, "Problem getting the key of the change, removing");
-            parent_pdp_->builtin_endpoints_->remove_from_pdp_reader_history(change);
-            return;
-        }
+        // Act as the standard PDPListener when the writer is matched.
+        // This will be the case for unauthenticated participants when
+        // allowed_unathenticated_participants is true
+        PDPListener::process_alive_data(old_data, new_data, writer_guid, reader, lock);
+        return;
     }
 
-    // Take GUID from instance handle
-    GUID_t guid;
-    iHandle2GUID(guid, change->instanceHandle);
-
-    if (change->kind == ALIVE)
+    if (old_data == nullptr)
     {
-        // Ignore announcement from own RTPSParticipant
-        if (guid == parent_pdp_->getRTPSParticipant()->getGuid())
-        {
-            EPROSIMA_LOG_INFO(RTPS_PDP, "Message from own RTPSParticipant, removing");
-            parent_pdp_->builtin_endpoints_->remove_from_pdp_reader_history(change);
-            return;
-        }
-
-        // Release reader lock to avoid ABBA lock. PDP mutex should always be first.
-        // Keep change information on local variables to check consistency later
-        SequenceNumber_t seq_num = change->sequenceNumber;
         reader->getMutex().unlock();
-        std::unique_lock<std::recursive_mutex> lock(*parent_pdp_->getMutex());
-        reader->getMutex().lock();
-
-        // If change is not consistent, it will be processed on the thread that has overriten it
-        if ((ALIVE != change->kind) || (seq_num != change->sequenceNumber) || (writer_guid != change->writerGUID))
-        {
-            return;
-        }
-
-        // Access to temp_participant_data_ is protected by reader lock
+        lock.unlock();
 
-        // Load information on temp_participant_data_
-        CDRMessage_t msg(change->serializedPayload);
-        temp_participant_data_.clear();
-        if (temp_participant_data_.readFromCDRMessage(&msg, true, parent_pdp_->getRTPSParticipant()->network_factory(),
-                parent_pdp_->getRTPSParticipant()->has_shm_transport(), true))
+        //! notify security manager in order to start handshake
+        bool ret = parent_pdp_->getRTPSParticipant()->security_manager().discovered_participant(new_data);
+        //! Reply to the remote participant
+        if (ret)
         {
-            // After correctly reading it
-            change->instanceHandle = temp_participant_data_.m_key;
-            guid = temp_participant_data_.m_guid;
-
-            // Filter locators
-            const auto& pattr = parent_pdp_->getRTPSParticipant()->getAttributes();
-            fastdds::rtps::ExternalLocatorsProcessor::filter_remote_locators(temp_participant_data_,
-                    pattr.builtin.metatraffic_external_unicast_locators, pattr.default_external_unicast_locators,
-                    pattr.ignore_non_matching_locators);
-
-            // Check if participant already exists (updated info)
-            ParticipantProxyData* pdata = nullptr;
-            for (ParticipantProxyData* it : parent_pdp_->participant_proxies_)
-            {
-                if (guid == it->m_guid)
-                {
-                    pdata = it;
-                    break;
-                }
-            }
-
-            if (pdata == nullptr)
-            {
-                // Create a new one when not found
-
-                reader->getMutex().unlock();
-                lock.unlock();
-
-                //! notify security manager in order to start handshake
-                bool ret = parent_pdp_->getRTPSParticipant()->security_manager().discovered_participant(
-                    temp_participant_data_);
-
-                //! Reply to the remote participant
-                if (ret)
-                {
-                    response_cb_(temp_participant_data_);
-                }
-
-                // Take again the reader lock
-                reader->getMutex().lock();
-
-            } //! Do nothing if already discovered
-
+            response_cb_(temp_participant_data_);
         }
 
-    } //! Do nothing on participant removal
-
-    //Remove change form history.
-    parent_pdp_->builtin_endpoints_->remove_from_pdp_reader_history(change);
-}
+        // Take again the reader lock
+        reader->getMutex().lock();
+    }
 
-bool PDPSecurityInitiatorListener::get_key(
-        CacheChange_t* change)
-{
-    return ParameterList::readInstanceHandleFromCDRMsg(change, fastdds::dds::PID_PARTICIPANT_GUID);
 }
 
 } /* namespace rtps */

programming_language: C++
filename: PDPSecurityInitiatorListener.hpp
change_type: ModificationType.MODIFY
diff: @@ -21,7 +21,7 @@
 #define _DS_PDP_SECURITY_INITIATOR_LISTENER_H_
 #ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC
 
-#include <fastdds/rtps/reader/ReaderListener.h>
+#include <fastdds/rtps/builtin/discovery/participant/PDPListener.h>
 #include <fastdds/rtps/builtin/data/ParticipantProxyData.h>
 
 #include <mutex>
@@ -36,7 +36,7 @@ class PDP;
  * Class PDPSecurityInitiatorListener, implementation for the secure discovery server handshake initiator.
  * @ingroup DISCOVERY_MODULE
  */
-class PDPSecurityInitiatorListener : public ReaderListener
+class PDPSecurityInitiatorListener : public PDPListener
 {
 
     using SecurityInitiatedCallback = std::function<void (const ParticipantProxyData& participant_data)>;
@@ -52,34 +52,14 @@ public:
 
     virtual ~PDPSecurityInitiatorListener() override = default;
 
-    /**
-     * New added cache
-     * @param reader
-     * @param change
-     */
-    void onNewCacheChangeAdded(
-            RTPSReader* reader,
-            const CacheChange_t* const change) override;
-
 protected:
 
-    /**
-     * Get the key of a CacheChange_t
-     * @param change Pointer to the CacheChange_t
-     * @return True on success
-     */
-    bool get_key(
-            CacheChange_t* change);
-
-    //!Pointer to the associated mp_SPDP;
-    PDP* parent_pdp_;
-
-    /**
-     * @brief Temporary data to avoid reallocations.
-     *
-     * @remarks This should be always accessed with the pdp_reader lock taken
-     */
-    ParticipantProxyData temp_participant_data_;
+    void process_alive_data(
+            ParticipantProxyData* old_data,
+            ParticipantProxyData& new_data,
+            GUID_t& writer_guid,
+            RTPSReader* reader,
+            std::unique_lock<std::recursive_mutex>& lock) override;
 
     //! What action to perform upon participant discovery
     SecurityInitiatedCallback response_cb_;

programming_language: C++
filename: PDP.cpp
change_type: ModificationType.MODIFY
diff: @@ -68,9 +68,7 @@ namespace eprosima {
 namespace fastrtps {
 namespace rtps {
 
-
 // Default configuration values for PDP reliable entities.
-
 const Duration_t pdp_heartbeat_period{ 0, 350 * 1000000  }; // 350 milliseconds
 const Duration_t pdp_nack_response_delay{ 0, 100 * 1000000  }; // 100 milliseconds
 const Duration_t pdp_nack_supression_duration{ 0, 11 * 1000000 }; // 11 milliseconds
@@ -93,7 +91,6 @@ PDP::PDP (
     , writer_proxies_number_(allocation.total_writers().initial)
     , writer_proxies_pool_(allocation.total_writers())
     , m_hasChangedLocalPDP(true)
-    , mp_listener(nullptr)
     , temp_reader_proxies_({
                 allocation.locators.max_unicast_locators,
                 allocation.locators.max_multicast_locators,
@@ -141,9 +138,6 @@ PDP::~PDP()
     builtin_endpoints_->delete_pdp_endpoints(mp_RTPSParticipant);
     builtin_endpoints_.reset();
 
-    delete mp_listener;
-    mp_listener = nullptr;
-
     for (ParticipantProxyData* it : participant_proxies_)
     {
         delete it;
@@ -524,7 +518,9 @@ void PDP::announceParticipantState(
         else
         {
             this->mp_mutex->lock();
-            ParticipantProxyData proxy_data_copy(*getLocalParticipantProxyData());
+            ParticipantProxyData* local_participant_data = getLocalParticipantProxyData();
+            InstanceHandle_t key = local_participant_data->m_key;
+            ParticipantProxyData proxy_data_copy(*local_participant_data);
             this->mp_mutex->unlock();
 
             if (history.getHistorySize() > 0)
@@ -536,7 +532,7 @@ void PDP::announceParticipantState(
                             {
                                 return cdr_size;
                             },
-                            NOT_ALIVE_DISPOSED_UNREGISTERED, getLocalParticipantProxyData()->m_key);
+                            NOT_ALIVE_DISPOSED_UNREGISTERED, key);
 
             if (change != nullptr)
             {
@@ -581,6 +577,39 @@ void PDP::resetParticipantAnnouncement()
     }
 }
 
+void PDP::notify_and_maybe_ignore_new_participant(
+        ParticipantProxyData* pdata,
+        bool& should_be_ignored)
+{
+    should_be_ignored = false;
+
+    EPROSIMA_LOG_INFO(RTPS_PDP_DISCOVERY, "New participant "
+            << pdata->m_guid << " at "
+            << "MTTLoc: " << pdata->metatraffic_locators
+            << " DefLoc:" << pdata->default_locators);
+
+    RTPSParticipantListener* listener = getRTPSParticipant()->getListener();
+    if (listener != nullptr)
+    {
+        {
+            std::lock_guard<std::mutex> cb_lock(callback_mtx_);
+            ParticipantDiscoveryInfo info(*pdata);
+            info.status = ParticipantDiscoveryInfo::DISCOVERED_PARTICIPANT;
+
+
+            listener->onParticipantDiscovery(
+                getRTPSParticipant()->getUserRTPSParticipant(),
+                std::move(info),
+                should_be_ignored);
+        }
+
+        if (should_be_ignored)
+        {
+            getRTPSParticipant()->ignore_participant(pdata->m_guid.guidPrefix);
+        }
+    }
+}
+
 bool PDP::has_reader_proxy_data(
         const GUID_t& reader)
 {
@@ -1461,6 +1490,131 @@ void PDP::set_external_participant_properties_(
     }
 }
 
+static void set_builtin_matched_allocation(
+        ResourceLimitedContainerConfig& allocation,
+        const RTPSParticipantAttributes& pattr)
+{
+    // Matched endpoints will depend on total number of participants
+    allocation = pattr.allocation.participants;
+
+    // As participants allocation policy includes the local participant, one has to be substracted
+    if (allocation.initial > 1)
+    {
+        allocation.initial--;
+    }
+    if ((allocation.maximum > 1) &&
+            (allocation.maximum < std::numeric_limits<size_t>::max()))
+    {
+        allocation.maximum--;
+    }
+}
+
+static void set_builtin_endpoint_locators(
+        EndpointAttributes& endpoint,
+        const PDP* pdp,
+        const BuiltinProtocols* builtin)
+{
+    const RTPSParticipantAttributes& pattr = pdp->getRTPSParticipant()->getRTPSParticipantAttributes();
+
+    auto part_data = pdp->getLocalParticipantProxyData();
+    if (nullptr == part_data)
+    {
+        // Local participant data has not yet been created.
+        // This means we are creating the PDP endpoints, so we copy the locators from mp_builtin
+        endpoint.multicastLocatorList = builtin->m_metatrafficMulticastLocatorList;
+        endpoint.unicastLocatorList = builtin->m_metatrafficUnicastLocatorList;
+    }
+    else
+    {
+        // Locators are copied from the local participant metatraffic locators
+        endpoint.unicastLocatorList.clear();
+        for (const Locator_t& loc : part_data->metatraffic_locators.unicast)
+        {
+            endpoint.unicastLocatorList.push_back(loc);
+        }
+        endpoint.multicastLocatorList.clear();
+        for (const Locator_t& loc : part_data->metatraffic_locators.multicast)
+        {
+            endpoint.multicastLocatorList.push_back(loc);
+        }
+    }
+
+    // External locators are always taken from the same place
+    endpoint.external_unicast_locators = pdp->builtin_attributes().metatraffic_external_unicast_locators;
+    endpoint.ignore_non_matching_locators = pattr.ignore_non_matching_locators;
+}
+
+ReaderAttributes PDP::create_builtin_reader_attributes() const
+{
+    ReaderAttributes attributes;
+
+    const RTPSParticipantAttributes& pattr = getRTPSParticipant()->getRTPSParticipantAttributes();
+    set_builtin_matched_allocation(attributes.matched_writers_allocation, pattr);
+    set_builtin_endpoint_locators(attributes.endpoint, this, mp_builtin);
+
+    // Builtin endpoints are always reliable, transient local, keyed topics
+    attributes.endpoint.reliabilityKind = RELIABLE;
+    attributes.endpoint.durabilityKind = TRANSIENT_LOCAL;
+    attributes.endpoint.topicKind = WITH_KEY;
+
+    // Built-in readers never expect inline qos
+    attributes.expectsInlineQos = false;
+
+    return attributes;
+}
+
+WriterAttributes PDP::create_builtin_writer_attributes() const
+{
+    WriterAttributes attributes;
+
+    const RTPSParticipantAttributes& pattr = getRTPSParticipant()->getRTPSParticipantAttributes();
+    set_builtin_matched_allocation(attributes.matched_readers_allocation, pattr);
+    set_builtin_endpoint_locators(attributes.endpoint, this, mp_builtin);
+
+    // Builtin endpoints are always reliable, transient local, keyed topics
+    attributes.endpoint.reliabilityKind = RELIABLE;
+    attributes.endpoint.durabilityKind = TRANSIENT_LOCAL;
+    attributes.endpoint.topicKind = WITH_KEY;
+
+    return attributes;
+}
+
+#if HAVE_SECURITY
+void PDP::add_builtin_security_attributes(
+        ReaderAttributes& ratt,
+        WriterAttributes& watt) const
+{
+    const security::ParticipantSecurityAttributes& part_attr = mp_RTPSParticipant->security_attributes();
+
+    ratt.endpoint.security_attributes().is_submessage_protected = part_attr.is_discovery_protected;
+    ratt.endpoint.security_attributes().plugin_endpoint_attributes = PLUGIN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_VALID;
+
+    watt.endpoint.security_attributes().is_submessage_protected = part_attr.is_discovery_protected;
+    watt.endpoint.security_attributes().plugin_endpoint_attributes = PLUGIN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_VALID;
+
+    if (part_attr.is_discovery_protected)
+    {
+        security::PluginParticipantSecurityAttributes plugin_part_attr(part_attr.plugin_participant_attributes);
+
+        if (plugin_part_attr.is_discovery_encrypted)
+        {
+            ratt.endpoint.security_attributes().plugin_endpoint_attributes |=
+                    PLUGIN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_SUBMESSAGE_ENCRYPTED;
+            watt.endpoint.security_attributes().plugin_endpoint_attributes |=
+                    PLUGIN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_SUBMESSAGE_ENCRYPTED;
+        }
+        if (plugin_part_attr.is_discovery_origin_authenticated)
+        {
+            ratt.endpoint.security_attributes().plugin_endpoint_attributes |=
+                    PLUGIN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_SUBMESSAGE_ORIGIN_AUTHENTICATED;
+            watt.endpoint.security_attributes().plugin_endpoint_attributes |=
+                    PLUGIN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_SUBMESSAGE_ORIGIN_AUTHENTICATED;
+        }
+    }
+}
+
+#endif // HAVE_SECURITY
+
 } /* namespace rtps */
 } /* namespace fastrtps */
 } /* namespace eprosima */

programming_language: C++
filename: PDPClient.cpp
change_type: ModificationType.MODIFY
diff: @@ -278,26 +278,20 @@ bool PDPClient::create_ds_pdp_best_effort_reader(
     ratt.endpoint.durabilityKind = VOLATILE;
     ratt.endpoint.reliabilityKind = BEST_EFFORT;
 
-    endpoints.stateless_listener.reset(new PDPSecurityInitiatorListener(this));
+    endpoints.stateless_reader.listener_.reset(new PDPSecurityInitiatorListener(this));
 
     // Create PDP Reader
     RTPSReader* reader = nullptr;
     if (mp_RTPSParticipant->createReader(&reader, ratt, endpoints.stateless_reader.history_.get(),
-            endpoints.stateless_listener.get(), c_EntityId_SPDPReader, true, false))
+            endpoints.stateless_reader.listener_.get(), c_EntityId_SPDPReader, true, false))
     {
         endpoints.stateless_reader.reader_ = dynamic_cast<fastrtps::rtps::StatelessReader*>(reader);
-
-        // Enable unknown clients to reach this reader
-        reader->enableMessagesFromUnkownWriters(true);
-
         mp_RTPSParticipant->set_endpoint_rtps_protection_supports(reader, false);
     }
     // Could not create PDP Reader, so return false
     else
     {
         EPROSIMA_LOG_ERROR(RTPS_PDP_SERVER, "PDPServer security initiation Reader creation failed");
-
-        endpoints.stateless_listener.reset();
         endpoints.stateless_reader.release();
         return false;
     }
@@ -360,7 +354,7 @@ bool PDPClient::create_ds_pdp_reliable_endpoints(
     }
 #endif // HAVE_SECURITY
 
-    mp_listener = new PDPListener(this);
+    endpoints.reader.listener_.reset(new PDPListener(this));
 
     RTPSReader* reader = nullptr;
 #if HAVE_SECURITY
@@ -369,7 +363,8 @@ bool PDPClient::create_ds_pdp_reliable_endpoints(
 #else
     EntityId_t reader_entity = c_EntityId_SPDPReader;
 #endif // if HAVE_SECURITY
-    if (mp_RTPSParticipant->createReader(&reader, ratt, endpoints.reader.history_.get(), mp_listener,
+    if (mp_RTPSParticipant->createReader(&reader, ratt, endpoints.reader.history_.get(),
+            endpoints.reader.listener_.get(),
             reader_entity, true, false))
     {
         endpoints.reader.reader_ = dynamic_cast<fastrtps::rtps::StatefulReader*>(reader);
@@ -381,8 +376,6 @@ bool PDPClient::create_ds_pdp_reliable_endpoints(
     else
     {
         EPROSIMA_LOG_ERROR(RTPS_PDP, "PDPClient Reader creation failed");
-        delete mp_listener;
-        mp_listener = nullptr;
         endpoints.reader.release();
         return false;
     }
@@ -483,25 +476,30 @@ bool PDPClient::create_ds_pdp_reliable_endpoints(
 void PDPClient::assignRemoteEndpoints(
         ParticipantProxyData* pdata)
 {
+    bool ignored = false;
+    notify_and_maybe_ignore_new_participant(pdata, ignored);
+    if (!ignored)
     {
-        eprosima::shared_lock<eprosima::shared_mutex> disc_lock(mp_builtin->getDiscoveryMutex());
-
-        // Verify if this participant is a server
-        for (auto& svr : mp_builtin->m_DiscoveryServers)
         {
-            if (data_matches_with_prefix(svr.guidPrefix, *pdata))
+            eprosima::shared_lock<eprosima::shared_mutex> disc_lock(mp_builtin->getDiscoveryMutex());
+
+            // Verify if this participant is a server
+            for (auto& svr : mp_builtin->m_DiscoveryServers)
             {
-                std::unique_lock<std::recursive_mutex> lock(*getMutex());
-                svr.proxy = pdata;
+                if (data_matches_with_prefix(svr.guidPrefix, *pdata))
+                {
+                    std::unique_lock<std::recursive_mutex> lock(*getMutex());
+                    svr.proxy = pdata;
+                }
             }
         }
-    }
 
 #if HAVE_SECURITY
-    if (mp_RTPSParticipant->security_manager().discovered_participant(*pdata))
+        if (mp_RTPSParticipant->security_manager().discovered_participant(*pdata))
 #endif // HAVE_SECURITY
-    {
-        perform_builtin_endpoints_matching(*pdata);
+        {
+            perform_builtin_endpoints_matching(*pdata);
+        }
     }
 }
 

programming_language: C++
filename: PDPEndpoints.hpp
change_type: ModificationType.MODIFY
diff: @@ -45,6 +45,8 @@ public:
      */
     virtual fastrtps::rtps::BuiltinEndpointSet_t builtin_endpoints() const = 0;
 
+    virtual const std::unique_ptr<fastrtps::rtps::ReaderListener>& main_listener() const = 0;
+
     virtual bool enable_pdp_readers(
             fastrtps::rtps::RTPSParticipantImpl* participant) = 0;
     virtual void disable_pdp_readers(

programming_language: C++
filename: PDPListener.cpp
change_type: ModificationType.MODIFY
diff: @@ -61,7 +61,7 @@ void PDPListener::onNewCacheChangeAdded(
 {
     CacheChange_t* change = const_cast<CacheChange_t*>(change_in);
     GUID_t writer_guid = change->writerGUID;
-    EPROSIMA_LOG_INFO(RTPS_PDP, "SPDP Message received from: " << change_in->writerGUID);
+    EPROSIMA_LOG_INFO(RTPS_PDP, "SPDP Message received from: " << writer_guid);
 
     // Make sure we have an instance handle (i.e GUID)
     if (change->instanceHandle == c_InstanceHandle_Unknown)
@@ -135,114 +135,10 @@ void PDPListener::onNewCacheChangeAdded(
                 }
             }
 
-            auto status = (pdata == nullptr) ? ParticipantDiscoveryInfo::DISCOVERED_PARTICIPANT :
-                    ParticipantDiscoveryInfo::CHANGED_QOS_PARTICIPANT;
-
-            if (pdata == nullptr)
-            {
-                // Create a new one when not found
-                pdata = parent_pdp_->createParticipantProxyData(temp_participant_data_, writer_guid);
-
-                reader->getMutex().unlock();
-                lock.unlock();
-
-                if (pdata != nullptr)
-                {
-                    EPROSIMA_LOG_INFO(RTPS_PDP_DISCOVERY, "New participant "
-                            << pdata->m_guid << " at "
-                            << "MTTLoc: " << pdata->metatraffic_locators
-                            << " DefLoc:" << pdata->default_locators);
-
-                    RTPSParticipantListener* listener = parent_pdp_->getRTPSParticipant()->getListener();
-                    if (listener != nullptr)
-                    {
-                        bool should_be_ignored = false;
-                        {
-                            std::lock_guard<std::mutex> cb_lock(parent_pdp_->callback_mtx_);
-                            ParticipantDiscoveryInfo info(*pdata);
-                            info.status = status;
-
-
-                            listener->onParticipantDiscovery(
-                                parent_pdp_->getRTPSParticipant()->getUserRTPSParticipant(),
-                                std::move(info),
-                                should_be_ignored);
-                        }
-                        if (should_be_ignored)
-                        {
-                            parent_pdp_->getRTPSParticipant()->ignore_participant(guid.guidPrefix);
-                        }
-
-                    }
-
-                    // Assigning remote endpoints implies sending a DATA(p) to all matched and fixed readers, since
-                    // StatelessWriter::matched_reader_add marks the entire history as unsent if the added reader's
-                    // durability is bigger or equal to TRANSIENT_LOCAL_DURABILITY_QOS (TRANSIENT_LOCAL or TRANSIENT),
-                    // which is the case of ENTITYID_BUILTIN_SDP_PARTICIPANT_READER (TRANSIENT_LOCAL). If a remote
-                    // participant is discovered before creating the first DATA(p) change (which happens at the end of
-                    // BuiltinProtocols::initBuiltinProtocols), then StatelessWriter::matched_reader_add ends up marking
-                    // no changes as unsent (since the history is empty), which is OK because this can only happen if a
-                    // participant is discovered in the middle of BuiltinProtocols::initBuiltinProtocols, which will
-                    // create the first DATA(p) upon finishing, thus triggering the sent to all fixed and matched
-                    // readers anyways.
-                    parent_pdp_->assignRemoteEndpoints(pdata);
-                }
-            }
-            else
-            {
-                pdata->updateData(temp_participant_data_);
-                pdata->isAlive = true;
-                reader->getMutex().unlock();
-
-                EPROSIMA_LOG_INFO(RTPS_PDP_DISCOVERY, "Update participant "
-                        << pdata->m_guid << " at "
-                        << "MTTLoc: " << pdata->metatraffic_locators
-                        << " DefLoc:" << pdata->default_locators);
-
-                if (parent_pdp_->updateInfoMatchesEDP())
-                {
-                    parent_pdp_->mp_EDP->assignRemoteEndpoints(*pdata, true);
-                }
-
-                lock.unlock();
-
-                RTPSParticipantListener* listener = parent_pdp_->getRTPSParticipant()->getListener();
-                if (listener != nullptr)
-                {
-                    bool should_be_ignored = false;
-
-                    {
-                        std::lock_guard<std::mutex> cb_lock(parent_pdp_->callback_mtx_);
-                        ParticipantDiscoveryInfo info(*pdata);
-                        info.status = status;
-
-                        listener->onParticipantDiscovery(
-                            parent_pdp_->getRTPSParticipant()->getUserRTPSParticipant(),
-                            std::move(info),
-                            should_be_ignored);
-                    }
-                    if (should_be_ignored)
-                    {
-                        parent_pdp_->getRTPSParticipant()->ignore_participant(temp_participant_data_.m_guid.guidPrefix);
-                    }
-                }
-            }
-
-#ifdef FASTDDS_STATISTICS
-            //! Addition or update of a participant proxy should trigger
-            //! a connections update on the local participant connection list
-            if (nullptr != parent_pdp_->getRTPSParticipant()->get_connections_observer())
-            {
-                parent_pdp_->getRTPSParticipant()->get_connections_observer()->on_local_entity_connections_change(
-                    parent_pdp_->getRTPSParticipant()->getGuid());
-            }
-#endif //FASTDDS_STATISTICS
-
-            // Take again the reader lock
-            reader->getMutex().lock();
+            process_alive_data(pdata, temp_participant_data_, writer_guid, reader, lock);
         }
     }
-    else
+    else if (reader->matched_writer_is_matched(writer_guid))
     {
         reader->getMutex().unlock();
         if (parent_pdp_->remove_remote_participant(guid, ParticipantDiscoveryInfo::REMOVED_PARTICIPANT))
@@ -267,6 +163,92 @@ void PDPListener::onNewCacheChangeAdded(
     parent_pdp_->builtin_endpoints_->remove_from_pdp_reader_history(change);
 }
 
+void PDPListener::process_alive_data(
+        ParticipantProxyData* old_data,
+        ParticipantProxyData& new_data,
+        GUID_t& writer_guid,
+        RTPSReader* reader,
+        std::unique_lock<std::recursive_mutex>& lock)
+{
+    GUID_t participant_guid = new_data.m_guid;
+
+    if (old_data == nullptr)
+    {
+        // Create a new one when not found
+        old_data = parent_pdp_->createParticipantProxyData(new_data, writer_guid);
+
+        reader->getMutex().unlock();
+        lock.unlock();
+
+        if (old_data != nullptr)
+        {
+            // Assigning remote endpoints implies sending a DATA(p) to all matched and fixed readers, since
+            // StatelessWriter::matched_reader_add marks the entire history as unsent if the added reader's
+            // durability is bigger or equal to TRANSIENT_LOCAL_DURABILITY_QOS (TRANSIENT_LOCAL or TRANSIENT),
+            // which is the case of ENTITYID_BUILTIN_SDP_PARTICIPANT_READER (TRANSIENT_LOCAL). If a remote
+            // participant is discovered before creating the first DATA(p) change (which happens at the end of
+            // BuiltinProtocols::initBuiltinProtocols), then StatelessWriter::matched_reader_add ends up marking
+            // no changes as unsent (since the history is empty), which is OK because this can only happen if a
+            // participant is discovered in the middle of BuiltinProtocols::initBuiltinProtocols, which will
+            // create the first DATA(p) upon finishing, thus triggering the sent to all fixed and matched
+            // readers anyways.
+            parent_pdp_->assignRemoteEndpoints(old_data);
+        }
+    }
+    else
+    {
+        old_data->updateData(new_data);
+        old_data->isAlive = true;
+        reader->getMutex().unlock();
+
+        EPROSIMA_LOG_INFO(RTPS_PDP_DISCOVERY, "Update participant "
+                << old_data->m_guid << " at "
+                << "MTTLoc: " << old_data->metatraffic_locators
+                << " DefLoc:" << old_data->default_locators);
+
+        if (parent_pdp_->updateInfoMatchesEDP())
+        {
+            parent_pdp_->mp_EDP->assignRemoteEndpoints(*old_data, true);
+        }
+
+        lock.unlock();
+
+        RTPSParticipantListener* listener = parent_pdp_->getRTPSParticipant()->getListener();
+        if (listener != nullptr)
+        {
+            bool should_be_ignored = false;
+
+            {
+                std::lock_guard<std::mutex> cb_lock(parent_pdp_->callback_mtx_);
+                ParticipantDiscoveryInfo info(*old_data);
+                info.status = ParticipantDiscoveryInfo::CHANGED_QOS_PARTICIPANT;
+
+                listener->onParticipantDiscovery(
+                    parent_pdp_->getRTPSParticipant()->getUserRTPSParticipant(),
+                    std::move(info),
+                    should_be_ignored);
+            }
+            if (should_be_ignored)
+            {
+                parent_pdp_->getRTPSParticipant()->ignore_participant(participant_guid.guidPrefix);
+            }
+        }
+    }
+
+#ifdef FASTDDS_STATISTICS
+    //! Addition or update of a participant proxy should trigger
+    //! a connections update on the local participant connection list
+    if (nullptr != parent_pdp_->getRTPSParticipant()->get_connections_observer())
+    {
+        parent_pdp_->getRTPSParticipant()->get_connections_observer()->on_local_entity_connections_change(
+            parent_pdp_->getRTPSParticipant()->getGuid());
+    }
+#endif //FASTDDS_STATISTICS
+
+    // Take again the reader lock
+    reader->getMutex().lock();
+}
+
 bool PDPListener::get_key(
         CacheChange_t* change)
 {

programming_language: C++
filename: PDPServer.cpp
change_type: ModificationType.MODIFY
diff: @@ -293,7 +293,7 @@ bool PDPServer::create_ds_pdp_best_effort_reader(
     ratt.endpoint.durabilityKind = VOLATILE;
     ratt.endpoint.reliabilityKind = BEST_EFFORT;
 
-    endpoints.stateless_listener.reset(new PDPSecurityInitiatorListener(this,
+    endpoints.stateless_reader.listener_.reset(new PDPSecurityInitiatorListener(this,
             [this](const ParticipantProxyData& participant_data)
             {
                 auto endpoints = static_cast<fastdds::rtps::DiscoveryServerPDPEndpoints*>(builtin_endpoints_.get());
@@ -320,21 +320,15 @@ bool PDPServer::create_ds_pdp_best_effort_reader(
     // Create PDP Reader
     RTPSReader* reader = nullptr;
     if (mp_RTPSParticipant->createReader(&reader, ratt, endpoints.stateless_reader.history_.get(),
-            endpoints.stateless_listener.get(), c_EntityId_SPDPReader, true, false))
+            endpoints.stateless_reader.listener_.get(), c_EntityId_SPDPReader, true, false))
     {
         endpoints.stateless_reader.reader_ = dynamic_cast<fastrtps::rtps::StatelessReader*>(reader);
-
-        // Enable unknown clients to reach this reader
-        reader->enableMessagesFromUnkownWriters(true);
-
         mp_RTPSParticipant->set_endpoint_rtps_protection_supports(reader, false);
     }
     // Could not create PDP Reader, so return false
     else
     {
         EPROSIMA_LOG_ERROR(RTPS_PDP_SERVER, "PDPServer security initiation Reader creation failed");
-
-        endpoints.stateless_listener.reset();
         endpoints.stateless_reader.release();
         return false;
     }
@@ -403,7 +397,7 @@ bool PDPServer::create_ds_pdp_reliable_endpoints(
 #endif // HAVE_SQLITE3
 
     // PDP Listener
-    mp_listener = new PDPServerListener(this);
+    endpoints.reader.listener_.reset(new PDPServerListener(this));
 
     // Create PDP Reader
     RTPSReader* reader = nullptr;
@@ -412,8 +406,8 @@ bool PDPServer::create_ds_pdp_reliable_endpoints(
 #else
     EntityId_t reader_entity = c_EntityId_SPDPReader;
 #endif // if HAVE_SECURITY
-    if (mp_RTPSParticipant->createReader(&reader, ratt, endpoints.reader.history_.get(), mp_listener,
-            reader_entity, true, false))
+    if (mp_RTPSParticipant->createReader(&reader, ratt, endpoints.reader.history_.get(),
+            endpoints.reader.listener_.get(), reader_entity, true, false))
     {
         endpoints.reader.reader_ = dynamic_cast<fastrtps::rtps::StatefulReader*>(reader);
 
@@ -428,8 +422,6 @@ bool PDPServer::create_ds_pdp_reliable_endpoints(
     else
     {
         EPROSIMA_LOG_ERROR(RTPS_PDP_SERVER, "PDPServer Reader creation failed");
-        delete mp_listener;
-        mp_listener = nullptr;
         endpoints.reader.release();
         return false;
     }
@@ -1781,7 +1773,7 @@ bool PDPServer::process_backup_discovery_database_restore(
             {
                 change_aux->writerGUID = change_aux->write_params.sample_identity().writer_guid();
                 change_aux->sequenceNumber = change_aux->write_params.sample_identity().sequence_number();
-                mp_listener->onNewCacheChangeAdded(endpoints->reader.reader_, change_aux);
+                builtin_endpoints_->main_listener()->onNewCacheChangeAdded(endpoints->reader.reader_, change_aux);
             }
         }
 

programming_language: C++
filename: PDPSimple.cpp
change_type: ModificationType.MODIFY
diff: @@ -41,16 +41,47 @@
 #include <fastrtps/utils/IPLocator.h>
 #include <fastrtps/utils/TimeConversion.h>
 
+#include <rtps/builtin/discovery/participant/DS/PDPSecurityInitiatorListener.hpp>
 #include <rtps/builtin/discovery/participant/simple/SimplePDPEndpoints.hpp>
+#include <rtps/builtin/discovery/participant/simple/SimplePDPEndpointsSecure.hpp>
 #include <rtps/history/TopicPayloadPoolRegistry.hpp>
 #include <rtps/participant/RTPSParticipantImpl.h>
 
-using namespace eprosima::fastrtps;
-
 namespace eprosima {
 namespace fastrtps {
 namespace rtps {
 
+static HistoryAttributes pdp_reader_history_attributes(
+        const BuiltinAttributes& builtin_att,
+        const RTPSParticipantAllocationAttributes& allocation)
+{
+    HistoryAttributes hatt;
+    hatt.payloadMaxSize = builtin_att.readerPayloadSize;
+    hatt.memoryPolicy = builtin_att.readerHistoryMemoryPolicy;
+    hatt.initialReservedCaches = 25;
+    if (allocation.participants.initial > 0)
+    {
+        hatt.initialReservedCaches = (int32_t)allocation.participants.initial;
+    }
+    if (allocation.participants.maximum < std::numeric_limits<size_t>::max())
+    {
+        hatt.maximumReservedCaches = (int32_t)allocation.participants.maximum;
+    }
+
+    return hatt;
+}
+
+static HistoryAttributes pdp_writer_history_attributes(
+        const BuiltinAttributes& builtin_att)
+{
+    HistoryAttributes hatt;
+    hatt.payloadMaxSize = builtin_att.writerPayloadSize;
+    hatt.memoryPolicy = builtin_att.writerHistoryMemoryPolicy;
+    hatt.initialReservedCaches = 1;
+    hatt.maximumReservedCaches = 1;
+
+    return hatt;
+}
 
 PDPSimple::PDPSimple (
         BuiltinProtocols* built,
@@ -233,15 +264,28 @@ void PDPSimple::announceParticipantState(
 {
     if (enabled_)
     {
-        auto endpoints = static_cast<fastdds::rtps::SimplePDPEndpoints*>(builtin_endpoints_.get());
-        StatelessWriter& writer = *(endpoints->writer.writer_);
-        WriterHistory& history = *(endpoints->writer.history_);
+        new_change |= m_hasChangedLocalPDP.exchange(false);
 
+#if HAVE_SECURITY
+        if (mp_RTPSParticipant->is_secure())
+        {
+            auto secure = dynamic_cast<fastdds::rtps::SimplePDPEndpointsSecure*>(builtin_endpoints_.get());
+            assert(nullptr != secure);
+
+            RTPSWriter& writer = *(secure->secure_writer.writer_);
+            WriterHistory& history = *(secure->secure_writer.history_);
+            PDP::announceParticipantState(writer, history, new_change, dispose, wp);
+        }
+#endif // HAVE_SECURITY
+
+        auto endpoints = dynamic_cast<fastdds::rtps::SimplePDPEndpoints*>(builtin_endpoints_.get());
+        RTPSWriter& writer = *(endpoints->writer.writer_);
+        WriterHistory& history = *(endpoints->writer.history_);
         PDP::announceParticipantState(writer, history, new_change, dispose, wp);
 
         if (!(dispose || new_change))
         {
-            writer.unsent_changes_reset();
+            endpoints->writer.writer_->unsent_changes_reset();
         }
     }
 }
@@ -250,218 +294,261 @@ bool PDPSimple::createPDPEndpoints()
 {
     EPROSIMA_LOG_INFO(RTPS_PDP, "Beginning");
 
+    fastdds::rtps::SimplePDPEndpoints* endpoints = nullptr;
+#if HAVE_SECURITY
+    fastdds::rtps::SimplePDPEndpointsSecure* secure_endpoints = nullptr;
+    bool is_secure = mp_RTPSParticipant->is_secure();
+    if (is_secure)
+    {
+        secure_endpoints = new fastdds::rtps::SimplePDPEndpointsSecure();
+        secure_endpoints->secure_reader.listener_.reset(new PDPListener(this));
+
+        endpoints = secure_endpoints;
+        endpoints->reader.listener_.reset(new PDPSecurityInitiatorListener(this));
+    }
+    else
+#endif  // HAVE_SECURITY
+    {
+        endpoints = new fastdds::rtps::SimplePDPEndpoints();
+        endpoints->reader.listener_.reset(new PDPListener(this));
+    }
+    builtin_endpoints_.reset(endpoints);
+
+    bool ret_val = create_dcps_participant_endpoints();
+#if HAVE_SECURITY
+    if (ret_val && is_secure)
+    {
+        create_dcps_participant_secure_endpoints();
+    }
+#endif  // HAVE_SECURITY
+    EPROSIMA_LOG_INFO(RTPS_PDP, "SPDP Endpoints creation finished");
+    return ret_val;
+}
+
+bool PDPSimple::create_dcps_participant_endpoints()
+{
     const RTPSParticipantAttributes& pattr = mp_RTPSParticipant->getRTPSParticipantAttributes();
     const RTPSParticipantAllocationAttributes& allocation = pattr.allocation;
     const BuiltinAttributes& builtin_att = mp_builtin->m_att;
+    auto endpoints = dynamic_cast<fastdds::rtps::SimplePDPEndpoints*>(builtin_endpoints_.get());
+    assert(nullptr != endpoints);
 
-    auto endpoints = new fastdds::rtps::SimplePDPEndpoints();
-    builtin_endpoints_.reset(endpoints);
+    constexpr const char* topic_name = "DCPSParticipant";
+    const EntityId_t reader_entity_id = c_EntityId_SPDPReader;
+    const EntityId_t writer_entity_id = c_EntityId_SPDPWriter;
 
-    //SPDP BUILTIN RTPSParticipant READER
+    // BUILTIN DCPSParticipant READER
+    auto& reader = endpoints->reader;
     HistoryAttributes hatt;
-    hatt.payloadMaxSize = builtin_att.readerPayloadSize;
-    hatt.memoryPolicy = builtin_att.readerHistoryMemoryPolicy;
-    hatt.initialReservedCaches = 25;
-    if (allocation.participants.initial > 0)
-    {
-        hatt.initialReservedCaches = (int32_t)allocation.participants.initial;
-    }
-    if (allocation.participants.maximum < std::numeric_limits<size_t>::max())
-    {
-        hatt.maximumReservedCaches = (int32_t)allocation.participants.maximum;
-    }
+    hatt = pdp_reader_history_attributes(builtin_att, allocation);
 
     PoolConfig reader_pool_cfg = PoolConfig::from_history_attributes(hatt);
-    endpoints->reader.payload_pool_ = TopicPayloadPoolRegistry::get("DCPSParticipant", reader_pool_cfg);
-    endpoints->reader.payload_pool_->reserve_history(reader_pool_cfg, true);
-
-    endpoints->reader.history_.reset(new ReaderHistory(hatt));
-
-    ReaderAttributes ratt;
-    ratt.endpoint.multicastLocatorList = mp_builtin->m_metatrafficMulticastLocatorList;
-    ratt.endpoint.unicastLocatorList = mp_builtin->m_metatrafficUnicastLocatorList;
-    ratt.endpoint.external_unicast_locators = mp_builtin->m_att.metatraffic_external_unicast_locators;
-    ratt.endpoint.ignore_non_matching_locators = pattr.ignore_non_matching_locators;
-    ratt.endpoint.topicKind = WITH_KEY;
-    ratt.endpoint.durabilityKind = TRANSIENT_LOCAL;
+    reader.payload_pool_ = TopicPayloadPoolRegistry::get(topic_name, reader_pool_cfg);
+    reader.payload_pool_->reserve_history(reader_pool_cfg, true);
+    reader.history_.reset(new ReaderHistory(hatt));
+
+    ReaderAttributes ratt = create_builtin_reader_attributes();
     ratt.endpoint.reliabilityKind = BEST_EFFORT;
-    ratt.matched_writers_allocation = allocation.participants;
-    mp_listener = new PDPListener(this);
-    RTPSReader* reader = nullptr;
-    if (mp_RTPSParticipant->createReader(&reader, ratt,
-            endpoints->reader.payload_pool_, endpoints->reader.history_.get(),
-            mp_listener, c_EntityId_SPDPReader, true, false))
-    {
-        endpoints->reader.reader_ = dynamic_cast<StatelessReader*>(reader);
+
+    RTPSReader* rtps_reader = nullptr;
+    if (mp_RTPSParticipant->createReader(&rtps_reader, ratt, reader.payload_pool_, reader.history_.get(),
+            reader.listener_.get(), reader_entity_id, true, false))
+    {
+        reader.reader_ = dynamic_cast<StatelessReader*>(rtps_reader);
+        assert(nullptr != reader.reader_);
+
 #if HAVE_SECURITY
-        mp_RTPSParticipant->set_endpoint_rtps_protection_supports(reader, false);
+        mp_RTPSParticipant->set_endpoint_rtps_protection_supports(rtps_reader, false);
 #endif // if HAVE_SECURITY
     }
     else
     {
-        EPROSIMA_LOG_ERROR(RTPS_PDP, "SimplePDP Reader creation failed");
-        delete mp_listener;
-        mp_listener = nullptr;
-        endpoints->reader.release();
+        EPROSIMA_LOG_ERROR(RTPS_PDP, "'" << topic_name << "' builtin reader creation failed");
+        reader.release();
         return false;
     }
 
-    //SPDP BUILTIN RTPSParticipant WRITER
-    hatt.payloadMaxSize = mp_builtin->m_att.writerPayloadSize;
-    hatt.initialReservedCaches = 1;
-    hatt.maximumReservedCaches = 1;
-    hatt.memoryPolicy = mp_builtin->m_att.writerHistoryMemoryPolicy;
+    // BUILTIN DCPSParticipant WRITER
+    auto& writer = endpoints->writer;
+    hatt = pdp_writer_history_attributes(builtin_att);
 
     PoolConfig writer_pool_cfg = PoolConfig::from_history_attributes(hatt);
-    endpoints->writer.payload_pool_ = TopicPayloadPoolRegistry::get("DCPSParticipant", writer_pool_cfg);
-    endpoints->writer.payload_pool_->reserve_history(writer_pool_cfg, false);
-
-    endpoints->writer.history_.reset(new WriterHistory(hatt));
-    WriterAttributes watt;
-    watt.endpoint.external_unicast_locators = mp_builtin->m_att.metatraffic_external_unicast_locators;
-    watt.endpoint.ignore_non_matching_locators = pattr.ignore_non_matching_locators;
-    watt.endpoint.endpointKind = WRITER;
-    watt.endpoint.durabilityKind = TRANSIENT_LOCAL;
+    writer.payload_pool_ = TopicPayloadPoolRegistry::get(topic_name, writer_pool_cfg);
+    writer.payload_pool_->reserve_history(writer_pool_cfg, false);
+    writer.history_.reset(new WriterHistory(hatt));
+
+    WriterAttributes watt = create_builtin_writer_attributes();
     watt.endpoint.reliabilityKind = BEST_EFFORT;
-    watt.endpoint.topicKind = WITH_KEY;
     watt.endpoint.remoteLocatorList = m_discovery.initialPeersList;
-    watt.matched_readers_allocation = allocation.participants;
 
     if (pattr.throughputController.bytesPerPeriod != UINT32_MAX && pattr.throughputController.periodMillisecs != 0)
     {
         watt.mode = ASYNCHRONOUS_WRITER;
     }
 
-    RTPSWriter* wout = nullptr;
-    if (mp_RTPSParticipant->createWriter(&wout, watt, endpoints->writer.payload_pool_, endpoints->writer.history_.get(),
-            nullptr,
-            c_EntityId_SPDPWriter, true))
+    RTPSWriter* rtps_writer = nullptr;
+    if (mp_RTPSParticipant->createWriter(&rtps_writer, watt, writer.payload_pool_, writer.history_.get(),
+            nullptr, writer_entity_id, true))
     {
-        endpoints->writer.writer_ = dynamic_cast<StatelessWriter*>(wout);
+        writer.writer_ = dynamic_cast<StatelessWriter*>(rtps_writer);
+        assert(nullptr != writer.writer_);
+
 #if HAVE_SECURITY
-        mp_RTPSParticipant->set_endpoint_rtps_protection_supports(wout, false);
+        mp_RTPSParticipant->set_endpoint_rtps_protection_supports(rtps_writer, false);
 #endif // if HAVE_SECURITY
-        if (endpoints->writer.writer_ != nullptr)
+
+        const NetworkFactory& network = mp_RTPSParticipant->network_factory();
+        LocatorList_t fixed_locators;
+        for (const Locator_t& loc : mp_builtin->m_initialPeersList)
         {
-            const NetworkFactory& network = mp_RTPSParticipant->network_factory();
-            LocatorList_t fixed_locators;
-            for (const Locator_t& loc : mp_builtin->m_initialPeersList)
+            if (network.is_locator_remote_or_allowed(loc))
             {
-                if (network.is_locator_remote_or_allowed(loc))
-                {
-                    // Add initial peers locator without transformation as we don't know whether the
-                    // remote transport will allow localhost
-                    fixed_locators.push_back(loc);
-
-                    /**
-                     * TCP special case:
-                     *
-                     * In TCP, it is not possible to open a socket with 'any' (0.0.0.0) address as it's done
-                     * in UDP, so when the TCP transports receive a locator with 'any', they open an input
-                     * channel for the specified port in each of the machine interfaces (with the exception
-                     * of localhost). In fact, a participant with a TCP transport will only listen on localhost
-                     * if localhost is the address of any of the initial peers.
-                     *
-                     * However, when the TCP enabled participant does not have a whitelist (or localhost is in
-                     * it), it allows for transformation of its locators to localhost for performance optimizations.
-                     * In this case, the remote TCP participant it will send data using a socket in localhost,
-                     * and for that the participant with the initial peers list needs to be listening there
-                     * to receive it.
-                     *
-                     * That means:
-                     *   1. Checking that the initial peer is not already localhost
-                     *   2. Checking that the initial peer locator is of TCP kind
-                     *   3. Checking that the network configuration allows for localhost locators
-                     */
-                    Locator_t local_locator;
-                    network.transform_remote_locator(loc, local_locator,
-                            DISC_NETWORK_CONFIGURATION_LISTENING_LOCALHOST_ALL);
-                    if (loc != local_locator
-                            && (loc.kind == LOCATOR_KIND_TCPv4 || loc.kind == LOCATOR_KIND_TCPv6)
-                            && network.is_locator_allowed(local_locator))
-                    {
-                        fixed_locators.push_back(local_locator);
-                    }
-                }
-                else
+                // Add initial peers locator without transformation as we don't know whether the
+                // remote transport will allow localhost
+                fixed_locators.push_back(loc);
+
+                /**
+                 * TCP special case:
+                 *
+                 * In TCP, it is not possible to open a socket with 'any' (0.0.0.0) address as it's done
+                 * in UDP, so when the TCP transports receive a locator with 'any', they open an input
+                 * channel for the specified port in each of the machine interfaces (with the exception
+                 * of localhost). In fact, a participant with a TCP transport will only listen on localhost
+                 * if localhost is the address of any of the initial peers.
+                 *
+                 * However, when the TCP enabled participant does not have a whitelist (or localhost is in
+                 * it), it allows for transformation of its locators to localhost for performance optimizations.
+                 * In this case, the remote TCP participant it will send data using a socket in localhost,
+                 * and for that the participant with the initial peers list needs to be listening there
+                 * to receive it.
+                 *
+                 * That means:
+                 *   1. Checking that the initial peer is not already localhost
+                 *   2. Checking that the initial peer locator is of TCP kind
+                 *   3. Checking that the network configuration allows for localhost locators
+                 */
+                Locator_t local_locator;
+                network.transform_remote_locator(loc, local_locator,
+                        DISC_NETWORK_CONFIGURATION_LISTENING_LOCALHOST_ALL);
+                if (loc != local_locator
+                        && (loc.kind == LOCATOR_KIND_TCPv4 || loc.kind == LOCATOR_KIND_TCPv6)
+                        && network.is_locator_allowed(local_locator))
                 {
-                    EPROSIMA_LOG_WARNING(RTPS_PDP, "Ignoring initial peers locator " << loc << " : not allowed.");
+                    fixed_locators.push_back(local_locator);
                 }
             }
-            endpoints->writer.writer_->set_fixed_locators(fixed_locators);
+            else
+            {
+                EPROSIMA_LOG_WARNING(RTPS_PDP, "Ignoring initial peers locator " << loc << " : not allowed.");
+            }
         }
+        writer.writer_->set_fixed_locators(fixed_locators);
     }
     else
     {
-        EPROSIMA_LOG_ERROR(RTPS_PDP, "SimplePDP Writer creation failed");
-        endpoints->writer.release();
+        EPROSIMA_LOG_ERROR(RTPS_PDP, "'" << topic_name << "' builtin writer creation failed");
+        writer.release();
         return false;
     }
-    EPROSIMA_LOG_INFO(RTPS_PDP, "SPDP Endpoints creation finished");
     return true;
 }
 
-void PDPSimple::assignRemoteEndpoints(
-        ParticipantProxyData* pdata)
+#if HAVE_SECURITY
+bool PDPSimple::create_dcps_participant_secure_endpoints()
 {
-    EPROSIMA_LOG_INFO(RTPS_PDP, "For RTPSParticipant: " << pdata->m_guid.guidPrefix);
+    const RTPSParticipantAttributes& pattr = mp_RTPSParticipant->getRTPSParticipantAttributes();
+    const RTPSParticipantAllocationAttributes& allocation = pattr.allocation;
+    const BuiltinAttributes& builtin_att = mp_builtin->m_att;
+    auto endpoints = dynamic_cast<fastdds::rtps::SimplePDPEndpointsSecure*>(builtin_endpoints_.get());
+    assert(nullptr != endpoints);
 
-    auto endpoints = static_cast<fastdds::rtps::SimplePDPEndpoints*>(builtin_endpoints_.get());
+    constexpr const char* topic_name = "DCPSParticipantsSecure";
+    const EntityId_t reader_entity_id = c_EntityId_spdp_reliable_participant_secure_reader;
+    const EntityId_t writer_entity_id = c_EntityId_spdp_reliable_participant_secure_writer;
 
-    const NetworkFactory& network = mp_RTPSParticipant->network_factory();
-    uint32_t endp = pdata->m_availableBuiltinEndpoints;
-    uint32_t auxendp = endp;
-    bool use_multicast_locators = !mp_RTPSParticipant->getAttributes().builtin.avoid_builtin_multicast ||
-            pdata->metatraffic_locators.unicast.empty();
-    auxendp &= DISC_BUILTIN_ENDPOINT_PARTICIPANT_ANNOUNCER;
-    if (auxendp != 0)
-    {
-        auto temp_writer_data = get_temporary_writer_proxies_pool().get();
+    // BUILTIN DCPSParticipantsSecure READER
+    auto& reader = endpoints->secure_reader;
+    HistoryAttributes hatt;
+    hatt = pdp_reader_history_attributes(builtin_att, allocation);
 
-        temp_writer_data->clear();
-        temp_writer_data->guid().guidPrefix = pdata->m_guid.guidPrefix;
-        temp_writer_data->guid().entityId = c_EntityId_SPDPWriter;
-        temp_writer_data->persistence_guid(pdata->get_persistence_guid());
-        temp_writer_data->set_persistence_entity_id(c_EntityId_SPDPWriter);
-        temp_writer_data->set_remote_locators(pdata->metatraffic_locators, network, use_multicast_locators);
-        temp_writer_data->m_qos.m_reliability.kind = RELIABLE_RELIABILITY_QOS;
-        temp_writer_data->m_qos.m_durability.kind = TRANSIENT_LOCAL_DURABILITY_QOS;
-        endpoints->reader.reader_->matched_writer_add(*temp_writer_data);
+    PoolConfig reader_pool_cfg = PoolConfig::from_history_attributes(hatt);
+    reader.payload_pool_ = TopicPayloadPoolRegistry::get(topic_name, reader_pool_cfg);
+    reader.payload_pool_->reserve_history(reader_pool_cfg, true);
+    reader.history_.reset(new ReaderHistory(hatt));
+
+    ReaderAttributes ratt = create_builtin_reader_attributes();
+    WriterAttributes watt = create_builtin_writer_attributes();
+    add_builtin_security_attributes(ratt, watt);
+
+    RTPSReader* rtps_reader = nullptr;
+    if (mp_RTPSParticipant->createReader(&rtps_reader, ratt, reader.payload_pool_, reader.history_.get(),
+            reader.listener_.get(), reader_entity_id, true, false))
+    {
+        reader.reader_ = dynamic_cast<StatefulReader*>(rtps_reader);
+        assert(nullptr != reader.reader_);
     }
-    auxendp = endp;
-    auxendp &= DISC_BUILTIN_ENDPOINT_PARTICIPANT_DETECTOR;
-    if (auxendp != 0)
+    else
     {
-        auto temp_reader_data = get_temporary_reader_proxies_pool().get();
+        EPROSIMA_LOG_ERROR(RTPS_PDP, "'" << topic_name << "' builtin reader creation failed");
+        reader.release();
+        return false;
+    }
 
-        temp_reader_data->clear();
-        temp_reader_data->m_expectsInlineQos = false;
-        temp_reader_data->guid().guidPrefix = pdata->m_guid.guidPrefix;
-        temp_reader_data->guid().entityId = c_EntityId_SPDPReader;
-        temp_reader_data->set_remote_locators(pdata->metatraffic_locators, network, use_multicast_locators);
-        temp_reader_data->m_qos.m_reliability.kind = BEST_EFFORT_RELIABILITY_QOS;
-        temp_reader_data->m_qos.m_durability.kind = TRANSIENT_LOCAL_DURABILITY_QOS;
-        endpoints->writer.writer_->matched_reader_add(*temp_reader_data);
+    // SPDP BUILTIN RTPSParticipant WRITER
+    auto& writer = endpoints->secure_writer;
+    hatt = pdp_writer_history_attributes(builtin_att);
 
-        StatelessWriter* pW = endpoints->writer.writer_;
+    PoolConfig writer_pool_cfg = PoolConfig::from_history_attributes(hatt);
+    writer.payload_pool_ = TopicPayloadPoolRegistry::get(topic_name, writer_pool_cfg);
+    writer.payload_pool_->reserve_history(writer_pool_cfg, false);
+    writer.history_.reset(new WriterHistory(hatt));
 
-        if (pW != nullptr)
+    RTPSWriter* rtps_writer = nullptr;
+    if (mp_RTPSParticipant->createWriter(&rtps_writer, watt, writer.payload_pool_, writer.history_.get(),
+            nullptr, writer_entity_id, true))
+    {
+        writer.writer_ = dynamic_cast<StatefulWriter*>(rtps_writer);
+        assert(nullptr != writer.writer_);
+    }
+    else
+    {
+        EPROSIMA_LOG_ERROR(RTPS_PDP, "'" << topic_name << "' builtin writer creation failed");
+        writer.release();
+        return false;
+    }
+    return true;
+}
+
+#endif  // HAVE_SECURITY
+
+void PDPSimple::assignRemoteEndpoints(
+        ParticipantProxyData* pdata)
+{
+    bool ignored = false;
+    notify_and_maybe_ignore_new_participant(pdata, ignored);
+    if (!ignored)
+    {
+#if HAVE_SECURITY
+        auto endpoints = dynamic_cast<fastdds::rtps::SimplePDPEndpointsSecure*>(builtin_endpoints_.get());
+        if (nullptr != endpoints)
         {
-            pW->unsent_changes_reset();
+            // This participant is secure.
+            // PDP should have been matched inside notifyAboveRemoteEndpoints after completing the authentication process.
+            // We now match the other builtin endpoints.
+            GUID_t remote_guid = pdata->m_guid;
+            remote_guid.entityId = c_EntityId_spdp_reliable_participant_secure_writer;
+            bool notify_secure = endpoints->secure_reader.reader_->matched_writer_is_matched(remote_guid);
+            assign_low_level_remote_endpoints(*pdata, notify_secure);
         }
         else
+#endif // if HAVE_SECURITY
         {
-            EPROSIMA_LOG_ERROR(RTPS_PDP, "Using PDPSimple protocol with a reliable writer");
+            // This participant is not secure.
+            // Match PDP and other builtin endpoints.
+            match_pdp_remote_endpoints(*pdata, false);
+            assign_low_level_remote_endpoints(*pdata, false);
         }
     }
-
-#if HAVE_SECURITY
-    // Validate remote participant
-    mp_RTPSParticipant->security_manager().discovered_participant(*pdata);
-#else
-    //Inform EDP of new RTPSParticipant data:
-    notifyAboveRemoteEndpoints(*pdata, true);
-#endif // if HAVE_SECURITY
 }
 
 void PDPSimple::removeRemoteEndpoints(
@@ -469,38 +556,175 @@ void PDPSimple::removeRemoteEndpoints(
 {
     EPROSIMA_LOG_INFO(RTPS_PDP, "For RTPSParticipant: " << pdata->m_guid);
 
-    auto endpoints = static_cast<fastdds::rtps::SimplePDPEndpoints*>(builtin_endpoints_.get());
+    GUID_t guid = pdata->m_guid;
 
-    uint32_t endp = pdata->m_availableBuiltinEndpoints;
-    uint32_t auxendp = endp;
-    auxendp &= DISC_BUILTIN_ENDPOINT_PARTICIPANT_ANNOUNCER;
-    if (auxendp != 0)
     {
-        GUID_t writer_guid(pdata->m_guid.guidPrefix, c_EntityId_SPDPWriter);
-        endpoints->reader.reader_->matched_writer_remove(writer_guid);
+        auto endpoints = dynamic_cast<fastdds::rtps::SimplePDPEndpoints*>(builtin_endpoints_.get());
+        assert(nullptr != endpoints);
+
+        guid.entityId = c_EntityId_SPDPWriter;
+        endpoints->reader.reader_->matched_writer_remove(guid);
+
+        guid.entityId = c_EntityId_SPDPReader;
+        endpoints->writer.writer_->matched_reader_remove(guid);
     }
-    auxendp = endp;
-    auxendp &= DISC_BUILTIN_ENDPOINT_PARTICIPANT_DETECTOR;
-    if (auxendp != 0)
+
+#if HAVE_SECURITY
+    auto endpoints = dynamic_cast<fastdds::rtps::SimplePDPEndpointsSecure*>(builtin_endpoints_.get());
+    if (nullptr != endpoints)
     {
-        GUID_t reader_guid(pdata->m_guid.guidPrefix, c_EntityId_SPDPReader);
-        endpoints->writer.writer_->matched_reader_remove(reader_guid);
+        guid.entityId = c_EntityId_spdp_reliable_participant_secure_writer;
+        endpoints->secure_reader.reader_->matched_writer_remove(guid);
+
+        guid.entityId = c_EntityId_spdp_reliable_participant_secure_reader;
+        endpoints->secure_writer.writer_->matched_reader_remove(guid);
     }
+#endif // HAVE_SECURITY
 }
 
 void PDPSimple::notifyAboveRemoteEndpoints(
         const ParticipantProxyData& pdata,
         bool notify_secure_endpoints)
 {
-    //Inform EDP of new RTPSParticipant data:
+    if (notify_secure_endpoints)
+    {
+        match_pdp_remote_endpoints(pdata, true);
+    }
+    else
+    {
+        // Add remote participant data
+        GUID_t writer_guid{ pdata.m_guid.guidPrefix, c_EntityId_SPDPWriter };
+        ParticipantProxyData* part_data = createParticipantProxyData(pdata, writer_guid);
+        if (part_data != nullptr)
+        {
+            bool ignored = false;
+            notify_and_maybe_ignore_new_participant(part_data, ignored);
+            if (!ignored)
+            {
+                match_pdp_remote_endpoints(*part_data, false);
+                assign_low_level_remote_endpoints(*part_data, false);
+            }
+        }
+    }
+
+}
+
+void PDPSimple::match_pdp_remote_endpoints(
+        const ParticipantProxyData& pdata,
+        bool notify_secure_endpoints)
+{
+#if !HAVE_SECURITY
+    static_cast<void>(notify_secure_endpoints);
+#endif // !HAVE_SECURITY
+
+    auto endpoints = static_cast<fastdds::rtps::SimplePDPEndpoints*>(builtin_endpoints_.get());
+
+    const NetworkFactory& network = mp_RTPSParticipant->network_factory();
+    bool use_multicast_locators = !mp_RTPSParticipant->getAttributes().builtin.avoid_builtin_multicast ||
+            pdata.metatraffic_locators.unicast.empty();
+    const uint32_t endp = pdata.m_availableBuiltinEndpoints;
+
+    // Default to values for non-secure endpoints
+    auto reliability_kind = BEST_EFFORT_RELIABILITY_QOS;
+    uint32_t pdp_reader_mask = DISC_BUILTIN_ENDPOINT_PARTICIPANT_DETECTOR;
+    uint32_t pdp_writer_mask = DISC_BUILTIN_ENDPOINT_PARTICIPANT_ANNOUNCER;
+    EntityId_t reader_entity_id = c_EntityId_SPDPReader;
+    EntityId_t writer_entity_id = c_EntityId_SPDPWriter;
+    RTPSReader* reader = endpoints->reader.reader_;
+    RTPSWriter* writer = endpoints->writer.writer_;
+
+#if HAVE_SECURITY
+    // If the other participant has been authenticated, use values for secure endpoints
+    if (notify_secure_endpoints)
+    {
+        auto secure_endpoints = static_cast<fastdds::rtps::SimplePDPEndpointsSecure*>(builtin_endpoints_.get());
+        reliability_kind = RELIABLE_RELIABILITY_QOS;
+        pdp_reader_mask = DISC_BUILTIN_ENDPOINT_PARTICIPANT_SECURE_DETECTOR;
+        pdp_writer_mask = DISC_BUILTIN_ENDPOINT_PARTICIPANT_SECURE_ANNOUNCER;
+        reader_entity_id = c_EntityId_spdp_reliable_participant_secure_reader;
+        writer_entity_id = c_EntityId_spdp_reliable_participant_secure_writer;
+        reader = secure_endpoints->secure_reader.reader_;
+        writer = secure_endpoints->secure_writer.writer_;
+    }
+#endif // HAVE_SECURITY
+
+    if (0 != (endp & pdp_writer_mask))
+    {
+        auto temp_writer_data = get_temporary_writer_proxies_pool().get();
+
+        temp_writer_data->clear();
+        temp_writer_data->guid().guidPrefix = pdata.m_guid.guidPrefix;
+        temp_writer_data->guid().entityId = writer_entity_id;
+        temp_writer_data->persistence_guid(pdata.get_persistence_guid());
+        temp_writer_data->set_persistence_entity_id(writer_entity_id);
+        temp_writer_data->set_remote_locators(pdata.metatraffic_locators, network, use_multicast_locators);
+        temp_writer_data->m_qos.m_reliability.kind = reliability_kind;
+        temp_writer_data->m_qos.m_durability.kind = TRANSIENT_LOCAL_DURABILITY_QOS;
+#if HAVE_SECURITY
+        if (notify_secure_endpoints)
+        {
+            if (!mp_RTPSParticipant->security_manager().discovered_builtin_writer(
+                        reader->getGuid(), pdata.m_guid, *temp_writer_data,
+                        reader->getAttributes().security_attributes()))
+            {
+                EPROSIMA_LOG_ERROR(RTPS_EDP, "Security manager returns an error for writer " <<
+                        temp_writer_data->guid());
+            }
+        }
+        else
+#endif // HAVE_SECURITY
+        {
+            reader->matched_writer_add(*temp_writer_data);
+        }
+    }
+
+    if (0 != (endp & pdp_reader_mask))
+    {
+        auto temp_reader_data = get_temporary_reader_proxies_pool().get();
+
+        temp_reader_data->clear();
+        temp_reader_data->m_expectsInlineQos = false;
+        temp_reader_data->guid().guidPrefix = pdata.m_guid.guidPrefix;
+        temp_reader_data->guid().entityId = reader_entity_id;
+        temp_reader_data->set_remote_locators(pdata.metatraffic_locators, network, use_multicast_locators);
+        temp_reader_data->m_qos.m_reliability.kind = reliability_kind;
+        temp_reader_data->m_qos.m_durability.kind = TRANSIENT_LOCAL_DURABILITY_QOS;
+#if HAVE_SECURITY
+        if (notify_secure_endpoints)
+        {
+            if (!mp_RTPSParticipant->security_manager().discovered_builtin_reader(
+                        writer->getGuid(), pdata.m_guid, *temp_reader_data,
+                        writer->getAttributes().security_attributes()))
+            {
+                EPROSIMA_LOG_ERROR(RTPS_EDP, "Security manager returns an error for reader " <<
+                        temp_reader_data->guid());
+            }
+        }
+        else
+#endif // HAVE_SECURITY
+        {
+            writer->matched_reader_add(*temp_reader_data);
+        }
+
+        if (BEST_EFFORT_RELIABILITY_QOS == reliability_kind)
+        {
+            endpoints->writer.writer_->unsent_changes_reset();
+        }
+    }
+}
+
+void PDPSimple::assign_low_level_remote_endpoints(
+        const ParticipantProxyData& pdata,
+        bool notify_secure_endpoints)
+{
     if (mp_EDP != nullptr)
     {
-        mp_EDP->assignRemoteEndpoints(pdata, (notify_secure_endpoints ? true : false));
+        mp_EDP->assignRemoteEndpoints(pdata, notify_secure_endpoints);
     }
 
     if (mp_builtin->mp_WLP != nullptr)
     {
-        mp_builtin->mp_WLP->assignRemoteEndpoints(pdata, (notify_secure_endpoints ? true : false));
+        mp_builtin->mp_WLP->assignRemoteEndpoints(pdata, notify_secure_endpoints);
     }
 
     if (mp_builtin->tlm_ != nullptr)
@@ -509,6 +733,37 @@ void PDPSimple::notifyAboveRemoteEndpoints(
     }
 }
 
+#if HAVE_SECURITY
+bool PDPSimple::pairing_remote_writer_with_local_reader_after_security(
+        const GUID_t& local_reader,
+        const WriterProxyData& remote_writer_data)
+{
+    auto endpoints = dynamic_cast<fastdds::rtps::SimplePDPEndpointsSecure*>(builtin_endpoints_.get());
+    if ((nullptr != endpoints) && (local_reader == endpoints->secure_reader.reader_->getGuid()))
+    {
+        endpoints->secure_reader.reader_->matched_writer_add(remote_writer_data);
+        return true;
+    }
+
+    return PDP::pairing_remote_writer_with_local_reader_after_security(local_reader, remote_writer_data);
+}
+
+bool PDPSimple::pairing_remote_reader_with_local_writer_after_security(
+        const GUID_t& local_writer,
+        const ReaderProxyData& remote_reader_data)
+{
+    auto endpoints = dynamic_cast<fastdds::rtps::SimplePDPEndpointsSecure*>(builtin_endpoints_.get());
+    if ((nullptr != endpoints) && (local_writer == endpoints->secure_writer.writer_->getGuid()))
+    {
+        endpoints->secure_writer.writer_->matched_reader_add(remote_reader_data);
+        return true;
+    }
+
+    return PDP::pairing_remote_reader_with_local_writer_after_security(local_writer, remote_reader_data);
+}
+
+#endif // HAVE_SECURITY
+
 bool PDPSimple::newRemoteEndpointStaticallyDiscovered(
         const GUID_t& pguid,
         int16_t userDefinedId,

programming_language: C++
filename: SimplePDPEndpoints.hpp
change_type: ModificationType.MODIFY
diff: @@ -46,6 +46,11 @@ struct SimplePDPEndpoints : public PDPEndpoints
         return DISC_BUILTIN_ENDPOINT_PARTICIPANT_ANNOUNCER | DISC_BUILTIN_ENDPOINT_PARTICIPANT_DETECTOR;
     }
 
+    const std::unique_ptr<fastrtps::rtps::ReaderListener>& main_listener() const override
+    {
+        return reader.listener_;
+    }
+
     bool enable_pdp_readers(
             fastrtps::rtps::RTPSParticipantImpl* participant) override
     {

programming_language: C++
filename: SimplePDPEndpointsSecure.hpp
change_type: ModificationType.ADD
diff: @@ -0,0 +1,109 @@
+// Copyright 2023 Proyectos y Sistemas de Mantenimiento SL (eProsima).
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unful required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @file SimplePDPEndpointsSecure.hpp
+ */
+
+#ifndef FASTDDS_RTPS_BUILTIN_DISCOVERY_PARTICIPANT_SIMPLE__SIMPLEPDPENDPOINTSSECURE_HPP_
+#define FASTDDS_RTPS_BUILTIN_DISCOVERY_PARTICIPANT_SIMPLE__SIMPLEPDPENDPOINTSSECURE_HPP_
+
+#include <memory>
+
+#include <fastdds/rtps/builtin/data/BuiltinEndpoints.hpp>
+#include <fastdds/rtps/reader/StatefulReader.h>
+#include <fastdds/rtps/writer/StatefulWriter.h>
+
+#include <rtps/builtin/BuiltinReader.hpp>
+#include <rtps/builtin/BuiltinWriter.hpp>
+#include <rtps/builtin/discovery/participant/simple/SimplePDPEndpoints.hpp>
+#include <rtps/history/ITopicPayloadPool.h>
+
+namespace eprosima {
+namespace fastdds {
+namespace rtps {
+
+/**
+ * Container for the builtin endpoints of SPDPSimple
+ */
+struct SimplePDPEndpointsSecure : public SimplePDPEndpoints
+{
+    ~SimplePDPEndpointsSecure() override = default;
+
+    fastrtps::rtps::BuiltinEndpointSet_t builtin_endpoints() const override
+    {
+        return SimplePDPEndpoints::builtin_endpoints() |
+               DISC_BUILTIN_ENDPOINT_PARTICIPANT_SECURE_ANNOUNCER | DISC_BUILTIN_ENDPOINT_PARTICIPANT_SECURE_DETECTOR;
+    }
+
+    const std::unique_ptr<fastrtps::rtps::ReaderListener>& main_listener() const override
+    {
+        return secure_reader.listener_;
+    }
+
+    bool enable_pdp_readers(
+            fastrtps::rtps::RTPSParticipantImpl* participant) override
+    {
+        return SimplePDPEndpoints::enable_pdp_readers(participant) &&
+               participant->enableReader(secure_reader.reader_);
+    }
+
+    void disable_pdp_readers(
+            fastrtps::rtps::RTPSParticipantImpl* participant) override
+    {
+        participant->disableReader(secure_reader.reader_);
+        SimplePDPEndpoints::disable_pdp_readers(participant);
+    }
+
+    void delete_pdp_endpoints(
+            fastrtps::rtps::RTPSParticipantImpl* participant) override
+    {
+        participant->deleteUserEndpoint(secure_reader.reader_->getGuid());
+        participant->deleteUserEndpoint(secure_writer.writer_->getGuid());
+        SimplePDPEndpoints::delete_pdp_endpoints(participant);
+    }
+
+    void remove_from_pdp_reader_history(
+            const fastrtps::rtps::InstanceHandle_t& remote_participant) override
+    {
+        secure_reader.remove_from_history(remote_participant);
+        SimplePDPEndpoints::remove_from_pdp_reader_history(remote_participant);
+    }
+
+    void remove_from_pdp_reader_history(
+            fastrtps::rtps::CacheChange_t* change) override
+    {
+        assert(nullptr != change);
+        if (change->writerGUID.entityId == fastrtps::rtps::c_EntityId_SPDPWriter)
+        {
+            secure_reader.history_->remove_change(change);
+        }
+        else
+        {
+            SimplePDPEndpoints::remove_from_pdp_reader_history(change);
+        }
+    }
+
+    //! Builtin Simple PDP secure reader
+    BuiltinReader<fastrtps::rtps::StatefulReader> secure_reader;
+
+    //! Builtin Simple PDP secure writer
+    BuiltinWriter<fastrtps::rtps::StatefulWriter> secure_writer;
+};
+
+} // namespace rtps
+} // namespace fastdds
+} // namespace eprosima
+
+#endif  // FASTDDS_RTPS_BUILTIN_DISCOVERY_PARTICIPANT_SIMPLE__SIMPLEPDPENDPOINTSSECURE_HPP_

programming_language: C++
filename: StatelessReader.cpp
change_type: ModificationType.MODIFY
diff: @@ -306,14 +306,24 @@ bool StatelessReader::change_received(
     // TODO Revisar si no hay que incluirlo.
     if (!thereIsUpperRecordOf(change->writerGUID, change->sequenceNumber))
     {
-        // Update Ownership strength.
-        if (EXCLUSIVE_OWNERSHIP_QOS == m_att.ownershipKind)
+        bool update_notified = true;
+
+        decltype(matched_writers_)::iterator writer = matched_writers_.end();
+        if ((EXCLUSIVE_OWNERSHIP_QOS == m_att.ownershipKind) ||
+                (m_trustedWriterEntityId == change->writerGUID.entityId))
         {
-            auto writer = std::find_if(matched_writers_.begin(), matched_writers_.end(),
+            writer = std::find_if(matched_writers_.begin(), matched_writers_.end(),
                             [change](const RemoteWriterInfo_t& item)
                             {
                                 return item.guid == change->writerGUID;
                             });
+            bool is_matched = matched_writers_.end() != writer;
+            update_notified = is_matched;
+        }
+
+        // Update Ownership strength.
+        if (EXCLUSIVE_OWNERSHIP_QOS == m_att.ownershipKind)
+        {
             assert(matched_writers_.end() != writer);
             change->reader_info.writer_ownership_strength = writer->ownership_strength;
         }
@@ -329,7 +339,11 @@ bool StatelessReader::change_received(
             auto seq = change->sequenceNumber;
 
             Time_t::now(change->reader_info.receptionTimestamp);
-            SequenceNumber_t previous_seq = update_last_notified(change->writerGUID, change->sequenceNumber);
+            SequenceNumber_t previous_seq{ 0, 0 };
+            if (update_notified)
+            {
+                previous_seq = update_last_notified(change->writerGUID, change->sequenceNumber);
+            }
             ++total_unread_;
 
             on_data_notify(guid, change->sourceTimestamp);

programming_language: C++
filename: SecurityManager.cpp
change_type: ModificationType.MODIFY
diff: @@ -680,6 +680,11 @@ bool SecurityManager::discovered_participant(
         {
             return false;
         }
+
+        if (remote_participant_info->auth_status_ == AUTHENTICATION_FAILED)
+        {
+            remote_participant_info->auth_status_ = AUTHENTICATION_REQUEST_NOT_SEND;
+        }
     }
 
     bool returnedValue = true;
@@ -846,6 +851,7 @@ bool SecurityManager::on_process_handshake(
 
     if (ret == VALIDATION_FAILED)
     {
+        remote_participant_info->auth_status_ = AUTHENTICATION_FAILED;
         on_validation_failed(participant_data, exception);
         return false;
     }
@@ -4180,9 +4186,13 @@ void SecurityManager::resend_handshake_message_token(
         {
             if (remote_participant_info->handshake_requests_sent_ >= DiscoveredParticipantInfo::MAX_HANDSHAKE_REQUESTS)
             {
-                SecurityException exception;
-                remote_participant_info->event_->cancel_timer();
-                on_validation_failed(dp_it->second->participant_data(), exception);
+                if (remote_participant_info->auth_status_ != AUTHENTICATION_FAILED)
+                {
+                    SecurityException exception;
+                    remote_participant_info->event_->cancel_timer();
+                    remote_participant_info->auth_status_ = AUTHENTICATION_FAILED;
+                    on_validation_failed(dp_it->second->participant_data(), exception);
+                }
             }
             else
             {

programming_language: C++
filename: BlackboxTestsSecurity.cpp
change_type: ModificationType.MODIFY
diff: @@ -16,21 +16,24 @@
 
 #if HAVE_SECURITY
 
+#include <atomic>
+#include <algorithm>
+#include <fstream>
+#include <map>
+
+#include <gtest/gtest.h>
+
 #include "PubSubReader.hpp"
 #include "PubSubWriter.hpp"
 #include "PubSubWriterReader.hpp"
 #include "PubSubParticipant.hpp"
 
-#include <gtest/gtest.h>
-#include <fstream>
-#include <map>
-#include <algorithm>
-
-#include <fastrtps/xmlparser/XMLProfileManager.h>
+#include <fastdds/dds/log/Log.hpp>
+#include <fastdds/rtps/common/EntityId_t.hpp>
 #include <fastdds/rtps/transport/shared_mem/SharedMemTransportDescriptor.h>
-#include <rtps/transport/test_UDPv4Transport.h>
+#include <fastrtps/xmlparser/XMLProfileManager.h>
 
-#include <fastdds/dds/log/Log.hpp>
+#include <rtps/transport/test_UDPv4Transport.h>
 
 using namespace eprosima::fastrtps;
 using namespace eprosima::fastrtps::rtps;
@@ -88,6 +91,31 @@ public:
 
 };
 
+struct UDPMessageSender
+{
+    asio::io_service service;
+    asio::ip::udp::socket socket;
+
+    UDPMessageSender()
+        : service()
+        , socket(service)
+    {
+        socket.open(asio::ip::udp::v4());
+    }
+
+    void send(
+            const CDRMessage_t& msg,
+            const Locator_t& destination)
+    {
+        std::string addr = IPLocator::toIPv4string(destination);
+        unsigned short port = static_cast<unsigned short>(destination.port);
+        auto remote = asio::ip::udp::endpoint(asio::ip::address::from_string(addr), port);
+        asio::error_code ec;
+
+        socket.send_to(asio::buffer(msg.buffer, msg.length), remote, 0, ec);
+    }
+
+};
 
 class SecurityPkcs : public ::testing::Test
 {
@@ -441,7 +469,7 @@ TEST_P(Security, BuiltinAuthenticationPlugin_PKIDH_lossy_conditions)
 }
 
 // Regresion test for Refs #13295, github #2362
-TEST_P(Security, BuiltinAuthenticationPlugin_second_participant_creation_loop)
+TEST(Security, BuiltinAuthenticationPlugin_second_participant_creation_loop)
 {
     constexpr size_t n_loops = 101;
 
@@ -477,6 +505,63 @@ TEST_P(Security, BuiltinAuthenticationPlugin_second_participant_creation_loop)
     Log::ClearConsumers();
     Log::RegisterConsumer(std::unique_ptr<LogConsumer>(new TestConsumer(n_logs)));
 
+    // Class to allow waiting for the authentication message to be sent
+    class AuthMessageSendStatus
+    {
+        bool message_sent_ = false;
+        std::mutex mutex_;
+        std::condition_variable cv_;
+
+    public:
+
+        void reset()
+        {
+            std::lock_guard < std::mutex> guard(mutex_);
+            message_sent_ = false;
+        }
+
+        void notify()
+        {
+            std::lock_guard<std::mutex> guard(mutex_);
+            message_sent_ = true;
+            cv_.notify_one();
+        }
+
+        void wait()
+        {
+            std::unique_lock<std::mutex> lock(mutex_);
+            cv_.wait(lock, [this]() -> bool
+                    {
+                        return message_sent_;
+                    });
+        }
+
+    };
+
+    // Prepare transport to check that the authentication message is sent
+    auto transport = std::make_shared<test_UDPv4TransportDescriptor>();
+    AuthMessageSendStatus auth_message_send_status;
+    transport->drop_data_messages_filter_ = [&auth_message_send_status](eprosima::fastrtps::rtps::CDRMessage_t& msg)
+            -> bool
+            {
+                auto old_pos = msg.pos;
+
+                // Jump to writer entity id
+                msg.pos += 2 + 2 + 4;
+
+                // Read writer entity id
+                eprosima::fastrtps::rtps::GUID_t writer_guid;
+                eprosima::fastrtps::rtps::CDRMessage::readEntityId(&msg, &writer_guid.entityId);
+                msg.pos = old_pos;
+
+                if (writer_guid.entityId == eprosima::fastrtps::rtps::participant_stateless_message_writer_entity_id)
+                {
+                    auth_message_send_status.notify();
+                }
+
+                return false;
+            };
+
     // Prepare participant properties
     PropertyPolicy property_policy;
     property_policy.properties().emplace_back(Property("dds.sec.auth.plugin", "builtin.PKI-DH"));
@@ -489,6 +574,7 @@ TEST_P(Security, BuiltinAuthenticationPlugin_second_participant_creation_loop)
 
     // Create the participant being checked
     PubSubReader<HelloWorldPubSubType> main_participant("HelloWorldTopic");
+    main_participant.disable_builtin_transport().add_user_transport_to_pparams(transport);
     main_participant.property_policy(property_policy).init();
     EXPECT_TRUE(main_participant.isInitialized());
 
@@ -501,13 +587,14 @@ TEST_P(Security, BuiltinAuthenticationPlugin_second_participant_creation_loop)
 
         // Wait for undiscovery so we can wait for discovery below
         EXPECT_TRUE(main_participant.wait_participant_undiscovery());
+        auth_message_send_status.reset();
 
         // Create another participant with authentication enabled
         PubSubParticipant<HelloWorldPubSubType> other_participant(0, 0, 0, 0);
         EXPECT_TRUE(other_participant.property_policy(property_policy).init_participant());
 
-        // Wait for the new participant to be discovered by the main one
-        EXPECT_TRUE(main_participant.wait_participant_discovery());
+        // Wait for the main participant to send an authentication message to the other participant
+        auth_message_send_status.wait();
 
         // The created participant gets out of scope here, and is destroyed
     }
@@ -3668,11 +3755,14 @@ TEST(Security, AllowUnauthenticatedParticipants_TwoSecureParticipantsWithDiffere
 
     ASSERT_TRUE(writer.isInitialized());
 
-    //! Wait enough time for the PKI requests to time out and give validation_failed (~15secs)
-    writer.wait_discovery(std::chrono::seconds(20));
+    //! Wait for the authorization to fail (~15secs)
+    writer.waitUnauthorized();
+
+    //! Wait for the discovery
+    writer.wait_discovery();
 
     //! check that the writer matches the reader because of having allow_unauthenticated_participants enabled
-    ASSERT_TRUE(writer.get_matched());
+    ASSERT_TRUE(writer.is_matched());
 
     //! Data is correctly sent and received
     auto data = default_helloworld_data_generator();
@@ -3748,13 +3838,16 @@ TEST(Security, AllowUnauthenticatedParticipants_TwoParticipantsDifferentCertific
 
     ASSERT_TRUE(writer.isInitialized());
 
-    //! Wait enough time for the PKI requests to time out and give validation_failed (~15secs)
-    writer.wait_discovery(std::chrono::seconds(20));
+    //! Wait for the authorization to fail (~15secs)
+    writer.waitUnauthorized();
+
+    //! Wait some time afterwards (this will time out)
+    writer.wait_discovery(std::chrono::seconds(1));
 
     //! check that the writer does not match the reader because of
     //! having read and write protection enabled
     //! despite allow_unauthenticated_participants is enabled
-    ASSERT_FALSE(writer.get_matched());
+    ASSERT_FALSE(writer.is_matched());
 }
 
 // *INDENT-OFF*
@@ -4497,32 +4590,7 @@ TEST(Security, MaliciousHeartbeatIgnore)
                 return avoid_sec_submessages.load() && (0x30 == (msg.buffer[msg.pos] & 0xF0));
             };
 
-    struct FakeMsg
-    {
-        asio::io_service service;
-        asio::ip::udp::socket socket;
-
-        FakeMsg()
-            : service()
-            , socket(service)
-        {
-            socket.open(asio::ip::udp::v4());
-        }
-
-        void send(
-                const CDRMessage_t& msg,
-                const Locator_t& destination)
-        {
-            std::string addr = IPLocator::toIPv4string(destination);
-            unsigned short port = static_cast<unsigned short>(destination.port);
-            auto remote = asio::ip::udp::endpoint(asio::ip::address::from_string(addr), port);
-            asio::error_code ec;
-
-            socket.send_to(asio::buffer(msg.buffer, msg.length), remote, 0, ec);
-        }
-
-    };
-    FakeMsg fake_msg;
+    UDPMessageSender fake_msg_sender;
 
     writer.disable_builtin_transport().add_user_transport_to_pparams(transport);
     reader.disable_builtin_transport().add_user_transport_to_pparams(transport);
@@ -4574,7 +4642,7 @@ TEST(Security, MaliciousHeartbeatIgnore)
         msg.init(reinterpret_cast<octet*>(&hb), msg_len);
         msg.length = msg_len;
         msg.pos = msg_len;
-        fake_msg.send(msg, reader_locator);
+        fake_msg_sender.send(msg, reader_locator);
     }
 
     // Enable secure submessages
@@ -4583,6 +4651,125 @@ TEST(Security, MaliciousHeartbeatIgnore)
     reader.block_for_all();
 }
 
+TEST_P(Security, MaliciousParticipantRemovalIgnore)
+{
+    PubSubWriter<HelloWorldPubSubType> writer("HelloWorldTopic_MaliciousParticipantRemovalIgnore");
+    PubSubReader<HelloWorldPubSubType> reader("HelloWorldTopic_MaliciousParticipantRemovalIgnore");
+
+    struct MaliciousParticipantRemoval
+    {
+        std::array<char, 4> rtps_id{ {'R', 'T', 'P', 'S'} };
+        std::array<uint8_t, 2> protocol_version{ {2, 3} };
+        std::array<uint8_t, 2> vendor_id{ {0x01, 0x0F} };
+        GuidPrefix_t sender_prefix{};
+
+        struct DataSubMsg
+        {
+            struct Header
+            {
+                uint8_t submessage_id = 0x15;
+#if FASTDDS_IS_BIG_ENDIAN_TARGET
+                uint8_t flags = 0x02;
+#else
+                uint8_t flags = 0x03;
+#endif  // FASTDDS_IS_BIG_ENDIAN_TARGET
+                uint16_t submessage_length = 2 + 2 + 4 + 4 + 8;
+                uint16_t extra_flags = 0;
+                uint16_t octets_to_inline_qos = 4 + 4 + 8;
+                EntityId_t reader_id{};
+                EntityId_t writer_id{};
+                SequenceNumber_t sn{};
+            };
+
+            struct InlineQos
+            {
+                struct KeyHash
+                {
+                    uint16_t pid = 0x0070;  // PID_KEY_HASH
+                    uint16_t plen = 16;
+                    GUID_t guid{};
+                };
+
+                struct StatusInfo
+                {
+                    uint16_t pid = 0x0071;  // PID_STATUS_INFO
+                    uint16_t plen = 4;
+                    uint8_t flags[4] = { 0x00, 0x00, 0x00, 0x03 };
+                };
+
+                struct Sentinel
+                {
+                    uint16_t pid = 0x0001;  // PID_SENTINEL
+                    uint16_t plen = 0;
+                };
+
+                KeyHash hash;
+                StatusInfo status;
+                Sentinel sentinel;
+            };
+
+            Header header;
+            InlineQos inline_qos;
+        }
+        data;
+    };
+
+    // Set common QoS
+    reader.history_depth(10).reliability(eprosima::fastrtps::RELIABLE_RELIABILITY_QOS);
+    writer.history_depth(10).reliability(eprosima::fastrtps::RELIABLE_RELIABILITY_QOS);
+
+    // Configure security
+    const std::string governance_file("governance_helloworld_all_enable.smime");
+    const std::string permissions_file("permissions_helloworld.smime");
+    CommonPermissionsConfigure(reader, writer, governance_file, permissions_file);
+
+    // Initialize and wait for authorization and discovery
+    reader.init();
+    ASSERT_TRUE(reader.isInitialized());
+    writer.init();
+    ASSERT_TRUE(writer.isInitialized());
+    reader.waitAuthorized();
+    writer.waitAuthorized();
+    reader.wait_discovery();
+    writer.wait_discovery();
+
+    // Send fake DATA(p[UD])
+    UDPMessageSender fake_msg_sender;
+    {
+        auto writer_guid = writer.datawriter_guid();
+        auto participant_guid = writer.participant_guid();
+        auto domain_id = static_cast<uint32_t>(GET_PID() % 230);
+
+        MaliciousParticipantRemoval packet{};
+        packet.sender_prefix = writer_guid.guidPrefix;
+        packet.data.header.submessage_length += sizeof(packet.data.inline_qos);
+        packet.data.header.writer_id = c_EntityId_SPDPWriter;
+        packet.data.header.reader_id = c_EntityId_SPDPReader;
+        packet.data.header.sn.low = 100;
+        packet.data.inline_qos.hash.guid = participant_guid;
+
+        Locator_t mcast_locator;
+        ASSERT_TRUE(IPLocator::setIPv4(mcast_locator, "239.255.0.1"));
+        mcast_locator.port = 7400 + 250 * domain_id;
+
+        CDRMessage_t msg(0);
+        uint32_t msg_len = static_cast<uint32_t>(sizeof(packet));
+        msg.init(reinterpret_cast<octet*>(&packet), msg_len);
+        msg.length = msg_len;
+        msg.pos = msg_len;
+        fake_msg_sender.send(msg, mcast_locator);
+    }
+
+    EXPECT_FALSE(reader.wait_participant_undiscovery(std::chrono::seconds(1)));
+
+    auto data = default_helloworld_data_generator();
+    reader.startReception(data);
+    writer.send(data);
+    ASSERT_TRUE(data.empty());
+    reader.block_for_all();
+}
+
+
 void blackbox_security_init()
 {
     certs_path = std::getenv("CERTS_PATH");

programming_language: C++
filename: RTPSParticipantImpl.h
change_type: ModificationType.MODIFY
diff: @@ -329,6 +329,8 @@ public:
 
     MOCK_METHOD(bool, should_match_local_endpoints, ());
 
+    MOCK_METHOD(bool, ignore_participant, (const GuidPrefix_t&));
+
 private:
 
     MockParticipantListener listener_;

programming_language: C++
filename: PDPTests.cpp
change_type: ModificationType.MODIFY
diff: @@ -15,6 +15,7 @@
 #include <chrono>
 #include <iostream>
 #include <future>
+#include <memory>
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 #include <string>
@@ -27,6 +28,7 @@
 #include <fastdds/dds/publisher/DataWriterListener.hpp>
 #include <fastdds/rtps/builtin/BuiltinProtocols.h>
 #include <fastdds/rtps/builtin/discovery/participant/PDP.h>
+#include <fastdds/rtps/reader/ReaderListener.h>
 #include <fastrtps/rtps/builtin/data/ReaderProxyData.h>
 #include <fastrtps/rtps/builtin/data/WriterProxyData.h>
 
@@ -71,6 +73,11 @@ class TesterPDPEndpoints : public fastdds::rtps::PDPEndpoints
         return DISC_BUILTIN_ENDPOINT_PARTICIPANT_ANNOUNCER | DISC_BUILTIN_ENDPOINT_PARTICIPANT_DETECTOR;
     }
 
+    const std::unique_ptr<fastrtps::rtps::ReaderListener>& main_listener() const override
+    {
+        return no_listener_;
+    }
+
     bool enable_pdp_readers(
             fastrtps::rtps::RTPSParticipantImpl*) override
     {
@@ -101,6 +108,8 @@ class TesterPDPEndpoints : public fastdds::rtps::PDPEndpoints
 
     }
 
+    std::unique_ptr<fastrtps::rtps::ReaderListener> no_listener_;
+
 };
 
 class PDPTester : public PDP

programming_language: C++