Coverage Report

Created: 2025-06-13 06:46

/src/Fast-DDS/src/cpp/utils/Host.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
#ifndef UTILS_HOST_HPP_
16
#define UTILS_HOST_HPP_
17
18
#include <fastcdr/cdr/fixed_size_string.hpp>
19
20
#include <fastdds/dds/log/Log.hpp>
21
#include <fastdds/rtps/common/LocatorList.hpp>
22
#include <fastdds/utils/IPFinder.hpp>
23
#include <fastdds/utils/md5.hpp>
24
25
26
namespace eprosima {
27
28
29
/**
30
 * This singleton generates a host_id based on system interfaces
31
 * ip addresses, mac addresses or the machine UUID.
32
 */
33
class Host
34
{
35
public:
36
37
    static const size_t mac_id_length = 6;
38
    struct uint48
39
    {
40
        unsigned char value[mac_id_length];
41
42
        uint48()
43
0
        {
44
0
            memset(value, 0, mac_id_length);
45
0
        }
46
47
    };
48
49
    inline uint16_t id() const
50
0
    {
51
0
        return id_;
52
0
    }
53
54
    inline uint48 mac_id() const
55
0
    {
56
0
        return mac_id_;
57
0
    }
58
59
    inline fastcdr::string_255 machine_id() const
60
0
    {
61
0
        return machine_id_;
62
0
    }
63
64
    static Host& instance()
65
0
    {
66
0
        static Host singleton;
67
0
        return singleton;
68
0
    }
69
70
    static inline uint16_t compute_id(
71
            const fastdds::rtps::LocatorList& loc)
72
0
    {
73
0
        uint16_t ret_val = 0;
74
75
0
        if (loc.size() > 0)
76
0
        {
77
0
            fastdds::MD5 md5;
78
0
            for (auto& l : loc)
79
0
            {
80
0
                md5.update(l.address, sizeof(l.address));
81
0
            }
82
0
            md5.finalize();
83
84
            // Hash the 16-bytes md5.digest into a uint16_t
85
0
            ret_val = 0;
86
0
            for (size_t i = 0; i < sizeof(md5.digest); i += 2)
87
0
            {
88
                // Treat the next two bytes as a big-endian uint16_t and
89
                // hash them into ret_val.
90
0
                uint16_t tmp = static_cast<uint16_t>(md5.digest[i]);
91
0
                tmp = (tmp << 8) | static_cast<uint16_t>(md5.digest[i + 1]);
92
0
                ret_val ^= tmp;
93
0
            }
94
0
        }
95
0
        else
96
0
        {
97
0
            reinterpret_cast<uint8_t*>(&ret_val)[0] = 127;
98
0
            reinterpret_cast<uint8_t*>(&ret_val)[1] = 1;
99
0
        }
100
101
0
        return ret_val;
102
0
    }
103
104
private:
105
106
    Host()
107
0
    {
108
        // Compute the host id
109
0
        fastdds::rtps::LocatorList loc;
110
0
        fastdds::rtps::IPFinder::getIP4Address(&loc);
111
0
        id_ = compute_id(loc);
112
113
        // Compute the MAC id
114
0
        std::vector<fastdds::rtps::IPFinder::info_MAC> macs;
115
0
        if (fastdds::rtps::IPFinder::getAllMACAddress(&macs) &&
116
0
                macs.size() > 0)
117
0
        {
118
0
            fastdds::MD5 md5;
119
0
            for (auto& m : macs)
120
0
            {
121
0
                md5.update(m.address, sizeof(m.address));
122
0
            }
123
0
            md5.finalize();
124
0
            for (size_t i = 0, j = 0; i < sizeof(md5.digest); ++i, ++j)
125
0
            {
126
0
                if (j >= mac_id_length)
127
0
                {
128
0
                    j = 0;
129
0
                }
130
0
                mac_id_.value[j] ^= md5.digest[i];
131
0
            }
132
0
        }
133
0
        else
134
0
        {
135
0
            EPROSIMA_LOG_WARNING(UTILS, "Cannot get MAC addresses. Failing back to IP based ID");
136
0
            for (size_t i = 0; i < mac_id_length; i += 2)
137
0
            {
138
0
                mac_id_.value[i] = (id_ >> 8);
139
0
                mac_id_.value[i + 1] = (id_ & 0xFF);
140
0
            }
141
0
        }
142
143
        // Compute the machine id hash
144
0
        machine_id_ = compute_machine_id();
145
0
        if (machine_id_ == "")
146
0
        {
147
0
            EPROSIMA_LOG_WARNING(UTILS, "Cannot get machine id. Failing back to IP based ID");
148
0
        }
149
0
    }
150
151
    static fastcdr::string_255 compute_machine_id();
152
153
    uint16_t id_;
154
    uint48 mac_id_;
155
    fastcdr::string_255 machine_id_;
156
};
157
158
} // eprosima
159
160
#endif // UTILS_HOST_HPP_