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. boolean()33 boolean() 34 : value_(0) 35 { 36 } 37 38 // Construct with a specific option value. boolean(bool v)39 explicit boolean(bool v) 40 : value_(v ? 1 : 0) 41 { 42 } 43 44 // Set the current value of the boolean. operator =(bool v)45 boolean& operator=(bool v) 46 { 47 value_ = v ? 1 : 0; 48 return *this; 49 } 50 51 // Get the current value of the boolean. value() const52 bool value() const 53 { 54 return !!value_; 55 } 56 57 // Convert to bool. operator bool() const58 operator bool() const 59 { 60 return !!value_; 61 } 62 63 // Test for false. operator !() const64 bool operator!() const 65 { 66 return !value_; 67 } 68 69 // Get the level of the socket option. 70 template <typename Protocol> level(const Protocol &) const71 int level(const Protocol&) const 72 { 73 return Level; 74 } 75 76 // Get the name of the socket option. 77 template <typename Protocol> name(const Protocol &) const78 int name(const Protocol&) const 79 { 80 return Name; 81 } 82 83 // Get the address of the boolean data. 84 template <typename Protocol> data(const Protocol &)85 int* data(const Protocol&) 86 { 87 return &value_; 88 } 89 90 // Get the address of the boolean data. 91 template <typename Protocol> data(const Protocol &) const92 const int* data(const Protocol&) const 93 { 94 return &value_; 95 } 96 97 // Get the size of the boolean data. 98 template <typename Protocol> size(const Protocol &) const99 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> resize(const Protocol &,std::size_t s)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. integer()136 integer() 137 : value_(0) 138 { 139 } 140 141 // Construct with a specific option value. integer(int v)142 explicit integer(int v) 143 : value_(v) 144 { 145 } 146 147 // Set the value of the int option. operator =(int v)148 integer& operator=(int v) 149 { 150 value_ = v; 151 return *this; 152 } 153 154 // Get the current value of the int option. value() const155 int value() const 156 { 157 return value_; 158 } 159 160 // Get the level of the socket option. 161 template <typename Protocol> level(const Protocol &) const162 int level(const Protocol&) const 163 { 164 return Level; 165 } 166 167 // Get the name of the socket option. 168 template <typename Protocol> name(const Protocol &) const169 int name(const Protocol&) const 170 { 171 return Name; 172 } 173 174 // Get the address of the int data. 175 template <typename Protocol> data(const Protocol &)176 int* data(const Protocol&) 177 { 178 return &value_; 179 } 180 181 // Get the address of the int data. 182 template <typename Protocol> data(const Protocol &) const183 const int* data(const Protocol&) const 184 { 185 return &value_; 186 } 187 188 // Get the size of the int data. 189 template <typename Protocol> size(const Protocol &) const190 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> resize(const Protocol &,std::size_t s)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. linger()216 linger() 217 { 218 value_.l_onoff = 0; 219 value_.l_linger = 0; 220 } 221 222 // Construct with specific option values. linger(bool e,int t)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. enabled(bool value)230 void enabled(bool value) 231 { 232 value_.l_onoff = value ? 1 : 0; 233 } 234 235 // Get the value for whether linger is enabled. enabled() const236 bool enabled() const 237 { 238 return value_.l_onoff != 0; 239 } 240 241 // Set the value for the linger timeout. ASIO_PREVENT_MACRO_SUBSTITUTION(int value)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. ASIO_PREVENT_MACRO_SUBSTITUTION() const248 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> level(const Protocol &) const255 int level(const Protocol&) const 256 { 257 return Level; 258 } 259 260 // Get the name of the socket option. 261 template <typename Protocol> name(const Protocol &) const262 int name(const Protocol&) const 263 { 264 return Name; 265 } 266 267 // Get the address of the linger data. 268 template <typename Protocol> data(const 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> data(const Protocol &) const276 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> size(const Protocol &) const283 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> resize(const Protocol &,std::size_t s)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