OpenDDS  Snapshot(2023/04/28-20:55)
Public Member Functions | Private Types | Private Attributes | List of all members
OpenDDS::RTPS::GuidGenerator Class Reference

#include <GuidGenerator.h>

Collaboration diagram for OpenDDS::RTPS::GuidGenerator:
Collaboration graph
[legend]

Public Member Functions

 GuidGenerator ()
 
int interfaceName (const char *nic)
 
void populate (DCPS::GUID_t &container)
 
ACE_UINT16 getCount (bool doIncrement=true)
 

Private Types

enum  { NODE_ID_SIZE = 6 }
 
typedef unsigned char Node_ID[NODE_ID_SIZE]
 

Private Attributes

Node_ID node_id_
 
pid_t pid_
 
ACE_Thread_Mutex counter_lock_
 
ACE_UINT16 counter_
 
OPENDDS_STRING interface_name_
 

Detailed Description

Generate GuidPrefix_t values for use with RTPS Also see GuidConverter.h in dds/DCPS 0 GUID_t.guidPrefix[ 0] == VendorId_t == 0x01 for OCI (used for OpenDDS) 1 GUID_t.guidPrefix[ 1] == VendorId_t == 0x03 for OCI (used for OpenDDS) 2 GUID_t.guidPrefix[ 2] == MAC Address 3 GUID_t.guidPrefix[ 3] == MAC Address 4 GUID_t.guidPrefix[ 4] == MAC Address 5 GUID_t.guidPrefix[ 5] == MAC Address 6 GUID_t.guidPrefix[ 6] == MAC Address 7 GUID_t.guidPrefix[ 7] == MAC Address 8 GUID_t.guidPrefix[ 8] == Process ID (MS byte) 9 GUID_t.guidPrefix[ 9] == Process ID (LS byte) 10 GUID_t.guidPrefix[10] == Counter (MS byte) 11 GUID_t.guidPrefix[11] == Counter (LS byte)

Definition at line 43 of file GuidGenerator.h.

Member Typedef Documentation

◆ Node_ID

typedef unsigned char OpenDDS::RTPS::GuidGenerator::Node_ID[NODE_ID_SIZE]
private

Borrowed from ACE::UUID_Node, definition of the MAC address holder type

Definition at line 64 of file GuidGenerator.h.

Member Enumeration Documentation

◆ anonymous enum

anonymous enum
private
Enumerator
NODE_ID_SIZE 

Definition at line 60 of file GuidGenerator.h.

Constructor & Destructor Documentation

◆ GuidGenerator()

OpenDDS::RTPS::GuidGenerator::GuidGenerator ( )

Definition at line 51 of file GuidGenerator.cpp.

References ACE_UINT16_MAX, counter_, ACE_OS::getmacaddress(), getpid(), ACE_OS::memcpy(), ACE_OS::macaddr_node_t::node, node_id_, NODE_ID_SIZE, pid_, and ACE_OS::rand_r().

52  : pid_(ACE_OS::getpid())
53 {
54  unsigned seed = static_cast<unsigned>(SystemTimePoint::now().value().usec() + reinterpret_cast<size_t>(this));
55 
56  if (pid_ == -1) {
57  pid_ = static_cast<pid_t>(ACE_OS::rand_r(&seed));
58  }
59 
60 #ifdef ACE_HAS_CPP11
61  std::mt19937 generator(seed);
62  std::uniform_int_distribution<ACE_UINT16> distribution(0, ACE_UINT16_MAX);
63  counter_ = distribution(generator);
64 #else
65  counter_ = static_cast<ACE_UINT16>(ACE_OS::rand_r(&seed));
66 #endif
67 
68  ACE_OS::macaddr_node_t macaddress;
69  const int result = ACE_OS::getmacaddress(&macaddress);
70 
71 #ifndef ACE_HAS_IOS
72  if (-1 != result) {
74  } else {
75  for (int i = 0; i < NODE_ID_SIZE; ++i) {
76  node_id_[i] = static_cast<unsigned char>(ACE_OS::rand_r(&seed));
77  }
78  }
79 #else
80  // iOS has non-unique MAC addresses
81  ACE_UNUSED_ARG(result);
82 
83  for (int i = 0; i < NODE_ID_SIZE; ++i) {
84  node_id_[i] = static_cast<unsigned char>(ACE_OS::rand_r(&seed));
85  }
86 #endif /* ACE_HAS_IOS */
87 }
void * memcpy(void *t, const void *s, size_t len)
unsigned char node[6]
int getmacaddress(struct macaddr_node_t *node)
pid_t getpid(void)
int rand_r(unsigned int *seed)

Member Function Documentation

◆ getCount()

ACE_UINT16 OpenDDS::RTPS::GuidGenerator::getCount ( bool  doIncrement = true)

Definition at line 90 of file GuidGenerator.cpp.

References counter_, and counter_lock_.

Referenced by populate().

91 {
93  if (doIncrement) {
94  ++counter_;
95  }
96  return counter_;
97 }
ACE_Thread_Mutex counter_lock_
Definition: GuidGenerator.h:68

◆ interfaceName()

int OpenDDS::RTPS::GuidGenerator::interfaceName ( const char *  nic)

override the MAC address to use a specific network interface instead of just the first (non-loopback) interface

Definition at line 100 of file GuidGenerator.cpp.

References ACE_ERROR, AF_INET, AF_UNSPEC, ACE_Wide_To_Ascii::char_rep(), ACE_OS::close(), OpenDDS::DCPS::LogLevel::Error, ACE_Allocator::free(), ACE_Allocator::instance(), interface_name_, ACE_OS::ioctl(), LM_ERROR, OpenDDS::DCPS::log_level, ACE_Allocator::malloc(), name, node_id_, PF_INET, SIOCGIFCONF, SIOCGIFHWADDR, SOCK_DGRAM, and ACE_OS::socket().

Referenced by OpenDDS::RTPS::RtpsDiscovery::add_domain_participant(), and OpenDDS::RTPS::RtpsDiscovery::generate_participant_guid().

101 {
102  // A shortcut to determine if a *valid* interface was already checked.
103  // The shortcut value (interface_name_) is stored IFF the method returns 0.
104  if (interface_name_ == iface) {
105  return 0;
106  }
107 
108  // See ace/OS_NS_netdb.cpp ACE_OS::getmacaddress()
109 #if defined ACE_WIN32 && !defined ACE_HAS_WINCE
110  ULONG size;
111  if (::GetAdaptersAddresses(AF_UNSPEC, 0, 0, 0, &size)
112  != ERROR_BUFFER_OVERFLOW) {
113  return -1;
114  }
116  IP_ADAPTER_ADDRESSES* const addrs =
117  static_cast<IP_ADAPTER_ADDRESSES*>(alloc->malloc(size));
118  if (!addrs) {
119  return -1;
120  }
121  if (::GetAdaptersAddresses(AF_UNSPEC, 0, 0, addrs, &size) != NO_ERROR) {
122  alloc->free(addrs);
123  return -1;
124  }
125 
126  bool found = false;
127  for (IP_ADAPTER_ADDRESSES* iter = addrs; iter && !found; iter = iter->Next) {
128  if (ACE_Wide_To_Ascii(iter->FriendlyName).char_rep() == iface) {
129  std::memcpy(node_id_, iter->PhysicalAddress,
130  std::min(static_cast<size_t>(iter->PhysicalAddressLength),
131  sizeof node_id_));
132  found = true;
133  }
134  }
135 
136  alloc->free(addrs);
137  if (found) {
138  interface_name_ = iface;
139  return 0;
140  } else {
141  return -1;
142  }
143 
144 #elif defined ACE_LINUX || defined ACE_ANDROID
145  ifreq ifr;
146  // Guarantee that iface will fit in ifr.ifr_name and still be null terminated
147  // ifr.ifr_name is sized to IFNAMSIZ
148  if (std::strlen(iface) >= sizeof(ifr.ifr_name)) {
150  ACE_ERROR((LM_ERROR, "(%P|%t) ERROR: GuidGenerator::interfaceName: "
151  "Interface name %C exceeds max allowable length, must be < %d.\n",
152  iface, IFNAMSIZ));
153  }
154  return -1;
155  }
156  std::strncpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name));
157  const ACE_HANDLE h = ACE_OS::socket(PF_INET, SOCK_DGRAM, 0);
158  if (h == ACE_INVALID_HANDLE) {
159  return -1;
160  }
161  if (ACE_OS::ioctl(h, SIOCGIFHWADDR, &ifr) < 0) {
162  ACE_OS::close(h);
163  return -1;
164  }
165  ACE_OS::close(h);
166  std::memcpy(node_id_, ifr.ifr_addr.sa_data, sizeof node_id_);
167 
168  interface_name_ = iface;
169  return 0;
170 #elif defined ACE_HAS_SIOCGIFCONF || defined ACE_HAS_MAC_OSX
171  const ACE_HANDLE h = ACE_OS::socket(AF_INET, SOCK_DGRAM, 0);
172  if (h == ACE_INVALID_HANDLE) {
173  return -1;
174  }
175 
176  const int BUFFERSIZE = 4000;
177  char buffer[BUFFERSIZE];
178  ifconf ifc;
179  ifc.ifc_len = BUFFERSIZE;
180  ifc.ifc_buf = buffer;
181 
182  if (ACE_OS::ioctl(h, SIOCGIFCONF, &ifc) < 0) {
183  ACE_OS::close(h);
184  return -1;
185  }
186 
187  bool found = false;
188  for (const char* ptr = buffer; !found && ptr < buffer + ifc.ifc_len;) {
189  const ifreq* ifr = reinterpret_cast<const ifreq*>(ptr);
190  if (ifr->ifr_addr.sa_family == AF_LINK && ifr->ifr_name == interface_name_) {
191  const sockaddr_dl* sdl =
192  reinterpret_cast<const sockaddr_dl*>(&ifr->ifr_addr);
193  std::memcpy(node_id_, LLADDR(sdl), sizeof node_id_);
194  found = true;
195  }
196 
197  ptr += sizeof ifr->ifr_name + std::max(sizeof ifr->ifr_addr,
198  static_cast<size_t>(ifr->ifr_addr.sa_len));
199  }
200 
201  ACE_OS::close(h);
202 
203  if (found) {
204  interface_name_ = iface;
205  return 0;
206  } else {
207  return -1;
208  }
209 #elif defined ACE_VXWORKS
210  int name[] = {CTL_NET, AF_ROUTE, 0, 0, NET_RT_IFLIST, 0};
211  static const size_t name_elts = sizeof name / sizeof name[0];
212 
213  size_t result_sz = 0u;
214  if (sysctl(name, name_elts, 0, &result_sz, 0, 0u) != 0) {
215  return -1;
216  }
217 
219  char* const result = static_cast<char*>(alloc->malloc(result_sz));
220 
221  if (sysctl(name, name_elts, result, &result_sz, 0, 0u) != 0) {
222  alloc->free(result);
223  return -1;
224  }
225 
226  for (size_t pos = 0, n; pos + sizeof(if_msghdr) < result_sz; pos += n) {
227  if_msghdr* const hdr = reinterpret_cast<if_msghdr*>(result + pos);
228  n = hdr->ifm_msglen;
229  sockaddr_dl* const addr =
230  reinterpret_cast<sockaddr_dl*>(result + pos + sizeof(if_msghdr));
231 
232  if (hdr->ifm_type == RTM_IFINFO && (hdr->ifm_addrs & RTA_IFP)
233  && std::memcmp(addr->sdl_data, iface, addr->sdl_nlen) == 0
234  && addr->sdl_alen >= sizeof node_id_) {
235  std::memcpy(node_id_, LLADDR(addr), sizeof node_id_);
236  alloc->free(result);
237 
238  interface_name_ = iface;
239  return 0;
240  }
241 
242  while (pos + n < result_sz) {
243  if_msghdr* const nxt = reinterpret_cast<if_msghdr*>(result + pos + n);
244  if (nxt->ifm_type != RTM_NEWADDR) {
245  break;
246  }
247  n += nxt->ifm_msglen;
248  }
249  }
250 
251  alloc->free(result);
252  return -1;
253 #else
254  return -1;
255 #endif
256 }
#define ACE_ERROR(X)
virtual void free(void *ptr)=0
char * char_rep(void)
int close(ACE_HANDLE handle)
ACE_HANDLE socket(int protocol_family, int type, int proto)
OPENDDS_STRING interface_name_
Definition: GuidGenerator.h:70
static ACE_Allocator * instance(void)
const char *const name
Definition: debug.cpp:60
OpenDDS_Dcps_Export LogLevel log_level
virtual void * malloc(size_type nbytes)=0
int ioctl(ACE_HANDLE handle, ACE_IOCTL_TYPE_ARG2 cmd, void *=0)

◆ populate()

void OpenDDS::RTPS::GuidGenerator::populate ( DCPS::GUID_t container)

populate a GUID container with a unique ID. This will increment the counter, and use a lock (if compiled with MT ACE) while doing so.

Definition at line 259 of file GuidGenerator.cpp.

References getCount(), OpenDDS::DCPS::GUID_t::guidPrefix, ACE_OS::memcpy(), node_id_, NODE_ID_SIZE, OPENDDS_END_VERSIONED_NAMESPACE_DECL, pid_, and OpenDDS::DCPS::VENDORID_OCI.

Referenced by OpenDDS::RTPS::RtpsDiscovery::add_domain_participant(), and OpenDDS::RTPS::RtpsDiscovery::generate_participant_guid().

260 {
261  container.guidPrefix[0] = DCPS::VENDORID_OCI[0];
262  container.guidPrefix[1] = DCPS::VENDORID_OCI[1];
263 
264  const ACE_UINT16 count = getCount();
265  ACE_OS::memcpy(&container.guidPrefix[2], node_id_, NODE_ID_SIZE);
266  container.guidPrefix[8] = static_cast<CORBA::Octet>(pid_ >> 8);
267  container.guidPrefix[9] = static_cast<CORBA::Octet>(pid_ & 0xFF);
268  container.guidPrefix[10] = static_cast<CORBA::Octet>(count >> 8);
269  container.guidPrefix[11] = static_cast<CORBA::Octet>(count & 0xFF);
270 }
ACE_UINT16 getCount(bool doIncrement=true)
void * memcpy(void *t, const void *s, size_t len)
ACE_CDR::Octet Octet
const GuidVendorId_t VENDORID_OCI
Vendor Id value specified for OCI is used for OpenDDS.
Definition: GuidUtils.h:29

Member Data Documentation

◆ counter_

ACE_UINT16 OpenDDS::RTPS::GuidGenerator::counter_
private

Definition at line 69 of file GuidGenerator.h.

Referenced by getCount(), and GuidGenerator().

◆ counter_lock_

ACE_Thread_Mutex OpenDDS::RTPS::GuidGenerator::counter_lock_
private

Definition at line 68 of file GuidGenerator.h.

Referenced by getCount().

◆ interface_name_

OPENDDS_STRING OpenDDS::RTPS::GuidGenerator::interface_name_
private

Definition at line 70 of file GuidGenerator.h.

Referenced by interfaceName().

◆ node_id_

Node_ID OpenDDS::RTPS::GuidGenerator::node_id_
private

Definition at line 66 of file GuidGenerator.h.

Referenced by GuidGenerator(), interfaceName(), and populate().

◆ pid_

pid_t OpenDDS::RTPS::GuidGenerator::pid_
private

Definition at line 67 of file GuidGenerator.h.

Referenced by GuidGenerator(), and populate().


The documentation for this class was generated from the following files: