GuidGenerator.cpp

Go to the documentation of this file.
00001 /*
00002  *
00003  *
00004  * Distributed under the OpenDDS License.
00005  * See: http://www.opendds.org/license.html
00006  */
00007 
00008 #include "dds/DCPS/RTPS/GuidGenerator.h"
00009 
00010 #include "dds/DCPS/GuidUtils.h"
00011 
00012 #include "dds/DdsDcpsGuidTypeSupportImpl.h"
00013 
00014 #include "ace/OS_NS_unistd.h"
00015 #include "ace/OS_NS_stdlib.h"
00016 #include "ace/OS_NS_netdb.h"
00017 #include "ace/OS_NS_sys_socket.h"
00018 #include "ace/OS_NS_sys_time.h"
00019 
00020 #include "ace/os_include/net/os_if.h"
00021 
00022 #include <cstring>
00023 
00024 #ifdef ACE_LINUX
00025 # include <sys/types.h>
00026 # include <ifaddrs.h>
00027 #endif
00028 
00029 #if defined ACE_WIN32 && !defined ACE_HAS_WINCE
00030 # include <winsock2.h>
00031 # include <iphlpapi.h>
00032 # include "ace/Version.h"
00033 // older versions of ACE don't link to IPHlpApi.Lib, see acedefaults.mpb
00034 # if ACE_MAJOR_VERSION == 6 && ACE_MINOR_VERSION == 0 && defined _MSC_VER
00035 #  pragma comment(lib, "IPHlpApi.Lib")
00036 # endif
00037 #endif
00038 
00039 #ifdef ACE_VXWORKS
00040 # include "ace/os_include/sys/os_sysctl.h"
00041 # include <net/route.h>
00042 #endif
00043 
00044 OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL
00045 
00046 namespace OpenDDS {
00047   namespace RTPS {
00048 
00049 GuidGenerator::GuidGenerator()
00050   : pid_(ACE_OS::getpid()),
00051     counter_(0)
00052 {
00053 
00054   if (pid_ == -1) {
00055     unsigned seed = static_cast<unsigned>(ACE_OS::gettimeofday().usec());
00056     pid_ = static_cast<pid_t>(ACE_OS::rand_r(&seed));
00057   }
00058 
00059   ACE_OS::macaddr_node_t macaddress;
00060   const int result = ACE_OS::getmacaddress(&macaddress);
00061 
00062   if (-1 != result) {
00063     ACE_OS::memcpy(node_id_, macaddress.node, NODE_ID_SIZE);
00064   } else {
00065     for (int i = 0; i < NODE_ID_SIZE; ++i) {
00066       node_id_[i] = static_cast<unsigned char>(ACE_OS::rand());
00067     }
00068   }
00069 }
00070 
00071 ACE_UINT16
00072 GuidGenerator::getCount()
00073 {
00074   ACE_Guard<ACE_SYNCH_MUTEX> guard(counter_lock_);
00075   return counter_++;
00076 }
00077 
00078 int
00079 GuidGenerator::interfaceName(const char* iface)
00080 {
00081   if (interface_name_ == iface) {
00082     return 0;
00083   }
00084   interface_name_ = iface;
00085   // See ace/OS_NS_netdb.cpp ACE_OS::getmacaddress()
00086 #if defined ACE_WIN32 && !defined ACE_HAS_WINCE
00087   ULONG size;
00088   if (::GetAdaptersAddresses(AF_UNSPEC, 0, 0, 0, &size)
00089       != ERROR_BUFFER_OVERFLOW) {
00090     return -1;
00091   }
00092   ACE_Allocator* const alloc = DCPS::SafetyProfilePool::instance();
00093   IP_ADAPTER_ADDRESSES* const addrs =
00094     static_cast<IP_ADAPTER_ADDRESSES*>(alloc->malloc(size));
00095   if (!addrs) {
00096     return -1;
00097   }
00098   if (::GetAdaptersAddresses(AF_UNSPEC, 0, 0, addrs, &size) != NO_ERROR) {
00099     alloc->free(addrs);
00100     return -1;
00101   }
00102 
00103   bool found = false;
00104   for (IP_ADAPTER_ADDRESSES* iter = addrs; iter && !found; iter = iter->Next) {
00105     if (ACE_Wide_To_Ascii(iter->FriendlyName).char_rep() == interface_name_) {
00106       std::memcpy(node_id_, iter->PhysicalAddress,
00107                   std::min(static_cast<size_t>(iter->PhysicalAddressLength),
00108                            sizeof node_id_));
00109       found = true;
00110     }
00111   }
00112 
00113   alloc->free(addrs);
00114   return found ? 0 : -1;
00115 #elif defined ACE_LINUX || defined __ANDROID_API__
00116   ifreq ifr;
00117   // Guarantee that iface will fit in ifr.ifr_name and still be null terminated
00118   // ifr.ifr_name is sized to IFNAMSIZ
00119   if (std::strlen(iface) >= sizeof(ifr.ifr_name)) {
00120     ACE_ERROR((LM_ERROR,
00121       ACE_TEXT("Interface name %C exceeds max allowable length, must be < %d."),
00122       iface, IFNAMSIZ));
00123     return -1;
00124   }
00125   std::strncpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name));
00126   const ACE_HANDLE h = ACE_OS::socket(PF_INET, SOCK_DGRAM, 0);
00127   if (h == ACE_INVALID_HANDLE) {
00128     return -1;
00129   }
00130   if (ACE_OS::ioctl(h, SIOCGIFHWADDR, &ifr) < 0) {
00131     ACE_OS::close(h);
00132     return -1;
00133   }
00134   ACE_OS::close(h);
00135   std::memcpy(node_id_, ifr.ifr_addr.sa_data, sizeof node_id_);
00136   return 0;
00137 #elif defined ACE_HAS_SIOCGIFCONF || defined ACE_HAS_MAC_OSX
00138   const ACE_HANDLE h = ACE_OS::socket(AF_INET, SOCK_DGRAM, 0);
00139   if (h == ACE_INVALID_HANDLE) {
00140     return -1;
00141   }
00142 
00143   const int BUFFERSIZE = 4000;
00144   char buffer[BUFFERSIZE];
00145   ifconf ifc;
00146   ifc.ifc_len = BUFFERSIZE;
00147   ifc.ifc_buf = buffer;
00148 
00149   if (ACE_OS::ioctl(h, SIOCGIFCONF, &ifc) < 0) {
00150     ACE_OS::close(h);
00151     return -1;
00152   }
00153 
00154   bool found = false;
00155   for (const char* ptr = buffer; !found && ptr < buffer + ifc.ifc_len;) {
00156     const ifreq* ifr = reinterpret_cast<const ifreq*>(ptr);
00157     if (ifr->ifr_addr.sa_family == AF_LINK && ifr->ifr_name == interface_name_) {
00158       const sockaddr_dl* sdl =
00159         reinterpret_cast<const sockaddr_dl*>(&ifr->ifr_addr);
00160       std::memcpy(node_id_, LLADDR(sdl), sizeof node_id_);
00161       found = true;
00162     }
00163 
00164     ptr += sizeof ifr->ifr_name + std::max(sizeof ifr->ifr_addr,
00165       static_cast<size_t>(ifr->ifr_addr.sa_len));
00166   }
00167 
00168   ACE_OS::close(h);
00169   return found ? 0 : -1;
00170 #elif defined ACE_VXWORKS
00171   int name[] = {CTL_NET, AF_ROUTE, 0, 0, NET_RT_IFLIST, 0};
00172   static const size_t name_elts = sizeof name / sizeof name[0];
00173 
00174   size_t result_sz = 0u;
00175   if (sysctl(name, name_elts, 0, &result_sz, 0, 0u) != 0) {
00176     return -1;
00177   }
00178 
00179   ACE_Allocator* const alloc = DCPS::SafetyProfilePool::instance();
00180   char* const result = static_cast<char*>(alloc->malloc(result_sz));
00181 
00182   if (sysctl(name, name_elts, result, &result_sz, 0, 0u) != 0) {
00183     alloc->free(result);
00184     return -1;
00185   }
00186 
00187   for (size_t pos = 0, n; pos + sizeof(if_msghdr) < result_sz; pos += n) {
00188     if_msghdr* const hdr = reinterpret_cast<if_msghdr*>(result + pos);
00189     n = hdr->ifm_msglen;
00190     sockaddr_dl* const addr =
00191       reinterpret_cast<sockaddr_dl*>(result + pos + sizeof(if_msghdr));
00192 
00193     if (hdr->ifm_type == RTM_IFINFO && (hdr->ifm_addrs & RTA_IFP)
00194         && std::memcmp(addr->sdl_data, iface, addr->sdl_nlen) == 0
00195         && addr->sdl_alen >= sizeof node_id_) {
00196       std::memcpy(node_id_, LLADDR(addr), sizeof node_id_);
00197       alloc->free(result);
00198       return 0;
00199     }
00200 
00201     while (pos + n < result_sz) {
00202       if_msghdr* const nxt = reinterpret_cast<if_msghdr*>(result + pos + n);
00203       if (nxt->ifm_type != RTM_NEWADDR) {
00204         break;
00205       }
00206       n += nxt->ifm_msglen;
00207     }
00208   }
00209 
00210   alloc->free(result);
00211   return -1;
00212 #else
00213   return -1;
00214 #endif
00215 }
00216 
00217 void
00218 GuidGenerator::populate(DCPS::GUID_t &container)
00219 {
00220   container.guidPrefix[0] = DCPS::VENDORID_OCI[0];
00221   container.guidPrefix[1] = DCPS::VENDORID_OCI[1];
00222 
00223   const ACE_UINT16 count = getCount();
00224   ACE_OS::memcpy(&container.guidPrefix[2], node_id_, NODE_ID_SIZE);
00225   container.guidPrefix[8] = static_cast<CORBA::Octet>(pid_ >> 8);
00226   container.guidPrefix[9] = static_cast<CORBA::Octet>(pid_ & 0xFF);
00227   container.guidPrefix[10] = static_cast<CORBA::Octet>(count >> 8);
00228   container.guidPrefix[11] = static_cast<CORBA::Octet>(count & 0xFF);
00229 }
00230 
00231 } // namespace RTPS
00232 } // namespace OpenDDS
00233 
00234 OPENDDS_END_VERSIONED_NAMESPACE_DECL
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 10 Aug 2018 for OpenDDS by  doxygen 1.6.1