Coverage Report

Created: 2022-08-24 06:19

/src/Fast-DDS/include/fastdds/rtps/common/Locator.h
Line
Count
Source (jump to first uncovered line)
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 Locator.h
17
 */
18
19
#ifndef _FASTDDS_RTPS_ELEM_LOCATOR_H_
20
#define _FASTDDS_RTPS_ELEM_LOCATOR_H_
21
22
#include <fastrtps/fastrtps_dll.h>
23
24
#include <fastdds/rtps/common/Types.h>
25
#include <fastrtps/utils/IPLocator.h>
26
27
#include <fastdds/dds/log/Log.hpp>
28
29
#include <sstream>
30
#include <vector>
31
#include <cstdint>
32
#include <cstring>
33
#include <iomanip>
34
#include <algorithm>
35
36
namespace eprosima {
37
namespace fastrtps {
38
namespace rtps {
39
40
/// Initialize locator with invalid values
41
0
#define LOCATOR_INVALID(loc)  {loc.kind = LOCATOR_KIND_INVALID; loc.port = LOCATOR_PORT_INVALID; \
42
0
                               LOCATOR_ADDRESS_INVALID(loc.address); \
43
0
}
44
/// Invalid locator kind
45
0
#define LOCATOR_KIND_INVALID -1
46
47
/// Set locator IP address to 0
48
4
#define LOCATOR_ADDRESS_INVALID(a) {std::memset(a, 0x00, 16 * sizeof(octet));}
49
50
/// Invalid locator port
51
0
#define LOCATOR_PORT_INVALID 0
52
53
/// Reserved locator kind
54
#define LOCATOR_KIND_RESERVED 0
55
/// UDP over IPv4 locator kind
56
0
#define LOCATOR_KIND_UDPv4 1
57
/// UDP over IPv6 locator kind
58
0
#define LOCATOR_KIND_UDPv6 2
59
/// TCP over IPv4 kind
60
0
#define LOCATOR_KIND_TCPv4 4
61
/// TCP over IPv6 locator kind
62
0
#define LOCATOR_KIND_TCPv6 8
63
/// Shared memory locator kind
64
0
#define LOCATOR_KIND_SHM 16
65
66
/**
67
 * @brief Class Locator_t, uniquely identifies a communication channel for a particular transport.
68
 * For example, an address + port combination in the case of UDP.
69
 * @ingroup COMMON_MODULE
70
 */
71
class RTPS_DllAPI Locator_t
72
{
73
public:
74
75
    /**
76
     * @brief Specifies the locator type. Valid values are:
77
     *
78
     * LOCATOR_KIND_UDPv4
79
     *
80
     * LOCATOR_KIND_UDPv6
81
     *
82
     * LOCATOR_KIND_TCPv4
83
     *
84
     * LOCATOR_KIND_TCPv6
85
     *
86
     * LOCATOR_KIND_SHM
87
     */
88
    int32_t kind;
89
    /// Network port
90
    uint32_t port;
91
    /// IP address
92
    octet address[16];
93
94
    /// Default constructor
95
    Locator_t()
96
        : kind(LOCATOR_KIND_UDPv4)
97
4
    {
98
4
        port = 0;
99
4
        LOCATOR_ADDRESS_INVALID(address);
100
4
    }
101
102
    /// Move constructor
103
    Locator_t(
104
            Locator_t&& loc)
105
        : kind(loc.kind)
106
0
    {
107
0
        port = loc.port;
108
0
        std::memcpy(address, loc.address, 16 * sizeof(octet));
109
0
    }
110
111
    /// Copy constructor
112
    Locator_t(
113
            const Locator_t& loc)
114
        : kind(loc.kind)
115
0
    {
116
0
        port = loc.port;
117
0
        std::memcpy(address, loc.address, 16 * sizeof(octet));
118
0
    }
119
120
    /// Port constructor
121
    Locator_t(
122
            uint32_t portin)
123
        : kind(LOCATOR_KIND_UDPv4)
124
0
    {
125
0
        port = portin;
126
0
        LOCATOR_ADDRESS_INVALID(address);
127
0
    }
128
129
    /// Kind and port constructor
130
    Locator_t(
131
            int32_t kindin,
132
            uint32_t portin)
133
        : kind(kindin)
134
0
    {
135
0
        port = portin;
136
0
        LOCATOR_ADDRESS_INVALID(address);
137
0
    }
138
139
    /// Copy assignment
140
    Locator_t& operator =(
141
            const Locator_t& loc)
142
0
    {
143
0
        kind = loc.kind;
144
0
        port = loc.port;
145
0
        std::memcpy(address, loc.address, 16 * sizeof(octet));
146
0
        return *this;
147
0
    }
148
149
    /**
150
     * @brief Set the locator IP address using another locator.
151
     *
152
     * @param other Locator which IP address is used to set this locator IP address.
153
     * @return always true.
154
     */
155
    bool set_address(
156
            const Locator_t& other)
157
0
    {
158
0
        memcpy(address, other.address, sizeof(octet) * 16);
159
0
        return true;
160
0
    }
161
162
    /**
163
     * @brief Getter for the locator IP address.
164
     *
165
     * @return IP address as octet pointer.
166
     */
167
    octet* get_address()
168
0
    {
169
0
        return address;
170
0
    }
171
172
    /**
173
     * @brief Getter for a specific field of the locator IP address.
174
     *
175
     * @param field IP address element to be accessed.
176
     * @return Octet value for the specific IP address element.
177
     */
178
    octet get_address(
179
            uint16_t field) const
180
0
    {
181
0
        return address[field];
182
0
    }
183
184
    /**
185
     * @brief Automatic setter for setting locator IP address to invalid address (0).
186
     */
187
    void set_Invalid_Address()
188
0
    {
189
0
        LOCATOR_ADDRESS_INVALID(address);
190
0
    }
191
192
};
193
194
/**
195
 * @brief Auxiliary method to check that IP address is not invalid (0).
196
 *
197
 * @param loc Locator which IP address is going to be checked.
198
 * @return true if IP address is defined (not 0).
199
 * @return false otherwise.
200
 */
201
inline bool IsAddressDefined(
202
        const Locator_t& loc)
203
0
{
204
0
    if (loc.kind == LOCATOR_KIND_UDPv4 || loc.kind == LOCATOR_KIND_TCPv4) // WAN addr in TCPv4 is optional, isn't?
205
0
    {
206
0
        for (uint8_t i = 12; i < 16; ++i)
207
0
        {
208
0
            if (loc.address[i] != 0)
209
0
            {
210
0
                return true;
211
0
            }
212
0
        }
213
0
    }
214
0
    else if (loc.kind == LOCATOR_KIND_UDPv6 || loc.kind == LOCATOR_KIND_TCPv6)
215
0
    {
216
0
        for (uint8_t i = 0; i < 16; ++i)
217
0
        {
218
0
            if (loc.address[i] != 0)
219
0
            {
220
0
                return true;
221
0
            }
222
0
        }
223
0
    }
224
0
    return false;
225
0
}
226
227
/**
228
 * @brief Auxiliary method to check that locator kind is not LOCATOR_KIND_INVALID (-1).
229
 *
230
 * @param loc Locator to be checked.
231
 * @return true if the locator kind is not LOCATOR_KIND_INVALID.
232
 * @return false otherwise.
233
 */
234
inline bool IsLocatorValid(
235
        const Locator_t& loc)
236
0
{
237
0
    return (0 <= loc.kind);
238
0
}
239
240
/**
241
 * @brief Less than operator.
242
 *
243
 * @param loc1 Left hand side locator being compared.
244
 * @param loc2 Right hand side locator being compared.
245
 * @return true if \c loc1 is less than \c loc2.
246
 * @return false otherwise.
247
 */
248
inline bool operator <(
249
        const Locator_t& loc1,
250
        const Locator_t& loc2)
251
0
{
252
0
    return memcmp(&loc1, &loc2, sizeof(Locator_t)) < 0;
253
0
}
254
255
/**
256
 * @brief Equal to operator.
257
 *
258
 * @param loc1 Left hand side locator being compared.
259
 * @param loc2 Right hand side locator being compared.
260
 * @return true if \c loc1 is equal to  \c loc2.
261
 * @return false otherwise.
262
 */
263
inline bool operator ==(
264
        const Locator_t& loc1,
265
        const Locator_t& loc2)
266
0
{
267
0
    if (loc1.kind != loc2.kind)
268
0
    {
269
0
        return false;
270
0
    }
271
0
    if (loc1.port != loc2.port)
272
0
    {
273
0
        return false;
274
0
    }
275
0
    if (!std::equal(loc1.address, loc1.address + 16, loc2.address))
276
0
    {
277
0
        return false;
278
0
    }
279
0
    return true;
280
0
}
281
282
/**
283
 * @brief Not equal to operator.
284
 *
285
 * @param loc1 Left hand side locator being compared.
286
 * @param loc2 Right hand side locator being compared.
287
 * @return true if \c loc1 is not equal to \c loc2.
288
 * @return false otherwise.
289
 */
290
inline bool operator !=(
291
        const Locator_t& loc1,
292
        const Locator_t& loc2)
293
0
{
294
0
    return !(loc1 == loc2);
295
0
}
296
297
/**
298
 * @brief Insertion operator: serialize a locator
299
 *        The serialization format is kind:[address]:port
300
 *        \c kind must be one of the following:
301
 *            - UDPv4
302
 *            - UDPv6
303
 *            - TCPv4
304
 *            - TCPv6
305
 *            - SHM
306
 *        \c address IP address unless \c kind is SHM
307
 *        \c port number
308
 *
309
 * @param output Output stream where the serialized locator is appended.
310
 * @param loc Locator to be serialized/inserted.
311
 * @return \c std::ostream& Reference to the output stream with the serialized locator appended.
312
 */
313
inline std::ostream& operator <<(
314
        std::ostream& output,
315
        const Locator_t& loc)
316
0
{
317
    // Stream Locator kind
318
0
    switch (loc.kind)
319
0
    {
320
0
        case LOCATOR_KIND_TCPv4:
321
0
        {
322
0
            output << "TCPv4:[";
323
0
            break;
324
0
        }
325
0
        case LOCATOR_KIND_UDPv4:
326
0
        {
327
0
            output << "UDPv4:[";
328
0
            break;
329
0
        }
330
0
        case LOCATOR_KIND_TCPv6:
331
0
        {
332
0
            output << "TCPv6:[";
333
0
            break;
334
0
        }
335
0
        case LOCATOR_KIND_UDPv6:
336
0
        {
337
0
            output << "UDPv6:[";
338
0
            break;
339
0
        }
340
0
        case LOCATOR_KIND_SHM:
341
0
        {
342
0
            output << "SHM:[";
343
0
            break;
344
0
        }
345
0
        default:
346
0
        {
347
0
            output << "Invalid_locator:[_]:0";
348
0
            return output;
349
0
        }
350
0
    }
351
352
    // Stream address
353
0
    if (loc.kind == LOCATOR_KIND_UDPv4 || loc.kind == LOCATOR_KIND_TCPv4)
354
0
    {
355
0
        output << IPLocator::toIPv4string(loc);
356
0
    }
357
0
    else if (loc.kind == LOCATOR_KIND_UDPv6 || loc.kind == LOCATOR_KIND_TCPv6)
358
0
    {
359
0
        output << IPLocator::toIPv6string(loc);
360
0
    }
361
0
    else if (loc.kind == LOCATOR_KIND_SHM)
362
0
    {
363
0
        if (loc.address[0] == 'M')
364
0
        {
365
0
            output << "M";
366
0
        }
367
0
        else
368
0
        {
369
0
            output << "_";
370
0
        }
371
0
    }
372
373
    // Stream port
374
0
    output << "]:" << loc.port;
375
376
0
    return output;
377
0
}
378
379
/**
380
 * @brief Extraction operator: deserialize a locator
381
 *        The deserialization format is kind:[address]:port
382
 *        \c kind must be one of the following:
383
 *            - UDPv4
384
 *            - UDPv6
385
 *            - TCPv4
386
 *            - TCPv6
387
 *            - SHM
388
 *        \c address must be either a name which can be resolved by DNS or the IP address unless \c kind is SHM
389
 *        \c port number
390
 *
391
 * @param input Input stream where the locator to be deserialized is located.
392
 * @param loc Locator where the deserialized locator is saved.
393
 * @return \c std::istream& Reference to the input stream after extracting the locator.
394
 */
395
inline std::istream& operator >>(
396
        std::istream& input,
397
        Locator_t& loc)
398
0
{
399
0
    std::istream::sentry s(input);
400
401
0
    if (s)
402
0
    {
403
0
        std::ios_base::iostate excp_mask = input.exceptions();
404
405
0
        try
406
0
        {
407
0
            input.exceptions(excp_mask | std::ios_base::failbit | std::ios_base::badbit);
408
409
            // Locator info
410
0
            int32_t kind;
411
0
            uint32_t port;
412
0
            std::string address;
413
414
            // Deserialization variables
415
0
            std::stringbuf sb_kind;
416
0
            std::stringbuf sb_address;
417
0
            std::string str_kind;
418
0
            char punct;
419
420
            // Check the locator kind
421
0
            input.get(sb_kind, ':');
422
0
            str_kind = sb_kind.str();
423
424
0
            if (str_kind == "SHM")
425
0
            {
426
0
                kind = LOCATOR_KIND_SHM;
427
0
            }
428
0
            else if (str_kind == "TCPv4")
429
0
            {
430
0
                kind = LOCATOR_KIND_TCPv4;
431
0
            }
432
0
            else if (str_kind == "TCPv6")
433
0
            {
434
0
                kind = LOCATOR_KIND_TCPv6;
435
0
            }
436
0
            else if (str_kind == "UDPv4")
437
0
            {
438
0
                kind = LOCATOR_KIND_UDPv4;
439
0
            }
440
0
            else if (str_kind == "UDPv6")
441
0
            {
442
0
                kind = LOCATOR_KIND_UDPv6;
443
0
            }
444
0
            else
445
0
            {
446
0
                kind = LOCATOR_KIND_INVALID;
447
0
            }
448
449
            // Get chars :[
450
0
            input >> punct >> punct;
451
452
            // Get address in string
453
0
            input.get(sb_address, ']');
454
0
            address = sb_address.str();
455
456
            // check if this is a valid IPv4 or IPv6 and call DNS if not
457
0
            if ((kind == LOCATOR_KIND_UDPv4 || kind == LOCATOR_KIND_TCPv4) &&
458
0
                    !IPLocator::isIPv4(address))
459
0
            {
460
0
                auto addresses = IPLocator::resolveNameDNS(address);
461
0
                if (addresses.first.empty())
462
0
                {
463
0
                    loc.kind = LOCATOR_KIND_INVALID;
464
0
                    logWarning(LOCATOR, "Error deserializing Locator");
465
0
                    return input;
466
0
                }
467
0
                address = *addresses.first.begin();
468
0
            }
469
0
            if ((kind == LOCATOR_KIND_UDPv6 || kind == LOCATOR_KIND_TCPv6) &&
470
0
                    !IPLocator::isIPv6(address))
471
0
            {
472
0
                auto addresses = IPLocator::resolveNameDNS(address);
473
0
                if (addresses.second.empty())
474
0
                {
475
0
                    loc.kind = LOCATOR_KIND_INVALID;
476
0
                    logWarning(LOCATOR, "Error deserializing Locator");
477
0
                    return input;
478
0
                }
479
0
                address = *addresses.second.begin();
480
0
            }
481
482
            // Get char ]:
483
0
            input >> punct >> punct;
484
485
            // Get port
486
0
            input >> port;
487
488
0
            IPLocator::createLocator(kind, address, port, loc);
489
0
        }
490
0
        catch (std::ios_base::failure& )
491
0
        {
492
0
            loc.kind = LOCATOR_KIND_INVALID;
493
0
            logWarning(LOCATOR, "Error deserializing Locator");
494
0
        }
495
496
0
        input.exceptions(excp_mask);
497
0
    }
498
0
    return input;
499
0
}
Unexecuted instantiation: eprosima::fastrtps::rtps::operator>>(std::__1::basic_istream<char, std::__1::char_traits<char> >&, eprosima::fastrtps::rtps::Locator_t&)
Unexecuted instantiation: eprosima::fastrtps::rtps::operator>>(std::__1::basic_istream<char, std::__1::char_traits<char> >&, eprosima::fastrtps::rtps::Locator_t&)
500
501
typedef std::vector<Locator_t>::iterator LocatorListIterator;
502
typedef std::vector<Locator_t>::const_iterator LocatorListConstIterator;
503
504
} // namespace rtps
505
} // namespace fastrtps
506
} // namespace eprosima
507
508
namespace eprosima {
509
namespace fastdds {
510
namespace rtps {
511
512
using Locator = eprosima::fastrtps::rtps::Locator_t;
513
514
} // namespace rtps
515
} // namespace fastdds
516
} // namespace eprosima
517
518
#include <fastdds/rtps/common/LocatorsIterator.hpp>
519
#include <fastdds/rtps/common/LocatorList.hpp>
520
521
namespace eprosima {
522
namespace fastrtps {
523
namespace rtps {
524
525
using LocatorsIterator = eprosima::fastdds::rtps::LocatorsIterator;
526
using Locators = eprosima::fastdds::rtps::Locators;
527
using LocatorList_t = eprosima::fastdds::rtps::LocatorList;
528
529
} // namespace rtps
530
} // namespace fastrtps
531
} // namespace eprosima
532
533
#endif /* _FASTDDS_RTPS_ELEM_LOCATOR_H_ */