Coverage Report

Created: 2026-10-28 07:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/Fast-DDS/src/cpp/rtps/builtin/liveliness/WLP.cpp
Line
Count
Source
1
// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
/**
16
 * @file WLP.cpp
17
 *
18
 */
19
20
#include <rtps/builtin/liveliness/WLP.hpp>
21
22
#include <limits>
23
#include <mutex>
24
25
#include <fastdds/dds/log/Log.hpp>
26
#include <fastdds/rtps/builtin/data/BuiltinEndpoints.hpp>
27
#include <fastdds/rtps/history/ReaderHistory.hpp>
28
#include <fastdds/rtps/history/WriterHistory.hpp>
29
#include <fastdds/rtps/writer/WriterListener.hpp>
30
31
#include <rtps/builtin/BuiltinProtocols.h>
32
#include <rtps/builtin/data/ParticipantProxyData.hpp>
33
#include <rtps/builtin/data/WriterProxyData.hpp>
34
#include <rtps/builtin/discovery/participant/PDPSimple.h>
35
#include <rtps/builtin/liveliness/WLPListener.h>
36
#include <rtps/history/TopicPayloadPoolRegistry.hpp>
37
#include <rtps/participant/RTPSParticipantImpl.hpp>
38
#include <rtps/reader/BaseReader.hpp>
39
#include <rtps/reader/StatefulReader.hpp>
40
#include <rtps/resources/ResourceEvent.h>
41
#include <rtps/resources/TimedEvent.h>
42
#include <rtps/writer/BaseWriter.hpp>
43
#include <rtps/writer/LivelinessManager.hpp>
44
#include <rtps/writer/StatefulWriter.hpp>
45
#include <utils/TimeConversion.hpp>
46
47
namespace eprosima {
48
namespace fastdds {
49
namespace rtps {
50
51
using BaseReader = fastdds::rtps::BaseReader;
52
53
static void set_builtin_reader_history_attributes(
54
        HistoryAttributes& hatt,
55
        const ResourceLimitedContainerConfig& allocation,
56
        bool is_secure)
57
0
{
58
0
    constexpr uint32_t c_upper_limit = (std::numeric_limits<uint32_t>::max)() / 2u;
59
60
0
    hatt.payloadMaxSize = is_secure ? 128 : 28;
61
62
0
    if ((allocation.maximum < c_upper_limit) &&
63
0
            (allocation.initial < c_upper_limit))
64
0
    {
65
0
        hatt.initialReservedCaches = static_cast<uint32_t>(allocation.initial) * 2;
66
0
        hatt.maximumReservedCaches = static_cast<uint32_t>(allocation.maximum) * 2;
67
0
    }
68
0
    else
69
0
    {
70
0
        hatt.initialReservedCaches = static_cast<uint32_t>(allocation.initial) * 2;
71
0
        hatt.maximumReservedCaches = 0;
72
0
    }
73
0
}
74
75
static void set_builtin_writer_history_attributes(
76
        HistoryAttributes& hatt,
77
        bool is_secure)
78
0
{
79
0
    hatt.payloadMaxSize = is_secure ? 128 : 28;
80
0
    hatt.initialReservedCaches = 2;
81
0
    hatt.maximumReservedCaches = 2;
82
0
}
83
84
WLP::WLP(
85
        BuiltinProtocols* p)
86
0
    : min_automatic_ms_(std::numeric_limits<double>::max())
87
0
    , min_manual_by_participant_ms_(std::numeric_limits<double>::max())
88
0
    , mp_participant(nullptr)
89
0
    , mp_builtinProtocols(p)
90
0
    , mp_builtinWriter(nullptr)
91
0
    , mp_builtinReader(nullptr)
92
0
    , mp_builtinWriterHistory(nullptr)
93
0
    , mp_builtinReaderHistory(nullptr)
94
0
    , mp_listener(nullptr)
95
0
    , automatic_liveliness_assertion_(nullptr)
96
0
    , manual_liveliness_assertion_(nullptr)
97
0
    , automatic_writers_()
98
0
    , manual_by_participant_writers_()
99
0
    , manual_by_topic_writers_()
100
0
    , readers_()
101
0
    , automatic_readers_(false)
102
0
    , pub_liveliness_manager_(nullptr)
103
0
    , sub_liveliness_manager_(nullptr)
104
#if HAVE_SECURITY
105
    , mp_builtinWriterSecure(nullptr)
106
    , mp_builtinReaderSecure(nullptr)
107
    , mp_builtinWriterSecureHistory(nullptr)
108
    , mp_builtinReaderSecureHistory(nullptr)
109
#endif // if HAVE_SECURITY
110
0
    , temp_reader_proxy_data_(
111
0
        p->mp_participantImpl->get_const_attributes().allocation.locators.max_unicast_locators,
112
0
        p->mp_participantImpl->get_const_attributes().allocation.locators.max_multicast_locators,
113
0
        p->mp_participantImpl->get_const_attributes().allocation.data_limits,
114
0
        p->mp_participantImpl->get_const_attributes().allocation.content_filter)
115
0
    , temp_writer_proxy_data_(
116
0
        p->mp_participantImpl->get_const_attributes().allocation.locators.max_unicast_locators,
117
0
        p->mp_participantImpl->get_const_attributes().allocation.locators.max_multicast_locators,
118
0
        p->mp_participantImpl->get_const_attributes().allocation.data_limits)
119
0
{
120
0
    GUID_t tmp_guid = p->mp_participantImpl->getGuid();
121
0
    tmp_guid.entityId = 0;
122
0
    automatic_instance_handle_ = tmp_guid;
123
0
    manual_by_participant_instance_handle_ = automatic_instance_handle_;
124
125
0
    automatic_instance_handle_.value[15] = dds::AUTOMATIC_LIVELINESS_QOS + 0x01;
126
0
    manual_by_participant_instance_handle_.value[15] = dds::MANUAL_BY_PARTICIPANT_LIVELINESS_QOS + 0x01;
127
0
}
128
129
WLP::~WLP()
130
0
{
131
0
    if (automatic_liveliness_assertion_ != nullptr)
132
0
    {
133
0
        delete automatic_liveliness_assertion_;
134
0
        automatic_liveliness_assertion_ = nullptr;
135
0
    }
136
0
    if (manual_liveliness_assertion_ != nullptr)
137
0
    {
138
0
        delete this->manual_liveliness_assertion_;
139
0
        manual_liveliness_assertion_ = nullptr;
140
0
    }
141
142
#if HAVE_SECURITY
143
    if (mp_participant->is_secure())
144
    {
145
        mp_participant->deleteUserEndpoint(mp_builtinReaderSecure->getGuid());
146
        mp_participant->deleteUserEndpoint(mp_builtinWriterSecure->getGuid());
147
148
        if (mp_builtinReaderSecureHistory)
149
        {
150
            PoolConfig sreader_pool_cfg = PoolConfig::from_history_attributes(mp_builtinReaderSecureHistory->m_att);
151
            delete mp_builtinReaderSecureHistory;
152
            secure_payload_pool_->release_history(sreader_pool_cfg, true);
153
        }
154
155
        if (mp_builtinWriterSecureHistory)
156
        {
157
            PoolConfig swriter_pool_cfg = PoolConfig::from_history_attributes(mp_builtinWriterSecureHistory->m_att);
158
            delete mp_builtinWriterSecureHistory;
159
            secure_payload_pool_->release_history(swriter_pool_cfg, false);
160
        }
161
    }
162
#endif // if HAVE_SECURITY
163
164
0
    mp_participant->deleteUserEndpoint(mp_builtinReader->getGuid());
165
0
    mp_participant->deleteUserEndpoint(mp_builtinWriter->getGuid());
166
167
0
    if (mp_builtinReaderHistory)
168
0
    {
169
0
        PoolConfig reader_pool_cfg = PoolConfig::from_history_attributes(mp_builtinReaderHistory->m_att);
170
0
        delete mp_builtinReaderHistory;
171
0
        payload_pool_->release_history(reader_pool_cfg, true);
172
0
    }
173
174
0
    if (mp_builtinWriterHistory)
175
0
    {
176
0
        PoolConfig writer_pool_cfg = PoolConfig::from_history_attributes(mp_builtinWriterHistory->m_att);
177
0
        delete mp_builtinWriterHistory;
178
0
        payload_pool_->release_history(writer_pool_cfg, false);
179
0
    }
180
181
0
    delete mp_listener;
182
183
0
    delete pub_liveliness_manager_;
184
0
    delete sub_liveliness_manager_;
185
0
}
186
187
bool WLP::initWL(
188
        RTPSParticipantImpl* p)
189
0
{
190
0
    EPROSIMA_LOG_INFO(RTPS_LIVELINESS, "Initializing Liveliness Protocol");
191
192
0
    mp_participant = p;
193
194
0
    pub_liveliness_manager_ = new LivelinessManager(
195
0
        [&](const GUID_t& guid,
196
0
        const dds::LivelinessQosPolicyKind& kind,
197
0
        const dds::Duration_t& lease_duration,
198
0
        int alive_count,
199
0
        int not_alive_count) -> void
200
0
        {
201
0
            pub_liveliness_changed(
202
0
                guid,
203
0
                kind,
204
0
                lease_duration,
205
0
                alive_count,
206
0
                not_alive_count);
207
0
        },
208
0
        mp_participant->getEventResource(),
209
0
        false);
210
211
0
    sub_liveliness_manager_ = new LivelinessManager(
212
0
        [&](const GUID_t& guid,
213
0
        const dds::LivelinessQosPolicyKind& kind,
214
0
        const dds::Duration_t& lease_duration,
215
0
        int alive_count,
216
0
        int not_alive_count) -> void
217
0
        {
218
0
            sub_liveliness_changed(
219
0
                guid,
220
0
                kind,
221
0
                lease_duration,
222
0
                alive_count,
223
0
                not_alive_count);
224
0
        },
225
0
        mp_participant->getEventResource());
226
227
0
    bool retVal = createEndpoints();
228
#if HAVE_SECURITY
229
    if (retVal && p->is_secure())
230
    {
231
        retVal = createSecureEndpoints();
232
    }
233
#endif // if HAVE_SECURITY
234
0
    return retVal;
235
0
}
236
237
bool WLP::createEndpoints()
238
0
{
239
0
    const ResourceLimitedContainerConfig& participants_allocation =
240
0
            mp_participant->get_const_attributes().allocation.participants;
241
242
    // Built-in writer history
243
0
    HistoryAttributes hatt;
244
0
    set_builtin_writer_history_attributes(hatt, false);
245
0
    PoolConfig writer_pool_cfg = PoolConfig::from_history_attributes(hatt);
246
0
    payload_pool_ = TopicPayloadPoolRegistry::get("DCPSParticipantMessage", writer_pool_cfg);
247
0
    payload_pool_->reserve_history(writer_pool_cfg, false);
248
0
    mp_builtinWriterHistory = new WriterHistory(hatt, payload_pool_);
249
250
    // Built-in writer
251
0
    WriterAttributes watt = mp_participant->pdp()->create_builtin_writer_attributes();
252
0
    watt.endpoint.remoteLocatorList = mp_builtinProtocols->m_initialPeersList;
253
254
0
    RTPSWriter* wout;
255
0
    if (mp_participant->createWriter(
256
0
                &wout,
257
0
                watt,
258
0
                mp_builtinWriterHistory,
259
0
                nullptr,
260
0
                c_EntityId_WriterLiveliness,
261
0
                true))
262
0
    {
263
0
        mp_builtinWriter = dynamic_cast<StatefulWriter*>(wout);
264
0
        EPROSIMA_LOG_INFO(RTPS_LIVELINESS, "Builtin Liveliness Writer created");
265
0
    }
266
0
    else
267
0
    {
268
0
        EPROSIMA_LOG_ERROR(RTPS_LIVELINESS, "Liveliness Writer Creation failed ");
269
0
        delete(mp_builtinWriterHistory);
270
0
        mp_builtinWriterHistory = nullptr;
271
0
        payload_pool_->release_history(writer_pool_cfg, false);
272
0
        return false;
273
0
    }
274
275
    // Built-in reader history
276
0
    set_builtin_reader_history_attributes(hatt, participants_allocation, false);
277
0
    mp_builtinReaderHistory = new ReaderHistory(hatt);
278
279
0
    PoolConfig reader_pool_cfg = PoolConfig::from_history_attributes(hatt);
280
0
    payload_pool_->reserve_history(reader_pool_cfg, true);
281
282
    // WLP listener
283
284
0
    mp_listener = new WLPListener(this);
285
286
    // Built-in reader
287
288
0
    ReaderAttributes ratt = mp_participant->pdp()->create_builtin_reader_attributes();
289
0
    ratt.endpoint.remoteLocatorList = mp_builtinProtocols->m_initialPeersList;
290
0
    ratt.expects_inline_qos = true;
291
292
0
    RTPSReader* rout;
293
0
    if (mp_participant->createReader(
294
0
                &rout,
295
0
                ratt,
296
0
                payload_pool_,
297
0
                mp_builtinReaderHistory,
298
0
                (ReaderListener*)mp_listener,
299
0
                c_EntityId_ReaderLiveliness,
300
0
                true))
301
0
    {
302
0
        mp_builtinReader = dynamic_cast<StatefulReader*>(rout);
303
0
        EPROSIMA_LOG_INFO(RTPS_LIVELINESS, "Builtin Liveliness Reader created");
304
0
    }
305
0
    else
306
0
    {
307
0
        EPROSIMA_LOG_ERROR(RTPS_LIVELINESS, "Liveliness Reader Creation failed.");
308
0
        delete(mp_builtinReaderHistory);
309
0
        mp_builtinReaderHistory = nullptr;
310
0
        delete(mp_listener);
311
0
        mp_listener = nullptr;
312
0
        payload_pool_->release_history(reader_pool_cfg, true);
313
0
        return false;
314
0
    }
315
316
0
    return true;
317
0
}
318
319
#if HAVE_SECURITY
320
321
bool WLP::createSecureEndpoints()
322
{
323
    const ResourceLimitedContainerConfig& participants_allocation =
324
            mp_participant->get_const_attributes().allocation.participants;
325
326
    //CREATE WRITER
327
    HistoryAttributes hatt;
328
    set_builtin_writer_history_attributes(hatt, true);
329
    PoolConfig writer_pool_cfg = PoolConfig::from_history_attributes(hatt);
330
    secure_payload_pool_ = TopicPayloadPoolRegistry::get("DCPSParticipantMessageSecure", writer_pool_cfg);
331
    secure_payload_pool_->reserve_history(writer_pool_cfg, false);
332
    mp_builtinWriterSecureHistory = new WriterHistory(hatt, secure_payload_pool_);
333
334
    WriterAttributes watt = mp_participant->pdp()->create_builtin_writer_attributes();
335
    //  Wparam.topic.topicName = "DCPSParticipantMessageSecure";
336
    //  Wparam.topic.topicDataType = "RTPSParticipantMessageData";
337
338
    const security::ParticipantSecurityAttributes& part_attrs = mp_participant->security_attributes();
339
    security::PluginParticipantSecurityAttributes plugin_attrs(part_attrs.plugin_participant_attributes);
340
    security::EndpointSecurityAttributes* sec_attrs = &watt.endpoint.security_attributes();
341
    sec_attrs->is_submessage_protected = part_attrs.is_liveliness_protected;
342
    if (part_attrs.is_liveliness_protected)
343
    {
344
        sec_attrs->plugin_endpoint_attributes |= PLUGIN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_VALID;
345
        if (plugin_attrs.is_liveliness_encrypted)
346
        {
347
            sec_attrs->plugin_endpoint_attributes |= PLUGIN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_SUBMESSAGE_ENCRYPTED;
348
        }
349
        if (plugin_attrs.is_liveliness_origin_authenticated)
350
        {
351
            sec_attrs->plugin_endpoint_attributes |=
352
                    PLUGIN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_SUBMESSAGE_ORIGIN_AUTHENTICATED;
353
        }
354
    }
355
356
    RTPSWriter* wout;
357
    if (mp_participant->createWriter(&wout, watt, mp_builtinWriterSecureHistory, nullptr,
358
            c_EntityId_WriterLivelinessSecure, true))
359
    {
360
        mp_builtinWriterSecure = dynamic_cast<StatefulWriter*>(wout);
361
        EPROSIMA_LOG_INFO(RTPS_LIVELINESS, "Builtin Secure Liveliness Writer created");
362
    }
363
    else
364
    {
365
        EPROSIMA_LOG_ERROR(RTPS_LIVELINESS, "Secure Liveliness Writer Creation failed ");
366
        delete(mp_builtinWriterSecureHistory);
367
        mp_builtinWriterSecureHistory = nullptr;
368
        secure_payload_pool_->release_history(writer_pool_cfg, false);
369
        return false;
370
    }
371
372
    set_builtin_reader_history_attributes(hatt, participants_allocation, true);
373
374
    PoolConfig reader_pool_cfg = PoolConfig::from_history_attributes(hatt);
375
    secure_payload_pool_->reserve_history(reader_pool_cfg, true);
376
377
    mp_builtinReaderSecureHistory = new ReaderHistory(hatt);
378
    ReaderAttributes ratt = mp_participant->pdp()->create_builtin_reader_attributes();
379
    ratt.expects_inline_qos = true;
380
    //Rparam.topic.topicName = "DCPSParticipantMessageSecure";
381
    //Rparam.topic.topicDataType = "RTPSParticipantMessageData";
382
383
    sec_attrs = &ratt.endpoint.security_attributes();
384
    sec_attrs->is_submessage_protected = part_attrs.is_liveliness_protected;
385
    if (part_attrs.is_liveliness_protected)
386
    {
387
        sec_attrs->plugin_endpoint_attributes |= PLUGIN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_VALID;
388
        if (plugin_attrs.is_liveliness_encrypted)
389
        {
390
            sec_attrs->plugin_endpoint_attributes |= PLUGIN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_SUBMESSAGE_ENCRYPTED;
391
        }
392
        if (plugin_attrs.is_liveliness_origin_authenticated)
393
        {
394
            sec_attrs->plugin_endpoint_attributes |=
395
                    PLUGIN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_SUBMESSAGE_ORIGIN_AUTHENTICATED;
396
        }
397
    }
398
    RTPSReader* rout;
399
    if (mp_participant->createReader(
400
                &rout,
401
                ratt, secure_payload_pool_,
402
                mp_builtinReaderSecureHistory,
403
                (ReaderListener*)mp_listener,
404
                c_EntityId_ReaderLivelinessSecure,
405
                true))
406
    {
407
        mp_builtinReaderSecure = dynamic_cast<StatefulReader*>(rout);
408
        EPROSIMA_LOG_INFO(RTPS_LIVELINESS, "Builtin Liveliness Reader created");
409
    }
410
    else
411
    {
412
        EPROSIMA_LOG_ERROR(RTPS_LIVELINESS, "Liveliness Reader Creation failed.");
413
        delete(mp_builtinReaderSecureHistory);
414
        mp_builtinReaderSecureHistory = nullptr;
415
        secure_payload_pool_->release_history(reader_pool_cfg, true);
416
        return false;
417
    }
418
419
    return true;
420
}
421
422
bool WLP::pairing_remote_reader_with_local_writer_after_security(
423
        const GUID_t& local_writer,
424
        const ReaderProxyData& remote_reader_data)
425
{
426
    if (local_writer.entityId == c_EntityId_WriterLivelinessSecure)
427
    {
428
        mp_builtinWriterSecure->matched_reader_add_edp(remote_reader_data);
429
        return true;
430
    }
431
432
    return false;
433
}
434
435
bool WLP::pairing_remote_writer_with_local_reader_after_security(
436
        const GUID_t& local_reader,
437
        const WriterProxyData& remote_writer_data)
438
{
439
    if (local_reader.entityId == c_EntityId_ReaderLivelinessSecure)
440
    {
441
        mp_builtinReaderSecure->matched_writer_add_edp(remote_writer_data);
442
        return true;
443
    }
444
445
    return false;
446
}
447
448
#endif // if HAVE_SECURITY
449
450
bool WLP::assignRemoteEndpoints(
451
        const ParticipantProxyData& pdata,
452
        bool assign_secure_endpoints)
453
0
{
454
0
    const NetworkFactory& network = mp_participant->network_factory();
455
0
    uint32_t endp = pdata.m_available_builtin_endpoints;
456
0
    uint32_t auxendp = endp;
457
0
    bool use_multicast_locators = !mp_participant->get_const_attributes().builtin.avoid_builtin_multicast ||
458
0
            pdata.metatraffic_locators.unicast.empty();
459
460
0
    std::lock_guard<std::mutex> data_guard(temp_data_lock_);
461
462
0
    temp_writer_proxy_data_.guid.guidPrefix = pdata.guid.guidPrefix;
463
0
    temp_writer_proxy_data_.persistence_guid = pdata.get_persistence_guid();
464
0
    temp_writer_proxy_data_.set_remote_locators(pdata.metatraffic_locators, network, use_multicast_locators,
465
0
            pdata.is_from_this_host());
466
0
    temp_writer_proxy_data_.topic_kind = WITH_KEY;
467
0
    temp_writer_proxy_data_.durability.kind = dds::TRANSIENT_LOCAL_DURABILITY_QOS;
468
0
    temp_writer_proxy_data_.reliability.kind = dds::RELIABLE_RELIABILITY_QOS;
469
470
0
    temp_reader_proxy_data_.clear();
471
0
    temp_reader_proxy_data_.expects_inline_qos = false;
472
0
    temp_reader_proxy_data_.guid.guidPrefix = pdata.guid.guidPrefix;
473
0
    temp_reader_proxy_data_.set_remote_locators(pdata.metatraffic_locators, network, use_multicast_locators,
474
0
            pdata.is_from_this_host());
475
0
    temp_reader_proxy_data_.topic_kind = WITH_KEY;
476
0
    temp_reader_proxy_data_.durability.kind = dds::TRANSIENT_LOCAL_DURABILITY_QOS;
477
0
    temp_reader_proxy_data_.reliability.kind = dds::RELIABLE_RELIABILITY_QOS;
478
479
0
    auxendp &= fastdds::rtps::BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_WRITER;
480
0
    if (auxendp != 0 && this->mp_builtinReader != nullptr)
481
0
    {
482
0
        EPROSIMA_LOG_INFO(RTPS_LIVELINESS, "Adding remote writer to my local Builtin Reader");
483
0
        temp_writer_proxy_data_.guid.entityId = c_EntityId_WriterLiveliness;
484
0
        temp_writer_proxy_data_.set_persistence_entity_id(c_EntityId_WriterLiveliness);
485
0
        mp_builtinReader->matched_writer_add_edp(temp_writer_proxy_data_);
486
0
    }
487
0
    auxendp = endp;
488
0
    auxendp &= fastdds::rtps::BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_READER;
489
0
    if (auxendp != 0 && this->mp_builtinWriter != nullptr)
490
0
    {
491
0
        EPROSIMA_LOG_INFO(RTPS_LIVELINESS, "Adding remote reader to my local Builtin Writer");
492
0
        temp_reader_proxy_data_.guid.entityId = c_EntityId_ReaderLiveliness;
493
0
        mp_builtinWriter->matched_reader_add_edp(temp_reader_proxy_data_);
494
0
    }
495
496
#if HAVE_SECURITY
497
    auxendp = endp;
498
    auxendp &= fastdds::rtps::BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_SECURE_DATA_WRITER;
499
    if (auxendp != 0 && this->mp_builtinReaderSecure != nullptr && assign_secure_endpoints)
500
    {
501
        EPROSIMA_LOG_INFO(RTPS_LIVELINESS, "Adding remote writer to my local Builtin Secure Reader");
502
        temp_writer_proxy_data_.guid.entityId = c_EntityId_WriterLivelinessSecure;
503
        temp_writer_proxy_data_.set_persistence_entity_id(c_EntityId_WriterLivelinessSecure);
504
505
        if (!mp_participant->security_manager().discovered_builtin_writer(
506
                    mp_builtinReaderSecure->getGuid(), pdata.guid, temp_writer_proxy_data_,
507
                    mp_builtinReaderSecure->getAttributes().security_attributes()))
508
        {
509
            EPROSIMA_LOG_ERROR(RTPS_EDP, "Security manager returns an error for reader "
510
                    << mp_builtinReaderSecure->getGuid());
511
        }
512
    }
513
    auxendp = endp;
514
    auxendp &= fastdds::rtps::BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_SECURE_DATA_READER;
515
    if (auxendp != 0 && this->mp_builtinWriterSecure != nullptr && assign_secure_endpoints)
516
    {
517
        EPROSIMA_LOG_INFO(RTPS_LIVELINESS, "Adding remote reader to my local Builtin Secure Writer");
518
        temp_reader_proxy_data_.guid.entityId = c_EntityId_ReaderLivelinessSecure;
519
        if (!mp_participant->security_manager().discovered_builtin_reader(
520
                    mp_builtinWriterSecure->getGuid(), pdata.guid, temp_reader_proxy_data_,
521
                    mp_builtinWriterSecure->getAttributes().security_attributes()))
522
        {
523
            EPROSIMA_LOG_ERROR(RTPS_EDP, "Security manager returns an error for writer "
524
                    << mp_builtinWriterSecure->getGuid());
525
        }
526
    }
527
#else
528
0
    static_cast<void>(assign_secure_endpoints);
529
0
#endif // if HAVE_SECURITY
530
531
0
    return true;
532
0
}
533
534
void WLP::removeRemoteEndpoints(
535
        ParticipantProxyData* pdata)
536
0
{
537
0
    GUID_t tmp_guid;
538
0
    tmp_guid.guidPrefix = pdata->guid.guidPrefix;
539
540
0
    EPROSIMA_LOG_INFO(RTPS_LIVELINESS, "for RTPSParticipant: " << pdata->guid);
541
0
    uint32_t endp = pdata->m_available_builtin_endpoints;
542
0
    uint32_t partdet = endp;
543
0
    uint32_t auxendp = endp;
544
0
    partdet &= fastdds::rtps::DISC_BUILTIN_ENDPOINT_PARTICIPANT_DETECTOR;
545
0
    auxendp &= fastdds::rtps::BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_WRITER;
546
547
0
    if ((auxendp != 0 || partdet != 0) && this->mp_builtinReader != nullptr)
548
0
    {
549
0
        EPROSIMA_LOG_INFO(RTPS_LIVELINESS, "Removing remote writer from my local Builtin Reader");
550
0
        tmp_guid.entityId = c_EntityId_WriterLiveliness;
551
0
        mp_builtinReader->matched_writer_remove(tmp_guid);
552
0
    }
553
0
    auxendp = endp;
554
0
    auxendp &= fastdds::rtps::BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_READER;
555
0
    if ((auxendp != 0 || partdet != 0) && this->mp_builtinWriter != nullptr)
556
0
    {
557
0
        EPROSIMA_LOG_INFO(RTPS_LIVELINESS, "Removing remote reader from my local Builtin Writer");
558
0
        tmp_guid.entityId = c_EntityId_ReaderLiveliness;
559
0
        mp_builtinWriter->matched_reader_remove(tmp_guid);
560
0
    }
561
562
#if HAVE_SECURITY
563
    auxendp = endp;
564
    auxendp &= fastdds::rtps::BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_SECURE_DATA_WRITER;
565
    if ((auxendp != 0 || partdet != 0) && this->mp_builtinReaderSecure != nullptr)
566
    {
567
        EPROSIMA_LOG_INFO(RTPS_LIVELINESS, "Removing remote writer from my local Builtin Secure Reader");
568
        tmp_guid.entityId = c_EntityId_WriterLivelinessSecure;
569
        if (mp_builtinReaderSecure->matched_writer_remove(tmp_guid))
570
        {
571
            mp_participant->security_manager().remove_writer(
572
                mp_builtinReaderSecure->getGuid(), pdata->guid, tmp_guid);
573
        }
574
    }
575
    auxendp = endp;
576
    auxendp &= fastdds::rtps::BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_SECURE_DATA_READER;
577
    if ((auxendp != 0 || partdet != 0) && this->mp_builtinWriterSecure != nullptr)
578
    {
579
        EPROSIMA_LOG_INFO(RTPS_LIVELINESS, "Removing remote reader from my local Builtin Secure Writer");
580
        tmp_guid.entityId = c_EntityId_ReaderLivelinessSecure;
581
        if (mp_builtinWriterSecure->matched_reader_remove(tmp_guid))
582
        {
583
            mp_participant->security_manager().remove_reader(
584
                mp_builtinWriterSecure->getGuid(), pdata->guid, tmp_guid);
585
        }
586
    }
587
#endif // if HAVE_SECURITY
588
0
}
589
590
bool WLP::add_local_writer(
591
        RTPSWriter* writer,
592
        const fastdds::dds::LivelinessQosPolicy& qos)
593
0
{
594
0
    std::lock_guard<std::recursive_mutex> guard(*mp_builtinProtocols->mp_PDP->getMutex());
595
596
0
    EPROSIMA_LOG_INFO(RTPS_LIVELINESS, writer->getGuid().entityId << " to Liveliness Protocol");
597
598
0
    BaseWriter* base_writer = BaseWriter::downcast(writer);
599
600
0
    double wAnnouncementPeriodMilliSec(TimeConv::Duration_t2MilliSecondsDouble(qos.announcement_period));
601
602
0
    if (qos.kind == dds::AUTOMATIC_LIVELINESS_QOS )
603
0
    {
604
0
        if (automatic_liveliness_assertion_ == nullptr)
605
0
        {
606
0
            automatic_liveliness_assertion_ = new TimedEvent(mp_participant->getEventResource(),
607
0
                            [&]() -> bool
608
0
                            {
609
0
                                automatic_liveliness_assertion();
610
0
                                return true;
611
0
                            },
612
0
                            wAnnouncementPeriodMilliSec);
613
0
            automatic_liveliness_assertion_->restart_timer();
614
0
            min_automatic_ms_ = wAnnouncementPeriodMilliSec;
615
0
        }
616
0
        else if (min_automatic_ms_ > wAnnouncementPeriodMilliSec)
617
0
        {
618
0
            min_automatic_ms_ = wAnnouncementPeriodMilliSec;
619
0
            automatic_liveliness_assertion_->update_interval_millisec(wAnnouncementPeriodMilliSec);
620
            //CHECK IF THE TIMER IS GOING TO BE CALLED AFTER THIS NEW SET LEASE DURATION
621
0
            if (automatic_liveliness_assertion_->getRemainingTimeMilliSec() > min_automatic_ms_)
622
0
            {
623
0
                automatic_liveliness_assertion_->cancel_timer();
624
0
            }
625
0
            automatic_liveliness_assertion_->restart_timer();
626
0
        }
627
0
        automatic_writers_.push_back(base_writer);
628
0
    }
629
0
    else if (qos.kind == dds::MANUAL_BY_PARTICIPANT_LIVELINESS_QOS)
630
0
    {
631
0
        if (manual_liveliness_assertion_ == nullptr)
632
0
        {
633
0
            manual_liveliness_assertion_ = new TimedEvent(mp_participant->getEventResource(),
634
0
                            [&]() -> bool
635
0
                            {
636
0
                                participant_liveliness_assertion();
637
0
                                return true;
638
0
                            },
639
0
                            wAnnouncementPeriodMilliSec);
640
0
            manual_liveliness_assertion_->restart_timer();
641
0
            min_manual_by_participant_ms_ = wAnnouncementPeriodMilliSec;
642
0
        }
643
0
        else if (min_manual_by_participant_ms_ > wAnnouncementPeriodMilliSec)
644
0
        {
645
0
            min_manual_by_participant_ms_ = wAnnouncementPeriodMilliSec;
646
0
            manual_liveliness_assertion_->update_interval_millisec(min_manual_by_participant_ms_);
647
            //CHECK IF THE TIMER IS GOING TO BE CALLED AFTER THIS NEW SET LEASE DURATION
648
0
            if (manual_liveliness_assertion_->getRemainingTimeMilliSec() > min_manual_by_participant_ms_)
649
0
            {
650
0
                manual_liveliness_assertion_->cancel_timer();
651
0
            }
652
0
            manual_liveliness_assertion_->restart_timer();
653
0
        }
654
0
        manual_by_participant_writers_.push_back(base_writer);
655
656
0
        if (!pub_liveliness_manager_->add_writer(
657
0
                    writer->getGuid(),
658
0
                    qos.kind,
659
0
                    qos.lease_duration))
660
0
        {
661
0
            EPROSIMA_LOG_ERROR(RTPS_LIVELINESS,
662
0
                    "Could not add writer " << writer->getGuid() << " to liveliness manager");
663
0
        }
664
0
    }
665
0
    else if (qos.kind == dds::MANUAL_BY_TOPIC_LIVELINESS_QOS)
666
0
    {
667
0
        manual_by_topic_writers_.push_back(base_writer);
668
669
0
        if (!pub_liveliness_manager_->add_writer(
670
0
                    writer->getGuid(),
671
0
                    qos.kind,
672
0
                    qos.lease_duration))
673
0
        {
674
0
            EPROSIMA_LOG_ERROR(RTPS_LIVELINESS,
675
0
                    "Could not add writer " << writer->getGuid() << " to liveliness manager");
676
0
        }
677
0
    }
678
679
0
    return true;
680
0
}
681
682
bool WLP::remove_local_writer(
683
        RTPSWriter* writer)
684
0
{
685
0
    std::lock_guard<std::recursive_mutex> guard(*mp_builtinProtocols->mp_PDP->getMutex());
686
687
0
    EPROSIMA_LOG_INFO(RTPS_LIVELINESS, writer->getGuid().entityId << " from Liveliness Protocol");
688
689
0
    LivelinessData::WriterStatus writer_status;
690
0
    BaseWriter* base_writer = BaseWriter::downcast(writer);
691
692
0
    if (base_writer->get_liveliness_kind() == dds::AUTOMATIC_LIVELINESS_QOS)
693
0
    {
694
0
        auto it = std::find(
695
0
            automatic_writers_.begin(),
696
0
            automatic_writers_.end(),
697
0
            base_writer);
698
699
0
        if (it == automatic_writers_.end())
700
0
        {
701
0
            EPROSIMA_LOG_WARNING(RTPS_LIVELINESS, "Writer " << base_writer->getGuid() << " not found.");
702
0
            return false;
703
0
        }
704
705
0
        automatic_writers_.erase(it);
706
707
0
        min_automatic_ms_ = std::numeric_limits<double>::max();
708
0
        if (automatic_writers_.size() == 0)
709
0
        {
710
0
            automatic_liveliness_assertion_->cancel_timer();
711
0
            return true;
712
0
        }
713
714
        // There are still some writers. Calculate the new minimum announcement period
715
0
        for (const auto& w : automatic_writers_)
716
0
        {
717
0
            auto announcement_period = fastdds::rtps::TimeConv::Duration_t2MilliSecondsDouble(
718
0
                w->get_liveliness_announcement_period());
719
0
            if (min_automatic_ms_ > announcement_period)
720
0
            {
721
0
                min_automatic_ms_ = announcement_period;
722
0
            }
723
0
        }
724
0
        automatic_liveliness_assertion_->update_interval_millisec(min_automatic_ms_);
725
0
        return true;
726
0
    }
727
0
    else if (base_writer->get_liveliness_kind() == dds::MANUAL_BY_PARTICIPANT_LIVELINESS_QOS)
728
0
    {
729
0
        auto it = std::find(
730
0
            manual_by_participant_writers_.begin(),
731
0
            manual_by_participant_writers_.end(),
732
0
            base_writer);
733
734
0
        if (it == manual_by_participant_writers_.end())
735
0
        {
736
0
            EPROSIMA_LOG_WARNING(RTPS_LIVELINESS, "Writer " << base_writer->getGuid() << " not found.");
737
0
            return false;
738
0
        }
739
740
0
        manual_by_participant_writers_.erase(it);
741
742
0
        if (!pub_liveliness_manager_->remove_writer(
743
0
                    base_writer->getGuid(),
744
0
                    base_writer->get_liveliness_kind(),
745
0
                    base_writer->get_liveliness_lease_duration(),
746
0
                    writer_status))
747
0
        {
748
0
            EPROSIMA_LOG_ERROR(RTPS_LIVELINESS,
749
0
                    "Could not remove writer " << base_writer->getGuid() << " from liveliness manager");
750
0
        }
751
752
0
        min_manual_by_participant_ms_ = std::numeric_limits<double>::max();
753
0
        if (manual_by_participant_writers_.size() == 0)
754
0
        {
755
0
            manual_liveliness_assertion_->cancel_timer();
756
0
            return true;
757
0
        }
758
759
        // There are still some writers. Calculate the new minimum announcement period
760
0
        for (const auto& w : manual_by_participant_writers_)
761
0
        {
762
0
            auto announcement_period = fastdds::rtps::TimeConv::Duration_t2MilliSecondsDouble(
763
0
                w->get_liveliness_announcement_period());
764
0
            if (min_manual_by_participant_ms_ > announcement_period)
765
0
            {
766
0
                min_manual_by_participant_ms_ = announcement_period;
767
0
            }
768
0
        }
769
0
        manual_liveliness_assertion_->update_interval_millisec(min_manual_by_participant_ms_);
770
0
        return true;
771
0
    }
772
0
    else if (base_writer->get_liveliness_kind() == dds::MANUAL_BY_TOPIC_LIVELINESS_QOS)
773
0
    {
774
0
        auto it = std::find(
775
0
            manual_by_topic_writers_.begin(),
776
0
            manual_by_topic_writers_.end(),
777
0
            base_writer);
778
779
0
        if (it == manual_by_topic_writers_.end())
780
0
        {
781
0
            EPROSIMA_LOG_WARNING(RTPS_LIVELINESS, "Writer " << base_writer->getGuid() << " not found.");
782
0
            return false;
783
0
        }
784
785
0
        manual_by_topic_writers_.erase(it);
786
787
0
        if (!pub_liveliness_manager_->remove_writer(
788
0
                    base_writer->getGuid(),
789
0
                    base_writer->get_liveliness_kind(),
790
0
                    base_writer->get_liveliness_lease_duration(),
791
0
                    writer_status))
792
0
        {
793
0
            EPROSIMA_LOG_ERROR(RTPS_LIVELINESS,
794
0
                    "Could not remove writer " << base_writer->getGuid() << " from liveliness manager");
795
0
        }
796
0
        return true;
797
0
    }
798
799
0
    EPROSIMA_LOG_WARNING(RTPS_LIVELINESS, "Writer " << base_writer->getGuid() << " not found.");
800
0
    return false;
801
0
}
802
803
bool WLP::add_local_reader(
804
        RTPSReader* reader,
805
        const fastdds::dds::LivelinessQosPolicy& qos)
806
0
{
807
0
    auto base_reader = BaseReader::downcast(reader);
808
809
0
    std::lock_guard<std::recursive_mutex> guard(*mp_builtinProtocols->mp_PDP->getMutex());
810
811
0
    if (qos.kind == dds::AUTOMATIC_LIVELINESS_QOS)
812
0
    {
813
0
        automatic_readers_ = true;
814
0
    }
815
816
0
    readers_.push_back(base_reader);
817
818
0
    return true;
819
0
}
820
821
bool WLP::remove_local_reader(
822
        RTPSReader* reader)
823
0
{
824
0
    auto base_reader = BaseReader::downcast(reader);
825
0
    std::lock_guard<std::recursive_mutex> guard(*mp_builtinProtocols->mp_PDP->getMutex());
826
827
0
    auto it = std::find(
828
0
        readers_.begin(),
829
0
        readers_.end(),
830
0
        base_reader);
831
0
    if (it != readers_.end())
832
0
    {
833
0
        readers_.erase(it);
834
0
        return true;
835
0
    }
836
837
0
    EPROSIMA_LOG_WARNING(RTPS_LIVELINESS, "Reader not removed from WLP, unknown reader");
838
0
    return false;
839
0
}
840
841
bool WLP::automatic_liveliness_assertion()
842
0
{
843
0
    std::unique_lock<std::recursive_mutex> lock(*mp_builtinProtocols->mp_PDP->getMutex());
844
845
0
    if (0 < automatic_writers_.size())
846
0
    {
847
0
        lock.unlock();
848
0
        return send_liveliness_message(automatic_instance_handle_);
849
0
    }
850
851
0
    return true;
852
0
}
853
854
bool WLP::participant_liveliness_assertion()
855
0
{
856
0
    std::unique_lock<std::recursive_mutex> lock(*mp_builtinProtocols->mp_PDP->getMutex());
857
858
0
    if (0 < manual_by_participant_writers_.size())
859
0
    {
860
0
        if (pub_liveliness_manager_->is_any_alive(dds::MANUAL_BY_PARTICIPANT_LIVELINESS_QOS))
861
0
        {
862
0
            lock.unlock();
863
0
            return send_liveliness_message(manual_by_participant_instance_handle_);
864
0
        }
865
0
    }
866
867
0
    return false;
868
0
}
869
870
bool WLP::send_liveliness_message(
871
        const InstanceHandle_t& instance)
872
0
{
873
0
    StatefulWriter* writer = builtin_writer();
874
0
    WriterHistory* history = builtin_writer_history();
875
0
    std::shared_ptr<IPayloadPool> pool = builtin_writer_pool();
876
877
0
    std::lock_guard<RecursiveTimedMutex> wguard(writer->getMutex());
878
879
0
    CacheChange_t* change = history->create_change(WLP::builtin_participant_data_max_size, ALIVE, instance);
880
0
    if (change != nullptr)
881
0
    {
882
0
        change->serializedPayload.encapsulation = (uint16_t)DEFAULT_ENCAPSULATION;
883
0
        change->serializedPayload.data[0] = 0;
884
0
        change->serializedPayload.data[1] = DEFAULT_ENCAPSULATION;
885
0
        change->serializedPayload.data[2] = 0;
886
0
        change->serializedPayload.data[3] = 0;
887
888
0
        memcpy(change->serializedPayload.data + 4, instance.value, 16);
889
890
0
        for (size_t i = 20; i < 28; ++i)
891
0
        {
892
0
            change->serializedPayload.data[i] = 0;
893
0
        }
894
0
        change->serializedPayload.length = 4 + 12 + 4 + 4 + 4;
895
896
0
        if (history->getHistorySize() > 0)
897
0
        {
898
0
            for (auto chit = history->changesBegin(); chit != history->changesEnd(); ++chit)
899
0
            {
900
0
                if ((*chit)->instanceHandle == change->instanceHandle)
901
0
                {
902
0
                    history->remove_change(*chit);
903
0
                    break;
904
0
                }
905
0
            }
906
0
        }
907
0
        history->add_change(change);
908
0
        return true;
909
0
    }
910
0
    return false;
911
0
}
912
913
StatefulWriter* WLP::builtin_writer()
914
0
{
915
0
    StatefulWriter* ret_val = mp_builtinWriter;
916
917
#if HAVE_SECURITY
918
    if (mp_participant->security_attributes().is_liveliness_protected)
919
    {
920
        ret_val = mp_builtinWriterSecure;
921
    }
922
#endif // if HAVE_SECURITY
923
924
0
    return ret_val;
925
0
}
926
927
WriterHistory* WLP::builtin_writer_history()
928
0
{
929
0
    WriterHistory* ret_val = mp_builtinWriterHistory;
930
931
#if HAVE_SECURITY
932
    if (mp_participant->security_attributes().is_liveliness_protected)
933
    {
934
        ret_val = mp_builtinWriterSecureHistory;
935
    }
936
#endif // if HAVE_SECURITY
937
938
0
    return ret_val;
939
0
}
940
941
std::shared_ptr<IPayloadPool> WLP::builtin_writer_pool()
942
0
{
943
#if HAVE_SECURITY
944
    if (mp_participant->security_attributes().is_liveliness_protected)
945
    {
946
        return secure_payload_pool_;
947
    }
948
#endif // if HAVE_SECURITY
949
950
0
    return payload_pool_;
951
0
}
952
953
bool WLP::assert_liveliness(
954
        GUID_t writer,
955
        dds::LivelinessQosPolicyKind kind,
956
        dds::Duration_t lease_duration)
957
0
{
958
0
    return pub_liveliness_manager_->assert_liveliness(
959
0
        writer,
960
0
        kind,
961
0
        lease_duration);
962
0
}
963
964
bool WLP::assert_liveliness_manual_by_participant()
965
0
{
966
0
    if (manual_by_participant_writers_.size() > 0)
967
0
    {
968
0
        return pub_liveliness_manager_->assert_liveliness(
969
0
            dds::MANUAL_BY_PARTICIPANT_LIVELINESS_QOS,
970
0
            mp_participant->getGuid().guidPrefix);
971
0
    }
972
0
    return false;
973
0
}
974
975
void WLP::pub_liveliness_changed(
976
        const GUID_t& writer,
977
        const dds::LivelinessQosPolicyKind& kind,
978
        const dds::Duration_t& lease_duration,
979
        int32_t alive_change,
980
        int32_t not_alive_change)
981
0
{
982
0
    (void)lease_duration;
983
0
    (void)alive_change;
984
985
    // On the publishing side we only have to notify if one of our writers loses liveliness
986
0
    if (not_alive_change != 1)
987
0
    {
988
0
        return;
989
0
    }
990
991
0
    if (kind == dds::AUTOMATIC_LIVELINESS_QOS)
992
0
    {
993
0
        for (BaseWriter* w: automatic_writers_)
994
0
        {
995
0
            if (w->getGuid() == writer)
996
0
            {
997
0
                w->liveliness_lost();
998
0
                return;
999
0
            }
1000
0
        }
1001
0
    }
1002
0
    else if (kind == dds::MANUAL_BY_PARTICIPANT_LIVELINESS_QOS)
1003
0
    {
1004
0
        for (BaseWriter* w: manual_by_participant_writers_)
1005
0
        {
1006
0
            if (w->getGuid() == writer)
1007
0
            {
1008
0
                w->liveliness_lost();
1009
0
                return;
1010
0
            }
1011
0
        }
1012
0
    }
1013
0
    else if (kind == dds::MANUAL_BY_TOPIC_LIVELINESS_QOS)
1014
0
    {
1015
0
        for (BaseWriter* w: manual_by_topic_writers_)
1016
0
        {
1017
0
            if (w->getGuid() == writer)
1018
0
            {
1019
0
                w->liveliness_lost();
1020
0
                return;
1021
0
            }
1022
0
        }
1023
0
    }
1024
0
}
1025
1026
void WLP::sub_liveliness_changed(
1027
        const GUID_t& writer,
1028
        const dds::LivelinessQosPolicyKind& kind,
1029
        const dds::Duration_t& lease_duration,
1030
        int32_t alive_change,
1031
        int32_t not_alive_change)
1032
0
{
1033
    // Writer with given guid lost liveliness, check which readers were matched and inform them
1034
1035
0
    for (BaseReader* reader : readers_)
1036
0
    {
1037
0
        if (reader->liveliness_kind() == kind &&
1038
0
                reader->liveliness_lease_duration() == lease_duration)
1039
0
        {
1040
0
            if (reader->matched_writer_is_matched(writer))
1041
0
            {
1042
0
                update_liveliness_changed_status(
1043
0
                    writer,
1044
0
                    reader,
1045
0
                    alive_change,
1046
0
                    not_alive_change);
1047
0
            }
1048
0
        }
1049
0
    }
1050
0
}
1051
1052
void WLP::update_liveliness_changed_status(
1053
        GUID_t writer,
1054
        BaseReader* reader,
1055
        int32_t alive_change,
1056
        int32_t not_alive_change)
1057
0
{
1058
0
    reader->update_liveliness_changed_status(writer, alive_change, not_alive_change);
1059
0
}
1060
1061
} /* namespace rtps */
1062
} /* namespace fastdds */
1063
} /* namespace eprosima */