Coverage Report

Created: 2026-09-14 06:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/Fast-DDS/src/cpp/rtps/messages/MessageReceiver.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 MessageReceiver.cpp
17
 *
18
 */
19
20
#include <cassert>
21
#include <limits>
22
#include <thread>
23
24
#include <fastdds/rtps/common/EntityId_t.hpp>
25
#include <fastdds/rtps/common/Guid.hpp>
26
27
#include <fastdds/core/policy/ParameterList.hpp>
28
#include <fastdds/dds/log/Log.hpp>
29
#include <fastdds/rtps/reader/RTPSReader.hpp>
30
#include <fastdds/rtps/writer/RTPSWriter.hpp>
31
32
#include <rtps/messages/MessageReceiver.h>
33
#include <rtps/participant/RTPSParticipantImpl.hpp>
34
#include <rtps/reader/BaseReader.hpp>
35
#include <rtps/writer/BaseWriter.hpp>
36
#include <statistics/rtps/messages/RTPSStatisticsMessages.hpp>
37
#include <statistics/rtps/StatisticsBase.hpp>
38
#include <utils/shared_mutex.hpp>
39
40
921
#define INFO_SRC_SUBMSG_LENGTH 20
41
42
#define IDSTRING "(ID:" << std::this_thread::get_id() << ") " <<
43
44
using ParameterList = eprosima::fastdds::dds::ParameterList;
45
46
namespace eprosima {
47
namespace fastdds {
48
namespace rtps {
49
50
MessageReceiver::MessageReceiver(
51
        RTPSParticipantImpl* participant,
52
        uint32_t rec_buffer_size)
53
1.73k
    : mtx_()
54
1.73k
    , associated_writers_()
55
1.73k
    , associated_readers_()
56
#if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
57
    , participant_(participant)
58
#endif // if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
59
1.73k
    , source_version_(c_ProtocolVersion)
60
1.73k
    , source_vendor_id_(c_VendorId_Unknown)
61
1.73k
    , source_guid_prefix_(c_GuidPrefix_Unknown)
62
1.73k
    , dest_guid_prefix_(c_GuidPrefix_Unknown)
63
1.73k
    , have_timestamp_(false)
64
1.73k
    , timestamp_(dds::c_TimeInvalid)
65
#if HAVE_SECURITY
66
    , crypto_msg_(participant->is_secure() ? rec_buffer_size : 0)
67
    , crypto_submsg_(participant->is_secure() ? rec_buffer_size : 0)
68
    , crypto_payload_(participant->is_secure() ? rec_buffer_size : 0)
69
#endif // if HAVE_SECURITY
70
1.73k
{
71
1.73k
    static_cast<void>(participant);
72
1.73k
    (void)rec_buffer_size;
73
1.73k
    EPROSIMA_LOG_INFO(RTPS_MSG_IN, "Created with CDRMessage of size: " << rec_buffer_size);
74
75
#if HAVE_SECURITY && !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
76
    if (participant->is_secure())
77
    {
78
        process_data_message_function_ = std::bind(
79
            &MessageReceiver::process_data_message_with_security,
80
            this,
81
            std::placeholders::_1,
82
            std::placeholders::_2,
83
            std::placeholders::_3);
84
85
        process_data_fragment_message_function_ = std::bind(
86
            &MessageReceiver::process_data_fragment_message_with_security,
87
            this,
88
            std::placeholders::_1,
89
            std::placeholders::_2,
90
            std::placeholders::_3,
91
            std::placeholders::_4,
92
            std::placeholders::_5,
93
            std::placeholders::_6);
94
    }
95
    else
96
    {
97
#endif // if HAVE_SECURITY && !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
98
1.73k
    process_data_message_function_ = std::bind(
99
1.73k
        &MessageReceiver::process_data_message_without_security,
100
1.73k
        this,
101
1.73k
        std::placeholders::_1,
102
1.73k
        std::placeholders::_2,
103
1.73k
        std::placeholders::_3);
104
105
1.73k
    process_data_fragment_message_function_ = std::bind(
106
1.73k
        &MessageReceiver::process_data_fragment_message_without_security,
107
1.73k
        this,
108
1.73k
        std::placeholders::_1,
109
1.73k
        std::placeholders::_2,
110
1.73k
        std::placeholders::_3,
111
1.73k
        std::placeholders::_4,
112
1.73k
        std::placeholders::_5,
113
1.73k
        std::placeholders::_6);
114
#if HAVE_SECURITY && !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
115
}
116
117
#endif // if HAVE_SECURITY && !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
118
1.73k
}
119
120
MessageReceiver::~MessageReceiver()
121
1.73k
{
122
1.73k
    EPROSIMA_LOG_INFO(RTPS_MSG_IN, "");
123
1.73k
    assert(associated_writers_.empty());
124
1.73k
    assert(associated_readers_.empty());
125
1.73k
}
126
127
 #if HAVE_SECURITY && !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
128
void MessageReceiver::process_data_message_with_security(
129
        const EntityId_t& reader_id,
130
        CacheChange_t& change,
131
        bool was_decoded)
132
{
133
    auto process_message = [was_decoded, &change, this](BaseReader* reader)
134
            {
135
                if (!was_decoded && reader->getAttributes().security_attributes().is_submessage_protected)
136
                {
137
                    return;
138
                }
139
140
                if (!reader->getAttributes().security_attributes().is_payload_protected)
141
                {
142
                    reader->process_data_msg(&change);
143
                    return;
144
                }
145
146
                if (!reader->matched_writer_is_matched(change.writerGUID))
147
                {
148
                    return;
149
                }
150
151
                if (!participant_->security_manager().decode_serialized_payload(change.serializedPayload,
152
                        crypto_payload_, reader->getGuid(), change.writerGUID))
153
                {
154
                    return;
155
                }
156
157
                std::swap(change.serializedPayload.data, crypto_payload_.data);
158
                std::swap(change.serializedPayload.length, crypto_payload_.length);
159
160
                octet* original_payload_data = change.serializedPayload.data;
161
                uint32_t original_payload_length {change.serializedPayload.length};
162
                reader->process_data_msg(&change);
163
                IPayloadPool* payload_pool = change.serializedPayload.payload_owner;
164
                if (payload_pool)
165
                {
166
                    payload_pool->release_payload(change.serializedPayload);
167
                    change.serializedPayload.data = original_payload_data;
168
                    change.serializedPayload.length = original_payload_length;
169
                }
170
                std::swap(change.serializedPayload.data, crypto_payload_.data);
171
                std::swap(change.serializedPayload.length, crypto_payload_.length);
172
            };
173
174
    findAllReaders(reader_id, process_message);
175
}
176
177
void MessageReceiver::process_data_fragment_message_with_security(
178
        const EntityId_t& reader_id,
179
        CacheChange_t& change,
180
        uint32_t sample_size,
181
        uint32_t fragment_starting_num,
182
        uint16_t fragments_in_submessage,
183
        bool was_decoded)
184
{
185
    auto process_message = [was_decoded, &change, sample_size, fragment_starting_num, fragments_in_submessage, this](
186
        BaseReader* reader)
187
            {
188
                if (!was_decoded && reader->getAttributes().security_attributes().is_submessage_protected)
189
                {
190
                    return;
191
                }
192
193
                if (!reader->getAttributes().security_attributes().is_payload_protected)
194
                {
195
                    reader->process_data_frag_msg(&change, sample_size, fragment_starting_num, fragments_in_submessage);
196
                    return;
197
                }
198
199
                if (!reader->matched_writer_is_matched(change.writerGUID))
200
                {
201
                    return;
202
                }
203
204
                if (!participant_->security_manager().decode_serialized_payload(change.serializedPayload,
205
                        crypto_payload_, reader->getGuid(), change.writerGUID))
206
                {
207
                    return;
208
                }
209
210
                std::swap(change.serializedPayload.data, crypto_payload_.data);
211
                std::swap(change.serializedPayload.length, crypto_payload_.length);
212
                reader->process_data_frag_msg(&change, sample_size, fragment_starting_num, fragments_in_submessage);
213
                std::swap(change.serializedPayload.data, crypto_payload_.data);
214
                std::swap(change.serializedPayload.length, crypto_payload_.length);
215
            };
216
217
    findAllReaders(reader_id, process_message);
218
}
219
220
#endif // if HAVE_SECURITY && !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
221
222
void MessageReceiver::process_data_message_without_security(
223
        const EntityId_t& reader_id,
224
        CacheChange_t& change,
225
        bool /*was_decoded*/)
226
0
{
227
0
    auto process_message = [&change](BaseReader* reader)
228
0
            {
229
0
                reader->process_data_msg(&change);
230
0
            };
231
232
0
    findAllReaders(reader_id, process_message);
233
0
}
234
235
void MessageReceiver::process_data_fragment_message_without_security(
236
        const EntityId_t& reader_id,
237
        CacheChange_t& change,
238
        uint32_t sample_size,
239
        uint32_t fragment_starting_num,
240
        uint16_t fragments_in_submessage,
241
        bool /*was_decoded*/)
242
0
{
243
0
    auto process_message = [&change, sample_size, fragment_starting_num, fragments_in_submessage](
244
0
        BaseReader* reader)
245
0
            {
246
0
                reader->process_data_frag_msg(&change, sample_size, fragment_starting_num, fragments_in_submessage);
247
0
            };
248
249
0
    findAllReaders(reader_id, process_message);
250
0
}
251
252
void MessageReceiver::associateEndpoint(
253
        Endpoint* to_add)
254
0
{
255
0
    std::lock_guard<eprosima::shared_mutex> guard(mtx_);
256
0
    if (to_add->getAttributes().endpointKind == WRITER)
257
0
    {
258
0
        const auto writer = BaseWriter::downcast(to_add);
259
0
        for (const auto& it : associated_writers_)
260
0
        {
261
0
            if (it == writer)
262
0
            {
263
0
                return;
264
0
            }
265
0
        }
266
267
0
        associated_writers_.push_back(writer);
268
0
    }
269
0
    else
270
0
    {
271
0
        const auto reader = BaseReader::downcast(to_add);
272
0
        const auto entityId = reader->getGuid().entityId;
273
        // search for set of readers by entity ID
274
0
        const auto readers = associated_readers_.find(entityId);
275
0
        if (readers == associated_readers_.end())
276
0
        {
277
0
            auto vec = std::vector<BaseReader*>();
278
0
            vec.push_back(reader);
279
0
            associated_readers_.emplace(entityId, vec);
280
0
        }
281
0
        else
282
0
        {
283
0
            for (const auto& it : readers->second)
284
0
            {
285
0
                if (it == reader)
286
0
                {
287
0
                    return;
288
0
                }
289
0
            }
290
291
0
            readers->second.push_back(reader);
292
0
        }
293
0
    }
294
0
}
295
296
void MessageReceiver::removeEndpoint(
297
        Endpoint* to_remove)
298
0
{
299
0
    std::lock_guard<eprosima::shared_mutex> guard(mtx_);
300
301
0
    if (to_remove->getAttributes().endpointKind == WRITER)
302
0
    {
303
0
        auto* var = dynamic_cast<BaseWriter*>(to_remove);
304
0
        for (auto it = associated_writers_.begin(); it != associated_writers_.end(); ++it)
305
0
        {
306
0
            if (*it == var)
307
0
            {
308
0
                associated_writers_.erase(it);
309
0
                break;
310
0
            }
311
0
        }
312
0
    }
313
0
    else
314
0
    {
315
0
        auto readers = associated_readers_.find(to_remove->getGuid().entityId);
316
0
        if (readers != associated_readers_.end())
317
0
        {
318
0
            auto* var = BaseReader::downcast(to_remove);
319
0
            for (auto it = readers->second.begin(); it != readers->second.end(); ++it)
320
0
            {
321
0
                if (*it == var)
322
0
                {
323
0
                    readers->second.erase(it);
324
0
                    if (readers->second.empty())
325
0
                    {
326
0
                        associated_readers_.erase(readers);
327
0
                    }
328
0
                    break;
329
0
                }
330
0
            }
331
0
        }
332
0
    }
333
0
}
334
335
void MessageReceiver::reset()
336
1.73k
{
337
1.73k
    source_version_ = c_ProtocolVersion;
338
1.73k
    source_vendor_id_ = c_VendorId_Unknown;
339
1.73k
    source_guid_prefix_ = c_GuidPrefix_Unknown;
340
1.73k
    dest_guid_prefix_ = c_GuidPrefix_Unknown;
341
1.73k
    have_timestamp_ = false;
342
1.73k
    timestamp_ = dds::c_TimeInvalid;
343
1.73k
}
344
345
void MessageReceiver::processCDRMsg(
346
        const Locator_t& source_locator,
347
        const Locator_t& reception_locator,
348
        CDRMessage_t* msg)
349
1.73k
{
350
1.73k
    if (msg->length < RTPSMESSAGE_HEADER_SIZE)
351
0
    {
352
0
        EPROSIMA_LOG_WARNING(RTPS_MSG_IN, IDSTRING "Received message too short, ignoring");
353
0
        return;
354
0
    }
355
356
1.73k
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
357
1.73k
    GuidPrefix_t participantGuidPrefix;
358
#else
359
    GuidPrefix_t participantGuidPrefix {participant_->getGuid().guidPrefix};
360
#endif // ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
361
362
#if HAVE_SECURITY && !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
363
    security::SecurityManager& security = participant_->security_manager();
364
    CDRMessage_t* auxiliary_buffer = &crypto_msg_;
365
    int decode_ret {0};
366
#endif // if HAVE_SECURITY && !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
367
368
1.73k
    bool ignore_submessages {false};
369
370
1.73k
    {
371
1.73k
        std::lock_guard<eprosima::shared_mutex> guard(mtx_);
372
373
1.73k
        reset();
374
375
1.73k
        dest_guid_prefix_ = participantGuidPrefix;
376
377
1.73k
        msg->pos = 0; //Start reading at 0
378
379
        //Once everything is set, the reading begins:
380
1.73k
        if (!checkRTPSHeader(msg))
381
66
        {
382
66
            return;
383
66
        }
384
385
#if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
386
        ignore_submessages = participant_->is_participant_ignored(source_guid_prefix_);
387
#endif  // if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
388
389
1.67k
        if (!ignore_submessages)
390
1.67k
        {
391
1.67k
            notify_network_statistics(source_locator, reception_locator, msg);
392
1.67k
        }
393
394
#if HAVE_SECURITY && !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
395
        decode_ret = security.decode_rtps_message(*msg, *auxiliary_buffer, source_guid_prefix_);
396
397
        if (decode_ret < 0)
398
        {
399
            return;
400
        }
401
402
        if (decode_ret == 0)
403
        {
404
            // The original CDRMessage buffer (msg) now points to the proprietary temporary buffer crypto_msg_.
405
            // The auxiliary buffer now points to the propietary temporary buffer crypto_submsg_.
406
            // This way each decoded sub-message will be processed using the crypto_submsg_ buffer.
407
            msg = auxiliary_buffer;
408
            auxiliary_buffer = &crypto_submsg_;
409
        }
410
#endif // if HAVE_SECURITY && !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
411
1.67k
    }
412
413
    // Loop until there are no more submessages
414
    // Each submessage processing method choses the lock kind required
415
0
    bool valid;
416
1.67k
    SubmessageHeader_t submsgh; //Current submessage header
417
418
21.4k
    while (msg->pos < msg->length)// end of the message
419
21.2k
    {
420
21.2k
        CDRMessage_t* submessage = msg;
421
422
21.2k
        bool current_message_was_decoded {false};
423
424
#if HAVE_SECURITY && !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
425
        decode_ret = security.decode_rtps_submessage(*msg, *auxiliary_buffer, source_guid_prefix_);
426
427
        if (decode_ret < 0)
428
        {
429
            return;
430
        }
431
432
        if (decode_ret == 0)
433
        {
434
            current_message_was_decoded = true;
435
            submessage = auxiliary_buffer;
436
        }
437
#endif // if HAVE_SECURITY && !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
438
439
        //First 4 bytes must contain: ID | flags | octets to next header
440
21.2k
        if (!readSubmessageHeader(submessage, &submsgh))
441
270
        {
442
270
            return;
443
270
        }
444
445
20.9k
        valid = true;
446
20.9k
        uint32_t next_msg_pos {submessage->pos};
447
20.9k
        next_msg_pos += (submsgh.submessageLength + 3u) & ~3u;
448
449
        // We ignore submessage if the source participant is to be ignored, unless the submessage king is INFO_SRC
450
        // which triggers a reevaluation of the flag.
451
20.9k
        bool ignore_current_submessage = ignore_submessages && submsgh.submessageId != INFO_SRC;
452
453
20.9k
        if (!ignore_current_submessage)
454
20.9k
        {
455
20.9k
            switch (submsgh.submessageId)
456
20.9k
            {
457
277
                case DATA:
458
277
                {
459
277
                    if (dest_guid_prefix_ != participantGuidPrefix)
460
251
                    {
461
251
                        EPROSIMA_LOG_INFO(RTPS_MSG_IN, IDSTRING "Data Submsg ignored, DST is another RTPSParticipant");
462
251
                    }
463
26
                    else
464
26
                    {
465
26
                        EPROSIMA_LOG_INFO(RTPS_MSG_IN, IDSTRING "Data Submsg received, processing.");
466
26
                        EntityId_t writerId {c_EntityId_Unknown};
467
26
                        valid = proc_Submsg_Data(submessage, &submsgh, writerId, current_message_was_decoded);
468
#if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
469
                        if (valid && writerId == c_EntityId_SPDPWriter)
470
                        {
471
                            ignore_submessages = participant_->is_participant_ignored(source_guid_prefix_);
472
                        }
473
#endif  // if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
474
475
26
                    }
476
277
                    break;
477
0
                }
478
236
                case DATA_FRAG:
479
236
                    if (dest_guid_prefix_ != participantGuidPrefix)
480
209
                    {
481
209
                        EPROSIMA_LOG_INFO(RTPS_MSG_IN,
482
209
                                IDSTRING "DataFrag Submsg ignored, DST is another RTPSParticipant");
483
209
                    }
484
27
                    else
485
27
                    {
486
27
                        EPROSIMA_LOG_INFO(RTPS_MSG_IN, IDSTRING "DataFrag Submsg received, processing.");
487
27
                        valid = proc_Submsg_DataFrag(submessage, &submsgh, current_message_was_decoded);
488
27
                    }
489
236
                    break;
490
6.16k
                case GAP:
491
6.16k
                {
492
6.16k
                    if (dest_guid_prefix_ != participantGuidPrefix)
493
269
                    {
494
269
                        EPROSIMA_LOG_INFO(RTPS_MSG_IN,
495
269
                                IDSTRING "Gap Submsg ignored, DST is another RTPSParticipant...");
496
269
                    }
497
5.89k
                    else
498
5.89k
                    {
499
5.89k
                        EPROSIMA_LOG_INFO(RTPS_MSG_IN, IDSTRING "Gap Submsg received, processing...");
500
5.89k
                        valid = proc_Submsg_Gap(submessage, &submsgh, current_message_was_decoded);
501
5.89k
                    }
502
6.16k
                    break;
503
0
                }
504
534
                case ACKNACK:
505
534
                {
506
534
                    if (dest_guid_prefix_ != participantGuidPrefix)
507
204
                    {
508
204
                        EPROSIMA_LOG_INFO(RTPS_MSG_IN,
509
204
                                IDSTRING "Acknack Submsg ignored, DST is another RTPSParticipant...");
510
204
                    }
511
330
                    else
512
330
                    {
513
330
                        EPROSIMA_LOG_INFO(RTPS_MSG_IN, IDSTRING "Acknack Submsg received, processing...");
514
330
                        valid = proc_Submsg_Acknack(submessage, &submsgh, current_message_was_decoded);
515
330
                    }
516
534
                    break;
517
0
                }
518
341
                case NACK_FRAG:
519
341
                {
520
341
                    if (dest_guid_prefix_ != participantGuidPrefix)
521
204
                    {
522
204
                        EPROSIMA_LOG_INFO(RTPS_MSG_IN,
523
204
                                IDSTRING "NackFrag Submsg ignored, DST is another RTPSParticipant...");
524
204
                    }
525
137
                    else
526
137
                    {
527
137
                        EPROSIMA_LOG_INFO(RTPS_MSG_IN, IDSTRING "NackFrag Submsg received, processing...");
528
137
                        valid = proc_Submsg_NackFrag(submessage, &submsgh, current_message_was_decoded);
529
137
                    }
530
341
                    break;
531
0
                }
532
3.31k
                case HEARTBEAT:
533
3.31k
                {
534
3.31k
                    if (dest_guid_prefix_ != participantGuidPrefix)
535
211
                    {
536
211
                        EPROSIMA_LOG_INFO(RTPS_MSG_IN, IDSTRING "HB Submsg ignored, DST is another RTPSParticipant...");
537
211
                    }
538
3.10k
                    else
539
3.10k
                    {
540
3.10k
                        EPROSIMA_LOG_INFO(RTPS_MSG_IN, IDSTRING "Heartbeat Submsg received, processing...");
541
3.10k
                        valid = proc_Submsg_Heartbeat(submessage, &submsgh, current_message_was_decoded);
542
3.10k
                    }
543
3.31k
                    break;
544
0
                }
545
94
                case HEARTBEAT_FRAG:
546
94
                {
547
94
                    if (dest_guid_prefix_ != participantGuidPrefix)
548
10
                    {
549
10
                        EPROSIMA_LOG_INFO(RTPS_MSG_IN,
550
10
                                IDSTRING "HBFrag Submsg ignored, DST is another RTPSParticipant...");
551
10
                    }
552
84
                    else
553
84
                    {
554
84
                        EPROSIMA_LOG_INFO(RTPS_MSG_IN, IDSTRING "HeartbeatFrag Submsg received, processing...");
555
84
                        valid = proc_Submsg_HeartbeatFrag(submessage, &submsgh, current_message_was_decoded);
556
84
                    }
557
94
                    break;
558
0
                }
559
1.31k
                case PAD:
560
1.31k
                    EPROSIMA_LOG_WARNING(RTPS_MSG_IN, IDSTRING "PAD messages not yet implemented, ignoring");
561
1.31k
                    break;
562
1.56k
                case INFO_DST:
563
1.56k
                    EPROSIMA_LOG_INFO(RTPS_MSG_IN, IDSTRING "InfoDST message received, processing...");
564
1.56k
                    valid = proc_Submsg_InfoDST(submessage, &submsgh);
565
1.56k
                    break;
566
921
                case INFO_SRC:
567
921
                    EPROSIMA_LOG_INFO(RTPS_MSG_IN, IDSTRING "InfoSRC message received, processing...");
568
921
                    valid = proc_Submsg_InfoSRC(submessage, &submsgh);
569
#if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
570
                    ignore_submessages = participant_->is_participant_ignored(source_guid_prefix_);
571
#endif  // if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
572
921
                    break;
573
5.00k
                case INFO_TS:
574
5.00k
                {
575
5.00k
                    EPROSIMA_LOG_INFO(RTPS_MSG_IN, IDSTRING "InfoTS Submsg received, processing...");
576
5.00k
                    valid = proc_Submsg_InfoTS(submessage, &submsgh);
577
5.00k
                    break;
578
0
                }
579
1
                case INFO_REPLY:
580
1
                    break;
581
1
                case INFO_REPLY_IP4:
582
1
                    break;
583
1.20k
                default:
584
1.20k
                    break;
585
20.9k
            }
586
20.9k
        }
587
20.9k
        if (!valid || submsgh.is_last)
588
1.17k
        {
589
1.17k
            break;
590
1.17k
        }
591
592
19.8k
        submessage->pos = next_msg_pos;
593
19.8k
    }
594
595
#if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
596
    participant_->assert_remote_participant_liveliness(source_guid_prefix_);
597
#endif // if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
598
1.67k
}
599
600
bool MessageReceiver::checkRTPSHeader(
601
        CDRMessage_t* msg)
602
1.73k
{
603
    //check and proccess the RTPS Header
604
1.73k
    if (msg->buffer[0] != 'R' ||  msg->buffer[1] != 'T' ||
605
1.71k
            msg->buffer[2] != 'P' ||  msg->buffer[3] != 'S')
606
51
    {
607
51
        EPROSIMA_LOG_INFO(RTPS_MSG_IN, IDSTRING "Msg received with no RTPS in header, ignoring...");
608
51
        return false;
609
51
    }
610
611
1.68k
    msg->pos += 4;
612
613
    //CHECK AND SET protocol version
614
1.68k
    if (msg->buffer[msg->pos] == c_ProtocolVersion.m_major)
615
1.67k
    {
616
1.67k
        source_version_.m_major = msg->buffer[msg->pos];
617
1.67k
        msg->pos++;
618
1.67k
        source_version_.m_minor = msg->buffer[msg->pos];
619
1.67k
        msg->pos++;
620
1.67k
    }
621
15
    else
622
15
    {
623
15
        EPROSIMA_LOG_WARNING(RTPS_MSG_IN, IDSTRING "Major RTPS Version not supported");
624
15
        return false;
625
15
    }
626
627
    //Set source vendor id
628
1.67k
    source_vendor_id_[0] = msg->buffer[msg->pos];
629
1.67k
    msg->pos++;
630
1.67k
    source_vendor_id_[1] = msg->buffer[msg->pos];
631
1.67k
    msg->pos++;
632
    //set source guid prefix
633
1.67k
    CDRMessage::readData(msg, source_guid_prefix_.value, GuidPrefix_t::size);
634
1.67k
    have_timestamp_ = false;
635
1.67k
    return true;
636
1.68k
}
637
638
bool MessageReceiver::readSubmessageHeader(
639
        CDRMessage_t* msg,
640
        SubmessageHeader_t* smh) const
641
31.3k
{
642
31.3k
    if (msg->length - msg->pos < 4)
643
92
    {
644
92
        EPROSIMA_LOG_WARNING(RTPS_MSG_IN, IDSTRING "SubmessageHeader too short");
645
92
        return false;
646
92
    }
647
648
31.2k
    smh->submessageId = msg->buffer[msg->pos];
649
31.2k
    msg->pos++;
650
31.2k
    smh->flags = msg->buffer[msg->pos];
651
31.2k
    msg->pos++;
652
653
    //Set endianness of message
654
31.2k
    msg->msg_endian = (smh->flags & BIT(0)) != 0 ? LITTLEEND : BIGEND;
655
31.2k
    uint16_t length {0};
656
31.2k
    CDRMessage::readUInt16(msg, &length);
657
31.2k
    if (msg->pos + length > msg->length)
658
312
    {
659
312
        EPROSIMA_LOG_WARNING(RTPS_MSG_IN, IDSTRING "SubMsg of invalid length (" << length
660
312
                                                                                <<
661
312
                ") with current msg position/length (" << msg->pos << "/" << msg->length << ")");
662
312
        return false;
663
312
    }
664
665
30.9k
    if ((length == 0) && (smh->submessageId != INFO_TS) && (smh->submessageId != PAD))
666
705
    {
667
        // THIS IS THE LAST SUBMESSAGE
668
705
        smh->submessageLength = msg->length - msg->pos;
669
705
        smh->is_last = true;
670
705
    }
671
30.2k
    else
672
30.2k
    {
673
30.2k
        smh->submessageLength = length;
674
30.2k
        smh->is_last = false;
675
30.2k
    }
676
677
30.9k
    return true;
678
31.2k
}
679
680
bool MessageReceiver::willAReaderAcceptMsgDirectedTo(
681
        const EntityId_t& readerID,
682
        BaseReader*& first_reader) const
683
28
{
684
28
    first_reader = nullptr;
685
28
    if (associated_readers_.empty())
686
28
    {
687
28
        EPROSIMA_LOG_WARNING(RTPS_MSG_IN, IDSTRING "Data received when NO readers are listening");
688
28
        return false;
689
28
    }
690
691
0
    if (readerID != c_EntityId_Unknown)
692
0
    {
693
0
        const auto readers = associated_readers_.find(readerID);
694
0
        if (readers != associated_readers_.end())
695
0
        {
696
0
            first_reader = readers->second.front();
697
0
            return true;
698
0
        }
699
0
    }
700
0
    else
701
0
    {
702
0
        for (const auto& readers : associated_readers_)
703
0
        {
704
0
            if (0 < readers.second.size())
705
0
            {
706
0
                first_reader = readers.second.front();
707
0
                return true;
708
0
            }
709
0
        }
710
0
    }
711
712
0
    EPROSIMA_LOG_WARNING(RTPS_MSG_IN, IDSTRING "No Reader accepts this message (directed to: " << readerID << ")");
713
0
    return false;
714
0
}
715
716
template<typename Functor>
717
void MessageReceiver::findAllReaders(
718
        const EntityId_t& readerID,
719
        const Functor& callback) const
720
8.58k
{
721
8.58k
    if (readerID != c_EntityId_Unknown)
722
5.88k
    {
723
5.88k
        const auto readers = associated_readers_.find(readerID);
724
5.88k
        if (readers != associated_readers_.end())
725
0
        {
726
0
            for (const auto& it : readers->second)
727
0
            {
728
0
                callback(it);
729
0
            }
730
0
        }
731
5.88k
    }
732
2.69k
    else
733
2.69k
    {
734
2.69k
        for (const auto& readers : associated_readers_)
735
0
        {
736
0
            for (const auto& it : readers.second)
737
0
            {
738
0
                callback(it);
739
0
            }
740
0
        }
741
2.69k
    }
742
8.58k
}
Unexecuted instantiation: MessageReceiver.cpp:void eprosima::fastdds::rtps::MessageReceiver::findAllReaders<eprosima::fastdds::rtps::MessageReceiver::process_data_message_without_security(eprosima::fastdds::rtps::EntityId_t const&, eprosima::fastdds::rtps::CacheChange_t&, bool)::$_0>(eprosima::fastdds::rtps::EntityId_t const&, eprosima::fastdds::rtps::MessageReceiver::process_data_message_without_security(eprosima::fastdds::rtps::EntityId_t const&, eprosima::fastdds::rtps::CacheChange_t&, bool)::$_0 const&) const
Unexecuted instantiation: MessageReceiver.cpp:void eprosima::fastdds::rtps::MessageReceiver::findAllReaders<eprosima::fastdds::rtps::MessageReceiver::process_data_fragment_message_without_security(eprosima::fastdds::rtps::EntityId_t const&, eprosima::fastdds::rtps::CacheChange_t&, unsigned int, unsigned int, unsigned short, bool)::$_0>(eprosima::fastdds::rtps::EntityId_t const&, eprosima::fastdds::rtps::MessageReceiver::process_data_fragment_message_without_security(eprosima::fastdds::rtps::EntityId_t const&, eprosima::fastdds::rtps::CacheChange_t&, unsigned int, unsigned int, unsigned short, bool)::$_0 const&) const
MessageReceiver.cpp:void eprosima::fastdds::rtps::MessageReceiver::findAllReaders<eprosima::fastdds::rtps::MessageReceiver::proc_Submsg_Heartbeat(eprosima::fastdds::rtps::CDRMessage_t*, eprosima::fastdds::rtps::SubmessageHeader_t*, bool) const::$_0>(eprosima::fastdds::rtps::EntityId_t const&, eprosima::fastdds::rtps::MessageReceiver::proc_Submsg_Heartbeat(eprosima::fastdds::rtps::CDRMessage_t*, eprosima::fastdds::rtps::SubmessageHeader_t*, bool) const::$_0 const&) const
Line
Count
Source
720
2.80k
{
721
2.80k
    if (readerID != c_EntityId_Unknown)
722
1.37k
    {
723
1.37k
        const auto readers = associated_readers_.find(readerID);
724
1.37k
        if (readers != associated_readers_.end())
725
0
        {
726
0
            for (const auto& it : readers->second)
727
0
            {
728
0
                callback(it);
729
0
            }
730
0
        }
731
1.37k
    }
732
1.43k
    else
733
1.43k
    {
734
1.43k
        for (const auto& readers : associated_readers_)
735
0
        {
736
0
            for (const auto& it : readers.second)
737
0
            {
738
0
                callback(it);
739
0
            }
740
0
        }
741
1.43k
    }
742
2.80k
}
MessageReceiver.cpp:void eprosima::fastdds::rtps::MessageReceiver::findAllReaders<eprosima::fastdds::rtps::MessageReceiver::proc_Submsg_Gap(eprosima::fastdds::rtps::CDRMessage_t*, eprosima::fastdds::rtps::SubmessageHeader_t*, bool) const::$_0>(eprosima::fastdds::rtps::EntityId_t const&, eprosima::fastdds::rtps::MessageReceiver::proc_Submsg_Gap(eprosima::fastdds::rtps::CDRMessage_t*, eprosima::fastdds::rtps::SubmessageHeader_t*, bool) const::$_0 const&) const
Line
Count
Source
720
5.77k
{
721
5.77k
    if (readerID != c_EntityId_Unknown)
722
4.51k
    {
723
4.51k
        const auto readers = associated_readers_.find(readerID);
724
4.51k
        if (readers != associated_readers_.end())
725
0
        {
726
0
            for (const auto& it : readers->second)
727
0
            {
728
0
                callback(it);
729
0
            }
730
0
        }
731
4.51k
    }
732
1.26k
    else
733
1.26k
    {
734
1.26k
        for (const auto& readers : associated_readers_)
735
0
        {
736
0
            for (const auto& it : readers.second)
737
0
            {
738
0
                callback(it);
739
0
            }
740
0
        }
741
1.26k
    }
742
5.77k
}
743
744
bool MessageReceiver::proc_Submsg_Data(
745
        CDRMessage_t* msg,
746
        SubmessageHeader_t* smh,
747
        EntityId_t& writerID,
748
        bool was_decoded) const
749
26
{
750
26
    eprosima::shared_lock<eprosima::shared_mutex> guard(mtx_);
751
752
    //READ and PROCESS
753
26
    if (smh->submessageLength < RTPSMESSAGE_DATA_MIN_LENGTH)
754
9
    {
755
9
        EPROSIMA_LOG_INFO(RTPS_MSG_IN, IDSTRING "Too short submessage received, ignoring");
756
9
        return false;
757
9
    }
758
    //Fill flags bool values
759
17
    bool endiannessFlag {(smh->flags & BIT(0)) != 0};
760
17
    bool inlineQosFlag {(smh->flags & BIT(1)) != 0};
761
17
    bool dataFlag {(smh->flags & BIT(2)) != 0};
762
17
    bool keyFlag {(smh->flags & BIT(3)) != 0};
763
17
    if (keyFlag && dataFlag)
764
5
    {
765
5
        EPROSIMA_LOG_WARNING(RTPS_MSG_IN, IDSTRING "Message received with Data and Key Flag set, ignoring");
766
5
        return false;
767
5
    }
768
769
    //Assign message endianness
770
12
    if (endiannessFlag)
771
7
    {
772
7
        msg->msg_endian = LITTLEEND;
773
7
    }
774
5
    else
775
5
    {
776
5
        msg->msg_endian = BIGEND;
777
5
    }
778
779
    //Extra flags don't matter now. Avoid those bytes
780
12
    msg->pos += 2;
781
782
12
    bool valid {true};
783
12
    uint16_t octetsToInlineQos {0};
784
12
    valid &= CDRMessage::readUInt16(msg, &octetsToInlineQos); //it should be 16 in this implementation
785
786
    //reader and writer ID
787
12
    BaseReader* first_reader = nullptr;
788
12
    EntityId_t readerID;
789
12
    valid &= CDRMessage::readEntityId(msg, &readerID);
790
791
    //WE KNOW THE READER THAT THE MESSAGE IS DIRECTED TO SO WE LOOK FOR IT:
792
12
    if (!willAReaderAcceptMsgDirectedTo(readerID, first_reader))
793
12
    {
794
12
        return false;
795
12
    }
796
797
    //FOUND THE READER.
798
    //We ask the reader for a cachechange to store the information.
799
0
    CacheChange_t ch;
800
0
    ch.kind = ALIVE;
801
0
    ch.writerGUID.guidPrefix = source_guid_prefix_;
802
0
    valid &= CDRMessage::readEntityId(msg, &ch.writerGUID.entityId);
803
804
0
    writerID = ch.writerGUID.entityId;
805
806
    //Get sequence number
807
0
    valid &= CDRMessage::readSequenceNumber(msg, &ch.sequenceNumber);
808
809
0
    if (!valid)
810
0
    {
811
0
        return false;
812
0
    }
813
814
0
    if (ch.sequenceNumber <= SequenceNumber_t())
815
0
    {
816
0
        EPROSIMA_LOG_WARNING(RTPS_MSG_IN, IDSTRING "Invalid message received, bad sequence Number");
817
0
        return false;
818
0
    }
819
820
    // Get the vendor id
821
0
    ch.vendor_id = source_vendor_id_;
822
823
    //Jump ahead if more parameters are before inlineQos (not in this version, maybe if further minor versions.)
824
0
    if (octetsToInlineQos > RTPSMESSAGE_OCTETSTOINLINEQOS_DATASUBMSG)
825
0
    {
826
0
        msg->pos += (octetsToInlineQos - RTPSMESSAGE_OCTETSTOINLINEQOS_DATASUBMSG);
827
0
        if (msg->pos > msg->length)
828
0
        {
829
0
            EPROSIMA_LOG_WARNING(RTPS_MSG_IN,
830
0
                    IDSTRING "Invalid jump through msg, msg->pos " << msg->pos << " > msg->length " << msg->length);
831
0
            return false;
832
0
        }
833
0
    }
834
835
0
    uint32_t inlineQosSize {0};
836
837
0
    if (inlineQosFlag)
838
0
    {
839
0
        if (!ParameterList::updateCacheChangeFromInlineQos(ch, msg, inlineQosSize))
840
0
        {
841
0
            EPROSIMA_LOG_INFO(RTPS_MSG_IN, IDSTRING "SubMessage Data ERROR, Inline Qos ParameterList error");
842
0
            return false;
843
0
        }
844
0
        ch.inline_qos.data = &msg->buffer[msg->pos - inlineQosSize];
845
0
        ch.inline_qos.max_size = inlineQosSize;
846
0
        ch.inline_qos.length = inlineQosSize;
847
0
        ch.inline_qos.encapsulation = endiannessFlag ? PL_CDR_LE : PL_CDR_BE;
848
0
        ch.inline_qos.pos = 0;
849
0
    }
850
851
0
    if (dataFlag || keyFlag)
852
0
    {
853
0
        uint32_t payload_size;
854
0
        const uint32_t submsg_no_payload_size =
855
0
                RTPSMESSAGE_DATA_EXTRA_INLINEQOS_SIZE + octetsToInlineQos + inlineQosSize;
856
857
        // Prevent integer overflow of variable payload_size
858
0
        if (smh->submessageLength < submsg_no_payload_size)
859
0
        {
860
0
            EPROSIMA_LOG_WARNING(RTPS_MSG_IN, IDSTRING "Serialized Payload avoided overflow "
861
0
                    "(" << smh->submessageLength << "/" << submsg_no_payload_size << ")");
862
0
            ch.serializedPayload.data = nullptr;
863
0
            ch.inline_qos.data = nullptr;
864
0
            return false;
865
0
        }
866
867
0
        payload_size = smh->submessageLength - submsg_no_payload_size;
868
0
        uint32_t next_pos {msg->pos + payload_size};
869
0
        if (msg->length >= next_pos && payload_size > 0)
870
0
        {
871
0
            ch.serializedPayload.data = &msg->buffer[msg->pos];
872
0
            ch.serializedPayload.length = payload_size;
873
0
            ch.serializedPayload.max_size = payload_size;
874
0
            ch.serializedPayload.is_serialized_key = keyFlag;
875
0
            msg->pos = next_pos;
876
0
        }
877
0
        else
878
0
        {
879
0
            EPROSIMA_LOG_WARNING(RTPS_MSG_IN,
880
0
                    IDSTRING "Serialized Payload value invalid or larger than maximum allowed size"
881
0
                    "(" << payload_size << "/" << (msg->length - msg->pos) << ")");
882
0
            ch.serializedPayload.data = nullptr;
883
0
            ch.inline_qos.data = nullptr;
884
0
            return false;
885
0
        }
886
0
    }
887
888
    // Set sourcetimestamp
889
0
    if (have_timestamp_)
890
0
    {
891
0
        ch.sourceTimestamp = timestamp_;
892
0
    }
893
894
0
    EPROSIMA_LOG_INFO(RTPS_MSG_IN, IDSTRING "from Writer " << ch.writerGUID << "; possible Reader entities: "
895
0
                                                           << associated_readers_.size());
896
897
    //Look for the correct reader to add the change
898
0
    process_data_message_function_(readerID, ch, was_decoded);
899
900
0
    IPayloadPool* payload_pool = ch.serializedPayload.payload_owner;
901
0
    if (payload_pool)
902
0
    {
903
0
        payload_pool->release_payload(ch.serializedPayload);
904
0
    }
905
906
    //TODO(Ricardo) If an exception is thrown (ex, by fastcdr), these lines are not executed -> segmentation fault
907
0
    ch.serializedPayload.data = nullptr;
908
0
    ch.inline_qos.data = nullptr;
909
910
0
    EPROSIMA_LOG_INFO(RTPS_MSG_IN, IDSTRING "Sub Message DATA processed");
911
0
    return true;
912
0
}
913
914
bool MessageReceiver::proc_Submsg_DataFrag(
915
        CDRMessage_t* msg,
916
        SubmessageHeader_t* smh,
917
        bool was_decoded) const
918
27
{
919
27
    eprosima::shared_lock<eprosima::shared_mutex> guard(mtx_);
920
921
    //READ and PROCESS
922
27
    if (smh->submessageLength < RTPSMESSAGE_DATA_MIN_LENGTH)
923
11
    {
924
11
        EPROSIMA_LOG_INFO(RTPS_MSG_IN, IDSTRING "Too short submessage received, ignoring");
925
11
        return false;
926
11
    }
927
928
    //Fill flags bool values
929
16
    bool endiannessFlag {(smh->flags & BIT(0)) != 0};
930
16
    bool inlineQosFlag {(smh->flags & BIT(1)) != 0};
931
16
    bool keyFlag {(smh->flags & BIT(2)) != 0};
932
933
    //Assign message endianness
934
16
    if (endiannessFlag)
935
7
    {
936
7
        msg->msg_endian = LITTLEEND;
937
7
    }
938
9
    else
939
9
    {
940
9
        msg->msg_endian = BIGEND;
941
9
    }
942
943
    //Extra flags don't matter now. Avoid those bytes
944
16
    msg->pos += 2;
945
946
16
    bool valid {true};
947
16
    uint16_t octetsToInlineQos {0};
948
16
    valid &= CDRMessage::readUInt16(msg, &octetsToInlineQos); //it should be 16 in this implementation
949
950
    //reader and writer ID
951
16
    BaseReader* first_reader = nullptr;
952
16
    EntityId_t readerID;
953
16
    valid &= CDRMessage::readEntityId(msg, &readerID);
954
955
    //WE KNOW THE READER THAT THE MESSAGE IS DIRECTED TO SO WE LOOK FOR IT:
956
16
    if (!willAReaderAcceptMsgDirectedTo(readerID, first_reader))
957
16
    {
958
16
        return false;
959
16
    }
960
961
    //FOUND THE READER.
962
    //We ask the reader for a cachechange to store the information.
963
0
    CacheChange_t ch;
964
0
    ch.kind = ALIVE;
965
0
    ch.writerGUID.guidPrefix = source_guid_prefix_;
966
0
    valid &= CDRMessage::readEntityId(msg, &ch.writerGUID.entityId);
967
968
    //Get sequence number
969
0
    valid &= CDRMessage::readSequenceNumber(msg, &ch.sequenceNumber);
970
971
0
    if (ch.sequenceNumber <= SequenceNumber_t())
972
0
    {
973
0
        EPROSIMA_LOG_WARNING(RTPS_MSG_IN, IDSTRING "Invalid message received, bad sequence Number");
974
0
        return false;
975
0
    }
976
977
    // Get the vendor id
978
0
    ch.vendor_id = source_vendor_id_;
979
980
    // READ FRAGMENT NUMBER
981
0
    uint32_t fragmentStartingNum {0};
982
0
    valid &= CDRMessage::readUInt32(msg, &fragmentStartingNum);
983
984
    // READ FRAGMENTSINSUBMESSAGE
985
0
    uint16_t fragmentsInSubmessage {0};
986
0
    valid &= CDRMessage::readUInt16(msg, &fragmentsInSubmessage);
987
988
    // READ FRAGMENTSIZE
989
0
    uint16_t fragmentSize {0};
990
0
    valid &= CDRMessage::readUInt16(msg, &fragmentSize);
991
992
    // READ SAMPLESIZE
993
0
    uint32_t sampleSize {0};
994
0
    valid &= CDRMessage::readUInt32(msg, &sampleSize);
995
996
0
    if (!valid)
997
0
    {
998
0
        return false;
999
0
    }
1000
1001
    //Jump ahead if more parameters are before inlineQos (not in this version, maybe if further minor versions.)
1002
0
    if (octetsToInlineQos > RTPSMESSAGE_OCTETSTOINLINEQOS_DATAFRAGSUBMSG)
1003
0
    {
1004
0
        msg->pos += (octetsToInlineQos - RTPSMESSAGE_OCTETSTOINLINEQOS_DATAFRAGSUBMSG);
1005
0
        if (msg->pos > msg->length)
1006
0
        {
1007
0
            EPROSIMA_LOG_WARNING(RTPS_MSG_IN,
1008
0
                    IDSTRING "Invalid jump through msg, msg->pos " << msg->pos << " > msg->length " << msg->length);
1009
0
            return false;
1010
0
        }
1011
0
    }
1012
1013
0
    uint32_t inlineQosSize {0};
1014
1015
0
    if (inlineQosFlag)
1016
0
    {
1017
0
        if (!ParameterList::updateCacheChangeFromInlineQos(ch, msg, inlineQosSize))
1018
0
        {
1019
0
            EPROSIMA_LOG_INFO(RTPS_MSG_IN, IDSTRING "SubMessage Data ERROR, Inline Qos ParameterList error");
1020
0
            return false;
1021
0
        }
1022
0
        ch.inline_qos.data = &msg->buffer[msg->pos - inlineQosSize];
1023
0
        ch.inline_qos.max_size = inlineQosSize;
1024
0
        ch.inline_qos.length = inlineQosSize;
1025
0
        ch.inline_qos.encapsulation = endiannessFlag ? PL_CDR_LE : PL_CDR_BE;
1026
0
        ch.inline_qos.pos = 0;
1027
0
    }
1028
1029
0
    uint32_t payload_size;
1030
0
    const uint32_t submsg_no_payload_size = RTPSMESSAGE_DATA_EXTRA_INLINEQOS_SIZE + octetsToInlineQos + inlineQosSize;
1031
0
    if (smh->submessageLength < submsg_no_payload_size)
1032
0
    {
1033
0
        EPROSIMA_LOG_WARNING(RTPS_MSG_IN, IDSTRING "Serialized Payload avoided underflow "
1034
0
                "(" << smh->submessageLength << "/" << submsg_no_payload_size << ")");
1035
0
        ch.serializedPayload.data = nullptr;
1036
0
        ch.inline_qos.data = nullptr;
1037
0
        return false;
1038
0
    }
1039
0
    payload_size = smh->submessageLength - submsg_no_payload_size;
1040
1041
    // Validations??? XXX TODO
1042
1043
0
    uint32_t next_pos {msg->pos + payload_size};
1044
0
    if (msg->length >= next_pos && payload_size > 0)
1045
0
    {
1046
0
        ch.serializedPayload.data = &msg->buffer[msg->pos];
1047
0
        ch.serializedPayload.length = payload_size;
1048
0
        ch.serializedPayload.max_size = payload_size;
1049
0
        ch.serializedPayload.is_serialized_key = keyFlag;
1050
0
        ch.setFragmentSize(fragmentSize);
1051
1052
0
        msg->pos = next_pos;
1053
0
    }
1054
0
    else
1055
0
    {
1056
0
        EPROSIMA_LOG_WARNING(RTPS_MSG_IN,
1057
0
                IDSTRING "Serialized Payload value invalid or larger than maximum allowed size "
1058
0
                "(" << payload_size << "/" << (msg->length - msg->pos) << ")");
1059
0
        ch.serializedPayload.data = nullptr;
1060
0
        ch.inline_qos.data = nullptr;
1061
0
        return false;
1062
0
    }
1063
1064
    // Set sourcetimestamp
1065
0
    if (have_timestamp_)
1066
0
    {
1067
0
        ch.sourceTimestamp = timestamp_;
1068
0
    }
1069
1070
0
    EPROSIMA_LOG_INFO(RTPS_MSG_IN, IDSTRING "from Writer " << ch.writerGUID << "; possible Reader entities: "
1071
0
                                                           << associated_readers_.size());
1072
0
    process_data_fragment_message_function_(readerID, ch, sampleSize, fragmentStartingNum, fragmentsInSubmessage,
1073
0
            was_decoded);
1074
0
    ch.serializedPayload.data = nullptr;
1075
0
    ch.inline_qos.data = nullptr;
1076
1077
0
    EPROSIMA_LOG_INFO(RTPS_MSG_IN, IDSTRING "Sub Message DATA_FRAG processed");
1078
1079
0
    return true;
1080
0
}
1081
1082
bool MessageReceiver::proc_Submsg_Heartbeat(
1083
        CDRMessage_t* msg,
1084
        SubmessageHeader_t* smh,
1085
        bool was_decoded) const
1086
3.10k
{
1087
3.10k
    eprosima::shared_lock<eprosima::shared_mutex> guard(mtx_);
1088
1089
3.10k
    bool endiannessFlag {(smh->flags & BIT(0)) != 0};
1090
3.10k
    bool finalFlag {(smh->flags & BIT(1)) != 0};
1091
3.10k
    bool livelinessFlag {(smh->flags & BIT(2)) != 0};
1092
    //Assign message endianness
1093
3.10k
    if (endiannessFlag)
1094
1.03k
    {
1095
1.03k
        msg->msg_endian = LITTLEEND;
1096
1.03k
    }
1097
2.06k
    else
1098
2.06k
    {
1099
2.06k
        msg->msg_endian = BIGEND;
1100
2.06k
    }
1101
1102
3.10k
    GUID_t readerGUID;
1103
3.10k
    GUID_t writerGUID;
1104
3.10k
    readerGUID.guidPrefix = dest_guid_prefix_;
1105
3.10k
    CDRMessage::readEntityId(msg, &readerGUID.entityId);
1106
3.10k
    writerGUID.guidPrefix = source_guid_prefix_;
1107
3.10k
    CDRMessage::readEntityId(msg, &writerGUID.entityId);
1108
3.10k
    SequenceNumber_t firstSN;
1109
3.10k
    SequenceNumber_t lastSN;
1110
3.10k
    CDRMessage::readSequenceNumber(msg, &firstSN);
1111
3.10k
    CDRMessage::readSequenceNumber(msg, &lastSN);
1112
1113
3.10k
    SequenceNumber_t zeroSN;
1114
3.10k
    if (firstSN <= zeroSN)
1115
56
    {
1116
56
        EPROSIMA_LOG_WARNING(RTPS_MSG_IN, IDSTRING "Invalid Heartbeat received (" << firstSN << " <= 0), ignoring");
1117
56
        return false;
1118
56
    }
1119
3.04k
    if (lastSN < firstSN && lastSN != firstSN - 1)
1120
208
    {
1121
208
        EPROSIMA_LOG_WARNING(RTPS_MSG_IN, IDSTRING "Invalid Heartbeat received (" << firstSN << ") - ("
1122
208
                                                                                  << lastSN << "), ignoring");
1123
208
        return false;
1124
208
    }
1125
2.83k
    uint32_t HBCount {0};
1126
2.83k
    if (!CDRMessage::readUInt32(msg, &HBCount))
1127
32
    {
1128
32
        EPROSIMA_LOG_WARNING(RTPS_MSG_IN, IDSTRING "Unable to read heartbeat count from heartbeat message");
1129
32
        return false;
1130
32
    }
1131
1132
    //Look for the correct reader and writers:
1133
2.80k
    findAllReaders(readerGUID.entityId,
1134
2.80k
            [was_decoded, &writerGUID, &HBCount, &firstSN, &lastSN, finalFlag, livelinessFlag, this](
1135
2.80k
                BaseReader* reader)
1136
2.80k
            {
1137
                // Only used when HAVE_SECURITY is defined
1138
0
                static_cast<void>(was_decoded);
1139
#if HAVE_SECURITY
1140
                if (was_decoded || !reader->getAttributes().security_attributes().is_submessage_protected)
1141
#endif  // HAVE_SECURITY
1142
0
                {
1143
0
                    reader->process_heartbeat_msg(writerGUID, HBCount, firstSN, lastSN, finalFlag, livelinessFlag,
1144
0
                    source_vendor_id_);
1145
0
                }
1146
0
            });
1147
1148
2.80k
    return true;
1149
2.83k
}
1150
1151
bool MessageReceiver::proc_Submsg_Acknack(
1152
        CDRMessage_t* msg,
1153
        SubmessageHeader_t* smh,
1154
        bool was_decoded) const
1155
330
{
1156
    // Only used when HAVE_SECURITY is defined
1157
330
    static_cast<void>(was_decoded);
1158
1159
330
    eprosima::shared_lock<eprosima::shared_mutex> guard(mtx_);
1160
1161
330
    bool endiannessFlag {(smh->flags & BIT(0)) != 0};
1162
330
    bool finalFlag {(smh->flags & BIT(1)) != 0};
1163
    //Assign message endianness
1164
330
    if (endiannessFlag)
1165
95
    {
1166
95
        msg->msg_endian = LITTLEEND;
1167
95
    }
1168
235
    else
1169
235
    {
1170
235
        msg->msg_endian = BIGEND;
1171
235
    }
1172
330
    GUID_t readerGUID;
1173
330
    GUID_t writerGUID;
1174
330
    readerGUID.guidPrefix = source_guid_prefix_;
1175
330
    CDRMessage::readEntityId(msg, &readerGUID.entityId);
1176
330
    writerGUID.guidPrefix = dest_guid_prefix_;
1177
330
    CDRMessage::readEntityId(msg, &writerGUID.entityId);
1178
1179
330
    SequenceNumberSet_t SNSet = CDRMessage::readSequenceNumberSet(msg);
1180
330
    uint32_t Ackcount {0};
1181
330
    if (!CDRMessage::readUInt32(msg, &Ackcount))
1182
311
    {
1183
311
        EPROSIMA_LOG_WARNING(RTPS_MSG_IN, IDSTRING "Unable to read ackcount from message");
1184
311
        return false;
1185
311
    }
1186
1187
    //Look for the correct writer to use the acknack
1188
19
    for (BaseWriter* it : associated_writers_)
1189
0
    {
1190
#if HAVE_SECURITY
1191
        if (was_decoded || !it->getAttributes().security_attributes().is_submessage_protected)
1192
#endif  // HAVE_SECURITY
1193
0
        {
1194
0
            bool result;
1195
0
            if (it->process_acknack(writerGUID, readerGUID, Ackcount, SNSet, finalFlag, result, source_vendor_id_))
1196
0
            {
1197
0
                if (!result)
1198
0
                {
1199
0
                    EPROSIMA_LOG_INFO(RTPS_MSG_IN, IDSTRING "Acknack msg to NOT stateful writer ");
1200
0
                }
1201
0
                return result;
1202
0
            }
1203
0
        }
1204
0
    }
1205
19
    EPROSIMA_LOG_INFO(RTPS_MSG_IN, IDSTRING "Acknack msg to UNKNOWN writer (I looked through "
1206
19
            << associated_writers_.size() << " writers in this ListenResource)");
1207
19
    return false;
1208
19
}
1209
1210
bool MessageReceiver::proc_Submsg_Gap(
1211
        CDRMessage_t* msg,
1212
        SubmessageHeader_t* smh,
1213
        bool was_decoded) const
1214
5.89k
{
1215
5.89k
    eprosima::shared_lock<eprosima::shared_mutex> guard(mtx_);
1216
1217
5.89k
    bool endiannessFlag {(smh->flags & BIT(0)) != 0};
1218
    //Assign message endianness
1219
5.89k
    if (endiannessFlag)
1220
3.12k
    {
1221
3.12k
        msg->msg_endian = LITTLEEND;
1222
3.12k
    }
1223
2.77k
    else
1224
2.77k
    {
1225
2.77k
        msg->msg_endian = BIGEND;
1226
2.77k
    }
1227
1228
5.89k
    GUID_t writerGUID;
1229
5.89k
    GUID_t readerGUID;
1230
5.89k
    readerGUID.guidPrefix = dest_guid_prefix_;
1231
5.89k
    CDRMessage::readEntityId(msg, &readerGUID.entityId);
1232
5.89k
    writerGUID.guidPrefix = source_guid_prefix_;
1233
5.89k
    CDRMessage::readEntityId(msg, &writerGUID.entityId);
1234
5.89k
    SequenceNumber_t gapStart;
1235
5.89k
    CDRMessage::readSequenceNumber(msg, &gapStart);
1236
5.89k
    SequenceNumberSet_t gapList = CDRMessage::readSequenceNumberSet(msg);
1237
5.89k
    if (gapStart <= SequenceNumber_t(0, 0))
1238
120
    {
1239
120
        return false;
1240
120
    }
1241
1242
5.77k
    findAllReaders(readerGUID.entityId,
1243
5.77k
            [was_decoded, &writerGUID, &gapStart, &gapList, this](BaseReader* reader)
1244
5.77k
            {
1245
                // Only used when HAVE_SECURITY is defined
1246
0
                static_cast<void>(was_decoded);
1247
#if HAVE_SECURITY
1248
                if (was_decoded || !reader->getAttributes().security_attributes().is_submessage_protected)
1249
#endif  // HAVE_SECURITY
1250
0
                {
1251
0
                    reader->process_gap_msg(writerGUID, gapStart, gapList, source_vendor_id_);
1252
0
                }
1253
0
            });
1254
1255
5.77k
    return true;
1256
5.89k
}
1257
1258
bool MessageReceiver::proc_Submsg_InfoTS(
1259
        CDRMessage_t* msg,
1260
        SubmessageHeader_t* smh)
1261
5.00k
{
1262
5.00k
    std::lock_guard<eprosima::shared_mutex> guard(mtx_);
1263
1264
5.00k
    bool endiannessFlag {(smh->flags & BIT(0)) != 0};
1265
5.00k
    bool timeFlag {(smh->flags & BIT(1)) != 0};
1266
    //Assign message endianness
1267
5.00k
    if (endiannessFlag)
1268
2.56k
    {
1269
2.56k
        msg->msg_endian = LITTLEEND;
1270
2.56k
    }
1271
2.44k
    else
1272
2.44k
    {
1273
2.44k
        msg->msg_endian = BIGEND;
1274
2.44k
    }
1275
5.00k
    if (!timeFlag)
1276
3.82k
    {
1277
3.82k
        have_timestamp_ = true;
1278
3.82k
        CDRMessage::readTimestamp(msg, &timestamp_);
1279
3.82k
    }
1280
1.18k
    else
1281
1.18k
    {
1282
1.18k
        have_timestamp_ = false;
1283
1.18k
    }
1284
1285
5.00k
    return true;
1286
5.00k
}
1287
1288
bool MessageReceiver::proc_Submsg_InfoDST(
1289
        CDRMessage_t* msg,
1290
        SubmessageHeader_t* smh)
1291
1.56k
{
1292
1.56k
    std::lock_guard<eprosima::shared_mutex> guard(mtx_);
1293
1294
1.56k
    bool endiannessFlag {(smh->flags & BIT(0)) != 0u};
1295
    //bool timeFlag = smh->flags & BIT(1) ? true : false;
1296
    //Assign message endianness
1297
1.56k
    if (endiannessFlag)
1298
819
    {
1299
819
        msg->msg_endian = LITTLEEND;
1300
819
    }
1301
750
    else
1302
750
    {
1303
750
        msg->msg_endian = BIGEND;
1304
750
    }
1305
1.56k
    GuidPrefix_t guidP;
1306
1.56k
    CDRMessage::readData(msg, guidP.value, GuidPrefix_t::size);
1307
1.56k
    if (guidP != c_GuidPrefix_Unknown)
1308
1.31k
    {
1309
1.31k
        dest_guid_prefix_ = guidP;
1310
1.31k
        EPROSIMA_LOG_INFO(RTPS_MSG_IN, IDSTRING "DST RTPSParticipant is now: " << dest_guid_prefix_);
1311
1.31k
    }
1312
1.56k
    return true;
1313
1.56k
}
1314
1315
bool MessageReceiver::proc_Submsg_InfoSRC(
1316
        CDRMessage_t* msg,
1317
        SubmessageHeader_t* smh)
1318
921
{
1319
921
    std::lock_guard<eprosima::shared_mutex> guard(mtx_);
1320
1321
921
    bool endiannessFlag {(smh->flags & BIT(0)) != 0};
1322
    //bool timeFlag = smh->flags & BIT(1) ? true : false;
1323
    //Assign message endianness
1324
921
    if (endiannessFlag)
1325
373
    {
1326
373
        msg->msg_endian = LITTLEEND;
1327
373
    }
1328
548
    else
1329
548
    {
1330
548
        msg->msg_endian = BIGEND;
1331
548
    }
1332
921
    if (smh->submessageLength == INFO_SRC_SUBMSG_LENGTH)
1333
883
    {
1334
        //AVOID FIRST 4 BYTES:
1335
883
        msg->pos += 4;
1336
883
        CDRMessage::readOctet(msg, &source_version_.m_major);
1337
883
        CDRMessage::readOctet(msg, &source_version_.m_minor);
1338
883
        CDRMessage::readData(msg, &source_vendor_id_[0], 2);
1339
883
        CDRMessage::readData(msg, source_guid_prefix_.value, GuidPrefix_t::size);
1340
883
        EPROSIMA_LOG_INFO(RTPS_MSG_IN, IDSTRING "SRC RTPSParticipant is now: " << source_guid_prefix_);
1341
883
        return true;
1342
883
    }
1343
38
    return false;
1344
921
}
1345
1346
bool MessageReceiver::proc_Submsg_NackFrag(
1347
        CDRMessage_t* msg,
1348
        SubmessageHeader_t* smh,
1349
        bool was_decoded) const
1350
137
{
1351
    // Only used when HAVE_SECURITY is defined
1352
137
    static_cast<void>(was_decoded);
1353
1354
137
    eprosima::shared_lock<eprosima::shared_mutex> guard(mtx_);
1355
1356
137
    bool endiannessFlag {(smh->flags & BIT(0)) != 0};
1357
    //Assign message endianness
1358
137
    if (endiannessFlag)
1359
57
    {
1360
57
        msg->msg_endian = LITTLEEND;
1361
57
    }
1362
80
    else
1363
80
    {
1364
80
        msg->msg_endian = BIGEND;
1365
80
    }
1366
1367
137
    GUID_t readerGUID;
1368
137
    GUID_t writerGUID;
1369
137
    readerGUID.guidPrefix = source_guid_prefix_;
1370
137
    CDRMessage::readEntityId(msg, &readerGUID.entityId);
1371
137
    writerGUID.guidPrefix = dest_guid_prefix_;
1372
137
    CDRMessage::readEntityId(msg, &writerGUID.entityId);
1373
1374
137
    SequenceNumber_t writerSN;
1375
137
    CDRMessage::readSequenceNumber(msg, &writerSN);
1376
1377
137
    FragmentNumberSet_t fnState;
1378
137
    CDRMessage::readFragmentNumberSet(msg, &fnState);
1379
1380
137
    uint32_t Ackcount {0};
1381
137
    if (!CDRMessage::readUInt32(msg, &Ackcount))
1382
117
    {
1383
117
        EPROSIMA_LOG_INFO(RTPS_MSG_IN, IDSTRING "Unable to read ackcount from message");
1384
117
        return false;
1385
117
    }
1386
1387
    //Look for the correct writer to use the acknack
1388
20
    for (BaseWriter* it : associated_writers_)
1389
0
    {
1390
#if HAVE_SECURITY
1391
        if (was_decoded || !it->getAttributes().security_attributes().is_submessage_protected)
1392
#endif  // HAVE_SECURITY
1393
0
        {
1394
0
            bool result;
1395
0
            if (it->process_nack_frag(writerGUID, readerGUID, Ackcount, writerSN, fnState, result, source_vendor_id_))
1396
0
            {
1397
0
                if (!result)
1398
0
                {
1399
0
                    EPROSIMA_LOG_INFO(RTPS_MSG_IN, IDSTRING "Acknack msg to NOT stateful writer ");
1400
0
                }
1401
0
                return result;
1402
0
            }
1403
0
        }
1404
0
    }
1405
20
    EPROSIMA_LOG_INFO(RTPS_MSG_IN, IDSTRING "Acknack msg to UNKNOWN writer (I looked through "
1406
20
            << associated_writers_.size() << " writers in this ListenResource)");
1407
20
    return false;
1408
20
}
1409
1410
bool MessageReceiver::proc_Submsg_HeartbeatFrag(
1411
        CDRMessage_t* msg,
1412
        SubmessageHeader_t* smh,
1413
        bool was_decoded) const
1414
84
{
1415
    // TODO: Add support for HEARTBEAT_FRAG submessage
1416
84
    static_cast<void>(msg);
1417
84
    static_cast<void>(smh);
1418
84
    static_cast<void>(was_decoded);
1419
1420
84
    return true;
1421
84
}
1422
1423
void MessageReceiver::notify_network_statistics(
1424
        const Locator_t& source_locator,
1425
        const Locator_t& reception_locator,
1426
        CDRMessage_t* msg) const
1427
1.67k
{
1428
1.67k
    static_cast<void>(source_locator);
1429
1.67k
    static_cast<void>(reception_locator);
1430
1.67k
    static_cast<void>(msg);
1431
1432
1.67k
#ifdef FASTDDS_STATISTICS
1433
1.67k
    using namespace eprosima::fastdds::statistics;
1434
1.67k
    using namespace eprosima::fastdds::statistics::rtps;
1435
1436
1.67k
    if ((c_VendorId_eProsima != source_vendor_id_) ||
1437
343
            (LOCATOR_KIND_SHM == source_locator.kind))
1438
1.32k
    {
1439
1.32k
        return;
1440
1.32k
    }
1441
1442
    // Keep track of current position, so we can restore it later.
1443
343
    uint32_t initial_pos {msg->pos};
1444
343
    uint32_t msg_length {msg->length};
1445
10.1k
    while (msg->pos < msg_length)
1446
10.0k
    {
1447
10.0k
        SubmessageHeader_t header;
1448
10.0k
        if (!readSubmessageHeader(msg, &header))
1449
134
        {
1450
134
            break;
1451
134
        }
1452
1453
9.95k
        if (FASTDDS_STATISTICS_NETWORK_SUBMESSAGE == header.submessageId)
1454
89
        {
1455
            // Check submessage validity
1456
89
            if ((statistics_submessage_data_length != header.submessageLength) ||
1457
70
                    ((msg->pos + header.submessageLength) > msg_length))
1458
19
            {
1459
19
                break;
1460
19
            }
1461
1462
70
            StatisticsSubmessageData data;
1463
70
            read_statistics_submessage(msg, data);
1464
#if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
1465
            participant_->on_network_statistics(
1466
                source_guid_prefix_, source_locator, reception_locator, data, msg_length);
1467
#endif // if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
1468
70
            break;
1469
89
        }
1470
1471
9.86k
        if (header.is_last)
1472
64
        {
1473
64
            break;
1474
64
        }
1475
9.80k
        msg->pos += (header.submessageLength + 3u) & ~3u;
1476
9.80k
    }
1477
1478
343
    msg->pos = initial_pos;
1479
343
#endif // FASTDDS_STATISTICS
1480
343
}
1481
1482
} /* namespace rtps */
1483
} /* namespace fastdds */
1484
} /* namespace eprosima */