$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
From: chris_at_[hidden]
Date: 2008-03-15 01:31:11
Author: chris_kohlhoff
Date: 2008-03-15 01:31:11 EDT (Sat, 15 Mar 2008)
New Revision: 43615
URL: http://svn.boost.org/trac/boost/changeset/43615
Log:
Merged fixes from trunk.
........
  r43570 | chris_kohlhoff | 2008-03-13 00:26:41 +1100 (Thu, 13 Mar 2008) | 3 lines
  
  Use unions to fix a sockaddr_storage aliasing problem that shows up with
  g++ 4.3.0.
........
  r43586 | chris_kohlhoff | 2008-03-13 17:59:02 +1100 (Thu, 13 Mar 2008) | 2 lines
  
  Fix incorrect use of sin_port with a sockaddr_in6 structure.
........
Properties modified: 
   branches/release/   (props changed)
Text files modified: 
   branches/release/boost/asio/detail/socket_ops.hpp |    60 ++++++++++----------                    
   branches/release/boost/asio/ip/basic_endpoint.hpp |   116 +++++++++++++++------------------------ 
   2 files changed, 73 insertions(+), 103 deletions(-)
Modified: branches/release/boost/asio/detail/socket_ops.hpp
==============================================================================
--- branches/release/boost/asio/detail/socket_ops.hpp	(original)
+++ branches/release/boost/asio/detail/socket_ops.hpp	2008-03-15 01:31:11 EDT (Sat, 15 Mar 2008)
@@ -699,40 +699,40 @@
     return 0;
   }
 
-  sockaddr_storage_type address;
+  union
+  {
+    socket_addr_type base;
+    sockaddr_storage_type storage;
+    sockaddr_in4_type v4;
+    sockaddr_in6_type v6;
+  } address;
   DWORD address_length;
   if (af == AF_INET)
   {
     address_length = sizeof(sockaddr_in4_type);
-    sockaddr_in4_type* ipv4_address =
-      reinterpret_cast<sockaddr_in4_type*>(&address);
-    ipv4_address->sin_family = AF_INET;
-    ipv4_address->sin_port = 0;
-    memcpy(&ipv4_address->sin_addr, src, sizeof(in4_addr_type));
+    address.v4.sin_family = AF_INET;
+    address.v4.sin_port = 0;
+    memcpy(&address.v4.sin_addr, src, sizeof(in4_addr_type));
   }
   else // AF_INET6
   {
     address_length = sizeof(sockaddr_in6_type);
-    sockaddr_in6_type* ipv6_address =
-      reinterpret_cast<sockaddr_in6_type*>(&address);
-    ipv6_address->sin6_family = AF_INET6;
-    ipv6_address->sin6_port = 0;
-    ipv6_address->sin6_flowinfo = 0;
-    ipv6_address->sin6_scope_id = scope_id;
-    memcpy(&ipv6_address->sin6_addr, src, sizeof(in6_addr_type));
+    address.v6.sin6_family = AF_INET6;
+    address.v6.sin6_port = 0;
+    address.v6.sin6_flowinfo = 0;
+    address.v6.sin6_scope_id = scope_id;
+    memcpy(&address.v6.sin6_addr, src, sizeof(in6_addr_type));
   }
 
   DWORD string_length = static_cast<DWORD>(length);
 #if defined(BOOST_NO_ANSI_APIS)
   LPWSTR string_buffer = (LPWSTR)_alloca(length * sizeof(WCHAR));
-  int result = error_wrapper(::WSAAddressToStringW(
-        reinterpret_cast<sockaddr*>(&address),
+  int result = error_wrapper(::WSAAddressToStringW(&address.base,
         address_length, 0, string_buffer, &string_length), ec);
   ::WideCharToMultiByte(CP_ACP, 0, string_buffer, -1, dest, length, 0, 0);
 #else
   int result = error_wrapper(::WSAAddressToStringA(
-        reinterpret_cast<sockaddr*>(&address),
-        address_length, 0, dest, &string_length), ec);
+        &address.base, address_length, 0, dest, &string_length), ec);
 #endif
 
   // Windows may set error code on success.
@@ -775,30 +775,30 @@
     return -1;
   }
 
-  sockaddr_storage_type address;
+  union
+  {
+    socket_addr_type base;
+    sockaddr_storage_type storage;
+    sockaddr_in4_type v4;
+    sockaddr_in6_type v6;
+  } address;
   int address_length = sizeof(sockaddr_storage_type);
 #if defined(BOOST_NO_ANSI_APIS)
   int num_wide_chars = strlen(src) + 1;
   LPWSTR wide_buffer = (LPWSTR)_alloca(num_wide_chars * sizeof(WCHAR));
   ::MultiByteToWideChar(CP_ACP, 0, src, -1, wide_buffer, num_wide_chars);
   int result = error_wrapper(::WSAStringToAddressW(
-        wide_buffer, af, 0,
-        reinterpret_cast<sockaddr*>(&address),
-        &address_length), ec);
+        wide_buffer, af, 0, &address.base, &address_length), ec);
 #else
   int result = error_wrapper(::WSAStringToAddressA(
-        const_cast<char*>(src), af, 0,
-        reinterpret_cast<sockaddr*>(&address),
-        &address_length), ec);
+        const_cast<char*>(src), af, 0, &address.base, &address_length), ec);
 #endif
 
   if (af == AF_INET)
   {
     if (result != socket_error_retval)
     {
-      sockaddr_in4_type* ipv4_address =
-        reinterpret_cast<sockaddr_in4_type*>(&address);
-      memcpy(dest, &ipv4_address->sin_addr, sizeof(in4_addr_type));
+      memcpy(dest, &address.v4.sin_addr, sizeof(in4_addr_type));
       clear_error(ec);
     }
     else if (strcmp(src, "255.255.255.255") == 0)
@@ -811,11 +811,9 @@
   {
     if (result != socket_error_retval)
     {
-      sockaddr_in6_type* ipv6_address =
-        reinterpret_cast<sockaddr_in6_type*>(&address);
-      memcpy(dest, &ipv6_address->sin6_addr, sizeof(in6_addr_type));
+      memcpy(dest, &address.v6.sin6_addr, sizeof(in6_addr_type));
       if (scope_id)
-        *scope_id = ipv6_address->sin6_scope_id;
+        *scope_id = address.v6.sin6_scope_id;
       clear_error(ec);
     }
   }
Modified: branches/release/boost/asio/ip/basic_endpoint.hpp
==============================================================================
--- branches/release/boost/asio/ip/basic_endpoint.hpp	(original)
+++ branches/release/boost/asio/ip/basic_endpoint.hpp	2008-03-15 01:31:11 EDT (Sat, 15 Mar 2008)
@@ -66,11 +66,9 @@
   basic_endpoint()
     : data_()
   {
-    boost::asio::detail::sockaddr_in4_type& data
-      = reinterpret_cast<boost::asio::detail::sockaddr_in4_type&>(data_);
-    data.sin_family = AF_INET;
-    data.sin_port = 0;
-    data.sin_addr.s_addr = INADDR_ANY;
+    data_.v4.sin_family = AF_INET;
+    data_.v4.sin_port = 0;
+    data_.v4.sin_addr.s_addr = INADDR_ANY;
   }
 
   /// Construct an endpoint using a port number, specified in the host's byte
@@ -95,24 +93,20 @@
     using namespace std; // For memcpy.
     if (protocol.family() == PF_INET)
     {
-      boost::asio::detail::sockaddr_in4_type& data
-        = reinterpret_cast<boost::asio::detail::sockaddr_in4_type&>(data_);
-      data.sin_family = AF_INET;
-      data.sin_port =
+      data_.v4.sin_family = AF_INET;
+      data_.v4.sin_port =
         boost::asio::detail::socket_ops::host_to_network_short(port_num);
-      data.sin_addr.s_addr = INADDR_ANY;
+      data_.v4.sin_addr.s_addr = INADDR_ANY;
     }
     else
     {
-      boost::asio::detail::sockaddr_in6_type& data
-        = reinterpret_cast<boost::asio::detail::sockaddr_in6_type&>(data_);
-      data.sin6_family = AF_INET6;
-      data.sin6_port =
+      data_.v6.sin6_family = AF_INET6;
+      data_.v6.sin6_port =
         boost::asio::detail::socket_ops::host_to_network_short(port_num);
-      data.sin6_flowinfo = 0;
+      data_.v6.sin6_flowinfo = 0;
       boost::asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT;
-      data.sin6_addr = tmp_addr;
-      data.sin6_scope_id = 0;
+      data_.v6.sin6_addr = tmp_addr;
+      data_.v6.sin6_scope_id = 0;
     }
   }
 
@@ -125,27 +119,23 @@
     using namespace std; // For memcpy.
     if (addr.is_v4())
     {
-      boost::asio::detail::sockaddr_in4_type& data
-        = reinterpret_cast<boost::asio::detail::sockaddr_in4_type&>(data_);
-      data.sin_family = AF_INET;
-      data.sin_port =
+      data_.v4.sin_family = AF_INET;
+      data_.v4.sin_port =
         boost::asio::detail::socket_ops::host_to_network_short(port_num);
-      data.sin_addr.s_addr =
+      data_.v4.sin_addr.s_addr =
         boost::asio::detail::socket_ops::host_to_network_long(
             addr.to_v4().to_ulong());
     }
     else
     {
-      boost::asio::detail::sockaddr_in6_type& data
-        = reinterpret_cast<boost::asio::detail::sockaddr_in6_type&>(data_);
-      data.sin6_family = AF_INET6;
-      data.sin6_port =
+      data_.v6.sin6_family = AF_INET6;
+      data_.v6.sin6_port =
         boost::asio::detail::socket_ops::host_to_network_short(port_num);
-      data.sin6_flowinfo = 0;
+      data_.v6.sin6_flowinfo = 0;
       boost::asio::ip::address_v6 v6_addr = addr.to_v6();
       boost::asio::ip::address_v6::bytes_type bytes = v6_addr.to_bytes();
-      memcpy(data.sin6_addr.s6_addr, bytes.elems, 16);
-      data.sin6_scope_id = v6_addr.scope_id();
+      memcpy(data_.v6.sin6_addr.s6_addr, bytes.elems, 16);
+      data_.v6.sin6_scope_id = v6_addr.scope_id();
     }
   }
 
@@ -165,7 +155,7 @@
   /// The protocol associated with the endpoint.
   protocol_type protocol() const
   {
-    if (is_v4(data_))
+    if (is_v4())
       return InternetProtocol::v4();
     return InternetProtocol::v6();
   }
@@ -173,19 +163,19 @@
   /// Get the underlying endpoint in the native type.
   data_type* data()
   {
-    return reinterpret_cast<data_type*>(&data_);
+    return &data_.base;
   }
 
   /// Get the underlying endpoint in the native type.
   const data_type* data() const
   {
-    return reinterpret_cast<const data_type*>(&data_);
+    return &data_.base;
   }
 
   /// Get the underlying size of the endpoint in the native type.
   std::size_t size() const
   {
-    if (is_v4(data_))
+    if (is_v4())
       return sizeof(boost::asio::detail::sockaddr_in4_type);
     else
       return sizeof(boost::asio::detail::sockaddr_in6_type);
@@ -194,7 +184,7 @@
   /// Set the underlying size of the endpoint in the native type.
   void resize(std::size_t size)
   {
-    if (size > sizeof(data_))
+    if (size > sizeof(boost::asio::detail::sockaddr_storage_type))
     {
       boost::system::system_error e(boost::asio::error::invalid_argument);
       boost::throw_exception(e);
@@ -204,24 +194,22 @@
   /// Get the capacity of the endpoint in the native type.
   std::size_t capacity() const
   {
-    return sizeof(data_);
+    return sizeof(boost::asio::detail::sockaddr_storage_type);
   }
 
   /// Get the port associated with the endpoint. The port number is always in
   /// the host's byte order.
   unsigned short port() const
   {
-    if (is_v4(data_))
+    if (is_v4())
     {
       return boost::asio::detail::socket_ops::network_to_host_short(
-          reinterpret_cast<const boost::asio::detail::sockaddr_in4_type&>(
-            data_).sin_port);
+          data_.v4.sin_port);
     }
     else
     {
       return boost::asio::detail::socket_ops::network_to_host_short(
-          reinterpret_cast<const boost::asio::detail::sockaddr_in6_type&>(
-            data_).sin6_port);
+          data_.v6.sin6_port);
     }
   }
 
@@ -229,14 +217,14 @@
   /// the host's byte order.
   void port(unsigned short port_num)
   {
-    if (is_v4(data_))
+    if (is_v4())
     {
-      reinterpret_cast<boost::asio::detail::sockaddr_in4_type&>(data_).sin_port
+      data_.v4.sin_port
         = boost::asio::detail::socket_ops::host_to_network_short(port_num);
     }
     else
     {
-      reinterpret_cast<boost::asio::detail::sockaddr_in6_type&>(data_).sin6_port
+      data_.v6.sin6_port
         = boost::asio::detail::socket_ops::host_to_network_short(port_num);
     }
   }
@@ -245,23 +233,17 @@
   boost::asio::ip::address address() const
   {
     using namespace std; // For memcpy.
-    if (is_v4(data_))
+    if (is_v4())
     {
-      const boost::asio::detail::sockaddr_in4_type& data
-        = reinterpret_cast<const boost::asio::detail::sockaddr_in4_type&>(
-            data_);
       return boost::asio::ip::address_v4(
           boost::asio::detail::socket_ops::network_to_host_long(
-            data.sin_addr.s_addr));
+            data_.v4.sin_addr.s_addr));
     }
     else
     {
-      const boost::asio::detail::sockaddr_in6_type& data
-        = reinterpret_cast<const boost::asio::detail::sockaddr_in6_type&>(
-            data_);
       boost::asio::ip::address_v6::bytes_type bytes;
-      memcpy(bytes.elems, data.sin6_addr.s6_addr, 16);
-      return boost::asio::ip::address_v6(bytes, data.sin6_scope_id);
+      memcpy(bytes.elems, data_.v6.sin6_addr.s6_addr, 16);
+      return boost::asio::ip::address_v6(bytes, data_.v6.sin6_scope_id);
     }
   }
 
@@ -299,29 +281,19 @@
 
 private:
   // Helper function to determine whether the endpoint is IPv4.
-#if defined(_AIX)
-  template <typename T, unsigned char (T::*)> struct is_v4_helper {};
-
-  template <typename T>
-  static bool is_v4(const T& ss, is_v4_helper<T, &T::ss_family>* = 0)
+  bool is_v4() const
   {
-    return ss.ss_family == AF_INET;
+    return data_.base.sa_family == AF_INET;
   }
 
-  template <typename T>
-  static bool is_v4(const T& ss, is_v4_helper<T, &T::__ss_family>* = 0)
-  {
-    return ss.__ss_family == AF_INET;
-  }
-#else
-  static bool is_v4(const boost::asio::detail::sockaddr_storage_type& ss)
-  {
-    return ss.ss_family == AF_INET;
-  }
-#endif
-
   // The underlying IP socket address.
-  boost::asio::detail::sockaddr_storage_type data_;
+  union data_union
+  {
+    boost::asio::detail::socket_addr_type base;
+    boost::asio::detail::sockaddr_storage_type storage;
+    boost::asio::detail::sockaddr_in4_type v4;
+    boost::asio::detail::sockaddr_in6_type v6;
+  } data_;
 };
 
 /// Output an endpoint as a string.