Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/asio/ssl/detail/io.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children | c530137014c0 |
comparison
equal
deleted
inserted
replaced
15:663ca0da4350 | 16:2665513ce2d3 |
---|---|
1 // | |
2 // ssl/detail/io.hpp | |
3 // ~~~~~~~~~~~~~~~~~ | |
4 // | |
5 // Copyright (c) 2003-2013 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_SSL_DETAIL_IO_HPP | |
12 #define BOOST_ASIO_SSL_DETAIL_IO_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 | |
20 #if !defined(BOOST_ASIO_ENABLE_OLD_SSL) | |
21 # include <boost/asio/ssl/detail/engine.hpp> | |
22 # include <boost/asio/ssl/detail/stream_core.hpp> | |
23 # include <boost/asio/write.hpp> | |
24 #endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL) | |
25 | |
26 #include <boost/asio/detail/push_options.hpp> | |
27 | |
28 namespace boost { | |
29 namespace asio { | |
30 namespace ssl { | |
31 namespace detail { | |
32 | |
33 #if !defined(BOOST_ASIO_ENABLE_OLD_SSL) | |
34 | |
35 template <typename Stream, typename Operation> | |
36 std::size_t io(Stream& next_layer, stream_core& core, | |
37 const Operation& op, boost::system::error_code& ec) | |
38 { | |
39 std::size_t bytes_transferred = 0; | |
40 do switch (op(core.engine_, ec, bytes_transferred)) | |
41 { | |
42 case engine::want_input_and_retry: | |
43 | |
44 // If the input buffer is empty then we need to read some more data from | |
45 // the underlying transport. | |
46 if (boost::asio::buffer_size(core.input_) == 0) | |
47 core.input_ = boost::asio::buffer(core.input_buffer_, | |
48 next_layer.read_some(core.input_buffer_, ec)); | |
49 | |
50 // Pass the new input data to the engine. | |
51 core.input_ = core.engine_.put_input(core.input_); | |
52 | |
53 // Try the operation again. | |
54 continue; | |
55 | |
56 case engine::want_output_and_retry: | |
57 | |
58 // Get output data from the engine and write it to the underlying | |
59 // transport. | |
60 boost::asio::write(next_layer, | |
61 core.engine_.get_output(core.output_buffer_), ec); | |
62 | |
63 // Try the operation again. | |
64 continue; | |
65 | |
66 case engine::want_output: | |
67 | |
68 // Get output data from the engine and write it to the underlying | |
69 // transport. | |
70 boost::asio::write(next_layer, | |
71 core.engine_.get_output(core.output_buffer_), ec); | |
72 | |
73 // Operation is complete. Return result to caller. | |
74 core.engine_.map_error_code(ec); | |
75 return bytes_transferred; | |
76 | |
77 default: | |
78 | |
79 // Operation is complete. Return result to caller. | |
80 core.engine_.map_error_code(ec); | |
81 return bytes_transferred; | |
82 | |
83 } while (!ec); | |
84 | |
85 // Operation failed. Return result to caller. | |
86 core.engine_.map_error_code(ec); | |
87 return 0; | |
88 } | |
89 | |
90 template <typename Stream, typename Operation, typename Handler> | |
91 class io_op | |
92 { | |
93 public: | |
94 io_op(Stream& next_layer, stream_core& core, | |
95 const Operation& op, Handler& handler) | |
96 : next_layer_(next_layer), | |
97 core_(core), | |
98 op_(op), | |
99 start_(0), | |
100 want_(engine::want_nothing), | |
101 bytes_transferred_(0), | |
102 handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)) | |
103 { | |
104 } | |
105 | |
106 #if defined(BOOST_ASIO_HAS_MOVE) | |
107 io_op(const io_op& other) | |
108 : next_layer_(other.next_layer_), | |
109 core_(other.core_), | |
110 op_(other.op_), | |
111 start_(other.start_), | |
112 want_(other.want_), | |
113 ec_(other.ec_), | |
114 bytes_transferred_(other.bytes_transferred_), | |
115 handler_(other.handler_) | |
116 { | |
117 } | |
118 | |
119 io_op(io_op&& other) | |
120 : next_layer_(other.next_layer_), | |
121 core_(other.core_), | |
122 op_(other.op_), | |
123 start_(other.start_), | |
124 want_(other.want_), | |
125 ec_(other.ec_), | |
126 bytes_transferred_(other.bytes_transferred_), | |
127 handler_(BOOST_ASIO_MOVE_CAST(Handler)(other.handler_)) | |
128 { | |
129 } | |
130 #endif // defined(BOOST_ASIO_HAS_MOVE) | |
131 | |
132 void operator()(boost::system::error_code ec, | |
133 std::size_t bytes_transferred = ~std::size_t(0), int start = 0) | |
134 { | |
135 switch (start_ = start) | |
136 { | |
137 case 1: // Called after at least one async operation. | |
138 do | |
139 { | |
140 switch (want_ = op_(core_.engine_, ec_, bytes_transferred_)) | |
141 { | |
142 case engine::want_input_and_retry: | |
143 | |
144 // If the input buffer already has data in it we can pass it to the | |
145 // engine and then retry the operation immediately. | |
146 if (boost::asio::buffer_size(core_.input_) != 0) | |
147 { | |
148 core_.input_ = core_.engine_.put_input(core_.input_); | |
149 continue; | |
150 } | |
151 | |
152 // The engine wants more data to be read from input. However, we | |
153 // cannot allow more than one read operation at a time on the | |
154 // underlying transport. The pending_read_ timer's expiry is set to | |
155 // pos_infin if a read is in progress, and neg_infin otherwise. | |
156 if (core_.pending_read_.expires_at() == core_.neg_infin()) | |
157 { | |
158 // Prevent other read operations from being started. | |
159 core_.pending_read_.expires_at(core_.pos_infin()); | |
160 | |
161 // Start reading some data from the underlying transport. | |
162 next_layer_.async_read_some( | |
163 boost::asio::buffer(core_.input_buffer_), | |
164 BOOST_ASIO_MOVE_CAST(io_op)(*this)); | |
165 } | |
166 else | |
167 { | |
168 // Wait until the current read operation completes. | |
169 core_.pending_read_.async_wait(BOOST_ASIO_MOVE_CAST(io_op)(*this)); | |
170 } | |
171 | |
172 // Yield control until asynchronous operation completes. Control | |
173 // resumes at the "default:" label below. | |
174 return; | |
175 | |
176 case engine::want_output_and_retry: | |
177 case engine::want_output: | |
178 | |
179 // The engine wants some data to be written to the output. However, we | |
180 // cannot allow more than one write operation at a time on the | |
181 // underlying transport. The pending_write_ timer's expiry is set to | |
182 // pos_infin if a write is in progress, and neg_infin otherwise. | |
183 if (core_.pending_write_.expires_at() == core_.neg_infin()) | |
184 { | |
185 // Prevent other write operations from being started. | |
186 core_.pending_write_.expires_at(core_.pos_infin()); | |
187 | |
188 // Start writing all the data to the underlying transport. | |
189 boost::asio::async_write(next_layer_, | |
190 core_.engine_.get_output(core_.output_buffer_), | |
191 BOOST_ASIO_MOVE_CAST(io_op)(*this)); | |
192 } | |
193 else | |
194 { | |
195 // Wait until the current write operation completes. | |
196 core_.pending_write_.async_wait(BOOST_ASIO_MOVE_CAST(io_op)(*this)); | |
197 } | |
198 | |
199 // Yield control until asynchronous operation completes. Control | |
200 // resumes at the "default:" label below. | |
201 return; | |
202 | |
203 default: | |
204 | |
205 // The SSL operation is done and we can invoke the handler, but we | |
206 // have to keep in mind that this function might be being called from | |
207 // the async operation's initiating function. In this case we're not | |
208 // allowed to call the handler directly. Instead, issue a zero-sized | |
209 // read so the handler runs "as-if" posted using io_service::post(). | |
210 if (start) | |
211 { | |
212 next_layer_.async_read_some( | |
213 boost::asio::buffer(core_.input_buffer_, 0), | |
214 BOOST_ASIO_MOVE_CAST(io_op)(*this)); | |
215 | |
216 // Yield control until asynchronous operation completes. Control | |
217 // resumes at the "default:" label below. | |
218 return; | |
219 } | |
220 else | |
221 { | |
222 // Continue on to run handler directly. | |
223 break; | |
224 } | |
225 } | |
226 | |
227 default: | |
228 if (bytes_transferred != ~std::size_t(0) && !ec_) | |
229 ec_ = ec; | |
230 | |
231 switch (want_) | |
232 { | |
233 case engine::want_input_and_retry: | |
234 | |
235 // Add received data to the engine's input. | |
236 core_.input_ = boost::asio::buffer( | |
237 core_.input_buffer_, bytes_transferred); | |
238 core_.input_ = core_.engine_.put_input(core_.input_); | |
239 | |
240 // Release any waiting read operations. | |
241 core_.pending_read_.expires_at(core_.neg_infin()); | |
242 | |
243 // Try the operation again. | |
244 continue; | |
245 | |
246 case engine::want_output_and_retry: | |
247 | |
248 // Release any waiting write operations. | |
249 core_.pending_write_.expires_at(core_.neg_infin()); | |
250 | |
251 // Try the operation again. | |
252 continue; | |
253 | |
254 case engine::want_output: | |
255 | |
256 // Release any waiting write operations. | |
257 core_.pending_write_.expires_at(core_.neg_infin()); | |
258 | |
259 // Fall through to call handler. | |
260 | |
261 default: | |
262 | |
263 // Pass the result to the handler. | |
264 op_.call_handler(handler_, | |
265 core_.engine_.map_error_code(ec_), | |
266 ec_ ? 0 : bytes_transferred_); | |
267 | |
268 // Our work here is done. | |
269 return; | |
270 } | |
271 } while (!ec_); | |
272 | |
273 // Operation failed. Pass the result to the handler. | |
274 op_.call_handler(handler_, core_.engine_.map_error_code(ec_), 0); | |
275 } | |
276 } | |
277 | |
278 //private: | |
279 Stream& next_layer_; | |
280 stream_core& core_; | |
281 Operation op_; | |
282 int start_; | |
283 engine::want want_; | |
284 boost::system::error_code ec_; | |
285 std::size_t bytes_transferred_; | |
286 Handler handler_; | |
287 }; | |
288 | |
289 template <typename Stream, typename Operation, typename Handler> | |
290 inline void* asio_handler_allocate(std::size_t size, | |
291 io_op<Stream, Operation, Handler>* this_handler) | |
292 { | |
293 return boost_asio_handler_alloc_helpers::allocate( | |
294 size, this_handler->handler_); | |
295 } | |
296 | |
297 template <typename Stream, typename Operation, typename Handler> | |
298 inline void asio_handler_deallocate(void* pointer, std::size_t size, | |
299 io_op<Stream, Operation, Handler>* this_handler) | |
300 { | |
301 boost_asio_handler_alloc_helpers::deallocate( | |
302 pointer, size, this_handler->handler_); | |
303 } | |
304 | |
305 template <typename Stream, typename Operation, typename Handler> | |
306 inline bool asio_handler_is_continuation( | |
307 io_op<Stream, Operation, Handler>* this_handler) | |
308 { | |
309 return this_handler->start_ == 0 ? true | |
310 : boost_asio_handler_cont_helpers::is_continuation(this_handler->handler_); | |
311 } | |
312 | |
313 template <typename Function, typename Stream, | |
314 typename Operation, typename Handler> | |
315 inline void asio_handler_invoke(Function& function, | |
316 io_op<Stream, Operation, Handler>* this_handler) | |
317 { | |
318 boost_asio_handler_invoke_helpers::invoke( | |
319 function, this_handler->handler_); | |
320 } | |
321 | |
322 template <typename Function, typename Stream, | |
323 typename Operation, typename Handler> | |
324 inline void asio_handler_invoke(const Function& function, | |
325 io_op<Stream, Operation, Handler>* this_handler) | |
326 { | |
327 boost_asio_handler_invoke_helpers::invoke( | |
328 function, this_handler->handler_); | |
329 } | |
330 | |
331 template <typename Stream, typename Operation, typename Handler> | |
332 inline void async_io(Stream& next_layer, stream_core& core, | |
333 const Operation& op, Handler& handler) | |
334 { | |
335 io_op<Stream, Operation, Handler>( | |
336 next_layer, core, op, handler)( | |
337 boost::system::error_code(), 0, 1); | |
338 } | |
339 | |
340 #endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL) | |
341 | |
342 } // namespace detail | |
343 } // namespace ssl | |
344 } // namespace asio | |
345 } // namespace boost | |
346 | |
347 #include <boost/asio/detail/pop_options.hpp> | |
348 | |
349 #endif // BOOST_ASIO_SSL_DETAIL_IO_HPP |