Coverage Report

Created: 2022-08-24 06:19

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