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
26namespace boost {
27namespace asio {
28namespace detail {
29namespace socket_option {
30
31// Helper template for implementing boolean-based options.
32template <int Level, int Name>
33class boolean
34{
35public:
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(ex);
126 }
127 }
128 }
129
130private:
131 int value_;
132};
133
134// Helper template for implementing integer options.
135template <int Level, int Name>
136class integer
137{
138public:
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(ex);
207 }
208 }
209
210private:
211 int value_;
212};
213
214// Helper template for implementing linger options.
215template <int Level, int Name>
216class linger
217{
218public:
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(ex);
304 }
305 }
306
307private:
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