text: // Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
  //
  // Licensed under the Apache License, Version 2.0 (the "License");
  // you may not use this file except in compliance with the License.
  // You may obtain a copy of the License at
  //
  //     http://www.apache.org/licenses/LICENSE-2.0
  //
  // Unless required by applicable law or agreed to in writing, software
  // distributed under the License is distributed on an "AS IS" BASIS,
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  // See the License for the specific language governing permissions and
  // limitations under the License.
  
  /**
   * @file BuiltinProtocols.cpp
   *
   */
  
  #include <fastdds/rtps/builtin/BuiltinProtocols.h>
  #include <fastdds/rtps/common/Locator.h>
  
  #include <fastdds/rtps/builtin/discovery/participant/PDPSimple.h>
  #include <fastdds/rtps/builtin/discovery/endpoint/EDP.h>
  #include <fastdds/rtps/builtin/discovery/endpoint/EDPStatic.h>
  
  #include <rtps/builtin/discovery/participant/PDPServer.hpp>
  #include <rtps/builtin/discovery/participant/PDPClient.h>
  
  #include <fastdds/rtps/builtin/data/ParticipantProxyData.h>
  
  #include <fastdds/rtps/builtin/liveliness/WLP.h>
  
  #include <fastdds/dds/builtin/typelookup/TypeLookupManager.hpp>
  
  #include <rtps/participant/RTPSParticipantImpl.h>
  
  #include <fastdds/dds/log/Log.hpp>
  #include <fastrtps/utils/IPFinder.h>
  
  #include <algorithm>
  
  using namespace eprosima::fastrtps;
  
  namespace eprosima {
  namespace fastrtps {
  namespace rtps {
  
  
  BuiltinProtocols::BuiltinProtocols()
      : mp_participantImpl(nullptr)
      , mp_PDP(nullptr)
      , mp_WLP(nullptr)
      , tlm_(nullptr)
  {
  }
  
  BuiltinProtocols::~BuiltinProtocols()
  {
      // Send participant is disposed
      if (mp_PDP != nullptr)
      {
          mp_PDP->announceParticipantState(true, true);
      }
  
      // TODO Auto-generated destructor stub
      delete mp_WLP;
      delete tlm_;
      delete mp_PDP;
  
  }
  
  bool BuiltinProtocols::initBuiltinProtocols(
          RTPSParticipantImpl* p_part,
          BuiltinAttributes& attributes)
  {
      mp_participantImpl = p_part;
      m_att = attributes;
      m_metatrafficUnicastLocatorList = m_att.metatrafficUnicastLocatorList;
      m_metatrafficMulticastLocatorList = m_att.metatrafficMulticastLocatorList;
      m_initialPeersList = m_att.initialPeersList;
  
      // TODO(jlbueno) The access to the list should be protected with the PDP mutex but requires a refactor on PDPClient
      // and PDPServer: read the remote servers list after the initialization of PDP.
      m_DiscoveryServers = m_att.discovery_config.m_DiscoveryServers;
  
      transform_server_remote_locators(p_part->network_factory());
  
      const RTPSParticipantAllocationAttributes& allocation = p_part->getRTPSParticipantAttributes().allocation;
  
      // PDP
      switch (m_att.discovery_config.discoveryProtocol)
      {
          case DiscoveryProtocol_t::NONE:
              logWarning(RTPS_PDP, "No participant discovery protocol specified");
              return true;
  
          case DiscoveryProtocol_t::SIMPLE:
              mp_PDP = new PDPSimple(this, allocation);
              break;
  
          case DiscoveryProtocol_t::EXTERNAL:
              logError(RTPS_PDP, "Flag only present for debugging purposes");
              return false;
  
          case DiscoveryProtocol_t::CLIENT:
              mp_PDP = new fastdds::rtps::PDPClient(this, allocation);
              break;
  
          case DiscoveryProtocol_t::SERVER:
              mp_PDP = new fastdds::rtps::PDPServer(this, allocation, DurabilityKind_t::TRANSIENT_LOCAL);
              break;
  
  #if HAVE_SQLITE3
          case DiscoveryProtocol_t::BACKUP:
              mp_PDP = new fastdds::rtps::PDPServer(this, allocation, DurabilityKind_t::TRANSIENT);
              break;
  #endif // if HAVE_SQLITE3
  
          case DiscoveryProtocol_t::SUPER_CLIENT:
              mp_PDP = new fastdds::rtps::PDPClient(this, allocation, true);
              break;
  
          default:
              logError(RTPS_PDP, "Unknown DiscoveryProtocol_t specified.");
              return false;
      }
  
      if (!mp_PDP->init(mp_participantImpl))
      {
          logError(RTPS_PDP, "Participant discovery configuration failed");
          return false;
      }
  
      // WLP
      if (m_att.use_WriterLivelinessProtocol)
      {
          mp_WLP = new WLP(this);
          mp_WLP->initWL(mp_participantImpl);
      }
  
      // TypeLookupManager
      if (m_att.typelookup_config.use_client || m_att.typelookup_config.use_server)
      {
          tlm_ = new fastdds::dds::builtin::TypeLookupManager(this);
          tlm_->init_typelookup_service(mp_participantImpl);
      }
  
      mp_PDP->announceParticipantState(true);
      mp_PDP->resetParticipantAnnouncement();
      mp_PDP->enable();
  
      return true;
  }
  
  bool BuiltinProtocols::updateMetatrafficLocators(
          LocatorList_t& loclist)
  {
      m_metatrafficUnicastLocatorList = loclist;
      return true;
  }
  
  void BuiltinProtocols::transform_server_remote_locators(
          NetworkFactory& nf)
  {
      // TODO(jlbueno) The access to the list should be protected with the PDP mutex but requires a refactor on PDPClient
      // and PDPServer: read the remote servers list after the initialization of PDP.
      for (eprosima::fastdds::rtps::RemoteServerAttributes& rs : m_DiscoveryServers)
      {
          for (Locator_t& loc : rs.metatrafficUnicastLocatorList)
          {
              Locator_t localized;
              if (nf.transform_remote_locator(loc, localized))
              {
                  loc = localized;
              }
          }
      }
  }
  
  bool BuiltinProtocols::addLocalWriter(
          RTPSWriter* w,
          const fastrtps::TopicAttributes& topicAtt,
          const fastrtps::WriterQos& wqos)
  {
      bool ok = false;
      if (mp_PDP != nullptr)
      {
          ok |= mp_PDP->getEDP()->newLocalWriterProxyData(w, topicAtt, wqos);
      }
      else
      {
          logWarning(RTPS_EDP, "EDP is not used in this Participant, register a Writer is impossible");
      }
      if (mp_WLP != nullptr)
      {
          ok |= mp_WLP->add_local_writer(w, wqos);
      }
      else
      {
          logWarning(RTPS_LIVELINESS, "LIVELINESS is not used in this Participant, register a Writer is impossible");
      }
      return ok;
  }
  
  bool BuiltinProtocols::addLocalReader(
          RTPSReader* R,
          const fastrtps::TopicAttributes& topicAtt,
          const fastrtps::ReaderQos& rqos)
  {
      bool ok = false;
      if (mp_PDP != nullptr)
      {
          ok |= mp_PDP->getEDP()->newLocalReaderProxyData(R, topicAtt, rqos);
      }
      else
      {
          logWarning(RTPS_EDP, "EDP is not used in this Participant, register a Reader is impossible");
      }
      if (mp_WLP != nullptr)
      {
          ok |= mp_WLP->add_local_reader(R, rqos);
      }
      return ok;
  }
  
  bool BuiltinProtocols::updateLocalWriter(
          RTPSWriter* W,
          const TopicAttributes& topicAtt,
          const WriterQos& wqos)
  {
      bool ok = false;
      if (mp_PDP != nullptr && mp_PDP->getEDP() != nullptr)
      {
          ok |= mp_PDP->getEDP()->updatedLocalWriter(W, topicAtt, wqos);
      }
      return ok;
  }
  
  bool BuiltinProtocols::updateLocalReader(
          RTPSReader* R,
          const TopicAttributes& topicAtt,
          const ReaderQos& rqos)
  {
      bool ok = false;
      if (mp_PDP != nullptr && mp_PDP->getEDP() != nullptr)
      {
          ok |= mp_PDP->getEDP()->updatedLocalReader(R, topicAtt, rqos);
      }
      return ok;
  }
  
  bool BuiltinProtocols::removeLocalWriter(
          RTPSWriter* W)
  {
      bool ok = false;
      if (mp_WLP != nullptr)
      {
          ok |= mp_WLP->remove_local_writer(W);
      }
      if (mp_PDP != nullptr && mp_PDP->getEDP() != nullptr)
      {
          ok |= mp_PDP->getEDP()->removeLocalWriter(W);
      }
      return ok;
  }
  
  bool BuiltinProtocols::removeLocalReader(
          RTPSReader* R)
  {
      bool ok = false;
      if (mp_WLP != nullptr)
      {
          ok |= mp_WLP->remove_local_reader(R);
      }
      if (mp_PDP != nullptr && mp_PDP->getEDP() != nullptr)
      {
          ok |= mp_PDP->getEDP()->removeLocalReader(R);
      }
      return ok;
  }
  
  void BuiltinProtocols::announceRTPSParticipantState()
  {
      assert(mp_PDP);
  
      if (mp_PDP)
      {
          mp_PDP->announceParticipantState(false);
      }
      else
      {
          logError(RTPS_EDP, "Trying to use BuiltinProtocols interfaces before initBuiltinProtocols call");
      }
  }
  
  void BuiltinProtocols::stopRTPSParticipantAnnouncement()
  {
      assert(mp_PDP);
  
      if (mp_PDP)
      {
          mp_PDP->stopParticipantAnnouncement();
      }
      else
      {
          logError(RTPS_EDP, "Trying to use BuiltinProtocols interfaces before initBuiltinProtocols call");
      }
  }
  
  void BuiltinProtocols::resetRTPSParticipantAnnouncement()
  {
      assert(mp_PDP);
  
      if (mp_PDP)
      {
          mp_PDP->resetParticipantAnnouncement();
      }
      else
      {
          logError(RTPS_EDP, "Trying to use BuiltinProtocols interfaces before initBuiltinProtocols call");
      }
  }
  
  } // namespace rtps
  } /* namespace rtps */
  } /* namespace eprosima */
  