CVE-2023-50257: Improper Access Control (CWE-284)
value: 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.
CWE description: The product does not restrict or incorrectly restricts access to a resource from an unauthorized actor.
Published: 2024-02-19T20:15Z
Repository: https://github.com/eProsima/Fast-DDS
Language: C
Files changed: include/fastrtps/config.h.in, include/fastrtps/rtps/common/Token.h, include/fastrtps/rtps/messages/CDRMessage.h, include/fastrtps/rtps/messages/CDRMessage.hpp, include/fastrtps/rtps/security/common/ParticipantGenericMessage.h, src/cpp/CMakeLists.txt, src/cpp/rtps/common/Token.cpp, src/cpp/rtps/security/SecurityManager.cpp, src/cpp/rtps/security/SecurityManager.h, test/mock/rtps/RTPSParticipantImpl/rtps/participant/RTPSParticipantImpl.h, test/mock/rtps/RTPSReader/fastrtps/rtps/reader/RTPSReader.h, test/mock/rtps/RTPSWriter/fastrtps/rtps/writer/RTPSWriter.h, test/mock/rtps/ReaderHistory/fastrtps/rtps/history/ReaderHistory.h, test/mock/rtps/SecurityPluginFactory/SecurityPluginFactory.cpp, test/mock/rtps/StatelessWriter/fastrtps/rtps/writer/StatelessWriter.h, test/mock/rtps/WriterHistory/fastrtps/rtps/history/WriterHistory.h, test/unittest/rtps/security/CMakeLists.txt, test/unittest/rtps/security/SecurityAuthenticationTests.cpp
Commit date: 2016-11-16 10:19:59 +0100
Commit message: Refs #1811. WIP SecurityManager.

Diff: diff --git a/include/fastrtps/config.h.in b/include/fastrtps/config.h.in
index ab057c14..a2ab6091 100644
--- a/include/fastrtps/config.h.in
+++ b/include/fastrtps/config.h.in
@@ -61,6 +61,11 @@
 #else
 #define NON_COPYABLE_CXX11 = delete
 #endif
 #endif
 
+// Security
+#ifndef SECURITY
+#define SECURITY @HAVE_SECURITY@
+#endif
+
 #endif // _FASTRTPS_CONFIG_H_
diff --git a/include/fastrtps/rtps/common/Token.h b/include/fastrtps/rtps/common/Token.h
index 953adb0b..a59c20b5 100644
--- a/include/fastrtps/rtps/common/Token.h
+++ b/include/fastrtps/rtps/common/Token.h
@@ -130,10 +130,18 @@ class DataHolderHelper
         static const std::vector<uint8_t>* find_binary_property_value(const DataHolder& data_holder, const std::string& name);
 
         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
 } //namespace fastrtps
 } //namespace eprosima
diff --git a/include/fastrtps/rtps/messages/CDRMessage.h b/include/fastrtps/rtps/messages/CDRMessage.h
index 8b7daa02..51fbc0be 100644
--- a/include/fastrtps/rtps/messages/CDRMessage.h
+++ b/include/fastrtps/rtps/messages/CDRMessage.h
@@ -24,10 +24,14 @@
 #include "../common/CDRMessage_t.h"
 #include "../../qos/ParameterTypes.h"
 #include "../common/Property.h"
 #include "../common/BinaryProperty.h"
 
+#ifdef SECURITY
+#include "../security/common/ParticipantGenericMessage.h"
+#endif
+
 using namespace eprosima::fastrtps;
 
 namespace eprosima {
 namespace fastrtps{
 namespace rtps {
@@ -51,20 +55,30 @@ namespace CDRMessage{
 	  inline bool readEntityId(CDRMessage_t* msg,const EntityId_t*id);
 	  inline bool readData(CDRMessage_t* msg, octet* o, uint32_t length);
 	  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);
 	  inline bool readLocator(CDRMessage_t* msg,Locator_t* loc);
 	  inline bool readOctet(CDRMessage_t* msg, octet* o);
 	  inline bool readSequenceNumberSet(CDRMessage_t* msg, SequenceNumberSet_t* snset);
 	  inline bool readFragmentNumberSet(CDRMessage_t* msg, FragmentNumberSet_t* snset);
 	  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);
 	///@}
 
 
 	/**
 	 * Initialize given CDR message with default size. It frees the memory already allocated and reserves new one.
@@ -119,10 +133,14 @@ namespace CDRMessage{
       inline bool addProperty(CDRMessage_t* msg, const Property& property);
       inline bool addBinaryProperty(CDRMessage_t* msg, const BinaryProperty& binary_property);
       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);
 }
 
 }
 } /* namespace rtps */
 } /* namespace eprosima */
diff --git a/include/fastrtps/rtps/messages/CDRMessage.hpp b/include/fastrtps/rtps/messages/CDRMessage.hpp
index 2991aea8..53184cf4 100644
--- a/include/fastrtps/rtps/messages/CDRMessage.hpp
+++ b/include/fastrtps/rtps/messages/CDRMessage.hpp
@@ -119,10 +119,31 @@ inline bool CDRMessage::readUInt32(CDRMessage_t* msg,uint32_t* ulo) {
         readDataReversed(msg,dest,4);
     }
     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;
     bool valid=readInt32(msg,&sn->high);
     valid&=readUInt32(msg,&sn->low);
@@ -649,11 +670,11 @@ inline bool CDRMessage::addString(CDRMessage_t*msg, const std::string& in_str)
     return valid;
 }
 
 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;
     }
 
     CDRMessage::addUInt16(msg, PID_RELATED_SAMPLE_IDENTITY);
@@ -665,49 +686,111 @@ inline bool CDRMessage::addParameterSampleIdentity(CDRMessage_t *msg, const Samp
     return true;
 }
 
 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)
             if(it->propagate())
                 ++number_to_serialize;
@@ -724,13 +807,15 @@ inline bool CDRMessage::addBinaryPropertySeq(CDRMessage_t* msg, const BinaryProp
     return returnedValue;
 }
 
 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;
         for(auto it = binary_properties.begin(); it != binary_properties.end() &&
                 it->name().compare(property_limit) != 0; ++it)
@@ -750,10 +835,174 @@ 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 */
 
 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
diff --git a/include/fastrtps/rtps/security/common/ParticipantGenericMessage.h b/include/fastrtps/rtps/security/common/ParticipantGenericMessage.h
new file mode 100644
index 00000000..6a014e6f
--- /dev/null
+++ b/include/fastrtps/rtps/security/common/ParticipantGenericMessage.h
@@ -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_
diff --git a/src/cpp/CMakeLists.txt b/src/cpp/CMakeLists.txt
index 4ac00808..3ff0c59b 100644
--- a/src/cpp/CMakeLists.txt
+++ b/src/cpp/CMakeLists.txt
@@ -119,10 +119,14 @@ if(SECURITY)
         security/authentication/PKIHandshakeHandle.cpp
         )
 
     include_directories(${OPENSSL_INCLUDE_DIR})
     set(EXTRA_LIBRARIES ${EXTRA_LIBRARIES} ${OPENSSL_LIBRARIES})
+
+    set(HAVE_SECURITY 1)
+else()
+    set(HAVE_SECURITY 0)
 endif()
 
 # Set version
 set(${PROJECT_NAME_UPPER}_VERSION_MAJOR ${PROJECT_MAJOR_VERSION})
 set(${PROJECT_NAME_UPPER}_VERSION_MINOR ${PROJECT_MINOR_VERSION})
diff --git a/src/cpp/rtps/common/Token.cpp b/src/cpp/rtps/common/Token.cpp
index fa5d5e6a..85c9af73 100644
--- a/src/cpp/rtps/common/Token.cpp
+++ b/src/cpp/rtps/common/Token.cpp
@@ -145,5 +145,27 @@ 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;
+}
diff --git a/src/cpp/rtps/security/SecurityManager.cpp b/src/cpp/rtps/security/SecurityManager.cpp
index d112a630..9f31f5eb 100644
--- a/src/cpp/rtps/security/SecurityManager.cpp
+++ b/src/cpp/rtps/security/SecurityManager.cpp
@@ -14,10 +14,15 @@
 #include <thread>
 
 #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;
 
 using namespace eprosima::fastrtps;
 using namespace ::rtps;
@@ -27,11 +32,13 @@ bool usleep_bool()
 {
     std::this_thread::sleep_for(std::chrono::milliseconds(100));
     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),
     participant_stateless_message_reader_history_(nullptr),
     authentication_plugin_(nullptr)
@@ -40,11 +47,35 @@ 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()
 {
     SecurityException exception;
@@ -107,29 +138,40 @@ void SecurityManager::remove_discovered_participant_info(const GUID_t remote_par
         discovered_participants_.erase(dp_it);
     }
 }
 
 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;
 
     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);
+        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;
 
     // Find information
@@ -191,98 +233,208 @@ bool SecurityManager::discovered_participant(IdentityToken&& remote_identity_tok
 
         if(auth_status == AUTHENTICATION_INIT)
             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();
 
     bool returnedValue = true;
 
     // 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()
 {
     if(create_participant_stateless_message_entities())
@@ -291,10 +443,15 @@ 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())
     {
         if(create_participant_stateless_message_reader())
@@ -332,10 +489,11 @@ bool SecurityManager::create_participant_stateless_message_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);
+        auth_source_guid = participant_stateless_message_writer_->getGuid();
 
         return true;
     }
 
     logError(SECURITY,"Participant Stateless Message Writer creation failed");
@@ -346,14 +504,20 @@ 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()
 {
     HistoryAttributes hatt;
@@ -362,31 +526,180 @@ bool SecurityManager::create_participant_stateless_message_reader()
     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))
+    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);
 
         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_;
+        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);
 }
diff --git a/src/cpp/rtps/security/SecurityManager.h b/src/cpp/rtps/security/SecurityManager.h
index 9053abc9..c43492d5 100644
--- a/src/cpp/rtps/security/SecurityManager.h
+++ b/src/cpp/rtps/security/SecurityManager.h
@@ -19,10 +19,12 @@
 #define _RTPS_SECURITY_SECURITYMANAGER_H_
 
 #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>
 
 namespace eprosima {
@@ -69,11 +71,12 @@ class SecurityManager
         {
             public:
 
                 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()
                 {
                     return identity_handle_ == nullptr;
                 }
@@ -127,35 +130,77 @@ class SecurityManager
                 void set_auth_status(AuthenticationStatus auth_status)
                 {
                     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;
 
                 IdentityHandle* identity_handle_;
 
                 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();
         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);
+        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_;
         WriterHistory* participant_stateless_message_writer_history_;
         StatelessReader* participant_stateless_message_reader_;
@@ -166,10 +211,12 @@ class SecurityManager
 
         IdentityHandle* local_identity_handle_;
 
         std::map<GUID_t, DiscoveredParticipantInfo> discovered_participants_;
 
+        GUID_t auth_source_guid;
+
         std::mutex mutex_;
 };
 
 } //namespace security
 } //namespace rtps
diff --git a/test/mock/rtps/RTPSParticipantImpl/rtps/participant/RTPSParticipantImpl.h b/test/mock/rtps/RTPSParticipantImpl/rtps/participant/RTPSParticipantImpl.h
index 3442ba2f..ce323f97 100644
--- a/test/mock/rtps/RTPSParticipantImpl/rtps/participant/RTPSParticipantImpl.h
+++ b/test/mock/rtps/RTPSParticipantImpl/rtps/participant/RTPSParticipantImpl.h
@@ -19,19 +19,19 @@
 #ifndef RTPS_PARTICIPANT_RTPSPARTICIPANTIMPL_H_
 #define RTPS_PARTICIPANT_RTPSPARTICIPANTIMPL_H_
 
 #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>
 
 namespace eprosima {
 namespace fastrtps {
 namespace rtps {
 
-class RTPSWriter;
-class RTPSReader;
 class WriterHistory;
 class ReaderHistory;
 class WriterListener;
 class ReaderListener;
 class EntityId_t;
@@ -42,15 +42,36 @@ class RTPSParticipantImpl
 
         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,
+        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
 } // namespace fastrtps
 } // namespace eprosima
diff --git a/test/mock/rtps/RTPSReader/fastrtps/rtps/reader/RTPSReader.h b/test/mock/rtps/RTPSReader/fastrtps/rtps/reader/RTPSReader.h
index f9c0bb30..27dbf078 100644
--- a/test/mock/rtps/RTPSReader/fastrtps/rtps/reader/RTPSReader.h
+++ b/test/mock/rtps/RTPSReader/fastrtps/rtps/reader/RTPSReader.h
@@ -17,10 +17,15 @@
  */
 
 #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 {
 
 class RTPSReader
@@ -28,10 +33,22 @@ class RTPSReader
     public:
 
         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
 } // namespace fastrtps
 } // namespace eprosima
diff --git a/test/mock/rtps/RTPSWriter/fastrtps/rtps/writer/RTPSWriter.h b/test/mock/rtps/RTPSWriter/fastrtps/rtps/writer/RTPSWriter.h
index a0fbf553..bf513c14 100644
--- a/test/mock/rtps/RTPSWriter/fastrtps/rtps/writer/RTPSWriter.h
+++ b/test/mock/rtps/RTPSWriter/fastrtps/rtps/writer/RTPSWriter.h
@@ -17,21 +17,30 @@
  */
 
 #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:
 
         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
 } // namespace fastrtps
 } // namespace eprosima
diff --git a/test/mock/rtps/ReaderHistory/fastrtps/rtps/history/ReaderHistory.h b/test/mock/rtps/ReaderHistory/fastrtps/rtps/history/ReaderHistory.h
index 5f9e85a2..d62b97d0 100644
--- a/test/mock/rtps/ReaderHistory/fastrtps/rtps/history/ReaderHistory.h
+++ b/test/mock/rtps/ReaderHistory/fastrtps/rtps/history/ReaderHistory.h
@@ -19,19 +19,23 @@
 #ifndef _RTPS_HISTORY_READERHISTORY_H_
 #define _RTPS_HISTORY_READERHISTORY_H_
 
 #include <fastrtps/rtps/attributes/HistoryAttributes.h>
 
+#include <gmock/gmock.h>
+
 namespace eprosima {
 namespace fastrtps {
 namespace rtps {
 
 class ReaderHistory
 {
     public:
 
         ReaderHistory(const HistoryAttributes& /*att*/){}
+
+        MOCK_METHOD1(remove_change, bool(CacheChange_t*));
 };
 
 } // namespace rtps
 } // namespace fastrtps
 } // namespace eprosima
diff --git a/test/mock/rtps/SecurityPluginFactory/SecurityPluginFactory.cpp b/test/mock/rtps/SecurityPluginFactory/SecurityPluginFactory.cpp
index 60f7b707..10360d47 100644
--- a/test/mock/rtps/SecurityPluginFactory/SecurityPluginFactory.cpp
+++ b/test/mock/rtps/SecurityPluginFactory/SecurityPluginFactory.cpp
@@ -23,17 +23,23 @@ using namespace ::security;
 
 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)
 {
     auth_plugin_ = plugin;
 }
 
 void SecurityPluginFactory::release_auth_plugin()
 {
-    auth_plugin_ = nullptr;
+    if(auth_plugin_ != nullptr)
+    {
+        delete auth_plugin_;
+        auth_plugin_ = nullptr;
+    }
 }
diff --git a/test/mock/rtps/StatelessWriter/fastrtps/rtps/writer/StatelessWriter.h b/test/mock/rtps/StatelessWriter/fastrtps/rtps/writer/StatelessWriter.h
index 9ca48188..61b910ad 100644
--- a/test/mock/rtps/StatelessWriter/fastrtps/rtps/writer/StatelessWriter.h
+++ b/test/mock/rtps/StatelessWriter/fastrtps/rtps/writer/StatelessWriter.h
@@ -30,10 +30,12 @@ class StatelessWriter : public RTPSWriter
     public:
 
         MOCK_METHOD1(matched_reader_add, bool(RemoteReaderAttributes&));
 
         MOCK_METHOD1(matched_reader_remove, bool(RemoteReaderAttributes&));
+
+        MOCK_METHOD0(getGuid, const GUID_t&());
 };
 
 } // namespace rtps
 } // namespace fastrtps
 } // namespace eprosima
diff --git a/test/mock/rtps/WriterHistory/fastrtps/rtps/history/WriterHistory.h b/test/mock/rtps/WriterHistory/fastrtps/rtps/history/WriterHistory.h
index 9a7d51f4..bcf5c144 100644
--- a/test/mock/rtps/WriterHistory/fastrtps/rtps/history/WriterHistory.h
+++ b/test/mock/rtps/WriterHistory/fastrtps/rtps/history/WriterHistory.h
@@ -29,10 +29,12 @@ class WriterHistory
 {
     public:
 
 
         WriterHistory(const HistoryAttributes& /*att*/){}
+
+        MOCK_METHOD1(add_change, bool(CacheChange_t*));
 };
 
 } // namespace rtps
 } // namespace fastrtps
 } // namespace eprosima
diff --git a/test/unittest/rtps/security/CMakeLists.txt b/test/unittest/rtps/security/CMakeLists.txt
index d15192a3..daf292c9 100644
--- a/test/unittest/rtps/security/CMakeLists.txt
+++ b/test/unittest/rtps/security/CMakeLists.txt
@@ -24,14 +24,15 @@ if(NOT ((MSVC OR MSVC_IDE) AND EPROSIMA_INSTALLER))
 
         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/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}
             ${CMAKE_CURRENT_SOURCE_DIR}/SecurityAuthenticationTests.cpp)
         add_gtest(SecurityAuthentication 
diff --git a/test/unittest/rtps/security/SecurityAuthenticationTests.cpp b/test/unittest/rtps/security/SecurityAuthenticationTests.cpp
index 0deed4f8..e3eded0a 100644
--- a/test/unittest/rtps/security/SecurityAuthenticationTests.cpp
+++ b/test/unittest/rtps/security/SecurityAuthenticationTests.cpp
@@ -13,10 +13,14 @@
 // limitations under the License.
 
 #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>
 
 #include <gtest/gtest.h>
 
@@ -50,17 +54,38 @@ typedef HandleImpl<MockHandshake> MockHandshakeHandle;
 
 // Default Values
 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:
 
         virtual void SetUp()
         {
             SecurityPluginFactory::set_auth_plugin(auth_plugin_);
+            fill_participant_key(guid);
         }
 
         virtual void TearDown()
         {
             SecurityPluginFactory::release_auth_plugin();
@@ -68,29 +93,115 @@ class SecurityAuthenticationTest : public ::testing::Test
 
         void initialization_ok()
         {
             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_;
 };
 
 TEST_F(SecurityAuthenticationTest, initialization_auth_nullptr)
 {
@@ -119,65 +230,76 @@ TEST_F(SecurityAuthenticationTest, initialization_fail_participant_stateless_mes
     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).
+    EXPECT_CALL(participant_, createWriter_mock(_,_,_,_,_,_)).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);
+    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());
 }
 
 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());
 }
 
 
 TEST_F(SecurityAuthenticationTest, initialization_ok)
 {
+    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(1).
+        WillOnce(Return(ValidationResult_t::VALIDATION_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));
+    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));
 }
 
 TEST_F(SecurityAuthenticationTest, discovered_participant_validation_remote_identity_ok)
 {
@@ -186,12 +308,15 @@ TEST_F(SecurityAuthenticationTest, discovered_participant_validation_remote_iden
     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)));
+    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));
 }
 
 TEST_F(SecurityAuthenticationTest, discovered_participant_validation_remote_identity_pending_handshake_message)
 {
@@ -200,12 +325,15 @@ TEST_F(SecurityAuthenticationTest, discovered_participant_validation_remote_iden
     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)));
+    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));
 }
 
 TEST_F(SecurityAuthenticationTest, discovered_participant_validation_remote_identity_pending_handshake_request_fail)
 {
@@ -216,12 +344,15 @@ 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_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));
 }
 
 TEST_F(SecurityAuthenticationTest, discovered_participant_validation_remote_identity_pending_handshake_request_ok)
 {
@@ -229,40 +360,125 @@ TEST_F(SecurityAuthenticationTest, discovered_participant_validation_remote_iden
 
     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)));
+                    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();
 
     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_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)
 {
     initialization_ok();
@@ -270,19 +486,31 @@ TEST_F(SecurityAuthenticationTest, discovered_participant_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));
+    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)
 {
     initialization_ok();
@@ -290,24 +518,36 @@ TEST_F(SecurityAuthenticationTest, discovered_participant_validate_remote_fail_a
     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(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).
         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));
 
     ASSERT_TRUE(manager_.discovered_participant(IdentityToken(), remote_participant_key));
+
+    delete change;
 }
 
 TEST_F(SecurityAuthenticationTest, discovered_participant_begin_handshake_request_fail_and_then_ok)
 {
     initialization_ok();
@@ -315,25 +555,648 @@ TEST_F(SecurityAuthenticationTest, discovered_participant_begin_handshake_reques
     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(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)
 {
     testing::InitGoogleMock(&argc, argv);

Vulnerable code:     if(msg->pos + 28 >= msg->max_size)
        return CDRMessage::addString(msg, property.name()) &&
            CDRMessage::addString(msg, property.value());
        return CDRMessage::addString(msg, binary_property.name()) &&
            CDRMessage::addOctetVector(msg, &binary_property.value());
    if(msg->pos + 4 <  msg->max_size)
        if(CDRMessage::addUInt32(msg, (uint32_t)properties.size()))
                returnedValue = CDRMessage::addProperty(msg, *it);
    if(msg->pos + 4 <  msg->max_size)
    if(msg->pos + 4 <  msg->max_size)
SecurityManager::SecurityManager(RTPSParticipantImpl *participant) : participant_(participant),
        IdentityHandle* remote_identity_handle)
        returnedValue = on_request_not_send(remote_participant_key, remote_identity_handle);
bool SecurityManager::on_request_not_send(const GUID_t& remote_participant_key,
        IdentityHandle* remote_identity_handle)
    HandshakeHandle* handshake_handle = nullptr;
    ValidationResult_t ret = authentication_plugin_->begin_handshake_request(&handshake_handle,
        restore_remote_identity_handle(remote_participant_key, remote_identity_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_identity_handle(remote_identity_handle, exception);
        return false;
    return true;
    //mp_listener = new PDPSimpleListener(this);
    if(participant_->createReader(&rout, ratt, participant_stateless_message_reader_history_, nullptr, participant_stateless_message_reader_entity_id, true, false))
    //delete(mp_listener);
    //mp_listener = nullptr;
                    auth_status_(auth_status){}
                IdentityHandle* remote_identity_handle);
        bool on_request_not_send(const GUID_t& remote_participant_key, IdentityHandle* remote_identity_handle);
class RTPSWriter;
class RTPSReader;
        MOCK_METHOD6(createWriter, bool (RTPSWriter** Writer, WriterAttributes& param, WriterHistory* hist,WriterListener* listen,
        MOCK_METHOD7(createReader, bool (RTPSReader** Reader, ReaderAttributes& param, ReaderHistory* hist,ReaderListener* listen,
    return auth_plugin_;
    auth_plugin_ = nullptr;
            ${PROJECT_SOURCE_DIR}/test/mock/rtps/SecurityPluginFactory/SecurityPluginFactory.cpp
            ${PROJECT_SOURCE_DIR}/src/cpp/rtps/security/SecurityManager.cpp
            EXPECT_CALL(participant_, createWriter(_,_,_,_,_,_)).Times(1).
                WillOnce(Return(true));
            EXPECT_CALL(participant_, createReader(_,_,_,_,_,_,_)).Times(1).
                WillOnce(Return(true));
        SecurityAuthenticationTest() : auth_plugin_(new MockAuthenticationPlugin()), manager_(&participant_) {}
    EXPECT_CALL(participant_, createWriter(_,_,_,_,_,_)).Times(1).
    EXPECT_CALL(participant_, createWriter(_,_,_,_,_,_)).Times(1).
        WillOnce(Return(true));
    EXPECT_CALL(participant_, createReader(_,_,_,_,_,_,_)).Times(1).
    EXPECT_CALL(participant_, createWriter(_,_,_,_,_,_)).Times(1).
        WillOnce(Return(true));
    EXPECT_CALL(participant_, createReader(_,_,_,_,_,_,_)).Times(1).
        WillOnce(Return(true));
    HandshakeMessageToken* p_handshake_message = new HandshakeMessageToken();
                    SetArgPointee<1>(p_handshake_message), Return(ValidationResult_t::VALIDATION_OK)));
Fixed code: // Security
#ifndef SECURITY
#define SECURITY @HAVE_SECURITY@
#endif


        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);}
#ifdef SECURITY
#include "../security/common/ParticipantGenericMessage.h"
#endif

	  inline bool readInt64(CDRMessage_t* msg, int64_t* lolo);

      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);
      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);
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;
}

    if(msg->pos + 28 > msg->max_size)
    assert(msg);

        if(!CDRMessage::addString(msg, property.name()))
            return false;
        if(!CDRMessage::addString(msg, property.value()))
            return false;
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;
}

    assert(msg);

    {
        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;
    assert(msg);

    if(msg->pos + 4 <=  msg->max_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;
                if(it->propagate())
                    returnedValue = CDRMessage::addProperty(msg, *it);
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;

}

    assert(msg);

    if(msg->pos + 4 <=  msg->max_size)
    assert(msg);

    if(msg->pos + 4 <=  msg->max_size)
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;
}

// 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_

    set(HAVE_SECURITY 1)
else()
    set(HAVE_SECURITY 0)

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;
}
#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.

SecurityManager::SecurityManager(RTPSParticipantImpl *participant) : 
    participant_stateless_message_listener_(*this),
    participant_(participant),
    {
        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();

    }
        IdentityHandle* remote_identity_handle,
        HandshakeHandle* handshake_handle)
        assert(dp_it->second.is_handshake_handle_null());
        dp_it->second.set_handshake_handle(handshake_handle);
    {

        if(handshake_handle)
            authentication_plugin_->return_handshake_handle(handshake_handle, exception);
    }
    if(authentication_plugin_ == nullptr)
        return true;

    int64_t last_sequence_number = 0;

        last_sequence_number = dp_it->second.get_last_sequence_number();

        returnedValue = on_process_handshake(remote_participant_key, AUTHENTICATION_REQUEST_NOT_SEND,
                MessageIdentity(), HandshakeMessageToken(),
                remote_identity_handle, nullptr, last_sequence_number);
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)
    ValidationResult_t ret = VALIDATION_FAILED;
    
    if(pre_auth_status == AUTHENTICATION_REQUEST_NOT_SEND)
    {
        ret = authentication_plugin_->begin_handshake_request(&handshake_handle,
    }
    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);
    }
        restore_remote_identity_handle(remote_participant_key, remote_identity_handle, handshake_handle);
    bool handshake_message_send = true;
    if(ret == VALIDATION_PENDING_HANDSHAKE_MESSAGE ||
            ret == VALIDATION_OK_WITH_FINAL_MESSAGE)
        handshake_message_send = false;
        assert(handshake_message);
        // Send hanshake message
        // 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)
        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;
        };

    if(handshake_handle != nullptr && (pre_auth_status == AUTHENTICATION_REQUEST_NOT_SEND ||
                pre_auth_status == AUTHENTICATION_WAITING_REQUEST))
        handshake_handle = nullptr;
    if(remote_identity_handle != nullptr)
        restore_remote_identity_handle(remote_participant_key, remote_identity_handle, handshake_handle);
    delete handshake_message;

    return returnedValue;
void SecurityManager::delete_entities()
{
    delete_participant_stateless_message_entities();
}

        auth_source_guid = participant_stateless_message_writer_->getGuid();
    {
        participant_stateless_message_writer_ = nullptr;
    }
    {
        participant_stateless_message_writer_history_ = nullptr;
    }
    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_ = nullptr;
    }
    {
        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);
#include <fastrtps/rtps/security/common/ParticipantGenericMessage.h>
#include <fastrtps/rtps/reader/ReaderListener.h>
                    auth_status_(auth_status), last_sequence_number_(1)
                {}
                void set_last_sequence_number(int64_t sequence_number)
                {
                    last_sequence_number_ = sequence_number;
                }

                int64_t get_last_sequence_number()
                {
                    return last_sequence_number_;
                }


                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_;

                IdentityHandle* remote_identity_handle,
                HandshakeHandle* handshake_handle = nullptr);
        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);
        GUID_t auth_source_guid;

#include <fastrtps/rtps/writer/RTPSWriter.h>
#include <fastrtps/rtps/reader/RTPSReader.h>
        MOCK_METHOD6(createWriter_mock, bool (RTPSWriter** writer, WriterAttributes& param, WriterHistory* hist,WriterListener* listen,
        MOCK_METHOD7(createReader_mock, bool (RTPSReader** reader, ReaderAttributes& param, ReaderHistory* hist,ReaderListener* listen,

        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;
        }
#include <fastrtps/rtps/history/ReaderHistory.h>
#include <fastrtps/rtps/reader/ReaderListener.h>

#include <gmock/gmock.h>


        MOCK_METHOD0(getHistory_mock, ReaderHistory*());

        ReaderHistory* getHistory()
        {
            getHistory_mock();
            return history_;
        }

        ReaderHistory* history_;

        ReaderListener* listener_;
#include <gmock/gmock.h>

class WriterHistory;


        MOCK_METHOD3(new_change, CacheChange_t*(const std::function<uint32_t()>&,
            ChangeKind_t, InstanceHandle_t));

        WriterHistory* history_;
#include <gmock/gmock.h>


        MOCK_METHOD1(remove_change, bool(CacheChange_t*));
    Authentication* ret =  auth_plugin_;
    auth_plugin_ = nullptr;
    return ret;
    if(auth_plugin_ != nullptr)
    {
        delete auth_plugin_;
        auth_plugin_ = nullptr;
    }

        MOCK_METHOD0(getGuid, const GUID_t&());

        MOCK_METHOD1(add_change, bool(CacheChange_t*));
            ${PROJECT_SOURCE_DIR}/src/cpp/rtps/common/Token.cpp
            ${PROJECT_SOURCE_DIR}/src/cpp/rtps/security/SecurityManager.cpp
            ${PROJECT_SOURCE_DIR}/test/mock/rtps/SecurityPluginFactory/SecurityPluginFactory.cpp
#include <fastrtps/rtps/writer/StatelessWriter.h>
#include <fastrtps/rtps/history/WriterHistory.h>
#include <fastrtps/rtps/reader/StatelessReader.h>
#include <fastrtps/rtps/history/ReaderHistory.h>
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;
}

            fill_participant_key(guid);
            stateless_writer_ = new NiceMock<StatelessWriter>();
            stateless_reader_ = new NiceMock<StatelessReader>();
            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)));
        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;
        }
        SecurityAuthenticationTest() : auth_plugin_(new MockAuthenticationPlugin()),
        stateless_writer_(nullptr), stateless_reader_(nullptr), manager_(&participant_) {}

        ~SecurityAuthenticationTest()
        {
        }

        NiceMock<StatelessWriter>* stateless_writer_;
        NiceMock<StatelessReader>* stateless_reader_;
    EXPECT_CALL(participant_, createWriter_mock(_,_,_,_,_,_)).Times(1).
    NiceMock<StatelessWriter>* stateless_writer = new NiceMock<StatelessWriter>();
    EXPECT_CALL(participant_, createWriter_mock(_,_,_,_,_,_)).Times(1).
        WillOnce(DoAll(SetArgPointee<0>(stateless_writer), Return(true)));
    EXPECT_CALL(participant_, createReader_mock(_,_,_,_,_,_,_)).Times(1).
    NiceMock<StatelessWriter>* stateless_writer = new NiceMock<StatelessWriter>();
    NiceMock<StatelessReader>* stateless_reader = new NiceMock<StatelessReader>();
    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));
    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(1).
        WillOnce(Return(ValidationResult_t::VALIDATION_OK));

    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(1).
        WillOnce(Return(ValidationResult_t::VALIDATION_OK));
    fill_participant_key(remote_participant_key);
    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
    fill_participant_key(remote_participant_key);
    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
    fill_participant_key(remote_participant_key);
    EXPECT_CALL(*auth_plugin_, return_identity_handle(_,_)).Times(2).
        WillRepeatedly(Return(ValidationResult_t::VALIDATION_OK));
    fill_participant_key(remote_participant_key);
                    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));
    fill_participant_key(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();
}

    CacheChange_t* change = new CacheChange_t(200);
    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));
    fill_participant_key(remote_participant_key);

    delete change;
    CacheChange_t* change = new CacheChange_t(200);
    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));
    fill_participant_key(remote_participant_key);

    delete change;
    CacheChange_t* change = new CacheChange_t(200);
    fill_participant_key(remote_participant_key);
    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));

    delete change;
    CacheChange_t* change = new CacheChange_t(200);
    fill_participant_key(remote_participant_key);
    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);

    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);