socket_option.hpp
Go to the documentation of this file.
00001 //
00002 // socket_option.hpp
00003 // ~~~~~~~~~~~~~~~~~
00004 //
00005 // Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
00006 //
00007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
00008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
00009 //
00010 
00011 #ifndef ASIO_IP_DETAIL_SOCKET_OPTION_HPP
00012 #define ASIO_IP_DETAIL_SOCKET_OPTION_HPP
00013 
00014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
00015 # pragma once
00016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
00017 
00018 #include "asio/detail/push_options.hpp"
00019 
00020 #include "asio/detail/push_options.hpp"
00021 #include <cstddef>
00022 #include <cstring>
00023 #include <boost/config.hpp>
00024 #include "asio/detail/pop_options.hpp"
00025 
00026 #include "asio/ip/address.hpp"
00027 #include "asio/detail/socket_ops.hpp"
00028 #include "asio/detail/socket_types.hpp"
00029 
00030 namespace asio {
00031 namespace ip {
00032 namespace detail {
00033 namespace socket_option {
00034 
00035 // Helper template for implementing multicast enable loopback options.
00036 template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>
00037 class multicast_enable_loopback
00038 {
00039 public:
00040 #if defined(__sun) || defined(__osf__)
00041   typedef unsigned char ipv4_value_type;
00042   typedef unsigned char ipv6_value_type;
00043 #elif defined(_AIX) || defined(__hpux)
00044   typedef unsigned char ipv4_value_type;
00045   typedef unsigned int ipv6_value_type;
00046 #else
00047   typedef int ipv4_value_type;
00048   typedef int ipv6_value_type;
00049 #endif
00050 
00051   // Default constructor.
00052   multicast_enable_loopback()
00053     : ipv4_value_(0),
00054       ipv6_value_(0)
00055   {
00056   }
00057 
00058   // Construct with a specific option value.
00059   explicit multicast_enable_loopback(bool v)
00060     : ipv4_value_(v ? 1 : 0),
00061       ipv6_value_(v ? 1 : 0)
00062   {
00063   }
00064 
00065   // Set the value of the boolean.
00066   multicast_enable_loopback& operator=(bool v)
00067   {
00068     ipv4_value_ = v ? 1 : 0;
00069     ipv6_value_ = v ? 1 : 0;
00070     return *this;
00071   }
00072 
00073   // Get the current value of the boolean.
00074   bool value() const
00075   {
00076     return !!ipv4_value_;
00077   }
00078 
00079   // Convert to bool.
00080   operator bool() const
00081   {
00082     return !!ipv4_value_;
00083   }
00084 
00085   // Test for false.
00086   bool operator!() const
00087   {
00088     return !ipv4_value_;
00089   }
00090 
00091   // Get the level of the socket option.
00092   template <typename Protocol>
00093   int level(const Protocol& protocol) const
00094   {
00095     if (protocol.family() == PF_INET6)
00096       return IPv6_Level;
00097     return IPv4_Level;
00098   }
00099 
00100   // Get the name of the socket option.
00101   template <typename Protocol>
00102   int name(const Protocol& protocol) const
00103   {
00104     if (protocol.family() == PF_INET6)
00105       return IPv6_Name;
00106     return IPv4_Name;
00107   }
00108 
00109   // Get the address of the boolean data.
00110   template <typename Protocol>
00111   void* data(const Protocol& protocol)
00112   {
00113     if (protocol.family() == PF_INET6)
00114       return &ipv6_value_;
00115     return &ipv4_value_;
00116   }
00117 
00118   // Get the address of the boolean data.
00119   template <typename Protocol>
00120   const void* data(const Protocol& protocol) const
00121   {
00122     if (protocol.family() == PF_INET6)
00123       return &ipv6_value_;
00124     return &ipv4_value_;
00125   }
00126 
00127   // Get the size of the boolean data.
00128   template <typename Protocol>
00129   std::size_t size(const Protocol& protocol) const
00130   {
00131     if (protocol.family() == PF_INET6)
00132       return sizeof(ipv6_value_);
00133     return sizeof(ipv4_value_);
00134   }
00135 
00136   // Set the size of the boolean data.
00137   template <typename Protocol>
00138   void resize(const Protocol& protocol, std::size_t s)
00139   {
00140     if (protocol.family() == PF_INET6)
00141     {
00142       if (s != sizeof(ipv6_value_))
00143       {
00144         throw std::length_error(
00145             "multicast_enable_loopback socket option resize");
00146       }
00147       ipv4_value_ = ipv6_value_ ? 1 : 0;
00148     }
00149     else
00150     {
00151       if (s != sizeof(ipv4_value_))
00152       {
00153         throw std::length_error(
00154             "multicast_enable_loopback socket option resize");
00155       }
00156       ipv6_value_ = ipv4_value_ ? 1 : 0;
00157     }
00158   }
00159 
00160 private:
00161   ipv4_value_type ipv4_value_;
00162   ipv6_value_type ipv6_value_;
00163 };
00164 
00165 // Helper template for implementing unicast hops options.
00166 template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>
00167 class unicast_hops
00168 {
00169 public:
00170   // Default constructor.
00171   unicast_hops()
00172     : value_(0)
00173   {
00174   }
00175 
00176   // Construct with a specific option value.
00177   explicit unicast_hops(int v)
00178     : value_(v)
00179   {
00180   }
00181 
00182   // Set the value of the option.
00183   unicast_hops& operator=(int v)
00184   {
00185     value_ = v;
00186     return *this;
00187   }
00188 
00189   // Get the current value of the option.
00190   int value() const
00191   {
00192     return value_;
00193   }
00194 
00195   // Get the level of the socket option.
00196   template <typename Protocol>
00197   int level(const Protocol& protocol) const
00198   {
00199     if (protocol.family() == PF_INET6)
00200       return IPv6_Level;
00201     return IPv4_Level;
00202   }
00203 
00204   // Get the name of the socket option.
00205   template <typename Protocol>
00206   int name(const Protocol& protocol) const
00207   {
00208     if (protocol.family() == PF_INET6)
00209       return IPv6_Name;
00210     return IPv4_Name;
00211   }
00212 
00213   // Get the address of the data.
00214   template <typename Protocol>
00215   int* data(const Protocol&)
00216   {
00217     return &value_;
00218   }
00219 
00220   // Get the address of the data.
00221   template <typename Protocol>
00222   const int* data(const Protocol&) const
00223   {
00224     return &value_;
00225   }
00226 
00227   // Get the size of the data.
00228   template <typename Protocol>
00229   std::size_t size(const Protocol&) const
00230   {
00231     return sizeof(value_);
00232   }
00233 
00234   // Set the size of the data.
00235   template <typename Protocol>
00236   void resize(const Protocol&, std::size_t s)
00237   {
00238     if (s != sizeof(value_))
00239       throw std::length_error("unicast hops socket option resize");
00240 #if defined(__hpux)
00241     if (value_ < 0)
00242       value_ = value_ & 0xFF;
00243 #endif
00244   }
00245 
00246 private:
00247   int value_;
00248 };
00249 
00250 // Helper template for implementing multicast hops options.
00251 template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>
00252 class multicast_hops
00253 {
00254 public:
00255 #if defined(BOOST_WINDOWS) && defined(UNDER_CE)
00256   typedef int ipv4_value_type;
00257 #else
00258   typedef unsigned char ipv4_value_type;
00259 #endif
00260   typedef int ipv6_value_type;
00261 
00262   // Default constructor.
00263   multicast_hops()
00264     : ipv4_value_(0),
00265       ipv6_value_(0)
00266   {
00267   }
00268 
00269   // Construct with a specific option value.
00270   explicit multicast_hops(int v)
00271   {
00272     if (v < 0 || v > 255)
00273       throw std::out_of_range("multicast hops value out of range");
00274     ipv4_value_ = (ipv4_value_type)v;
00275     ipv6_value_ = v;
00276   }
00277 
00278   // Set the value of the option.
00279   multicast_hops& operator=(int v)
00280   {
00281     if (v < 0 || v > 255)
00282       throw std::out_of_range("multicast hops value out of range");
00283     ipv4_value_ = (ipv4_value_type)v;
00284     ipv6_value_ = v;
00285     return *this;
00286   }
00287 
00288   // Get the current value of the option.
00289   int value() const
00290   {
00291     return ipv6_value_;
00292   }
00293 
00294   // Get the level of the socket option.
00295   template <typename Protocol>
00296   int level(const Protocol& protocol) const
00297   {
00298     if (protocol.family() == PF_INET6)
00299       return IPv6_Level;
00300     return IPv4_Level;
00301   }
00302 
00303   // Get the name of the socket option.
00304   template <typename Protocol>
00305   int name(const Protocol& protocol) const
00306   {
00307     if (protocol.family() == PF_INET6)
00308       return IPv6_Name;
00309     return IPv4_Name;
00310   }
00311 
00312   // Get the address of the data.
00313   template <typename Protocol>
00314   void* data(const Protocol& protocol)
00315   {
00316     if (protocol.family() == PF_INET6)
00317       return &ipv6_value_;
00318     return &ipv4_value_;
00319   }
00320 
00321   // Get the address of the data.
00322   template <typename Protocol>
00323   const void* data(const Protocol& protocol) const
00324   {
00325     if (protocol.family() == PF_INET6)
00326       return &ipv6_value_;
00327     return &ipv4_value_;
00328   }
00329 
00330   // Get the size of the data.
00331   template <typename Protocol>
00332   std::size_t size(const Protocol& protocol) const
00333   {
00334     if (protocol.family() == PF_INET6)
00335       return sizeof(ipv6_value_);
00336     return sizeof(ipv4_value_);
00337   }
00338 
00339   // Set the size of the data.
00340   template <typename Protocol>
00341   void resize(const Protocol& protocol, std::size_t s)
00342   {
00343     if (protocol.family() == PF_INET6)
00344     {
00345       if (s != sizeof(ipv6_value_))
00346         throw std::length_error("multicast hops socket option resize");
00347       if (ipv6_value_ < 0)
00348         ipv4_value_ = 0;
00349       else if (ipv6_value_ > 255)
00350         ipv4_value_ = 255;
00351       else
00352         ipv4_value_ = (ipv4_value_type)ipv6_value_;
00353     }
00354     else
00355     {
00356       if (s != sizeof(ipv4_value_))
00357         throw std::length_error("multicast hops socket option resize");
00358       ipv6_value_ = ipv4_value_;
00359     }
00360   }
00361 
00362 private:
00363   ipv4_value_type ipv4_value_;
00364   ipv6_value_type ipv6_value_;
00365 };
00366 
00367 // Helper template for implementing ip_mreq-based options.
00368 template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>
00369 class multicast_request
00370 {
00371 public:
00372   // Default constructor.
00373   multicast_request()
00374   {
00375     ipv4_value_.imr_multiaddr.s_addr =
00376       asio::detail::socket_ops::host_to_network_long(
00377           asio::ip::address_v4::any().to_ulong());
00378     ipv4_value_.imr_interface.s_addr =
00379       asio::detail::socket_ops::host_to_network_long(
00380           asio::ip::address_v4::any().to_ulong());
00381 
00382     asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT;
00383     ipv6_value_.ipv6mr_multiaddr = tmp_addr;
00384     ipv6_value_.ipv6mr_interface = 0;
00385   }
00386 
00387   // Construct with multicast address only.
00388   explicit multicast_request(const asio::ip::address& multicast_address)
00389   {
00390     if (multicast_address.is_v6())
00391     {
00392       ipv4_value_.imr_multiaddr.s_addr =
00393         asio::detail::socket_ops::host_to_network_long(
00394             asio::ip::address_v4::any().to_ulong());
00395       ipv4_value_.imr_interface.s_addr =
00396         asio::detail::socket_ops::host_to_network_long(
00397             asio::ip::address_v4::any().to_ulong());
00398 
00399       using namespace std; // For memcpy.
00400       asio::ip::address_v6 ipv6_address = multicast_address.to_v6();
00401       asio::ip::address_v6::bytes_type bytes = ipv6_address.to_bytes();
00402       memcpy(ipv6_value_.ipv6mr_multiaddr.s6_addr, bytes.elems, 16);
00403       ipv6_value_.ipv6mr_interface = 0;
00404     }
00405     else
00406     {
00407       ipv4_value_.imr_multiaddr.s_addr =
00408         asio::detail::socket_ops::host_to_network_long(
00409             multicast_address.to_v4().to_ulong());
00410       ipv4_value_.imr_interface.s_addr =
00411         asio::detail::socket_ops::host_to_network_long(
00412             asio::ip::address_v4::any().to_ulong());
00413 
00414       asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT;
00415       ipv6_value_.ipv6mr_multiaddr = tmp_addr;
00416       ipv6_value_.ipv6mr_interface = 0;
00417     }
00418   }
00419 
00420   // Construct with multicast address and IPv4 address specifying an interface.
00421   explicit multicast_request(
00422       const asio::ip::address_v4& multicast_address,
00423       const asio::ip::address_v4& network_interface
00424         = asio::ip::address_v4::any())
00425   {
00426     ipv4_value_.imr_multiaddr.s_addr =
00427       asio::detail::socket_ops::host_to_network_long(
00428           multicast_address.to_ulong());
00429     ipv4_value_.imr_interface.s_addr =
00430       asio::detail::socket_ops::host_to_network_long(
00431           network_interface.to_ulong());
00432 
00433     asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT;
00434     ipv6_value_.ipv6mr_multiaddr = tmp_addr;
00435     ipv6_value_.ipv6mr_interface = 0;
00436   }
00437 
00438   // Construct with multicast address and IPv6 network interface index.
00439   explicit multicast_request(
00440       const asio::ip::address_v6& multicast_address,
00441       unsigned long network_interface = 0)
00442   {
00443     ipv4_value_.imr_multiaddr.s_addr =
00444       asio::detail::socket_ops::host_to_network_long(
00445           asio::ip::address_v4::any().to_ulong());
00446     ipv4_value_.imr_interface.s_addr =
00447       asio::detail::socket_ops::host_to_network_long(
00448           asio::ip::address_v4::any().to_ulong());
00449 
00450     using namespace std; // For memcpy.
00451     asio::ip::address_v6::bytes_type bytes =
00452       multicast_address.to_bytes();
00453     memcpy(ipv6_value_.ipv6mr_multiaddr.s6_addr, bytes.elems, 16);
00454     ipv6_value_.ipv6mr_interface = network_interface;
00455   }
00456 
00457   // Get the level of the socket option.
00458   template <typename Protocol>
00459   int level(const Protocol& protocol) const
00460   {
00461     if (protocol.family() == PF_INET6)
00462       return IPv6_Level;
00463     return IPv4_Level;
00464   }
00465 
00466   // Get the name of the socket option.
00467   template <typename Protocol>
00468   int name(const Protocol& protocol) const
00469   {
00470     if (protocol.family() == PF_INET6)
00471       return IPv6_Name;
00472     return IPv4_Name;
00473   }
00474 
00475   // Get the address of the option data.
00476   template <typename Protocol>
00477   const void* data(const Protocol& protocol) const
00478   {
00479     if (protocol.family() == PF_INET6)
00480       return &ipv6_value_;
00481     return &ipv4_value_;
00482   }
00483 
00484   // Get the size of the option data.
00485   template <typename Protocol>
00486   std::size_t size(const Protocol& protocol) const
00487   {
00488     if (protocol.family() == PF_INET6)
00489       return sizeof(ipv6_value_);
00490     return sizeof(ipv4_value_);
00491   }
00492 
00493 private:
00494   asio::detail::in4_mreq_type ipv4_value_;
00495   asio::detail::in6_mreq_type ipv6_value_;
00496 };
00497 
00498 // Helper template for implementing options that specify a network interface.
00499 template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>
00500 class network_interface
00501 {
00502 public:
00503   // Default constructor.
00504   network_interface()
00505   {
00506     ipv4_value_.s_addr =
00507       asio::detail::socket_ops::host_to_network_long(
00508           asio::ip::address_v4::any().to_ulong());
00509     ipv6_value_ = 0;
00510   }
00511 
00512   // Construct with IPv4 interface.
00513   explicit network_interface(const asio::ip::address_v4& ipv4_interface)
00514   {
00515     ipv4_value_.s_addr =
00516       asio::detail::socket_ops::host_to_network_long(
00517           ipv4_interface.to_ulong());
00518     ipv6_value_ = 0;
00519   }
00520 
00521   // Construct with IPv6 interface.
00522   explicit network_interface(unsigned int ipv6_interface)
00523   {
00524     ipv4_value_.s_addr =
00525       asio::detail::socket_ops::host_to_network_long(
00526           asio::ip::address_v4::any().to_ulong());
00527     ipv6_value_ = ipv6_interface;
00528   }
00529 
00530   // Get the level of the socket option.
00531   template <typename Protocol>
00532   int level(const Protocol& protocol) const
00533   {
00534     if (protocol.family() == PF_INET6)
00535       return IPv6_Level;
00536     return IPv4_Level;
00537   }
00538 
00539   // Get the name of the socket option.
00540   template <typename Protocol>
00541   int name(const Protocol& protocol) const
00542   {
00543     if (protocol.family() == PF_INET6)
00544       return IPv6_Name;
00545     return IPv4_Name;
00546   }
00547 
00548   // Get the address of the option data.
00549   template <typename Protocol>
00550   const void* data(const Protocol& protocol) const
00551   {
00552     if (protocol.family() == PF_INET6)
00553       return &ipv6_value_;
00554     return &ipv4_value_;
00555   }
00556 
00557   // Get the size of the option data.
00558   template <typename Protocol>
00559   std::size_t size(const Protocol& protocol) const
00560   {
00561     if (protocol.family() == PF_INET6)
00562       return sizeof(ipv6_value_);
00563     return sizeof(ipv4_value_);
00564   }
00565 
00566 private:
00567   asio::detail::in4_addr_type ipv4_value_;
00568   unsigned int ipv6_value_;
00569 };
00570 
00571 } // namespace socket_option
00572 } // namespace detail
00573 } // namespace ip
00574 } // namespace asio
00575 
00576 #include "asio/detail/pop_options.hpp"
00577 
00578 #endif // ASIO_IP_DETAIL_SOCKET_OPTION_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines


Castor
Author(s): Carpe Noctem
autogenerated on Fri Nov 8 2013 11:05:39