Fast DDS  Version 3.6.1.0
Fast DDS
Locator.hpp
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 
19 #ifndef FASTDDS_RTPS_COMMON__LOCATOR_HPP
20 #define FASTDDS_RTPS_COMMON__LOCATOR_HPP
21 
22 #include <algorithm>
23 #include <cstdint>
24 #include <cstring>
25 #include <iomanip>
26 #include <sstream>
27 #include <string>
28 #include <vector>
29 
30 #include <fastdds/config.hpp>
31 #include <fastdds/dds/log/Log.hpp>
32 #include <fastdds/fastdds_dll.hpp>
33 #include <fastdds/rtps/common/Types.hpp>
34 #include <fastdds/utils/IPLocator.hpp>
35 
36 namespace eprosima {
37 namespace fastdds {
38 namespace rtps {
39 
41 #define LOCATOR_INVALID(loc) {loc.kind = LOCATOR_KIND_INVALID; loc.port = LOCATOR_PORT_INVALID; \
42  LOCATOR_ADDRESS_INVALID(loc.address); \
43 }
45 #define LOCATOR_KIND_INVALID -1
46 
48 #define LOCATOR_ADDRESS_INVALID(a) {std::memset(a, 0x00, 16 * sizeof(octet));}
49 
51 #define LOCATOR_PORT_INVALID 0
52 
54 #define LOCATOR_KIND_RESERVED 0
56 #define LOCATOR_KIND_UDPv4 1
58 #define LOCATOR_KIND_UDPv6 2
60 #define LOCATOR_KIND_TCPv4 4
62 #define LOCATOR_KIND_TCPv6 8
64 #define LOCATOR_KIND_SHM 16 + FASTDDS_VERSION_MAJOR
66 #define LOCATOR_KIND_ETHERNET 0x02000000
67 
73 class FASTDDS_EXPORTED_API Locator_t
74 {
75 public:
76 
92  int32_t kind;
94  uint32_t port;
96  octet address[16];
97 
100  : kind(LOCATOR_KIND_UDPv4)
101  {
102  port = 0;
103  LOCATOR_ADDRESS_INVALID(address);
104  }
105 
108  Locator_t&& loc)
109  : kind(loc.kind)
110  {
111  port = loc.port;
112  std::memcpy(address, loc.address, 16 * sizeof(octet));
113  }
114 
117  const Locator_t& loc)
118  : kind(loc.kind)
119  {
120  port = loc.port;
121  std::memcpy(address, loc.address, 16 * sizeof(octet));
122  }
123 
126  uint32_t portin)
127  : kind(LOCATOR_KIND_UDPv4)
128  {
129  port = portin;
130  LOCATOR_ADDRESS_INVALID(address);
131  }
132 
135  int32_t kindin,
136  uint32_t portin)
137  : kind(kindin)
138  {
139  port = portin;
140  LOCATOR_ADDRESS_INVALID(address);
141  }
142 
144  Locator_t& operator =(
145  const Locator_t& loc)
146  {
147  kind = loc.kind;
148  port = loc.port;
149  std::memcpy(address, loc.address, 16 * sizeof(octet));
150  return *this;
151  }
152 
160  const Locator_t& other)
161  {
162  memcpy(address, other.address, sizeof(octet) * 16);
163  return true;
164  }
165 
172  {
173  return address;
174  }
175 
183  uint16_t field) const
184  {
185  return address[field];
186  }
187 
192  {
193  LOCATOR_ADDRESS_INVALID(address);
194  }
195 
205  int32_t kind,
206  const std::string& address,
207  uint32_t port);
208 
209 };
210 
218 inline bool IsAddressDefined(
219  const Locator_t& loc)
220 {
221  if (loc.kind == LOCATOR_KIND_UDPv4 || loc.kind == LOCATOR_KIND_TCPv4) // WAN addr in TCPv4 is optional, isn't?
222  {
223  for (uint8_t i = 12; i < 16; ++i)
224  {
225  if (loc.address[i] != 0)
226  {
227  return true;
228  }
229  }
230  }
231  else if (loc.kind == LOCATOR_KIND_UDPv6 || loc.kind == LOCATOR_KIND_TCPv6 ||
232  loc.kind == LOCATOR_KIND_SHM || loc.kind == LOCATOR_KIND_ETHERNET)
233  {
234  for (uint8_t i = 0; i < 16; ++i)
235  {
236  if (loc.address[i] != 0)
237  {
238  return true;
239  }
240  }
241  }
242  return false;
243 }
244 
252 inline bool IsLocatorValid(
253  const Locator_t& loc)
254 {
255  return (0 <= loc.kind);
256 }
257 
266 inline bool operator <(
267  const Locator_t& loc1,
268  const Locator_t& loc2)
269 {
270  return memcmp(&loc1, &loc2, sizeof(Locator_t)) < 0;
271 }
272 
281 inline bool operator ==(
282  const Locator_t& loc1,
283  const Locator_t& loc2)
284 {
285  if (loc1.kind != loc2.kind)
286  {
287  return false;
288  }
289  if (loc1.port != loc2.port)
290  {
291  return false;
292  }
293  if (!std::equal(loc1.address, loc1.address + 16, loc2.address))
294  {
295  return false;
296  }
297  return true;
298 }
299 
308 inline bool operator !=(
309  const Locator_t& loc1,
310  const Locator_t& loc2)
311 {
312  return !(loc1 == loc2);
313 }
314 
332 inline std::ostream& operator <<(
333  std::ostream& output,
334  const Locator_t& loc)
335 {
336  // Stream Locator kind
337  switch (loc.kind)
338  {
339  case LOCATOR_KIND_TCPv4:
340  {
341  output << "TCPv4:[";
342  break;
343  }
344  case LOCATOR_KIND_UDPv4:
345  {
346  output << "UDPv4:[";
347  break;
348  }
349  case LOCATOR_KIND_TCPv6:
350  {
351  output << "TCPv6:[";
352  break;
353  }
354  case LOCATOR_KIND_UDPv6:
355  {
356  output << "UDPv6:[";
357  break;
358  }
359  case LOCATOR_KIND_SHM:
360  {
361  output << "SHM:[";
362  break;
363  }
364  case LOCATOR_KIND_ETHERNET:
365  {
366  output << "ETH:[";
367  break;
368  }
369  default:
370  {
371  output << "Invalid_locator:[_]:0";
372  return output;
373  }
374  }
375 
376  // Stream address
377  switch (loc.kind)
378  {
379  case LOCATOR_KIND_UDPv4:
380  case LOCATOR_KIND_TCPv4:
381  output << IPLocator::toIPv4string(loc);
382  break;
383 
384  case LOCATOR_KIND_UDPv6:
385  case LOCATOR_KIND_TCPv6:
386  output << IPLocator::toIPv6string(loc);
387  break;
388 
389  case LOCATOR_KIND_ETHERNET:
390  output << std::hex << std::setfill('0') << std::setw(2) << (int)loc.address[10];
391  for (int i = 1; i < 6; ++i)
392  {
393  output << ":" << std::hex << std::setfill('0') << std::setw(2) << (int)loc.address[10 + i];
394  }
395  break;
396 
397  case LOCATOR_KIND_SHM:
398  if (loc.address[0] == 'M')
399  {
400  output << "M";
401  }
402  else
403  {
404  output << "_";
405  }
406  break;
407  }
408 
409  // Stream port
410  if (loc.kind == LOCATOR_KIND_TCPv4 || loc.kind == LOCATOR_KIND_TCPv6)
411  {
412  output << "]:" << std::to_string(IPLocator::getPhysicalPort(loc)) << "-"
413  << std::to_string(IPLocator::getLogicalPort(
414  loc));
415  }
416  else
417  {
418  output << "]:" << loc.port;
419  }
420 
421  return output;
422 }
423 
441 inline std::istream& operator >>(
442  std::istream& input,
443  Locator_t& loc)
444 {
445  std::istream::sentry s(input);
446 
447  if (s)
448  {
449  std::ios_base::iostate excp_mask = input.exceptions();
450 
451  try
452  {
453  input.exceptions(excp_mask | std::ios_base::failbit | std::ios_base::badbit);
454 
455  // Locator info
456  int32_t kind;
457  uint32_t port;
458  std::string address;
459 
460  // Deserialization variables
461  std::stringbuf sb_kind;
462  std::stringbuf sb_address;
463  std::string str_kind;
464  char punct;
465 
466  // Check the locator kind
467  input.get(sb_kind, ':');
468  str_kind = sb_kind.str();
469 
470  if (str_kind == "SHM")
471  {
472  kind = LOCATOR_KIND_SHM;
473  }
474  else if (str_kind == "ETH")
475  {
476  kind = LOCATOR_KIND_ETHERNET;
477  }
478  else if (str_kind == "TCPv4")
479  {
480  kind = LOCATOR_KIND_TCPv4;
481  }
482  else if (str_kind == "TCPv6")
483  {
484  kind = LOCATOR_KIND_TCPv6;
485  }
486  else if (str_kind == "UDPv4")
487  {
488  kind = LOCATOR_KIND_UDPv4;
489  }
490  else if (str_kind == "UDPv6")
491  {
492  kind = LOCATOR_KIND_UDPv6;
493  }
494  else
495  {
496  kind = LOCATOR_KIND_INVALID;
497  loc.kind = LOCATOR_KIND_INVALID;
498  }
499 
500  if (kind != LOCATOR_KIND_INVALID)
501  {
502  // Get chars :[
503  input >> punct >> punct;
504 
505  // Get address in string
506  input.get(sb_address, ']');
507  address = sb_address.str();
508 
509  // check if this is a valid IPv4 or IPv6 and call DNS if not
510  if ((kind == LOCATOR_KIND_UDPv4 || kind == LOCATOR_KIND_TCPv4) &&
511  !IPLocator::isIPv4(address))
512  {
513  auto addresses = IPLocator::resolveNameDNS(address);
514  if (addresses.first.empty())
515  {
516  loc.kind = LOCATOR_KIND_INVALID;
517  EPROSIMA_LOG_WARNING(LOCATOR, "Error deserializing Locator");
518  return input;
519  }
520  address = *addresses.first.begin();
521  }
522  if ((kind == LOCATOR_KIND_UDPv6 || kind == LOCATOR_KIND_TCPv6) &&
523  !IPLocator::isIPv6(address))
524  {
525  auto addresses = IPLocator::resolveNameDNS(address);
526  if (addresses.second.empty())
527  {
528  loc.kind = LOCATOR_KIND_INVALID;
529  EPROSIMA_LOG_WARNING(LOCATOR, "Error deserializing Locator");
530  return input;
531  }
532  address = *addresses.second.begin();
533  }
534  if ((kind == LOCATOR_KIND_SHM) && (address != "M") && (address != "_"))
535  {
536  loc.kind = LOCATOR_KIND_INVALID;
537  EPROSIMA_LOG_WARNING(LOCATOR, "Error deserializing Locator");
538  return input;
539  }
540 
541  // Get char ]:
542  input >> punct >> punct;
543 
544  // Get port
545  input >> port;
546 
547  loc = Locator_t::create_locator(kind, address, port);
548  }
549  }
550  catch (std::ios_base::failure& )
551  {
552  loc.kind = LOCATOR_KIND_INVALID;
553  EPROSIMA_LOG_WARNING(LOCATOR, "Error deserializing Locator");
554  }
555 
556  input.exceptions(excp_mask);
557  }
558  return input;
559 }
560 
561 typedef std::vector<Locator_t>::iterator LocatorListIterator;
562 typedef std::vector<Locator_t>::const_iterator LocatorListConstIterator;
563 
564 } // namespace rtps
565 } // namespace fastdds
566 } // namespace eprosima
567 
568 namespace eprosima {
569 namespace fastdds {
570 namespace rtps {
571 
573 
574 } // namespace rtps
575 } // namespace fastdds
576 } // namespace eprosima
577 
578 #endif // FASTDDS_RTPS_COMMON__LOCATOR_HPP
static FASTDDS_EXPORTED_API bool isIPv4(const std::string &address)
Check whether a string contains an IPv4 format.
static FASTDDS_EXPORTED_API uint16_t getLogicalPort(const Locator_t &locator)
Gets locator's logical port (as in RTCP protocol)
static FASTDDS_EXPORTED_API bool isIPv6(const std::string &address)
Check whether a string contains an IPv6 format.
static FASTDDS_EXPORTED_API uint16_t getPhysicalPort(const Locator_t &locator)
Gets locator's physical port (as in RTCP protocol)
static FASTDDS_EXPORTED_API std::string toIPv6string(const Locator_t &locator)
Returns a string representation of the locator's IPv6 following RFC 5952 recommendation.
static FASTDDS_EXPORTED_API std::string toIPv4string(const Locator_t &locator)
Returns a string representation of the locator's IPv4.
static FASTDDS_EXPORTED_API std::pair< std::set< std::string >, std::set< std::string > > resolveNameDNS(const std::string &address_name)
Resolve an address name by a DNS request and return the IP that this address references by a DNS serv...
Class Locator_t, uniquely identifies a communication channel for a particular transport.
Definition: Locator.hpp:74
int32_t kind
Specifies the locator type.
Definition: Locator.hpp:92
octet * get_address()
Getter for the locator IP address.
Definition: Locator.hpp:171
octet address[16]
IP address.
Definition: Locator.hpp:96
Locator_t(uint32_t portin)
Port constructor.
Definition: Locator.hpp:125
bool set_address(const Locator_t &other)
Set the locator IP address using another locator.
Definition: Locator.hpp:159
octet get_address(uint16_t field) const
Getter for a specific field of the locator IP address.
Definition: Locator.hpp:182
Locator_t(int32_t kindin, uint32_t portin)
Kind and port constructor.
Definition: Locator.hpp:134
static Locator_t create_locator(int32_t kind, const std::string &address, uint32_t port)
Create a locator with the given parameters.
uint32_t port
Network port.
Definition: Locator.hpp:94
void set_Invalid_Address()
Automatic setter for setting locator IP address to invalid address (0).
Definition: Locator.hpp:191
Locator_t(Locator_t &&loc)
Move constructor.
Definition: Locator.hpp:107
Locator_t()
Default constructor.
Definition: Locator.hpp:99
Locator_t(const Locator_t &loc)
Copy constructor.
Definition: Locator.hpp:116
std::istream & operator>>(std::istream &input, EntityId_t &enP)
Definition: EntityId_t.hpp:289
bool IsAddressDefined(const Locator_t &loc)
Auxiliary method to check that IP address is not invalid (0).
Definition: Locator.hpp:218
bool operator!=(const EntityId_t &id1, const EntityId_t &id2)
Guid prefix comparison operator.
Definition: EntityId_t.hpp:267
std::vector< Locator_t >::const_iterator LocatorListConstIterator
Constant iterator to iterate over a vector of locators.
Definition: Locator.hpp:562
uint8_t octet
Definition: Types.hpp:83
bool operator==(const BuiltinTransportsOptions &bto1, const BuiltinTransportsOptions &bto2)
Equal to operator.
Definition: BuiltinTransports.hpp:79
std::vector< Locator_t >::iterator LocatorListIterator
Iterator to iterate over a vector of locators.
Definition: Locator.hpp:561
std::ostream & operator<<(std::ostream &output, BuiltinTransports transports)
Definition: BuiltinTransports.hpp:118
bool operator<(const GUID_t &g1, const GUID_t &g2)
Definition: Guid.hpp:192
bool IsLocatorValid(const Locator_t &loc)
Auxiliary method to check that locator kind is not LOCATOR_KIND_INVALID (-1).
Definition: Locator.hpp:252