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 BOOST_ASIO_DETAIL_SOCKET_OPTION_HPP 12 #define BOOST_ASIO_DETAIL_SOCKET_OPTION_HPP 13 14 #if defined(_MSC_VER) && (_MSC_VER >= 1200) 15 # pragma once 16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 17 18 #include <boost/asio/detail/config.hpp> 19 #include <cstddef> 20 #include <stdexcept> 21 #include <boost/asio/detail/socket_types.hpp> 22 #include <boost/asio/detail/throw_exception.hpp> 23 24 #include <boost/asio/detail/push_options.hpp> 25 26 namespace boost { 27 namespace asio { 28 namespace detail { 29 namespace socket_option { 30 31 // Helper template for implementing boolean-based options. 32 template <int Level, int Name> 33 class boolean 34 { 35 public: 36 // Default constructor. boolean()37 boolean() 38 : value_(0) 39 { 40 } 41 42 // Construct with a specific option value. boolean(bool v)43 explicit boolean(bool v) 44 : value_(v ? 1 : 0) 45 { 46 } 47 48 // Set the current value of the boolean. operator =(bool v)49 boolean& operator=(bool v) 50 { 51 value_ = v ? 1 : 0; 52 return *this; 53 } 54 55 // Get the current value of the boolean. value() const56 bool value() const 57 { 58 return !!value_; 59 } 60 61 // Convert to bool. operator bool() const62 operator bool() const 63 { 64 return !!value_; 65 } 66 67 // Test for false. operator !() const68 bool operator!() const 69 { 70 return !value_; 71 } 72 73 // Get the level of the socket option. 74 template <typename Protocol> level(const Protocol &) const75 int level(const Protocol&) const 76 { 77 return Level; 78 } 79 80 // Get the name of the socket option. 81 template <typename Protocol> name(const Protocol &) const82 int name(const Protocol&) const 83 { 84 return Name; 85 } 86 87 // Get the address of the boolean data. 88 template <typename Protocol> data(const Protocol &)89 int* data(const Protocol&) 90 { 91 return &value_; 92 } 93 94 // Get the address of the boolean data. 95 template <typename Protocol> data(const Protocol &) const96 const int* data(const Protocol&) const 97 { 98 return &value_; 99 } 100 101 // Get the size of the boolean data. 102 template <typename Protocol> size(const Protocol &) const103 std::size_t size(const Protocol&) const 104 { 105 return sizeof(value_); 106 } 107 108 // Set the size of the boolean data. 109 template <typename Protocol> resize(const Protocol &,std::size_t s)110 void resize(const Protocol&, std::size_t s) 111 { 112 // On some platforms (e.g. Windows Vista), the getsockopt function will 113 // return the size of a boolean socket option as one byte, even though a 114 // four byte integer was passed in. 115 switch (s) 116 { 117 case sizeof(char): 118 value_ = *reinterpret_cast<char*>(&value_) ? 1 : 0; 119 break; 120 case sizeof(value_): 121 break; 122 default: 123 { 124 std::length_error ex("boolean socket option resize"); 125 boost::asio::detail::throw_exception(ex); 126 } 127 } 128 } 129 130 private: 131 int value_; 132 }; 133 134 // Helper template for implementing integer options. 135 template <int Level, int Name> 136 class integer 137 { 138 public: 139 // Default constructor. integer()140 integer() 141 : value_(0) 142 { 143 } 144 145 // Construct with a specific option value. integer(int v)146 explicit integer(int v) 147 : value_(v) 148 { 149 } 150 151 // Set the value of the int option. operator =(int v)152 integer& operator=(int v) 153 { 154 value_ = v; 155 return *this; 156 } 157 158 // Get the current value of the int option. value() const159 int value() const 160 { 161 return value_; 162 } 163 164 // Get the level of the socket option. 165 template <typename Protocol> level(const Protocol &) const166 int level(const Protocol&) const 167 { 168 return Level; 169 } 170 171 // Get the name of the socket option. 172 template <typename Protocol> name(const Protocol &) const173 int name(const Protocol&) const 174 { 175 return Name; 176 } 177 178 // Get the address of the int data. 179 template <typename Protocol> data(const Protocol &)180 int* data(const Protocol&) 181 { 182 return &value_; 183 } 184 185 // Get the address of the int data. 186 template <typename Protocol> data(const Protocol &) const187 const int* data(const Protocol&) const 188 { 189 return &value_; 190 } 191 192 // Get the size of the int data. 193 template <typename Protocol> size(const Protocol &) const194 std::size_t size(const Protocol&) const 195 { 196 return sizeof(value_); 197 } 198 199 // Set the size of the int data. 200 template <typename Protocol> resize(const Protocol &,std::size_t s)201 void resize(const Protocol&, std::size_t s) 202 { 203 if (s != sizeof(value_)) 204 { 205 std::length_error ex("integer socket option resize"); 206 boost::asio::detail::throw_exception(ex); 207 } 208 } 209 210 private: 211 int value_; 212 }; 213 214 // Helper template for implementing linger options. 215 template <int Level, int Name> 216 class linger 217 { 218 public: 219 // Default constructor. linger()220 linger() 221 { 222 value_.l_onoff = 0; 223 value_.l_linger = 0; 224 } 225 226 // Construct with specific option values. linger(bool e,int t)227 linger(bool e, int t) 228 { 229 enabled(e); 230 timeout BOOST_ASIO_PREVENT_MACRO_SUBSTITUTION(t); 231 } 232 233 // Set the value for whether linger is enabled. enabled(bool value)234 void enabled(bool value) 235 { 236 value_.l_onoff = value ? 1 : 0; 237 } 238 239 // Get the value for whether linger is enabled. enabled() const240 bool enabled() const 241 { 242 return value_.l_onoff != 0; 243 } 244 245 // Set the value for the linger timeout. BOOST_ASIO_PREVENT_MACRO_SUBSTITUTION(int value)246 void timeout BOOST_ASIO_PREVENT_MACRO_SUBSTITUTION(int value) 247 { 248 #if defined(WIN32) 249 value_.l_linger = static_cast<u_short>(value); 250 #else 251 value_.l_linger = value; 252 #endif 253 } 254 255 // Get the value for the linger timeout. BOOST_ASIO_PREVENT_MACRO_SUBSTITUTION() const256 int timeout BOOST_ASIO_PREVENT_MACRO_SUBSTITUTION() const 257 { 258 return static_cast<int>(value_.l_linger); 259 } 260 261 // Get the level of the socket option. 262 template <typename Protocol> level(const Protocol &) const263 int level(const Protocol&) const 264 { 265 return Level; 266 } 267 268 // Get the name of the socket option. 269 template <typename Protocol> name(const Protocol &) const270 int name(const Protocol&) const 271 { 272 return Name; 273 } 274 275 // Get the address of the linger data. 276 template <typename Protocol> data(const Protocol &)277 detail::linger_type* data(const Protocol&) 278 { 279 return &value_; 280 } 281 282 // Get the address of the linger data. 283 template <typename Protocol> data(const Protocol &) const284 const detail::linger_type* data(const Protocol&) const 285 { 286 return &value_; 287 } 288 289 // Get the size of the linger data. 290 template <typename Protocol> size(const Protocol &) const291 std::size_t size(const Protocol&) const 292 { 293 return sizeof(value_); 294 } 295 296 // Set the size of the int data. 297 template <typename Protocol> resize(const Protocol &,std::size_t s)298 void resize(const Protocol&, std::size_t s) 299 { 300 if (s != sizeof(value_)) 301 { 302 std::length_error ex("linger socket option resize"); 303 boost::asio::detail::throw_exception(ex); 304 } 305 } 306 307 private: 308 detail::linger_type value_; 309 }; 310 311 } // namespace socket_option 312 } // namespace detail 313 } // namespace asio 314 } // namespace boost 315 316 #include <boost/asio/detail/pop_options.hpp> 317 318 #endif // BOOST_ASIO_DETAIL_SOCKET_OPTION_HPP 319