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
|