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/statistics/rtps/messages/RTPSStatisticsMessages.hpp
Line
Count
Source
1
// Copyright 2021 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 RTPSStatisticsMessages.hpp
17
 */
18
19
#ifndef _STATISTICS_RTPS_MESSAGES_RTPSSTATISTICSMESSAGES_HPP_
20
#define _STATISTICS_RTPS_MESSAGES_RTPSSTATISTICSMESSAGES_HPP_
21
22
#include <cstddef>
23
#include <cstdint>
24
#include <cstring>
25
26
#include <fastdds/rtps/common/CDRMessage_t.hpp>
27
#include <fastdds/rtps/common/Types.hpp>
28
#include <rtps/messages/CDRMessage.hpp>
29
#include <rtps/messages/RTPSMessageCreator.hpp>
30
31
8.61k
#define FASTDDS_STATISTICS_NETWORK_SUBMESSAGE 0x80
32
33
namespace eprosima {
34
namespace fastdds {
35
namespace statistics {
36
namespace rtps {
37
38
struct StatisticsSubmessageData
39
{
40
    struct TimeStamp
41
    {
42
        int32_t seconds = 0;
43
        uint32_t fraction = 0;
44
    };
45
46
    struct Sequence
47
    {
48
        uint64_t sequence = 0;
49
        uint64_t bytes = 0;
50
        uint16_t bytes_high = 0;
51
52
        void add_message(
53
                uint32_t message_size)
54
0
        {
55
0
            sequence++;
56
0
            auto new_bytes = bytes + message_size;
57
0
            bytes_high += (new_bytes < bytes);
58
0
            bytes = new_bytes;
59
0
        }
60
61
        static Sequence distance(
62
                const Sequence& from,
63
                const Sequence& to)
64
0
        {
65
            // Check to >= from
66
0
            assert(to.sequence >= from.sequence);
67
0
            assert(to.bytes_high >= from.bytes_high);
68
0
            assert((to.bytes_high > from.bytes_high) || (to.bytes >= from.bytes));
69
70
0
            Sequence ret;
71
0
            ret.sequence = to.sequence - from.sequence;
72
0
            ret.bytes_high = to.bytes_high - from.bytes_high;
73
0
            ret.bytes = to.bytes - from.bytes;
74
0
            ret.bytes_high -= (ret.bytes > to.bytes);
75
76
0
            return ret;
77
0
        }
78
79
    };
80
81
    eprosima::fastdds::rtps::Locator_t destination;
82
    TimeStamp ts{};
83
    Sequence seq{};
84
};
85
86
constexpr uint16_t statistics_submessage_data_length = sizeof(StatisticsSubmessageData);
87
constexpr uint16_t statistics_submessage_length =
88
        RTPSMESSAGE_SUBMESSAGEHEADER_SIZE + // submessage header
89
        statistics_submessage_data_length;  // submessage data
90
91
/**
92
 * @brief Adds an empty statistics submessage to a message.
93
 * @param msg Message where the statistics submessage will be added.
94
 * @pre There should be room in the message for the statistics submessage.
95
 */
96
inline void add_statistics_submessage(
97
        eprosima::fastdds::rtps::CDRMessage_t* msg)
98
0
{
99
0
    static_cast<void>(msg);
100
101
0
#ifdef FASTDDS_STATISTICS
102
0
    assert(msg->max_size >= msg->length + statistics_submessage_length);
103
104
0
    using namespace eprosima::fastdds::rtps;
105
0
    RTPSMessageCreator::addSubmessageHeader(
106
0
        msg, FASTDDS_STATISTICS_NETWORK_SUBMESSAGE, 0x00, statistics_submessage_data_length);
107
0
    memset(msg->buffer + msg->pos, 0, statistics_submessage_data_length);
108
0
    msg->length += statistics_submessage_data_length;
109
0
    msg->pos += statistics_submessage_data_length;
110
0
#endif // FASTDDS_STATISTICS
111
0
}
112
113
/**
114
 * @brief Read a statistics submessage from a message.
115
 * @param [in,out] msg Message from where to extract the submessage.
116
 * @param [out] data Data read from the statistics submessage.
117
 * @pre msg->pos should point to the beginning of the statistics submessage payload
118
 * @post msg->length will be decremented by @c statistics_submessage_length (i.e. the
119
 *       submessage will be consumed, and it won't be available anymore)
120
 */
121
inline void read_statistics_submessage(
122
        eprosima::fastdds::rtps::CDRMessage_t* msg,
123
        StatisticsSubmessageData& data)
124
22
{
125
22
    static_cast<void>(msg);
126
22
    static_cast<void>(data);
127
128
22
#ifdef FASTDDS_STATISTICS
129
    // Should be exactly at the end
130
22
    assert(msg->pos + statistics_submessage_data_length == msg->length);
131
132
    // Read all fields
133
22
    using namespace eprosima::fastdds::rtps;
134
22
    CDRMessage::read_locator(msg, &data.destination);
135
22
    CDRMessage::readInt32(msg, &data.ts.seconds);
136
22
    CDRMessage::readUInt32(msg, &data.ts.fraction);
137
22
    CDRMessage::readUInt64(msg, &data.seq.sequence);
138
22
    CDRMessage::readUInt64(msg, &data.seq.bytes);
139
22
    CDRMessage::readUInt16(msg, &data.seq.bytes_high);
140
141
    // Consume submessage
142
22
    msg->length -= statistics_submessage_length;
143
22
    msg->pos = msg->length;
144
22
#endif // FASTDDS_STATISTICS
145
22
}
146
147
#ifdef FASTDDS_STATISTICS
148
inline uint32_t get_statistics_message_pos(
149
        const eprosima::fastdds::rtps::octet* send_buffer,
150
        uint32_t send_buffer_size)
151
0
{
152
0
    // zero can be use as an error value because the minimum valid value
153
0
    // is RTPSMESSAGE_HEADER_SIZE
154
0
    uint32_t statistics_pos = 0;
155
0
156
0
    // Message should contain RTPS header and statistic submessage
157
0
    if (statistics_submessage_length + RTPSMESSAGE_HEADER_SIZE <= send_buffer_size)
158
0
    {
159
0
        // The last submessage should be the statistics submessage
160
0
        uint32_t pos = send_buffer_size - statistics_submessage_length;
161
0
        if (FASTDDS_STATISTICS_NETWORK_SUBMESSAGE == send_buffer[pos])
162
0
        {
163
0
            // only succeed if the message is properly formatted
164
0
            statistics_pos = pos;
165
0
        }
166
0
    }
167
0
168
0
    return statistics_pos;
169
0
}
170
171
inline bool is_statistics_buffer(
172
        const eprosima::fastdds::rtps::NetworkBuffer& stat_buffer)
173
0
{
174
0
    return statistics_submessage_length == stat_buffer.size &&
175
0
           FASTDDS_STATISTICS_NETWORK_SUBMESSAGE ==
176
0
           static_cast<const eprosima::fastdds::rtps::octet*>(stat_buffer.buffer)[0];
177
0
}
178
179
#endif // FASTDDS_STATISTICS
180
181
inline void set_statistics_submessage_from_transport(
182
        const eprosima::fastdds::rtps::Locator_t& destination,
183
        const eprosima::fastdds::rtps::NetworkBuffer& send_buffer,
184
        const uint32_t& total_bytes,
185
        StatisticsSubmessageData::Sequence& sequence)
186
0
{
187
0
    static_cast<void>(destination);
188
0
    static_cast<void>(send_buffer);
189
0
    static_cast<void>(total_bytes);
190
0
    static_cast<void>(sequence);
191
192
0
#ifdef FASTDDS_STATISTICS
193
0
    using namespace eprosima::fastdds::rtps;
194
195
0
    if (is_statistics_buffer(send_buffer))
196
0
    {
197
0
        uint32_t statistics_pos = 0;
198
199
        // Accumulate bytes on sequence
200
0
        sequence.add_message(total_bytes);
201
202
        // Skip the submessage header
203
0
        statistics_pos += RTPSMESSAGE_SUBMESSAGEHEADER_SIZE;
204
205
        // Set current timestamp and sequence
206
0
        auto current_pos = &static_cast<const octet*>(send_buffer.buffer)[statistics_pos];
207
0
        eprosima::fastdds::rtps::Time_t ts;
208
0
        eprosima::fastdds::rtps::Time_t::now(ts);
209
210
        /*
211
         * This set of memcpy blocks is intended to prevent an undefined behavior caused when casting from an octet* to a StatisticsSubmessageData*
212
         * since these classes have different alignment.
213
         */
214
215
0
        memcpy((char*)current_pos + offsetof(StatisticsSubmessageData, destination), &destination, sizeof(destination));
216
0
        memcpy((char*)current_pos + offsetof(StatisticsSubmessageData, ts.seconds), &ts.seconds(),
217
0
                sizeof(StatisticsSubmessageData::ts.seconds));
218
0
        memcpy((char*)current_pos + offsetof(StatisticsSubmessageData, ts.fraction), &ts.fraction(),
219
0
                sizeof(StatisticsSubmessageData::ts.fraction));
220
0
        memcpy((char*)current_pos + offsetof(StatisticsSubmessageData, seq.sequence), &sequence.sequence,
221
0
                sizeof(sequence.sequence));
222
0
        memcpy((char*)current_pos + offsetof(StatisticsSubmessageData, seq.bytes), &sequence.bytes,
223
0
                sizeof(sequence.bytes));
224
0
        memcpy((char*)current_pos + offsetof(StatisticsSubmessageData, seq.bytes_high), &sequence.bytes_high,
225
0
                sizeof(sequence.bytes_high));
226
0
    }
227
0
#endif // FASTDDS_STATISTICS
228
0
}
229
230
inline bool remove_statistics_buffer(
231
        const eprosima::fastdds::rtps::NetworkBuffer& stat_buffer,
232
        uint32_t& total_bytes)
233
0
{
234
0
    static_cast<void>(stat_buffer);
235
0
    static_cast<void>(total_bytes);
236
237
0
#ifdef FASTDDS_STATISTICS
238
0
    if (is_statistics_buffer(stat_buffer))
239
0
    {
240
0
        total_bytes -= statistics_submessage_length;
241
0
        return true;
242
0
    }
243
0
#endif // FASTDDS_STATISTICS
244
0
    return false;
245
0
}
246
247
} // namespace rtps
248
} // namespace statistics
249
} // namespace fastdds
250
} // namespace eprosima
251
252
#endif  // _STATISTICS_RTPS_MESSAGES_RTPSSTATISTICSMESSAGES_HPP_