Coverage Report

Created: 2025-06-13 06:46

/src/Fast-DDS/src/cpp/rtps/common/GuidUtils.hpp
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2020 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 GuidUtils.hpp
17
 */
18
19
#ifndef RTPS_COMMON_GUIDUTILS_HPP_
20
#define RTPS_COMMON_GUIDUTILS_HPP_
21
22
#include <cstdint>
23
#include <limits>
24
#include <random>
25
26
#include <fastdds/rtps/common/GuidPrefix_t.hpp>
27
#include <fastdds/rtps/common/VendorId_t.hpp>
28
29
#include <utils/SystemInfo.hpp>
30
31
namespace eprosima {
32
namespace fastdds {
33
namespace rtps {
34
35
/**
36
 * This singleton handles the generation of GUID prefix
37
 */
38
class GuidUtils
39
{
40
41
public:
42
43
    /**
44
     * Create a GUID prefix based on a participant id.
45
     *
46
     * @param [in]  participant_id  Identifier of the participant for which to generate the GUID prefix.
47
     * @param [out] guid_prefix     Generated GUID prefix.
48
     */
49
    void guid_prefix_create(
50
            uint32_t participant_id,
51
            GuidPrefix_t& guid_prefix) const
52
0
    {
53
        // Use precalculated vendor-host-process part of the prefix
54
0
        std::copy(prefix_.value, prefix_.value + 8, guid_prefix.value);
55
56
        // Add little endian serialization of participant_id
57
0
        guid_prefix.value[8] = static_cast<octet>(participant_id & 0xFF);
58
0
        guid_prefix.value[9] = static_cast<octet>((participant_id >> 8) & 0xFF);
59
0
        guid_prefix.value[10] = static_cast<octet>((participant_id >> 16) & 0xFF);
60
0
        guid_prefix.value[11] = static_cast<octet>((participant_id >> 24) & 0xFF);
61
0
    }
62
63
    /**
64
     * Get a copy of \c prefix_ attribute.
65
     *
66
     * @return copy of \c prefix_ attribute.
67
     */
68
    GuidPrefix_t prefix() const
69
0
    {
70
0
        return prefix_;
71
0
    }
72
73
    /**
74
     * Get a reference to the singleton instance.
75
     *
76
     * @return reference to the singleton instance.
77
     */
78
    static const GuidUtils& instance()
79
0
    {
80
0
        static GuidUtils singleton;
81
0
        return singleton;
82
0
    }
83
84
private:
85
86
    GuidUtils()
87
0
    {
88
        // This is to comply with RTPS section 9.3.1.5 - Mapping of the GUID_t
89
0
        prefix_.value[0] = c_VendorId_eProsima[0];
90
0
        prefix_.value[1] = c_VendorId_eProsima[1];
91
92
        // On Fast DDS, next two bytes should be the same across all processes on the same host
93
0
        uint16_t host_id = SystemInfo::instance().host_id();
94
0
        prefix_.value[2] = static_cast<octet>(host_id & 0xFF);
95
0
        prefix_.value[3] = static_cast<octet>((host_id >> 8) & 0xFF);
96
97
        // On Fast DDS, next four bytes would be the same across all participants on the same process.
98
        // Even though using the process id here might seem a nice idea, there are cases where it might not serve as
99
        // unique identifier of the process:
100
        // - One of them is when using a Kubernetes pod on which several containers with their own PID namespace are
101
        //   created.
102
        // - Another one is when a system in which a Fast DDS application is started during boot time. If the system
103
        //   crashes and is then re-started, it may happen that the participant may be considered an old one if the
104
        //   announcement lease duration did not expire.
105
        // In order to behave correctly in those situations, we will use the 16 least-significant bits of the PID,
106
        // along with a random 16 bits value. This should not be a problem, as the PID is known to be 16 bits long on
107
        // several systems. On those where it is longer, using the 16 least-significant ones along with a random value
108
        // should still give enough uniqueness for our use cases.
109
0
        int pid = SystemInfo::instance().process_id();
110
0
        prefix_.value[4] = static_cast<octet>(pid & 0xFF);
111
0
        prefix_.value[5] = static_cast<octet>((pid >> 8) & 0xFF);
112
113
0
        std::random_device generator;
114
0
        std::uniform_int_distribution<uint16_t> distribution(0, std::numeric_limits<uint16_t>::max());
115
0
        uint16_t rand_value = distribution(generator);
116
0
        prefix_.value[6] = static_cast<octet>(rand_value & 0xFF);
117
0
        prefix_.value[7] = static_cast<octet>((rand_value >> 8) & 0xFF);
118
0
    }
119
120
    GuidPrefix_t prefix_;
121
};
122
123
} // namespace rtps
124
} // namespace fastdds
125
} // namespace eprosima
126
127
#endif // RTPS_COMMON_GUIDUTILS_HPP_