$search
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_DETAIL_SOCKET_OPTION_HPP 00012 #define ASIO_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 <stdexcept> 00023 #include <boost/config.hpp> 00024 #include "asio/detail/pop_options.hpp" 00025 00026 #include "asio/detail/socket_types.hpp" 00027 00028 namespace asio { 00029 namespace detail { 00030 namespace socket_option { 00031 00032 // Helper template for implementing boolean-based options. 00033 template <int Level, int Name> 00034 class boolean 00035 { 00036 public: 00037 // Default constructor. 00038 boolean() 00039 : value_(0) 00040 { 00041 } 00042 00043 // Construct with a specific option value. 00044 explicit boolean(bool v) 00045 : value_(v ? 1 : 0) 00046 { 00047 } 00048 00049 // Set the current value of the boolean. 00050 boolean& operator=(bool v) 00051 { 00052 value_ = v ? 1 : 0; 00053 return *this; 00054 } 00055 00056 // Get the current value of the boolean. 00057 bool value() const 00058 { 00059 return !!value_; 00060 } 00061 00062 // Convert to bool. 00063 operator bool() const 00064 { 00065 return !!value_; 00066 } 00067 00068 // Test for false. 00069 bool operator!() const 00070 { 00071 return !value_; 00072 } 00073 00074 // Get the level of the socket option. 00075 template <typename Protocol> 00076 int level(const Protocol&) const 00077 { 00078 return Level; 00079 } 00080 00081 // Get the name of the socket option. 00082 template <typename Protocol> 00083 int name(const Protocol&) const 00084 { 00085 return Name; 00086 } 00087 00088 // Get the address of the boolean data. 00089 template <typename Protocol> 00090 int* data(const Protocol&) 00091 { 00092 return &value_; 00093 } 00094 00095 // Get the address of the boolean data. 00096 template <typename Protocol> 00097 const int* data(const Protocol&) const 00098 { 00099 return &value_; 00100 } 00101 00102 // Get the size of the boolean data. 00103 template <typename Protocol> 00104 std::size_t size(const Protocol&) const 00105 { 00106 return sizeof(value_); 00107 } 00108 00109 // Set the size of the boolean data. 00110 template <typename Protocol> 00111 void resize(const Protocol&, std::size_t s) 00112 { 00113 // On some platforms (e.g. Windows Vista), the getsockopt function will 00114 // return the size of a boolean socket option as one byte, even though a 00115 // four byte integer was passed in. 00116 switch (s) 00117 { 00118 case sizeof(char): 00119 value_ = *reinterpret_cast<char*>(&value_) ? 1 : 0; 00120 break; 00121 case sizeof(value_): 00122 break; 00123 default: 00124 throw std::length_error("boolean socket option resize"); 00125 } 00126 } 00127 00128 private: 00129 int value_; 00130 }; 00131 00132 // Helper template for implementing integer options. 00133 template <int Level, int Name> 00134 class integer 00135 { 00136 public: 00137 // Default constructor. 00138 integer() 00139 : value_(0) 00140 { 00141 } 00142 00143 // Construct with a specific option value. 00144 explicit integer(int v) 00145 : value_(v) 00146 { 00147 } 00148 00149 // Set the value of the int option. 00150 integer& operator=(int v) 00151 { 00152 value_ = v; 00153 return *this; 00154 } 00155 00156 // Get the current value of the int option. 00157 int value() const 00158 { 00159 return value_; 00160 } 00161 00162 // Get the level of the socket option. 00163 template <typename Protocol> 00164 int level(const Protocol&) const 00165 { 00166 return Level; 00167 } 00168 00169 // Get the name of the socket option. 00170 template <typename Protocol> 00171 int name(const Protocol&) const 00172 { 00173 return Name; 00174 } 00175 00176 // Get the address of the int data. 00177 template <typename Protocol> 00178 int* data(const Protocol&) 00179 { 00180 return &value_; 00181 } 00182 00183 // Get the address of the int data. 00184 template <typename Protocol> 00185 const int* data(const Protocol&) const 00186 { 00187 return &value_; 00188 } 00189 00190 // Get the size of the int data. 00191 template <typename Protocol> 00192 std::size_t size(const Protocol&) const 00193 { 00194 return sizeof(value_); 00195 } 00196 00197 // Set the size of the int data. 00198 template <typename Protocol> 00199 void resize(const Protocol&, std::size_t s) 00200 { 00201 if (s != sizeof(value_)) 00202 throw std::length_error("integer socket option resize"); 00203 } 00204 00205 private: 00206 int value_; 00207 }; 00208 00209 // Helper template for implementing linger options. 00210 template <int Level, int Name> 00211 class linger 00212 { 00213 public: 00214 // Default constructor. 00215 linger() 00216 { 00217 value_.l_onoff = 0; 00218 value_.l_linger = 0; 00219 } 00220 00221 // Construct with specific option values. 00222 linger(bool e, int t) 00223 { 00224 enabled(e); 00225 timeout(t); 00226 } 00227 00228 // Set the value for whether linger is enabled. 00229 void enabled(bool value) 00230 { 00231 value_.l_onoff = value ? 1 : 0; 00232 } 00233 00234 // Get the value for whether linger is enabled. 00235 bool enabled() const 00236 { 00237 return value_.l_onoff != 0; 00238 } 00239 00240 // Set the value for the linger timeout. 00241 void timeout(int value) 00242 { 00243 #if defined(WIN32) 00244 value_.l_linger = static_cast<u_short>(value); 00245 #else 00246 value_.l_linger = value; 00247 #endif 00248 } 00249 00250 // Get the value for the linger timeout. 00251 int timeout() const 00252 { 00253 return static_cast<int>(value_.l_linger); 00254 } 00255 00256 // Get the level of the socket option. 00257 template <typename Protocol> 00258 int level(const Protocol&) const 00259 { 00260 return Level; 00261 } 00262 00263 // Get the name of the socket option. 00264 template <typename Protocol> 00265 int name(const Protocol&) const 00266 { 00267 return Name; 00268 } 00269 00270 // Get the address of the linger data. 00271 template <typename Protocol> 00272 ::linger* data(const Protocol&) 00273 { 00274 return &value_; 00275 } 00276 00277 // Get the address of the linger data. 00278 template <typename Protocol> 00279 const ::linger* data(const Protocol&) const 00280 { 00281 return &value_; 00282 } 00283 00284 // Get the size of the linger data. 00285 template <typename Protocol> 00286 std::size_t size(const Protocol&) const 00287 { 00288 return sizeof(value_); 00289 } 00290 00291 // Set the size of the int data. 00292 template <typename Protocol> 00293 void resize(const Protocol&, std::size_t s) 00294 { 00295 if (s != sizeof(value_)) 00296 throw std::length_error("linger socket option resize"); 00297 } 00298 00299 private: 00300 ::linger value_; 00301 }; 00302 00303 } // namespace socket_option 00304 } // namespace detail 00305 } // namespace asio 00306 00307 #include "asio/detail/pop_options.hpp" 00308 00309 #endif // ASIO_DETAIL_SOCKET_OPTION_HPP