LCOV - code coverage report
Current view: top level - modules/dds - dds_factory.cc (source / functions) Hit Total Coverage
Test: vlink Lines: 429 516 83.1 %
Date: 2026-06-27 19:56:04 Functions: 33 48 68.8 %
Branches: 463 944 49.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (C) 2026 by Thun Lu. All rights reserved.
       3                 :            :  * Author: Thun Lu <thun.lu@zohomail.cn>
       4                 :            :  * Repo:   https://github.com/thun-res/vlink
       5                 :            :  *  _    __   __      _           __
       6                 :            :  * | |  / /  / /     (_) ____    / /__
       7                 :            :  * | | / /  / /     / / / __ \  / //_/
       8                 :            :  * | |/ /  / /___  / / / / / / / ,<
       9                 :            :  * |___/  /_____/ /_/ /_/ /_/ /_/|_|
      10                 :            :  *
      11                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
      12                 :            :  * you may not use this file except in compliance with the License.
      13                 :            :  * You may obtain a copy of the License at
      14                 :            :  *
      15                 :            :  *     http://www.apache.org/licenses/LICENSE-2.0
      16                 :            :  *
      17                 :            :  * Unless required by applicable law or agreed to in writing, software
      18                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
      19                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      20                 :            :  * See the License for the specific language governing permissions and
      21                 :            :  * limitations under the License.
      22                 :            :  */
      23                 :            : 
      24                 :            : #include "./dds_factory.h"
      25                 :            : 
      26                 :            : #include <charconv>
      27                 :            : #include <memory>
      28                 :            : #include <string>
      29                 :            : #include <utility>
      30                 :            : #include <vector>
      31                 :            : 
      32                 :            : #include "./base/helpers.h"
      33                 :            : #include "./base/utils.h"
      34                 :            : #include "./dds_qos.h"
      35                 :            : #include "./extension/qos_profile.h"
      36                 :            : #include "./impl/ssl_options.h"
      37                 :            : 
      38                 :            : namespace vlink {
      39                 :            : 
      40                 :            : // DdsFactory
      41         [ +  - ]:         13 : DdsFactory::DdsFactory() {
      42                 :         13 :   Bytes::init_memory_pool();
      43                 :            : 
      44         [ -  + ]:         13 :   if VUNLIKELY (DdsConf::get_thread_count() != 1) {
      45   [ #  #  #  # ]:          0 :     VLOG_W("DdsFactory: Dds does not support setting thread count.");
      46                 :            :   }
      47                 :            : 
      48         [ +  + ]:        221 :   for (const auto& [name, qos] : QosProfile::get_available_qos_map()) {
      49         [ +  - ]:        208 :     DdsConf::register_qos_internal(name, qos);
      50                 :            :   }
      51                 :            : 
      52   [ +  -  +  - ]:         26 :   std::string dds_debug_str = Utils::get_env("VLINK_DDS_DEBUG");
      53                 :            : 
      54         [ -  + ]:         13 :   if (dds_debug_str == "1") {
      55         [ #  # ]:          0 :     dds::Log::SetVerbosity(dds::Log::Kind::Info);
      56                 :            :   } else {
      57         [ +  - ]:         13 :     dds::Log::SetVerbosity(dds::Log::Kind::Error);
      58                 :            :   }
      59                 :            : 
      60         [ +  - ]:         13 :   dds_factory_ = dds::DomainParticipantFactory::get_instance();
      61                 :            : 
      62   [ +  -  +  - ]:         26 :   std::string qos_file = Utils::get_env("VLINK_FASTDDS_QOS_FILE");
      63                 :            : 
      64         [ -  + ]:         13 :   if (!qos_file.empty()) {
      65         [ #  # ]:          0 :     dds_factory_->load_XML_profiles_file(qos_file);
      66                 :            :   }
      67                 :            : 
      68   [ +  -  +  - ]:         26 :   std::string default_event_qos_str = Utils::get_env("VLINK_DDS_EVENT_QOS");
      69   [ +  -  +  - ]:         26 :   std::string default_method_qos_str = Utils::get_env("VLINK_DDS_METHOD_QOS");
      70   [ +  -  +  - ]:         26 :   std::string default_field_qos_str = Utils::get_env("VLINK_DDS_FIELD_QOS");
      71                 :            : 
      72         [ +  - ]:         13 :   if (default_event_qos_str.empty()) {
      73                 :         13 :     default_event_qos_ = QosProfile::kEvent;
      74                 :            :   } else {
      75         [ #  # ]:          0 :     default_event_qos_ = DdsConf::find_qos(default_event_qos_str);
      76                 :            :   }
      77                 :            : 
      78         [ +  - ]:         13 :   if (default_method_qos_str.empty()) {
      79                 :         13 :     default_method_qos_ = QosProfile::kMethod;
      80                 :            :   } else {
      81         [ #  # ]:          0 :     default_method_qos_ = DdsConf::find_qos(default_method_qos_str);
      82                 :            :   }
      83                 :            : 
      84         [ +  - ]:         13 :   if (default_field_qos_str.empty()) {
      85                 :         13 :     default_field_qos_ = QosProfile::kField;
      86                 :            :   } else {
      87         [ #  # ]:          0 :     default_field_qos_ = DdsConf::find_qos(default_field_qos_str);
      88                 :            :   }
      89                 :         13 : }
      90                 :            : 
      91                 :         13 : DdsFactory::~DdsFactory() = default;
      92                 :            : 
      93                 :          5 : std::vector<std::tuple<std::string, std::string>> DdsFactory::get_discovered_topics(int32_t _domain) {
      94                 :          5 :   std::vector<std::tuple<std::string, std::string>> topics;
      95                 :            : 
      96   [ +  +  +  -  :          5 :   static auto& factory = DdsFactory::get();
             +  -  -  - ]
      97                 :            : 
      98         [ +  - ]:          5 :   auto* part = factory.dds_factory_->lookup_participant(_domain);
      99                 :            : 
     100         [ +  + ]:          5 :   if VUNLIKELY (!part) {
     101                 :          4 :     return topics;
     102                 :            :   }
     103                 :            : 
     104                 :          1 :   std::vector<dds::InstanceHandle_t> topic_handles;
     105         [ +  - ]:          1 :   part->get_discovered_topics(topic_handles);
     106                 :            : 
     107         [ +  - ]:          1 :   topics.reserve(topic_handles.size());
     108                 :            : 
     109         [ -  + ]:          1 :   for (const auto& instance : topic_handles) {
     110         [ #  # ]:          0 :     dds::builtin::TopicBuiltinTopicData topic_data;
     111         [ #  # ]:          0 :     part->get_discovered_topic_data(topic_data, instance);
     112         [ #  # ]:          0 :     topics.emplace_back(std::forward_as_tuple(std::move(topic_data.name), std::move(topic_data.type_name)));
     113                 :          0 :   }
     114                 :            : 
     115                 :          1 :   return topics;
     116                 :          1 : }
     117                 :            : 
     118                 :          2 : bool DdsFactory::load_global_qos_file(const std::string& filepath) {
     119   [ +  -  +  -  :          2 :   static auto& factory = DdsFactory::get();
             +  -  -  - ]
     120                 :            : 
     121                 :            : #ifdef VLINK_SUPPORT_DDS_V3
     122                 :            :   return factory.dds_factory_->load_XML_profiles_file(filepath) == dds::RETCODE_OK;
     123                 :            : #else
     124         [ +  - ]:          2 :   return factory.dds_factory_->load_XML_profiles_file(filepath) == ReturnCode_t::RETCODE_OK;
     125                 :            : #endif
     126                 :            : }
     127                 :            : 
     128                 :        256 : std::shared_ptr<dds::DomainParticipant> DdsFactory::create_participant(uint8_t type, const DdsConf& conf,
     129                 :            :                                                                        const Conf::PropertiesMap& properties) {
     130   [ +  +  +  -  :        256 :   static auto& factory = DdsFactory::get();
             +  -  -  - ]
     131                 :            : 
     132   [ +  -  +  - ]:        256 :   const auto& dds_qos_ext = get_qos_ext(conf.qos_ext, "part");
     133         [ +  - ]:        256 :   const auto& id = std::make_tuple(type, conf.domain, dds_qos_ext, properties);
     134                 :            : 
     135         [ +  - ]:        256 :   std::unique_lock lock(factory.mtx_);
     136                 :            : 
     137         [ +  - ]:        256 :   std::shared_ptr<dds::DomainParticipant> part = get_weak_ptr(factory.part_map_, id).lock();
     138                 :            : 
     139         [ +  + ]:        256 :   if (!part) {
     140         [ +  - ]:        124 :     lock.unlock();
     141                 :            : 
     142                 :        124 :     dds::DomainParticipant* ptr = nullptr;
     143                 :            : 
     144         [ +  + ]:        124 :     if (dds_qos_ext.empty()) {
     145         [ +  - ]:        123 :       auto dds_qos = dds::PARTICIPANT_QOS_DEFAULT;
     146                 :            : 
     147         [ +  - ]:        123 :       set_participant_qos(dds_qos, properties);
     148                 :            : 
     149         [ +  - ]:        123 :       ptr = factory.dds_factory_->create_participant(conf.domain, dds_qos, nullptr, dds::StatusMask::all());
     150                 :        123 :     } else {
     151         [ +  - ]:          1 :       ptr = factory.dds_factory_->create_participant_with_profile(conf.domain, dds_qos_ext, nullptr,
     152                 :          2 :                                                                   dds::StatusMask::all());
     153                 :            :     }
     154                 :            : 
     155         [ +  + ]:        124 :     if VUNLIKELY (!ptr) {
     156   [ +  -  +  - ]:          4 :       VLOG_E("DdsFactory: Failed to create participant.");
     157                 :          2 :       return nullptr;
     158                 :            :     }
     159                 :            : 
     160   [ +  -  +  - ]:        244 :     part = std::shared_ptr<dds::DomainParticipant>(ptr, [id](dds::DomainParticipant* part) {
     161                 :            :       {
     162         [ +  - ]:        122 :         std::lock_guard lock(factory.mtx_);
     163         [ +  - ]:        122 :         auto iter = factory.part_map_.find(id);
     164                 :            : 
     165   [ +  -  +  -  :        122 :         if (iter != factory.part_map_.end() && iter->second.expired()) {
                   +  - ]
     166         [ +  - ]:        122 :           factory.part_map_.erase(iter);
     167                 :            :         }
     168                 :        122 :       }
     169                 :            : 
     170                 :        122 :       factory.dds_factory_->delete_participant(part);
     171                 :        244 :     });
     172                 :            : 
     173         [ +  - ]:        122 :     lock.lock();
     174                 :            : 
     175         [ +  - ]:        122 :     auto [iter, inserted] = factory.part_map_.emplace(id, part);
     176                 :            : 
     177         [ -  + ]:        122 :     if (!inserted) {
     178                 :          0 :       auto inserted_part = iter->second.lock();
     179         [ #  # ]:          0 :       if VLIKELY (inserted_part) {
     180         [ #  # ]:          0 :         lock.unlock();
     181                 :          0 :         part = std::move(inserted_part);
     182                 :            :       } else {
     183                 :          0 :         iter->second = part;
     184                 :            :       }
     185                 :          0 :     }
     186                 :            :   }
     187                 :            : 
     188                 :        254 :   return part;
     189                 :        256 : }
     190                 :            : 
     191                 :        303 : std::shared_ptr<dds::Topic> DdsFactory::create_topic(uint8_t type, const DdsConf& conf, dds::DomainParticipant* part,
     192                 :            :                                                      bool is_cdr_type, std::string topic) {
     193   [ +  +  +  -  :        303 :   static auto& factory = DdsFactory::get();
             +  -  -  - ]
     194                 :            : 
     195                 :        303 :   dds::TypeSupport type_support;
     196                 :            : 
     197         [ +  + ]:        303 :   if (topic.empty()) {
     198         [ +  - ]:        209 :     topic = conf.topic;
     199                 :            :   }
     200                 :            : 
     201         [ +  - ]:        303 :   Function<void*()> type_support_callback = DdsConf::find_type_support(topic);
     202                 :            : 
     203         [ -  + ]:        303 :   if (is_cdr_type) {
     204         [ #  # ]:          0 :     if VUNLIKELY (!type_support_callback) {
     205   [ #  #  #  # ]:          0 :       VLOG_F("DdsFactory: Topic ", topic, " has no registered typesupport.");
     206                 :            :     }
     207                 :            :   } else {
     208         [ -  + ]:        303 :     if VUNLIKELY (type_support_callback) {
     209   [ #  #  #  # ]:          0 :       VLOG_F("DdsFactory: Topic ", topic, " does not support BuiltIn::Raw.");
     210                 :            :     }
     211                 :            : 
     212         [ +  - ]:        303 :     std::lock_guard raw_lock(factory.raw_typesupport_mtx_);
     213                 :            : 
     214         [ +  + ]:        303 :     if VUNLIKELY (!factory.raw_typesupport_) {
     215   [ +  -  +  -  :         12 :       factory.raw_typesupport_.reset(new BuiltInRawPubSubType);  // NOLINT(modernize-make-shared)
                   +  - ]
     216                 :            :     }
     217                 :        303 :   }
     218                 :            : 
     219   [ +  -  +  - ]:        303 :   const auto& dds_qos_ext = get_qos_ext(conf.qos_ext, "topic");
     220                 :            : 
     221         [ +  + ]:        303 :   if VUNLIKELY (!part) {
     222   [ +  -  +  - ]:          4 :     VLOG_E("DdsFactory: Cannot create topic without participant.");
     223                 :          2 :     return nullptr;
     224                 :            :   }
     225                 :            : 
     226         [ +  - ]:        301 :   const auto& id = std::make_tuple(type, conf.domain, topic, part);
     227                 :            : 
     228         [ +  - ]:        301 :   std::unique_lock lock(factory.mtx_);
     229         [ +  - ]:        301 :   std::shared_ptr<dds::Topic> dds_topic = get_weak_ptr(factory.topic_map_, id).lock();
     230                 :            : 
     231         [ +  + ]:        301 :   if (!dds_topic) {
     232         [ +  - ]:        166 :     lock.unlock();
     233                 :            : 
     234         [ -  + ]:        166 :     if (is_cdr_type) {
     235   [ #  #  #  # ]:          0 :       type_support.reset(static_cast<dds::TopicDataType*>(type_support_callback()));
     236                 :            :     } else {
     237         [ +  - ]:        166 :       std::lock_guard raw_lock(factory.raw_typesupport_mtx_);
     238                 :        166 :       type_support = factory.raw_typesupport_;
     239                 :        166 :     }
     240                 :            : 
     241         [ +  - ]:        166 :     if VLIKELY (type_support) {
     242         [ +  - ]:        166 :       part->register_type(type_support);
     243                 :            :     } else {
     244   [ #  #  #  # ]:          0 :       VLOG_F("DdsFactory: Topic ", topic, " registration failed.");
     245                 :            :     }
     246                 :            : 
     247                 :        166 :     dds::Topic* ptr = nullptr;
     248                 :            : 
     249         [ +  + ]:        166 :     if (dds_qos_ext.empty()) {
     250         [ +  - ]:        165 :       auto dds_qos = dds::TOPIC_QOS_DEFAULT;
     251                 :            : 
     252         [ +  - ]:        165 :       ptr = part->create_topic(topic, type_support.get_type_name(), dds_qos);
     253                 :        165 :     } else {
     254         [ +  - ]:          1 :       ptr = part->create_topic_with_profile(topic, type_support.get_type_name(), dds_qos_ext);
     255                 :            :     }
     256                 :            : 
     257         [ +  + ]:        166 :     if VUNLIKELY (!ptr) {
     258   [ +  -  +  - ]:          2 :       VLOG_E("DdsFactory: Failed to create topic: ", topic, ".");
     259                 :          1 :       return nullptr;
     260                 :            :     }
     261                 :            : 
     262   [ +  -  +  - ]:        330 :     dds_topic = std::shared_ptr<dds::Topic>(ptr, [id](dds::Topic* topic) {
     263                 :            :       {
     264         [ +  - ]:        165 :         std::lock_guard lock(factory.mtx_);
     265         [ +  - ]:        165 :         auto iter = factory.topic_map_.find(id);
     266                 :            : 
     267   [ +  -  +  -  :        165 :         if (iter != factory.topic_map_.end() && iter->second.expired()) {
                   +  - ]
     268         [ +  - ]:        165 :           factory.topic_map_.erase(iter);
     269                 :            :         }
     270                 :        165 :       }
     271                 :            : 
     272                 :        165 :       auto* participant = const_cast<dds::DomainParticipant*>(topic->get_participant());
     273                 :        165 :       participant->delete_topic(topic);
     274                 :        330 :     });
     275                 :            : 
     276         [ +  - ]:        165 :     lock.lock();
     277                 :            : 
     278         [ +  - ]:        165 :     auto [iter, inserted] = factory.topic_map_.emplace(id, dds_topic);
     279                 :            : 
     280         [ -  + ]:        165 :     if (!inserted) {
     281                 :          0 :       auto inserted_topic = iter->second.lock();
     282         [ #  # ]:          0 :       if VLIKELY (inserted_topic) {
     283         [ #  # ]:          0 :         lock.unlock();
     284                 :          0 :         dds_topic = std::move(inserted_topic);
     285                 :            :       } else {
     286                 :          0 :         iter->second = dds_topic;
     287                 :            :       }
     288                 :          0 :     }
     289                 :            :   } else {
     290         [ +  - ]:        135 :     type_support = part->find_type(dds_topic->get_type_name());
     291                 :            : 
     292         [ -  + ]:        135 :     if (!type_support) {
     293         [ #  # ]:          0 :       if (is_cdr_type) {
     294   [ #  #  #  # ]:          0 :         type_support.reset(static_cast<dds::TopicDataType*>(type_support_callback()));
     295                 :            :       } else {
     296         [ #  # ]:          0 :         std::lock_guard raw_lock(factory.raw_typesupport_mtx_);
     297                 :          0 :         type_support = factory.raw_typesupport_;
     298                 :          0 :       }
     299                 :            :     }
     300                 :            : 
     301         [ +  - ]:        135 :     if VLIKELY (type_support) {
     302         [ +  - ]:        135 :       part->register_type(type_support);
     303                 :            :     } else {
     304   [ #  #  #  # ]:          0 :       VLOG_F("DdsFactory: Topic ", topic, " registration failed.");
     305                 :            :     }
     306                 :            :   }
     307                 :            : 
     308                 :        300 :   return dds_topic;
     309                 :        303 : }
     310                 :            : 
     311                 :         47 : std::pair<std::shared_ptr<dds::Topic>, std::shared_ptr<dds::Topic>> DdsFactory::create_method_topic(
     312                 :            :     uint8_t type, const DdsConf& conf, dds::DomainParticipant* part, bool is_cdr_type) {
     313         [ +  - ]:         47 :   const std::string& resp_topic = conf.topic + DdsConf::kRespSuffix;
     314                 :            : 
     315   [ +  -  -  +  :         47 :   if VUNLIKELY (conf.topic.empty() || resp_topic.empty()) {
                   -  + ]
     316   [ #  #  #  # ]:          0 :     VLOG_F("DdsFactory: Method conf topic error.");
     317                 :            :   }
     318                 :            : 
     319         [ -  + ]:         47 :   if VUNLIKELY (conf.topic == resp_topic) {
     320   [ #  #  #  # ]:          0 :     VLOG_F("DdsFactory: Method conf topic req and resp cannot be equal.");
     321                 :            :   }
     322                 :            : 
     323   [ +  -  +  - ]:         94 :   return {create_topic(type, conf, part, is_cdr_type, conf.topic),
     324   [ +  -  +  - ]:         94 :           create_topic(type, conf, part, is_cdr_type, resp_topic)};
     325                 :         47 : }
     326                 :            : 
     327                 :        157 : std::shared_ptr<dds::Publisher> DdsFactory::create_publisher(uint8_t type, const DdsConf& conf,
     328                 :            :                                                              dds::DomainParticipant* part) {
     329   [ +  +  +  -  :        157 :   static auto& factory = DdsFactory::get();
             +  -  -  - ]
     330                 :            : 
     331   [ +  -  +  - ]:        157 :   const auto& dds_qos_ext = get_qos_ext(conf.qos_ext, "pub");
     332   [ +  -  +  - ]:        157 :   const auto& writer_qos = get_qos_ext(conf.qos_ext, "writer");
     333                 :            : 
     334         [ +  + ]:        157 :   if VUNLIKELY (!part) {
     335   [ +  -  +  - ]:          4 :     VLOG_E("DdsFactory: Cannot create publisher without participant.");
     336                 :          2 :     return nullptr;
     337                 :            :   }
     338                 :            : 
     339         [ +  - ]:        155 :   const auto& id = std::make_tuple(type, conf.domain, conf.qos, dds_qos_ext, writer_qos, part);
     340                 :            : 
     341         [ +  - ]:        155 :   std::unique_lock lock(factory.mtx_);
     342         [ +  - ]:        155 :   std::shared_ptr<dds::Publisher> publisher = get_weak_ptr(factory.publisher_map_, id).lock();
     343                 :            : 
     344         [ +  + ]:        155 :   if (!publisher) {
     345         [ +  - ]:        138 :     lock.unlock();
     346                 :            : 
     347                 :        138 :     dds::Publisher* ptr = nullptr;
     348                 :            : 
     349         [ +  + ]:        138 :     if (dds_qos_ext.empty()) {
     350         [ +  - ]:        137 :       auto dds_qos = dds::PUBLISHER_QOS_DEFAULT;
     351                 :            : 
     352         [ +  - ]:        137 :       ptr = part->create_publisher(dds_qos, nullptr);
     353                 :        137 :     } else {
     354         [ +  - ]:          1 :       ptr = part->create_publisher_with_profile(dds_qos_ext, nullptr);
     355                 :            :     }
     356                 :            : 
     357         [ +  + ]:        138 :     if VUNLIKELY (!ptr) {
     358   [ +  -  +  - ]:          2 :       VLOG_E("DdsFactory: Failed to create publisher.");
     359                 :          1 :       return nullptr;
     360                 :            :     }
     361                 :            : 
     362   [ +  -  +  - ]:        274 :     publisher = std::shared_ptr<dds::Publisher>(ptr, [id](dds::Publisher* publisher) {
     363                 :            :       {
     364         [ +  - ]:        137 :         std::lock_guard lock(factory.mtx_);
     365         [ +  - ]:        137 :         auto iter = factory.publisher_map_.find(id);
     366                 :            : 
     367   [ +  -  +  -  :        137 :         if (iter != factory.publisher_map_.end() && iter->second.expired()) {
                   +  - ]
     368         [ +  - ]:        137 :           factory.publisher_map_.erase(iter);
     369                 :            :         }
     370                 :        137 :       }
     371                 :        137 :       auto* participant = const_cast<dds::DomainParticipant*>(publisher->get_participant());
     372                 :        137 :       participant->delete_publisher(publisher);
     373                 :        274 :     });
     374                 :            : 
     375         [ +  - ]:        137 :     lock.lock();
     376                 :            : 
     377         [ +  - ]:        137 :     auto [iter, inserted] = factory.publisher_map_.emplace(id, publisher);
     378                 :            : 
     379         [ -  + ]:        137 :     if (!inserted) {
     380                 :          0 :       auto inserted_publisher = iter->second.lock();
     381         [ #  # ]:          0 :       if VLIKELY (inserted_publisher) {
     382         [ #  # ]:          0 :         lock.unlock();
     383                 :          0 :         publisher = std::move(inserted_publisher);
     384                 :            :       } else {
     385                 :          0 :         iter->second = publisher;
     386                 :            :       }
     387                 :          0 :     }
     388                 :            :   }
     389                 :            : 
     390                 :        154 :   return publisher;
     391                 :        157 : }
     392                 :            : 
     393                 :        146 : std::shared_ptr<dds::Subscriber> DdsFactory::create_subscriber(uint8_t type, const DdsConf& conf,
     394                 :            :                                                                dds::DomainParticipant* part) {
     395   [ +  +  +  -  :        146 :   static auto& factory = DdsFactory::get();
             +  -  -  - ]
     396                 :            : 
     397   [ +  -  +  - ]:        146 :   const auto& dds_qos_ext = get_qos_ext(conf.qos_ext, "sub");
     398   [ +  -  +  - ]:        146 :   const auto& reader_qos = get_qos_ext(conf.qos_ext, "reader");
     399                 :            : 
     400         [ -  + ]:        146 :   if VUNLIKELY (!part) {
     401   [ #  #  #  # ]:          0 :     VLOG_E("DdsFactory: Cannot create subscriber without participant.");
     402                 :          0 :     return nullptr;
     403                 :            :   }
     404                 :            : 
     405         [ +  - ]:        146 :   const auto& id = std::make_tuple(type, conf.domain, conf.qos, dds_qos_ext, reader_qos, part);
     406                 :            : 
     407         [ +  - ]:        146 :   std::unique_lock lock(factory.mtx_);
     408                 :            : 
     409         [ +  - ]:        146 :   std::shared_ptr<dds::Subscriber> subscriber = get_weak_ptr(factory.subscriber_map_, id).lock();
     410                 :            : 
     411         [ +  + ]:        146 :   if (!subscriber) {
     412         [ +  - ]:        132 :     lock.unlock();
     413                 :        132 :     dds::Subscriber* ptr = nullptr;
     414         [ +  + ]:        132 :     if (dds_qos_ext.empty()) {
     415         [ +  - ]:        131 :       auto dds_qos = dds::SUBSCRIBER_QOS_DEFAULT;
     416                 :            : 
     417         [ +  - ]:        131 :       ptr = part->create_subscriber(dds_qos, nullptr);
     418                 :        131 :     } else {
     419         [ +  - ]:          1 :       ptr = part->create_subscriber_with_profile(dds_qos_ext, nullptr);
     420                 :            :     }
     421                 :            : 
     422         [ +  + ]:        132 :     if VUNLIKELY (!ptr) {
     423   [ +  -  +  - ]:          2 :       VLOG_E("DdsFactory: Failed to create subscriber.");
     424                 :          1 :       return nullptr;
     425                 :            :     }
     426                 :            : 
     427   [ +  -  +  - ]:        262 :     subscriber = std::shared_ptr<dds::Subscriber>(ptr, [id](dds::Subscriber* subscriber) {
     428                 :            :       {
     429         [ +  - ]:        131 :         std::lock_guard lock(factory.mtx_);
     430         [ +  - ]:        131 :         auto iter = factory.subscriber_map_.find(id);
     431                 :            : 
     432   [ +  -  +  -  :        131 :         if (iter != factory.subscriber_map_.end() && iter->second.expired()) {
                   +  - ]
     433         [ +  - ]:        131 :           factory.subscriber_map_.erase(iter);
     434                 :            :         }
     435                 :        131 :       }
     436                 :        131 :       auto* participant = const_cast<dds::DomainParticipant*>(subscriber->get_participant());
     437                 :        131 :       participant->delete_subscriber(subscriber);
     438                 :        262 :     });
     439                 :            : 
     440         [ +  - ]:        131 :     lock.lock();
     441                 :            : 
     442         [ +  - ]:        131 :     auto [iter, inserted] = factory.subscriber_map_.emplace(id, subscriber);
     443                 :            : 
     444         [ -  + ]:        131 :     if (!inserted) {
     445                 :          0 :       auto inserted_subscriber = iter->second.lock();
     446         [ #  # ]:          0 :       if VLIKELY (inserted_subscriber) {
     447         [ #  # ]:          0 :         lock.unlock();
     448                 :          0 :         subscriber = std::move(inserted_subscriber);
     449                 :            :       } else {
     450                 :          0 :         iter->second = subscriber;
     451                 :            :       }
     452                 :          0 :     }
     453                 :            :   }
     454                 :            : 
     455                 :        145 :   return subscriber;
     456                 :        146 : }
     457                 :            : 
     458                 :        154 : std::shared_ptr<dds::DataWriter> DdsFactory::create_datawriter(uint8_t type, const DdsConf& conf,
     459                 :            :                                                                dds::Publisher* publisher, dds::Topic* topic,
     460                 :            :                                                                dds::DataWriterListener* listener) {
     461   [ +  +  +  -  :        154 :   static auto& factory = DdsFactory::get();
             +  -  -  - ]
     462                 :            : 
     463   [ +  -  +  - ]:        154 :   const auto& dds_qos_ext = get_qos_ext(conf.qos_ext, "writer");
     464                 :            : 
     465   [ +  +  -  +  :        154 :   if VUNLIKELY (!publisher || !topic) {
                   +  + ]
     466   [ +  -  +  - ]:          2 :     VLOG_E("DdsFactory: Cannot create datawriter without publisher/topic.");
     467                 :          1 :     return nullptr;
     468                 :            :   }
     469                 :            : 
     470                 :        153 :   dds::DataWriter* ptr = nullptr;
     471                 :            : 
     472         [ +  + ]:        153 :   if (dds_qos_ext.empty()) {
     473         [ +  - ]:        152 :     auto dds_qos = dds::DATAWRITER_QOS_DEFAULT;
     474                 :            : 
     475         [ +  + ]:        152 :     if (conf.qos.empty()) {
     476   [ +  +  -  + ]:        129 :       if ((type & kPublisher) || (type & kSubscriber)) {
     477         [ +  - ]:         54 :         convert_qos(dds_qos, factory.default_event_qos_, conf.depth);
     478   [ +  +  +  + ]:         75 :       } else if ((type & kClient) || (type & kServer)) {
     479         [ +  - ]:         53 :         convert_qos(dds_qos, factory.default_method_qos_, conf.depth);
     480   [ -  +  -  - ]:         22 :       } else if ((type & kSetter) || (type & kGetter)) {
     481         [ +  - ]:         22 :         convert_qos(dds_qos, factory.default_field_qos_, conf.depth);
     482                 :            :       }
     483                 :            :     } else {
     484   [ +  -  +  - ]:         23 :       convert_qos(dds_qos, DdsConf::find_qos(conf.qos), conf.depth);
     485                 :            :     }
     486                 :            : 
     487         [ +  - ]:        152 :     ptr = publisher->create_datawriter(topic, dds_qos, listener);
     488                 :        152 :   } else {
     489         [ +  - ]:          1 :     ptr = publisher->create_datawriter_with_profile(topic, dds_qos_ext, listener);
     490                 :            :   }
     491                 :            : 
     492         [ +  + ]:        153 :   if VUNLIKELY (!ptr) {
     493   [ +  -  +  - ]:          8 :     VLOG_E("DdsFactory: Failed to create datawriter.");
     494                 :          4 :     return nullptr;
     495                 :            :   }
     496                 :            : 
     497                 :        149 :   return std::shared_ptr<dds::DataWriter>(ptr, [](dds::DataWriter* writer) {
     498         [ +  - ]:        149 :     writer->set_listener(nullptr, dds::StatusMask::none());
     499                 :        149 :     auto* publisher = const_cast<dds::Publisher*>(writer->get_publisher());
     500                 :        149 :     publisher->delete_datawriter(writer);
     501         [ +  - ]:        298 :   });
     502                 :        154 : }
     503                 :            : 
     504                 :        135 : std::shared_ptr<dds::DataReader> DdsFactory::create_datareader(uint8_t type, const DdsConf& conf,
     505                 :            :                                                                dds::Subscriber* subscriber, dds::Topic* topic,
     506                 :            :                                                                dds::DataReaderListener* listener) {
     507   [ +  +  +  -  :        135 :   static auto& factory = DdsFactory::get();
             +  -  -  - ]
     508                 :            : 
     509   [ +  -  +  - ]:        135 :   const auto& dds_qos_ext = get_qos_ext(conf.qos_ext, "reader");
     510                 :            : 
     511   [ +  -  -  +  :        135 :   if VUNLIKELY (!subscriber || !topic) {
                   -  + ]
     512   [ #  #  #  # ]:          0 :     VLOG_E("DdsFactory: Cannot create datareader without subscriber/topic.");
     513                 :          0 :     return nullptr;
     514                 :            :   }
     515                 :            : 
     516                 :        135 :   dds::DataReader* ptr = nullptr;
     517                 :            : 
     518         [ +  - ]:        135 :   if (dds_qos_ext.empty()) {
     519         [ +  - ]:        135 :     auto dds_qos = dds::DATAREADER_QOS_DEFAULT;
     520                 :            : 
     521         [ +  + ]:        135 :     if (conf.qos.empty()) {
     522   [ +  -  +  + ]:        114 :       if ((type & kPublisher) || (type & kSubscriber)) {
     523         [ +  - ]:         41 :         convert_qos(dds_qos, factory.default_event_qos_, conf.depth);
     524   [ +  +  +  + ]:         73 :       } else if ((type & kClient) || (type & kServer)) {
     525         [ +  - ]:         51 :         convert_qos(dds_qos, factory.default_method_qos_, conf.depth);
     526   [ +  -  +  - ]:         22 :       } else if ((type & kSetter) || (type & kGetter)) {
     527         [ +  - ]:         22 :         convert_qos(dds_qos, factory.default_field_qos_, conf.depth);
     528                 :            :       }
     529                 :            :     } else {
     530   [ +  -  +  - ]:         21 :       convert_qos(dds_qos, DdsConf::find_qos(conf.qos), conf.depth);
     531                 :            :     }
     532                 :            : 
     533   [ +  -  +  - ]:        135 :     ptr = subscriber->create_datareader(topic, dds_qos, listener);
     534                 :        135 :   } else {
     535   [ #  #  #  # ]:          0 :     ptr = subscriber->create_datareader_with_profile(topic, dds_qos_ext, listener);
     536                 :            :   }
     537                 :            : 
     538         [ +  + ]:        135 :   if VUNLIKELY (!ptr) {
     539   [ +  -  +  - ]:          6 :     VLOG_E("DdsFactory: Failed to create datareader.");
     540                 :          3 :     return nullptr;
     541                 :            :   }
     542                 :            : 
     543                 :        132 :   return std::shared_ptr<dds::DataReader>(ptr, [](dds::DataReader* reader) {
     544         [ +  - ]:        132 :     reader->set_listener(nullptr, dds::StatusMask::none());
     545                 :        132 :     auto* subscriber = const_cast<dds::Subscriber*>(reader->get_subscriber());
     546                 :        132 :     subscriber->delete_datareader(reader);
     547         [ +  - ]:        264 :   });
     548                 :        135 : }
     549                 :            : 
     550                 :        193 : bool DdsFactory::write_data(dds::DataWriter* writer, const Bytes& bytes, uint64_t id) {
     551         [ -  + ]:        193 :   if VUNLIKELY (bytes.is_ptr()) {
     552   [ #  #  #  # ]:          0 :     VLOG_E("DdsFactory: write_data() type mismatch, expected raw bytes but received ptr type.");
     553                 :          0 :     return false;
     554                 :            :   }
     555                 :            : 
     556         [ +  - ]:        193 :   BuiltInRaw raw;
     557         [ +  - ]:        193 :   raw.id() = id;
     558                 :            : 
     559         [ +  - ]:        193 :   raw.data().shallow_copy(bytes);
     560                 :            : 
     561                 :            : #ifdef VLINK_SUPPORT_DDS_V3
     562                 :            :   return writer->write(&raw) == dds::RETCODE_OK;
     563                 :            : #else
     564         [ +  - ]:        193 :   return writer->write(&raw);
     565                 :            : #endif
     566                 :        193 : }
     567                 :            : 
     568                 :          0 : bool DdsFactory::write_cdr_data(dds::DataWriter* writer, const Bytes& bytes, rtps::WriteParams* params) {
     569         [ #  # ]:          0 :   if VUNLIKELY (!bytes.is_ptr()) {
     570   [ #  #  #  # ]:          0 :     VLOG_E("DdsFactory: write_cdr_data() type mismatch, expected ptr type but received raw bytes.");
     571                 :          0 :     return false;
     572                 :            :   }
     573                 :            : 
     574                 :            : #ifdef VLINK_SUPPORT_DDS_V3
     575                 :            : 
     576                 :            :   if (params) {
     577                 :            :     return writer->write(bytes.to_ptr(), *params) == dds::RETCODE_OK;
     578                 :            :   }
     579                 :            : 
     580                 :            :   return writer->write(bytes.to_ptr()) == dds::RETCODE_OK;
     581                 :            : #else
     582                 :            : 
     583         [ #  # ]:          0 :   if (params) {
     584                 :          0 :     return writer->write(bytes.to_ptr(), *params);
     585                 :            :   }
     586                 :            : 
     587                 :          0 :   return writer->write(bytes.to_ptr());
     588                 :            : #endif
     589                 :            : }
     590                 :            : 
     591                 :        380 : bool DdsFactory::take_data(dds::DataReader* reader, ReadMessage& msg) {
     592         [ +  - ]:        380 :   auto ret = reader->take_next_sample(&msg.raw, &msg.info);
     593                 :            : 
     594                 :            : #ifdef VLINK_SUPPORT_DDS_V3
     595                 :            : 
     596                 :            :   if (ret == dds::RETCODE_NO_DATA) {
     597                 :            :     return false;
     598                 :            :   }
     599                 :            : 
     600                 :            :   if VUNLIKELY (ret != dds::RETCODE_OK) {
     601                 :            :     VLOG_E("DdsFactory: Failed to take data.");
     602                 :            :     return false;
     603                 :            :   }
     604                 :            : #else
     605                 :            : 
     606         [ +  + ]:        380 :   if (ret == ReturnCode_t::RETCODE_NO_DATA) {
     607                 :        190 :     return false;
     608                 :            :   }
     609                 :            : 
     610         [ -  + ]:        190 :   if VUNLIKELY (ret != ReturnCode_t::RETCODE_OK) {
     611   [ #  #  #  # ]:          0 :     VLOG_E("DdsFactory: Failed to take data.");
     612                 :          0 :     return false;
     613                 :            :   }
     614                 :            : #endif
     615                 :            : 
     616         [ +  - ]:        190 :   msg.id = msg.raw.id();
     617                 :            : 
     618         [ +  - ]:        190 :   msg.bytes.shallow_copy(msg.raw.data());
     619                 :            : 
     620         [ +  - ]:        190 :   msg.timestamp = msg.info.source_timestamp.to_ns();
     621                 :            : 
     622                 :            :   // std::memcpy(&msg.guid, msg.info.publication_handle.value + 8, sizeof(uint64_t));
     623                 :            : 
     624                 :        190 :   return true;
     625                 :            : }
     626                 :            : 
     627                 :          0 : bool DdsFactory::take_cdr_data(dds::DataReader* reader, ReadCdrMessage& msg) {
     628         [ #  # ]:          0 :   auto ret = reader->take_next_sample(msg.sample, &msg.info);
     629                 :            : 
     630                 :            : #ifdef VLINK_SUPPORT_DDS_V3
     631                 :            : 
     632                 :            :   if (ret == dds::RETCODE_NO_DATA) {
     633                 :            :     return false;
     634                 :            :   }
     635                 :            : 
     636                 :            :   if VUNLIKELY (ret != dds::RETCODE_OK) {
     637                 :            :     VLOG_E("DdsFactory: Failed to take data.");
     638                 :            :     return false;
     639                 :            :   }
     640                 :            : #else
     641                 :            : 
     642         [ #  # ]:          0 :   if (ret == ReturnCode_t::RETCODE_NO_DATA) {
     643                 :          0 :     return false;
     644                 :            :   }
     645                 :            : 
     646         [ #  # ]:          0 :   if VUNLIKELY (ret != ReturnCode_t::RETCODE_OK) {
     647   [ #  #  #  # ]:          0 :     VLOG_E("DdsFactory: Failed to take data.");
     648                 :          0 :     return false;
     649                 :            :   }
     650                 :            : #endif
     651                 :            : 
     652                 :          0 :   msg.bytes = Bytes::shallow_copy_ptr(msg.sample);
     653                 :            : 
     654         [ #  # ]:          0 :   msg.timestamp = msg.info.source_timestamp.to_ns();
     655                 :            : 
     656                 :          0 :   return true;
     657                 :            : }
     658                 :            : 
     659                 :         27 : uint64_t DdsFactory::get_guid(const rtps::GUID_t& guid, uint32_t seq) {
     660                 :         27 :   const auto& handle = static_cast<const rtps::InstanceHandle_t&>(guid);
     661                 :            : 
     662                 :         27 :   uint64_t result = static_cast<uint64_t>(handle.value[0] + handle.value[1] + handle.value[2] + handle.value[3]) << 24 |
     663                 :         27 :                     static_cast<uint64_t>(handle.value[4] + handle.value[5] + handle.value[6] + handle.value[7]) << 16 |
     664                 :         27 :                     static_cast<uint64_t>(handle.value[8] + handle.value[9] + handle.value[10] + handle.value[11])
     665                 :         27 :                         << 8 |
     666                 :         27 :                     static_cast<uint64_t>(handle.value[12] + handle.value[13] + handle.value[14] + handle.value[15]);
     667                 :            : 
     668                 :         27 :   return result << 32 | seq;
     669                 :            : }
     670                 :            : 
     671                 :         13 : int DdsFactory::get_default_domain_id() {
     672   [ +  -  +  - ]:         13 :   const std::string& domain_str = Utils::get_env("VLINK_DDS_DOMAIN");
     673                 :         26 :   return Helpers::to_int(domain_str, 0);
     674                 :         13 : }
     675                 :            : 
     676                 :        123 : void DdsFactory::set_participant_qos(dds::DomainParticipantQos& dds_qos, const Conf::PropertiesMap& properties) {
     677   [ +  +  +  -  :        123 :   static const std::string& ip_str = Utils::get_env("VLINK_DDS_IP");
          +  -  +  -  -  
                      - ]
     678   [ +  +  +  -  :        123 :   static const std::string& ip_multicast_str = Utils::get_env("VLINK_DDS_MULTICAST_IP");
          +  -  +  -  -  
                      - ]
     679   [ +  +  +  -  :        123 :   static const std::string& peer_str = Utils::get_env("VLINK_DDS_PEER");
          +  -  +  -  -  
                      - ]
     680   [ +  +  +  -  :        123 :   static const std::string& buf_str = Utils::get_env("VLINK_DDS_BUF");
          +  -  +  -  -  
                      - ]
     681   [ +  +  +  -  :        123 :   static const std::string& mtu_str = Utils::get_env("VLINK_DDS_MTU");
          +  -  +  -  -  
                      - ]
     682                 :            : 
     683   [ +  +  +  -  :        123 :   static bool enable_udp = Helpers::to_int(Utils::get_env("VLINK_DDS_UDP"), 1) != 0;
          +  -  +  -  -  
                      - ]
     684   [ +  +  +  -  :        123 :   static bool enable_tcp = Helpers::to_int(Utils::get_env("VLINK_DDS_TCP"), 0) != 0;
          +  -  +  -  -  
                      - ]
     685   [ +  +  +  -  :        123 :   static bool enable_shm = Helpers::to_int(Utils::get_env("VLINK_DDS_SHM"), 0) != 0;
          +  -  +  -  -  
                      - ]
     686                 :            : 
     687   [ +  +  +  -  :        123 :   static bool enable_less_memory = Helpers::to_int(Utils::get_env("VLINK_DDS_LESS_MEMORY"), 0) != 0;
          +  -  +  -  -  
                      - ]
     688                 :            : 
     689   [ +  +  +  -  :        123 :   static bool enable_ip_filter = Helpers::to_int(Utils::get_env("VLINK_DDS_IP_FILTER"), 0) != 0;
          +  -  +  -  -  
                      - ]
     690                 :            : 
     691   [ +  +  +  - ]:        123 :   static std::vector<std::string> default_ip_list = Utils::get_dds_default_address(enable_ip_filter);
     692                 :            : 
     693         [ +  - ]:        123 :   std::string prop_ip_str = ip_str;
     694         [ +  - ]:        123 :   std::string prop_ip_multicast_str = ip_multicast_str;
     695         [ +  - ]:        123 :   std::string prop_peer_str = peer_str;
     696                 :        123 :   size_t prop_buf = 0;
     697                 :        123 :   size_t prop_mtu = 0;
     698                 :        123 :   bool prop_enable_udp = enable_udp;
     699                 :        123 :   bool prop_enable_tcp = enable_tcp;
     700                 :        123 :   [[maybe_unused]] bool prop_enable_shm = enable_shm;
     701                 :        123 :   [[maybe_unused]] bool prop_enable_less_memory = enable_less_memory;
     702                 :            : 
     703         [ -  + ]:        123 :   if (!buf_str.empty()) {
     704         [ #  # ]:          0 :     std::from_chars(buf_str.data(), buf_str.data() + buf_str.size(), prop_buf);
     705                 :            :   }
     706                 :            : 
     707         [ -  + ]:        123 :   if (!mtu_str.empty()) {
     708         [ #  # ]:          0 :     std::from_chars(mtu_str.data(), mtu_str.data() + mtu_str.size(), prop_mtu);
     709                 :            :   }
     710                 :            : 
     711         [ +  + ]:        179 :   for (const auto& [prop, value] : properties) {
     712         [ +  + ]:         56 :     if (!Helpers::has_startwith(prop, "dds.")) {
     713                 :         10 :       continue;
     714                 :            :     }
     715                 :            : 
     716         [ +  + ]:         46 :     if (prop == "dds.ip") {
     717         [ +  - ]:          8 :       prop_ip_str = value;
     718         [ +  + ]:         38 :     } else if (prop == "dds.multicast.ip") {
     719         [ +  - ]:          3 :       prop_ip_multicast_str = value;
     720         [ +  + ]:         35 :     } else if (prop == "dds.peer") {
     721         [ +  - ]:          3 :       prop_peer_str = value;
     722         [ +  + ]:         32 :     } else if (prop == "dds.buf") {
     723         [ +  - ]:          7 :       std::from_chars(value.data(), value.data() + value.size(), prop_buf);
     724         [ +  + ]:         25 :     } else if (prop == "dds.mtu") {
     725         [ +  - ]:          7 :       std::from_chars(value.data(), value.data() + value.size(), prop_mtu);
     726         [ +  + ]:         18 :     } else if (prop == "dds.udp") {
     727                 :          5 :       prop_enable_udp = (value == "1");
     728         [ +  + ]:         13 :     } else if (prop == "dds.tcp") {
     729                 :          6 :       prop_enable_tcp = (value == "1");
     730         [ +  + ]:          7 :     } else if (prop == "dds.shm") {
     731                 :          3 :       prop_enable_shm = (value == "1");
     732         [ +  + ]:          4 :     } else if (prop == "dds.less_memory") {
     733                 :          3 :       prop_enable_less_memory = (value == "1");
     734                 :            :     } else {
     735         [ +  - ]:          1 :       dds_qos.properties().properties().emplace_back(prop, value);
     736                 :            :     }
     737                 :            :   }
     738                 :            : 
     739                 :        123 :   dds_qos.transport().use_builtin_transports = false;
     740                 :        123 :   dds_qos.wire_protocol().ignore_non_matching_locators = true;
     741                 :        123 :   dds_qos.wire_protocol().builtin.avoid_builtin_multicast = true;
     742                 :            : 
     743                 :            :   //   dds_qos.wire_protocol().port.domainIDGain = 250;
     744                 :            :   //   dds_qos.wire_protocol().port.participantIDGain = 2;
     745                 :            :   //   dds_qos.wire_protocol().port.portBase = 7400;
     746                 :            :   //   dds_qos.wire_protocol().port.offsetd0 = 0;
     747                 :            :   //   dds_qos.wire_protocol().port.offsetd1 = 10;
     748                 :            :   //   dds_qos.wire_protocol().port.offsetd2 = 1;
     749                 :            :   //   dds_qos.wire_protocol().port.offsetd3 = 11;
     750                 :            :   // #ifdef VLINK_SUPPORT_DDS_V3
     751                 :            :   //   dds_qos.wire_protocol().builtin.discovery_config.discoveryProtocol = rtps::DiscoveryProtocol::SIMPLE;
     752                 :            :   // #else
     753                 :            :   //   dds_qos.wire_protocol().builtin.discovery_config.discoveryProtocol = rtps::DiscoveryProtocol_t::SIMPLE;
     754                 :            :   // #endif
     755                 :            :   //   dds_qos.wire_protocol().builtin.discovery_config.use_SIMPLE_EndpointDiscoveryProtocol = true;
     756                 :            :   //   dds_qos.wire_protocol().builtin.discovery_config.m_simpleEDP.use_PublicationReaderANDSubscriptionWriter = true;
     757                 :            :   //   dds_qos.wire_protocol().builtin.discovery_config.m_simpleEDP.use_PublicationWriterANDSubscriptionReader = true;
     758                 :            :   //   dds_qos.wire_protocol().builtin.discovery_config.leaseDuration = get_dds_duration(20000);
     759                 :            :   //   dds_qos.wire_protocol().builtin.discovery_config.leaseDuration_announcementperiod = get_dds_duration(3000);
     760                 :            :   //   dds_qos.wire_protocol().builtin.discovery_config.initial_announcements.count = 5;
     761                 :            :   //   dds_qos.wire_protocol().builtin.discovery_config.initial_announcements.period = get_dds_duration(100);
     762                 :            :   //   dds_qos.wire_protocol().builtin.discovery_config.ignoreParticipantFlags =
     763                 :            :   //       static_cast<rtps::ParticipantFilteringFlags>(rtps::ParticipantFilteringFlags::FILTER_SAME_PROCESS);
     764                 :            : 
     765         [ +  + ]:        123 :   if (prop_enable_less_memory) {
     766                 :          3 :     dds_qos.wire_protocol().builtin.readerHistoryMemoryPolicy = rtps::DYNAMIC_RESERVE_MEMORY_MODE;
     767                 :          3 :     dds_qos.wire_protocol().builtin.writerHistoryMemoryPolicy = rtps::DYNAMIC_RESERVE_MEMORY_MODE;
     768                 :            :     // dds_qos.allocation().participants = {2, 10, 1};
     769                 :            :     // dds_qos.allocation().readers = {2, 20, 1};
     770                 :            :     // dds_qos.allocation().writers = {2, 20, 1};
     771                 :            :     // dds_qos.wire_protocol().builtin.readerPayloadSize = 512;
     772                 :            :     // dds_qos.wire_protocol().builtin.writerPayloadSize = 512;
     773                 :            :     // dds_qos.allocation().locators.max_unicast_locators = 4;
     774                 :            :     // dds_qos.allocation().locators.max_multicast_locators = 1;
     775                 :            :     // dds_qos.allocation().data_limits.max_user_data = 256;
     776                 :            :     // dds_qos.allocation().data_limits.max_properties = 512;
     777                 :            :     // dds_qos.allocation().data_limits.max_partitions = 256;
     778                 :            :   }
     779                 :            : 
     780                 :            : #if !defined(__ANDROID__) && !defined(_WIN32)
     781                 :            : 
     782         [ -  + ]:        123 :   if (prop_enable_shm) {
     783         [ #  # ]:          0 :     auto shm_descriptor = std::make_shared<rtps2::SharedMemTransportDescriptor>();
     784         [ #  # ]:          0 :     dds_qos.transport().user_transports.emplace_back(std::move(shm_descriptor));
     785                 :          0 :   }
     786                 :            : #endif
     787                 :            : 
     788                 :            :   {
     789                 :        123 :     rtps::Locator_t pdp_locator;
     790                 :        123 :     pdp_locator.kind = LOCATOR_KIND_UDPv4;
     791   [ +  -  +  - ]:        123 :     rtps::IPLocator::setIPv4(pdp_locator, "239.255.0.1");
     792         [ +  - ]:        123 :     dds_qos.wire_protocol().builtin.metatrafficMulticastLocatorList.push_back(std::move(pdp_locator));
     793                 :            :   }
     794                 :            : 
     795                 :        123 :   std::vector<std::string> ip_str_list;
     796                 :            : 
     797         [ -  + ]:        123 :   if (prop_ip_str.empty()) {
     798         [ #  # ]:          0 :     ip_str_list = default_ip_list;
     799                 :            :   } else {
     800                 :        123 :     ip_str_list = Helpers::split_any(prop_ip_str);
     801                 :            :   }
     802                 :            : 
     803         [ +  - ]:        123 :   rtps::LocatorList_t ip_locators = get_locators(ip_str_list);
     804                 :            : 
     805         [ +  - ]:        123 :   if (!ip_locators.empty()) {
     806         [ +  - ]:        123 :     if (!prop_enable_shm) {
     807         [ +  - ]:        123 :       dds_qos.wire_protocol().default_unicast_locator_list.push_back(ip_locators);
     808                 :            :     }
     809                 :            : 
     810         [ +  - ]:        123 :     dds_qos.wire_protocol().builtin.metatrafficUnicastLocatorList.push_back(ip_locators);
     811                 :            :   }
     812                 :            : 
     813         [ +  + ]:        123 :   if (!prop_ip_multicast_str.empty()) {
     814                 :          3 :     ip_str_list = Helpers::split_any(prop_ip_multicast_str);
     815         [ +  - ]:          3 :     rtps::LocatorList_t multicast_ip_locators = get_locators(ip_str_list);
     816                 :            : 
     817         [ +  - ]:          3 :     if (!multicast_ip_locators.empty()) {
     818         [ +  - ]:          3 :       dds_qos.wire_protocol().default_multicast_locator_list.push_back(std::move(multicast_ip_locators));
     819                 :            :     }
     820                 :          3 :   }
     821                 :            : 
     822         [ +  + ]:        123 :   if (!prop_peer_str.empty()) {
     823                 :          3 :     auto peer_str_list = Helpers::split_any(prop_peer_str);
     824         [ +  - ]:          3 :     rtps::LocatorList_t peer_locators = get_locators(peer_str_list);
     825                 :            : 
     826         [ +  - ]:          3 :     if (!peer_locators.empty()) {
     827         [ -  + ]:          3 :       if (dds_qos.wire_protocol().builtin.metatrafficUnicastLocatorList.empty()) {
     828         [ #  # ]:          0 :         dds_qos.wire_protocol().builtin.metatrafficUnicastLocatorList.push_back(rtps::LocatorList_t());
     829                 :            :       }
     830                 :            : 
     831         [ +  - ]:          3 :       dds_qos.wire_protocol().builtin.initialPeersList.push_back(std::move(peer_locators));
     832                 :            :     }
     833                 :          3 :   }
     834                 :            : 
     835         [ +  + ]:        123 :   if (prop_enable_udp) {
     836         [ +  - ]:        121 :     auto udp_descriptor = std::make_shared<rtps2::UDPv4TransportDescriptor>();
     837                 :            : 
     838   [ -  +  -  -  :        121 :     if (ip_str_list.size() == 1 || !prop_ip_str.empty()) {
                   +  - ]
     839                 :            : #ifdef VLINK_SUPPORT_DDS_V3
     840                 :            :       udp_descriptor->interface_allowlist.reserve(ip_str_list.size());
     841                 :            : 
     842                 :            :       for (const auto& ip : ip_str_list) {
     843                 :            :         // rtps::NetmaskFilterKind::OFF
     844                 :            :         udp_descriptor->interface_allowlist.emplace_back(ip);
     845                 :            :       }
     846                 :            : #else
     847         [ +  - ]:        121 :       udp_descriptor->interfaceWhiteList = ip_str_list;
     848                 :            : #endif
     849                 :            :     }
     850                 :            : 
     851         [ +  + ]:        121 :     if (prop_buf > 0) {
     852                 :          6 :       udp_descriptor->sendBufferSize = static_cast<uint32_t>(prop_buf);
     853                 :          6 :       udp_descriptor->receiveBufferSize = static_cast<uint32_t>(prop_buf);
     854                 :            :     }
     855                 :            : 
     856         [ +  + ]:        121 :     if (prop_mtu > 0) {
     857                 :          6 :       udp_descriptor->maxMessageSize = static_cast<uint32_t>(prop_mtu);
     858                 :            :     }
     859                 :            : 
     860         [ +  - ]:        121 :     dds_qos.transport().user_transports.emplace_back(std::move(udp_descriptor));
     861                 :        121 :   }
     862                 :            : 
     863                 :        123 :   auto ssl_cfg = SslOptions::parse_from(properties);
     864                 :            : 
     865                 :        123 :   bool ssl_cfg_valid = ssl_cfg.is_valid();
     866                 :            : 
     867   [ +  +  +  - ]:        123 :   if (ssl_cfg_valid && !prop_enable_tcp) {
     868                 :          2 :     prop_enable_tcp = true;
     869                 :            :   }
     870                 :            : 
     871         [ +  + ]:        123 :   if (prop_enable_tcp) {
     872         [ +  - ]:          2 :     auto tcp_descriptor = std::make_shared<rtps2::TCPv4TransportDescriptor>();
     873                 :            : 
     874         [ +  + ]:          2 :     if (prop_buf > 0) {
     875                 :          1 :       tcp_descriptor->sendBufferSize = static_cast<uint32_t>(prop_buf);
     876                 :          1 :       tcp_descriptor->receiveBufferSize = static_cast<uint32_t>(prop_buf);
     877                 :            :     }
     878                 :            : 
     879                 :          2 :     tcp_descriptor->keep_alive_frequency_ms = 1000;
     880                 :          2 :     tcp_descriptor->keep_alive_timeout_ms = 3000;
     881                 :            : 
     882         [ +  - ]:          2 :     if (ssl_cfg_valid) {
     883                 :          2 :       tcp_descriptor->apply_security = true;
     884                 :            : 
     885         [ +  - ]:          2 :       if (!ssl_cfg.ca_file.empty()) {
     886         [ +  - ]:          2 :         tcp_descriptor->tls_config.verify_file = ssl_cfg.ca_file;
     887                 :            :       }
     888                 :            : 
     889         [ +  + ]:          2 :       if (!ssl_cfg.cert_file.empty()) {
     890         [ +  - ]:          1 :         tcp_descriptor->tls_config.cert_chain_file = ssl_cfg.cert_file;
     891                 :            :       }
     892                 :            : 
     893         [ +  + ]:          2 :       if (!ssl_cfg.key_file.empty()) {
     894         [ +  - ]:          1 :         tcp_descriptor->tls_config.private_key_file = ssl_cfg.key_file;
     895                 :            :       }
     896                 :            : 
     897         [ +  + ]:          2 :       if (!ssl_cfg.key_password.empty()) {
     898         [ +  - ]:          1 :         tcp_descriptor->tls_config.password = ssl_cfg.key_password;
     899                 :            :       }
     900                 :            : 
     901         [ +  + ]:          2 :       if (!ssl_cfg.server_name.empty()) {
     902         [ +  - ]:          1 :         tcp_descriptor->tls_config.server_name = ssl_cfg.server_name;
     903                 :            :       }
     904                 :            : 
     905         [ +  + ]:          2 :       if (ssl_cfg.verify_peer) {
     906                 :          1 :         tcp_descriptor->tls_config.add_verify_mode(
     907                 :            :             rtps2::TCPTransportDescriptor::TLSConfig::TLSVerifyMode::VERIFY_PEER);
     908                 :            :       } else {
     909                 :          1 :         tcp_descriptor->tls_config.add_verify_mode(
     910                 :            :             rtps2::TCPTransportDescriptor::TLSConfig::TLSVerifyMode::VERIFY_NONE);
     911                 :            :       }
     912                 :            : 
     913                 :          2 :       tcp_descriptor->tls_config.add_option(rtps2::TCPTransportDescriptor::TLSConfig::TLSOptions::DEFAULT_WORKAROUNDS);
     914                 :          2 :       tcp_descriptor->tls_config.add_option(rtps2::TCPTransportDescriptor::TLSConfig::TLSOptions::NO_SSLV2);
     915                 :          2 :       tcp_descriptor->tls_config.add_option(rtps2::TCPTransportDescriptor::TLSConfig::TLSOptions::NO_SSLV3);
     916                 :            :     }
     917                 :            : 
     918         [ +  - ]:          2 :     tcp_descriptor->add_listener_port(0);
     919                 :          2 :     rtps::Locator_t tcp_locator;
     920                 :          2 :     tcp_locator.kind = LOCATOR_KIND_TCPv4;
     921   [ +  -  +  - ]:          2 :     rtps::IPLocator::setIPv4(tcp_locator, "0.0.0.0");
     922         [ +  - ]:          2 :     rtps::IPLocator::setPhysicalPort(tcp_locator, 0);
     923         [ +  - ]:          2 :     rtps::IPLocator::setLogicalPort(tcp_locator, 0);
     924         [ +  - ]:          2 :     dds_qos.wire_protocol().builtin.metatrafficUnicastLocatorList.push_back(tcp_locator);
     925         [ +  - ]:          2 :     dds_qos.wire_protocol().default_unicast_locator_list.push_back(tcp_locator);
     926                 :          2 :     rtps::Locator_t pdp_locator;
     927                 :          2 :     pdp_locator.kind = LOCATOR_KIND_UDPv4;
     928   [ +  -  +  - ]:          2 :     rtps::IPLocator::setIPv4(pdp_locator, "239.255.0.1");
     929         [ +  - ]:          2 :     dds_qos.wire_protocol().builtin.metatrafficMulticastLocatorList.push_back(std::move(pdp_locator));
     930         [ +  - ]:          2 :     dds_qos.transport().user_transports.emplace_back(std::move(tcp_descriptor));
     931                 :          2 :   }
     932                 :        123 : }
     933                 :            : 
     934                 :        129 : rtps::LocatorList_t DdsFactory::get_locators(const std::vector<std::string>& list) {
     935                 :        129 :   rtps::LocatorList_t locator_list;
     936                 :            : 
     937         [ -  + ]:        129 :   if (list.empty()) {
     938                 :          0 :     return locator_list;
     939                 :            :   }
     940                 :            : 
     941         [ +  + ]:        258 :   for (const auto& ip : list) {
     942         [ -  + ]:        129 :     if (ip.find(':') != std::string::npos) {
     943                 :          0 :       rtps2::Locator locator;
     944                 :          0 :       locator.kind = LOCATOR_KIND_UDPv6;
     945                 :          0 :       locator.port = 0;
     946                 :            : 
     947   [ #  #  #  # ]:          0 :       if VLIKELY (rtps::IPLocator::setIPv6(locator, ip)) {
     948         [ #  # ]:          0 :         locator_list.push_back(std::move(locator));
     949                 :            :       }
     950                 :            :     } else {
     951                 :        129 :       rtps2::Locator locator;
     952                 :        129 :       locator.kind = LOCATOR_KIND_UDPv4;
     953                 :        129 :       locator.port = 0;
     954                 :            : 
     955   [ +  -  +  - ]:        129 :       if VLIKELY (rtps::IPLocator::setIPv4(locator, ip)) {
     956         [ +  - ]:        129 :         locator_list.push_back(std::move(locator));
     957                 :            :       }
     958                 :            :     }
     959                 :            :   }
     960                 :            : 
     961                 :        129 :   return locator_list;
     962                 :          0 : }
     963                 :            : 
     964                 :       1454 : std::string DdsFactory::get_qos_ext(const Conf::PropertiesMap& ext, const std::string& key) {
     965         [ +  - ]:       1454 :   auto iter = ext.find(key);
     966                 :            : 
     967         [ +  + ]:       1454 :   if (iter == ext.end()) {
     968         [ +  - ]:       1447 :     return "";
     969                 :            :   }
     970                 :            : 
     971         [ +  - ]:          7 :   return iter->second;
     972                 :            : }
     973                 :            : 
     974                 :            : }  // namespace vlink

Generated by: LCOV version 1.14