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 23namespace asio { 24namespace detail { 25namespace socket_option { 26 27// Helper template for implementing boolean-based options. 28template <int Level, int Name> 29class boolean 30{ 31public: 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 126private: 127 int value_; 128}; 129 130// Helper template for implementing integer options. 131template <int Level, int Name> 132class integer 133{ 134public: 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 206private: 207 int value_; 208}; 209 210// Helper template for implementing linger options. 211template <int Level, int Name> 212class linger 213{ 214public: 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 299private: 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