Home | History | Annotate | Download | only in detail
      1 //
      2 // detail/socket_option.hpp
      3 // ~~~~~~~~~~~~~~~~~~~~~~~~
      4 //
      5 // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
      6 //
      7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
      8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
      9 //
     10 
     11 #ifndef ASIO_DETAIL_SOCKET_OPTION_HPP
     12 #define ASIO_DETAIL_SOCKET_OPTION_HPP
     13 
     14 
     15 #include "asio/detail/config.hpp"
     16 #include <cstddef>
     17 #include <stdexcept>
     18 #include "asio/detail/socket_types.hpp"
     19 #include "asio/detail/throw_exception.hpp"
     20 
     21 #include "asio/detail/push_options.hpp"
     22 
     23 namespace asio {
     24 namespace detail {
     25 namespace socket_option {
     26 
     27 // Helper template for implementing boolean-based options.
     28 template <int Level, int Name>
     29 class boolean
     30 {
     31 public:
     32   // Default constructor.
     33   boolean()
     34     : value_(0)
     35   {
     36   }
     37 
     38   // Construct with a specific option value.
     39   explicit boolean(bool v)
     40     : value_(v ? 1 : 0)
     41   {
     42   }
     43 
     44   // Set the current value of the boolean.
     45   boolean& operator=(bool v)
     46   {
     47     value_ = v ? 1 : 0;
     48     return *this;
     49   }
     50 
     51   // Get the current value of the boolean.
     52   bool value() const
     53   {
     54     return !!value_;
     55   }
     56 
     57   // Convert to bool.
     58   operator bool() const
     59   {
     60     return !!value_;
     61   }
     62 
     63   // Test for false.
     64   bool operator!() const
     65   {
     66     return !value_;
     67   }
     68 
     69   // Get the level of the socket option.
     70   template <typename Protocol>
     71   int level(const Protocol&) const
     72   {
     73     return Level;
     74   }
     75 
     76   // Get the name of the socket option.
     77   template <typename Protocol>
     78   int name(const Protocol&) const
     79   {
     80     return Name;
     81   }
     82 
     83   // Get the address of the boolean data.
     84   template <typename Protocol>
     85   int* data(const Protocol&)
     86   {
     87     return &value_;
     88   }
     89 
     90   // Get the address of the boolean data.
     91   template <typename Protocol>
     92   const int* data(const Protocol&) const
     93   {
     94     return &value_;
     95   }
     96 
     97   // Get the size of the boolean data.
     98   template <typename Protocol>
     99   std::size_t size(const Protocol&) const
    100   {
    101     return sizeof(value_);
    102   }
    103 
    104   // Set the size of the boolean data.
    105   template <typename Protocol>
    106   void resize(const Protocol&, std::size_t s)
    107   {
    108     // On some platforms (e.g. Windows Vista), the getsockopt function will
    109     // return the size of a boolean socket option as one byte, even though a
    110     // four byte integer was passed in.
    111     switch (s)
    112     {
    113     case sizeof(char):
    114       value_ = *reinterpret_cast<char*>(&value_) ? 1 : 0;
    115       break;
    116     case sizeof(value_):
    117       break;
    118     default:
    119       {
    120         std::length_error ex("boolean socket option resize");
    121         asio::detail::throw_exception(ex);
    122       }
    123     }
    124   }
    125 
    126 private:
    127   int value_;
    128 };
    129 
    130 // Helper template for implementing integer options.
    131 template <int Level, int Name>
    132 class integer
    133 {
    134 public:
    135   // Default constructor.
    136   integer()
    137     : value_(0)
    138   {
    139   }
    140 
    141   // Construct with a specific option value.
    142   explicit integer(int v)
    143     : value_(v)
    144   {
    145   }
    146 
    147   // Set the value of the int option.
    148   integer& operator=(int v)
    149   {
    150     value_ = v;
    151     return *this;
    152   }
    153 
    154   // Get the current value of the int option.
    155   int value() const
    156   {
    157     return value_;
    158   }
    159 
    160   // Get the level of the socket option.
    161   template <typename Protocol>
    162   int level(const Protocol&) const
    163   {
    164     return Level;
    165   }
    166 
    167   // Get the name of the socket option.
    168   template <typename Protocol>
    169   int name(const Protocol&) const
    170   {
    171     return Name;
    172   }
    173 
    174   // Get the address of the int data.
    175   template <typename Protocol>
    176   int* data(const Protocol&)
    177   {
    178     return &value_;
    179   }
    180 
    181   // Get the address of the int data.
    182   template <typename Protocol>
    183   const int* data(const Protocol&) const
    184   {
    185     return &value_;
    186   }
    187 
    188   // Get the size of the int data.
    189   template <typename Protocol>
    190   std::size_t size(const Protocol&) const
    191   {
    192     return sizeof(value_);
    193   }
    194 
    195   // Set the size of the int data.
    196   template <typename Protocol>
    197   void resize(const Protocol&, std::size_t s)
    198   {
    199     if (s != sizeof(value_))
    200     {
    201       std::length_error ex("integer socket option resize");
    202       asio::detail::throw_exception(ex);
    203     }
    204   }
    205 
    206 private:
    207   int value_;
    208 };
    209 
    210 // Helper template for implementing linger options.
    211 template <int Level, int Name>
    212 class linger
    213 {
    214 public:
    215   // Default constructor.
    216   linger()
    217   {
    218     value_.l_onoff = 0;
    219     value_.l_linger = 0;
    220   }
    221 
    222   // Construct with specific option values.
    223   linger(bool e, int t)
    224   {
    225     enabled(e);
    226     timeout ASIO_PREVENT_MACRO_SUBSTITUTION(t);
    227   }
    228 
    229   // Set the value for whether linger is enabled.
    230   void enabled(bool value)
    231   {
    232     value_.l_onoff = value ? 1 : 0;
    233   }
    234 
    235   // Get the value for whether linger is enabled.
    236   bool enabled() const
    237   {
    238     return value_.l_onoff != 0;
    239   }
    240 
    241   // Set the value for the linger timeout.
    242   void timeout ASIO_PREVENT_MACRO_SUBSTITUTION(int value)
    243   {
    244     value_.l_linger = value;
    245   }
    246 
    247   // Get the value for the linger timeout.
    248   int timeout ASIO_PREVENT_MACRO_SUBSTITUTION() const
    249   {
    250     return static_cast<int>(value_.l_linger);
    251   }
    252 
    253   // Get the level of the socket option.
    254   template <typename Protocol>
    255   int level(const Protocol&) const
    256   {
    257     return Level;
    258   }
    259 
    260   // Get the name of the socket option.
    261   template <typename Protocol>
    262   int name(const Protocol&) const
    263   {
    264     return Name;
    265   }
    266 
    267   // Get the address of the linger data.
    268   template <typename Protocol>
    269   detail::linger_type* data(const Protocol&)
    270   {
    271     return &value_;
    272   }
    273 
    274   // Get the address of the linger data.
    275   template <typename Protocol>
    276   const detail::linger_type* data(const Protocol&) const
    277   {
    278     return &value_;
    279   }
    280 
    281   // Get the size of the linger data.
    282   template <typename Protocol>
    283   std::size_t size(const Protocol&) const
    284   {
    285     return sizeof(value_);
    286   }
    287 
    288   // Set the size of the int data.
    289   template <typename Protocol>
    290   void resize(const Protocol&, std::size_t s)
    291   {
    292     if (s != sizeof(value_))
    293     {
    294       std::length_error ex("linger socket option resize");
    295       asio::detail::throw_exception(ex);
    296     }
    297   }
    298 
    299 private:
    300   detail::linger_type value_;
    301 };
    302 
    303 } // namespace socket_option
    304 } // namespace detail
    305 } // namespace asio
    306 
    307 #include "asio/detail/pop_options.hpp"
    308 
    309 #endif // ASIO_DETAIL_SOCKET_OPTION_HPP
    310