Realistic 3D camera system
3D camera system components
io.hpp
Go to the documentation of this file.
1 //
2 // ssl/detail/io.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_SSL_DETAIL_IO_HPP
12 #define 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 "asio/detail/config.hpp"
19 
20 #if !defined(ASIO_ENABLE_OLD_SSL)
23 # include "asio/write.hpp"
24 #endif // !defined(ASIO_ENABLE_OLD_SSL)
25 
27 
28 namespace asio {
29 namespace ssl {
30 namespace detail {
31 
32 #if !defined(ASIO_ENABLE_OLD_SSL)
33 
34 template <typename Stream, typename Operation>
35 std::size_t io(Stream& next_layer, stream_core& core,
36  const Operation& op, asio::error_code& ec)
37 {
38  std::size_t bytes_transferred = 0;
39  do switch (op(core.engine_, ec, bytes_transferred))
40  {
42 
43  // If the input buffer is empty then we need to read some more data from
44  // the underlying transport.
45  if (asio::buffer_size(core.input_) == 0)
46  core.input_ = asio::buffer(core.input_buffer_,
47  next_layer.read_some(core.input_buffer_, ec));
48 
49  // Pass the new input data to the engine.
50  core.input_ = core.engine_.put_input(core.input_);
51 
52  // Try the operation again.
53  continue;
54 
56 
57  // Get output data from the engine and write it to the underlying
58  // transport.
59  asio::write(next_layer,
60  core.engine_.get_output(core.output_buffer_), ec);
61 
62  // Try the operation again.
63  continue;
64 
66 
67  // Get output data from the engine and write it to the underlying
68  // transport.
69  asio::write(next_layer,
70  core.engine_.get_output(core.output_buffer_), ec);
71 
72  // Operation is complete. Return result to caller.
73  core.engine_.map_error_code(ec);
74  return bytes_transferred;
75 
76  default:
77 
78  // Operation is complete. Return result to caller.
79  core.engine_.map_error_code(ec);
80  return bytes_transferred;
81 
82  } while (!ec);
83 
84  // Operation failed. Return result to caller.
85  core.engine_.map_error_code(ec);
86  return 0;
87 }
88 
89 template <typename Stream, typename Operation, typename Handler>
90 class io_op
91 {
92 public:
93  io_op(Stream& next_layer, stream_core& core,
94  const Operation& op, Handler& handler)
95  : next_layer_(next_layer),
96  core_(core),
97  op_(op),
98  start_(0),
99  want_(engine::want_nothing),
101  handler_(ASIO_MOVE_CAST(Handler)(handler))
102  {
103  }
104 
105 #if defined(ASIO_HAS_MOVE)
106  io_op(const io_op& other)
107  : next_layer_(other.next_layer_),
108  core_(other.core_),
109  op_(other.op_),
110  start_(other.start_),
111  want_(other.want_),
112  ec_(other.ec_),
114  handler_(other.handler_)
115  {
116  }
117 
118  io_op(io_op&& other)
119  : next_layer_(other.next_layer_),
120  core_(other.core_),
121  op_(other.op_),
122  start_(other.start_),
123  want_(other.want_),
124  ec_(other.ec_),
126  handler_(ASIO_MOVE_CAST(Handler)(other.handler_))
127  {
128  }
129 #endif // defined(ASIO_HAS_MOVE)
130 
132  std::size_t bytes_transferred = ~std::size_t(0), int start = 0)
133  {
134  switch (start_ = start)
135  {
136  case 1: // Called after at least one async operation.
137  do
138  {
140  {
142 
143  // If the input buffer already has data in it we can pass it to the
144  // engine and then retry the operation immediately.
145  if (asio::buffer_size(core_.input_) != 0)
146  {
148  continue;
149  }
150 
151  // The engine wants more data to be read from input. However, we
152  // cannot allow more than one read operation at a time on the
153  // underlying transport. The pending_read_ timer's expiry is set to
154  // pos_infin if a read is in progress, and neg_infin otherwise.
155  if (core_.pending_read_.expires_at() == core_.neg_infin())
156  {
157  // Prevent other read operations from being started.
158  core_.pending_read_.expires_at(core_.pos_infin());
159 
160  // Start reading some data from the underlying transport.
161  next_layer_.async_read_some(
163  ASIO_MOVE_CAST(io_op)(*this));
164  }
165  else
166  {
167  // Wait until the current read operation completes.
168  core_.pending_read_.async_wait(ASIO_MOVE_CAST(io_op)(*this));
169  }
170 
171  // Yield control until asynchronous operation completes. Control
172  // resumes at the "default:" label below.
173  return;
174 
176  case engine::want_output:
177 
178  // The engine wants some data to be written to the output. However, we
179  // cannot allow more than one write operation at a time on the
180  // underlying transport. The pending_write_ timer's expiry is set to
181  // pos_infin if a write is in progress, and neg_infin otherwise.
182  if (core_.pending_write_.expires_at() == core_.neg_infin())
183  {
184  // Prevent other write operations from being started.
185  core_.pending_write_.expires_at(core_.pos_infin());
186 
187  // Start writing all the data to the underlying transport.
188  asio::async_write(next_layer_,
190  ASIO_MOVE_CAST(io_op)(*this));
191  }
192  else
193  {
194  // Wait until the current write operation completes.
195  core_.pending_write_.async_wait(ASIO_MOVE_CAST(io_op)(*this));
196  }
197 
198  // Yield control until asynchronous operation completes. Control
199  // resumes at the "default:" label below.
200  return;
201 
202  default:
203 
204  // The SSL operation is done and we can invoke the handler, but we
205  // have to keep in mind that this function might be being called from
206  // the async operation's initiating function. In this case we're not
207  // allowed to call the handler directly. Instead, issue a zero-sized
208  // read so the handler runs "as-if" posted using io_service::post().
209  if (start)
210  {
211  next_layer_.async_read_some(
213  ASIO_MOVE_CAST(io_op)(*this));
214 
215  // Yield control until asynchronous operation completes. Control
216  // resumes at the "default:" label below.
217  return;
218  }
219  else
220  {
221  // Continue on to run handler directly.
222  break;
223  }
224  }
225 
226  default:
227  if (bytes_transferred == ~std::size_t(0))
228  bytes_transferred = 0; // Timer cancellation, no data transferred.
229  else if (!ec_)
230  ec_ = ec;
231 
232  switch (want_)
233  {
235 
236  // Add received data to the engine's input.
238  core_.input_buffer_, bytes_transferred);
240 
241  // Release any waiting read operations.
242  core_.pending_read_.expires_at(core_.neg_infin());
243 
244  // Try the operation again.
245  continue;
246 
248 
249  // Release any waiting write operations.
250  core_.pending_write_.expires_at(core_.neg_infin());
251 
252  // Try the operation again.
253  continue;
254 
255  case engine::want_output:
256 
257  // Release any waiting write operations.
258  core_.pending_write_.expires_at(core_.neg_infin());
259 
260  // Fall through to call handler.
261 
262  default:
263 
264  // Pass the result to the handler.
265  op_.call_handler(handler_,
267  ec_ ? 0 : bytes_transferred_);
268 
269  // Our work here is done.
270  return;
271  }
272  } while (!ec_);
273 
274  // Operation failed. Pass the result to the handler.
275  op_.call_handler(handler_, core_.engine_.map_error_code(ec_), 0);
276  }
277  }
278 
279 //private:
280  Stream& next_layer_;
282  Operation op_;
283  int start_;
286  std::size_t bytes_transferred_;
287  Handler handler_;
288 };
289 
290 template <typename Stream, typename Operation, typename Handler>
291 inline void* asio_handler_allocate(std::size_t size,
292  io_op<Stream, Operation, Handler>* this_handler)
293 {
295  size, this_handler->handler_);
296 }
297 
298 template <typename Stream, typename Operation, typename Handler>
299 inline void asio_handler_deallocate(void* pointer, std::size_t size,
300  io_op<Stream, Operation, Handler>* this_handler)
301 {
303  pointer, size, this_handler->handler_);
304 }
305 
306 template <typename Stream, typename Operation, typename Handler>
308  io_op<Stream, Operation, Handler>* this_handler)
309 {
310  return this_handler->start_ == 0 ? true
312 }
313 
314 template <typename Function, typename Stream,
315  typename Operation, typename Handler>
316 inline void asio_handler_invoke(Function& function,
317  io_op<Stream, Operation, Handler>* this_handler)
318 {
320  function, this_handler->handler_);
321 }
322 
323 template <typename Function, typename Stream,
324  typename Operation, typename Handler>
325 inline void asio_handler_invoke(const Function& function,
326  io_op<Stream, Operation, Handler>* this_handler)
327 {
329  function, this_handler->handler_);
330 }
331 
332 template <typename Stream, typename Operation, typename Handler>
333 inline void async_io(Stream& next_layer, stream_core& core,
334  const Operation& op, Handler& handler)
335 {
337  next_layer, core, op, handler)(
338  asio::error_code(), 0, 1);
339 }
340 
341 #endif // !defined(ASIO_ENABLE_OLD_SSL)
342 
343 } // namespace detail
344 } // namespace ssl
345 } // namespace asio
346 
348 
349 #endif // ASIO_SSL_DETAIL_IO_HPP
void async_io(Stream &next_layer, stream_core &core, const Operation &op, Handler &handler)
Definition: io.hpp:333
asio::steady_timer pending_read_
Definition: stream_core.hpp:84
asio::steady_timer pending_write_
Definition: stream_core.hpp:87
static asio::steady_timer::time_point neg_infin()
Definition: stream_core.hpp:90
io_op(Stream &next_layer, stream_core &core, const Operation &op, Handler &handler)
Definition: io.hpp:93
void asio_handler_invoke(Function &function, io_op< Stream, Operation, Handler > *this_handler)
Definition: io.hpp:316
Stream & next_layer_
Definition: io.hpp:280
stream_core & core_
Definition: io.hpp:281
std::size_t write(SyncWriteStream &s, const ConstBufferSequence &buffers, CompletionCondition completion_condition, asio::error_code &ec)
Write a certain amount of data to a stream before returning.
Definition: write.hpp:37
mutable_buffers_1 buffer(const mutable_buffer &b)
Create a new modifiable buffer from an existing buffer.
Definition: buffer.hpp:706
std::size_t bytes_transferred_
Definition: io.hpp:286
std::size_t io(Stream &next_layer, stream_core &core, const Operation &op, asio::error_code &ec)
Definition: io.hpp:35
asio::error_code ec_
Definition: io.hpp:285
std::size_t buffer_size(const mutable_buffer &b)
Get the number of bytes in a modifiable buffer.
Definition: buffer.hpp:357
void invoke(Function &function, Context &context)
static asio::steady_timer::time_point pos_infin()
Definition: stream_core.hpp:96
ASIO_DECL asio::mutable_buffers_1 get_output(const asio::mutable_buffer &data)
Definition: engine.ipp:173
bool asio_handler_is_continuation(io_op< Stream, Operation, Handler > *this_handler)
Definition: io.hpp:307
void * asio_handler_allocate(std::size_t size, io_op< Stream, Operation, Handler > *this_handler)
Definition: io.hpp:291
const asio::mutable_buffers_1 input_buffer_
bool is_continuation(Context &context)
void operator()(asio::error_code ec, std::size_t bytes_transferred=~std::size_t(0), int start=0)
Definition: io.hpp:131
engine::want want_
Definition: io.hpp:284
Class to represent an error code value.
Definition: error_code.hpp:80
void deallocate(void *p, std::size_t s, Handler &h)
ASIO_DECL asio::const_buffer put_input(const asio::const_buffer &data)
Definition: engine.ipp:184
void asio_handler_deallocate(void *pointer, std::size_t size, io_op< Stream, Operation, Handler > *this_handler)
Definition: io.hpp:299
void * allocate(std::size_t s, Handler &h)
ASIO_DECL const asio::error_code & map_error_code(asio::error_code &ec) const
Definition: engine.ipp:195
#define ASIO_MOVE_CAST(type)
Definition: config.hpp:138
const asio::mutable_buffers_1 output_buffer_