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. |
37 | boolean() |
38 | : value_(0) |
39 | { |
40 | } |
41 | |
42 | // Construct with a specific option value. |
43 | explicit boolean(bool v) |
44 | : value_(v ? 1 : 0) |
45 | { |
46 | } |
47 | |
48 | // Set the current value of the boolean. |
49 | boolean& operator=(bool v) |
50 | { |
51 | value_ = v ? 1 : 0; |
52 | return *this; |
53 | } |
54 | |
55 | // Get the current value of the boolean. |
56 | bool value() const |
57 | { |
58 | return !!value_; |
59 | } |
60 | |
61 | // Convert to bool. |
62 | operator bool() const |
63 | { |
64 | return !!value_; |
65 | } |
66 | |
67 | // Test for false. |
68 | bool operator!() const |
69 | { |
70 | return !value_; |
71 | } |
72 | |
73 | // Get the level of the socket option. |
74 | template <typename Protocol> |
75 | int level(const Protocol&) const |
76 | { |
77 | return Level; |
78 | } |
79 | |
80 | // Get the name of the socket option. |
81 | template <typename Protocol> |
82 | int name(const Protocol&) const |
83 | { |
84 | return Name; |
85 | } |
86 | |
87 | // Get the address of the boolean data. |
88 | template <typename Protocol> |
89 | int* data(const Protocol&) |
90 | { |
91 | return &value_; |
92 | } |
93 | |
94 | // Get the address of the boolean data. |
95 | template <typename Protocol> |
96 | const int* data(const Protocol&) const |
97 | { |
98 | return &value_; |
99 | } |
100 | |
101 | // Get the size of the boolean data. |
102 | template <typename Protocol> |
103 | 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> |
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(e: 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. |
140 | integer() |
141 | : value_(0) |
142 | { |
143 | } |
144 | |
145 | // Construct with a specific option value. |
146 | explicit integer(int v) |
147 | : value_(v) |
148 | { |
149 | } |
150 | |
151 | // Set the value of the int option. |
152 | integer& operator=(int v) |
153 | { |
154 | value_ = v; |
155 | return *this; |
156 | } |
157 | |
158 | // Get the current value of the int option. |
159 | int value() const |
160 | { |
161 | return value_; |
162 | } |
163 | |
164 | // Get the level of the socket option. |
165 | template <typename Protocol> |
166 | int level(const Protocol&) const |
167 | { |
168 | return Level; |
169 | } |
170 | |
171 | // Get the name of the socket option. |
172 | template <typename Protocol> |
173 | int name(const Protocol&) const |
174 | { |
175 | return Name; |
176 | } |
177 | |
178 | // Get the address of the int data. |
179 | template <typename Protocol> |
180 | int* data(const Protocol&) |
181 | { |
182 | return &value_; |
183 | } |
184 | |
185 | // Get the address of the int data. |
186 | template <typename Protocol> |
187 | const int* data(const Protocol&) const |
188 | { |
189 | return &value_; |
190 | } |
191 | |
192 | // Get the size of the int data. |
193 | template <typename Protocol> |
194 | 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> |
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(e: 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. |
220 | linger() |
221 | { |
222 | value_.l_onoff = 0; |
223 | value_.l_linger = 0; |
224 | } |
225 | |
226 | // Construct with specific option values. |
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. |
234 | void enabled(bool value) |
235 | { |
236 | value_.l_onoff = value ? 1 : 0; |
237 | } |
238 | |
239 | // Get the value for whether linger is enabled. |
240 | bool enabled() const |
241 | { |
242 | return value_.l_onoff != 0; |
243 | } |
244 | |
245 | // Set the value for the linger timeout. |
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. |
256 | 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> |
263 | int level(const Protocol&) const |
264 | { |
265 | return Level; |
266 | } |
267 | |
268 | // Get the name of the socket option. |
269 | template <typename Protocol> |
270 | int name(const Protocol&) const |
271 | { |
272 | return Name; |
273 | } |
274 | |
275 | // Get the address of the linger data. |
276 | template <typename 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> |
284 | 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> |
291 | 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> |
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(e: 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 | |