Realistic 3D camera system
3D camera system components
reactive_socket_service.hpp
Go to the documentation of this file.
1 //
2 // detail/reactive_socket_service.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_DETAIL_REACTIVE_SOCKET_SERVICE_HPP
12 #define ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_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_HAS_IOCP)
21 
22 #include "asio/buffer.hpp"
23 #include "asio/error.hpp"
24 #include "asio/io_service.hpp"
25 #include "asio/socket_base.hpp"
35 #include "asio/detail/reactor.hpp"
40 
42 
43 namespace asio {
44 namespace detail {
45 
46 template <typename Protocol>
49 {
50 public:
51  // The protocol type.
52  typedef Protocol protocol_type;
53 
54  // The endpoint type.
55  typedef typename Protocol::endpoint endpoint_type;
56 
57  // The native type of a socket.
59 
60  // The implementation type of the socket.
63  {
64  // Default constructor.
66  : protocol_(endpoint_type().protocol())
67  {
68  }
69 
70  // The protocol associated with the socket.
71  protocol_type protocol_;
72  };
73 
74  // Constructor.
76  : reactive_socket_service_base(io_service)
77  {
78  }
79 
80  // Move-construct a new socket implementation.
82  implementation_type& other_impl)
83  {
84  this->base_move_construct(impl, other_impl);
85 
86  impl.protocol_ = other_impl.protocol_;
87  other_impl.protocol_ = endpoint_type().protocol();
88  }
89 
90  // Move-assign from another socket implementation.
92  reactive_socket_service_base& other_service,
93  implementation_type& other_impl)
94  {
95  this->base_move_assign(impl, other_service, other_impl);
96 
97  impl.protocol_ = other_impl.protocol_;
98  other_impl.protocol_ = endpoint_type().protocol();
99  }
100 
101  // Move-construct a new socket implementation from another protocol type.
102  template <typename Protocol1>
104  typename reactive_socket_service<
105  Protocol1>::implementation_type& other_impl)
106  {
107  this->base_move_construct(impl, other_impl);
108 
109  impl.protocol_ = protocol_type(other_impl.protocol_);
110  other_impl.protocol_ = typename Protocol1::endpoint().protocol();
111  }
112 
113  // Open a new socket implementation.
115  const protocol_type& protocol, asio::error_code& ec)
116  {
117  if (!do_open(impl, protocol.family(),
118  protocol.type(), protocol.protocol(), ec))
119  impl.protocol_ = protocol;
120  return ec;
121  }
122 
123  // Assign a native socket to a socket implementation.
125  const protocol_type& protocol, const native_handle_type& native_socket,
126  asio::error_code& ec)
127  {
128  if (!do_assign(impl, protocol.type(), native_socket, ec))
129  impl.protocol_ = protocol;
130  return ec;
131  }
132 
133  // Get the native socket representation.
134  native_handle_type native_handle(implementation_type& impl)
135  {
136  return impl.socket_;
137  }
138 
139  // Bind the socket to the specified local endpoint.
141  const endpoint_type& endpoint, asio::error_code& ec)
142  {
143  socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec);
144  return ec;
145  }
146 
147  // Set a socket option.
148  template <typename Option>
150  const Option& option, asio::error_code& ec)
151  {
153  option.level(impl.protocol_), option.name(impl.protocol_),
154  option.data(impl.protocol_), option.size(impl.protocol_), ec);
155  return ec;
156  }
157 
158  // Set a socket option.
159  template <typename Option>
161  Option& option, asio::error_code& ec) const
162  {
163  std::size_t size = option.size(impl.protocol_);
165  option.level(impl.protocol_), option.name(impl.protocol_),
166  option.data(impl.protocol_), &size, ec);
167  if (!ec)
168  option.resize(impl.protocol_, size);
169  return ec;
170  }
171 
172  // Get the local endpoint.
173  endpoint_type local_endpoint(const implementation_type& impl,
174  asio::error_code& ec) const
175  {
176  endpoint_type endpoint;
177  std::size_t addr_len = endpoint.capacity();
178  if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec))
179  return endpoint_type();
180  endpoint.resize(addr_len);
181  return endpoint;
182  }
183 
184  // Get the remote endpoint.
185  endpoint_type remote_endpoint(const implementation_type& impl,
186  asio::error_code& ec) const
187  {
188  endpoint_type endpoint;
189  std::size_t addr_len = endpoint.capacity();
191  endpoint.data(), &addr_len, false, ec))
192  return endpoint_type();
193  endpoint.resize(addr_len);
194  return endpoint;
195  }
196 
197  // Send a datagram to the specified endpoint. Returns the number of bytes
198  // sent.
199  template <typename ConstBufferSequence>
200  size_t send_to(implementation_type& impl, const ConstBufferSequence& buffers,
201  const endpoint_type& destination, socket_base::message_flags flags,
202  asio::error_code& ec)
203  {
205  ConstBufferSequence> bufs(buffers);
206 
207  return socket_ops::sync_sendto(impl.socket_, impl.state_,
208  bufs.buffers(), bufs.count(), flags,
209  destination.data(), destination.size(), ec);
210  }
211 
212  // Wait until data can be sent without blocking.
214  const endpoint_type&, socket_base::message_flags,
215  asio::error_code& ec)
216  {
217  // Wait for socket to become ready.
218  socket_ops::poll_write(impl.socket_, impl.state_, ec);
219 
220  return 0;
221  }
222 
223  // Start an asynchronous send. The data being sent must be valid for the
224  // lifetime of the asynchronous operation.
225  template <typename ConstBufferSequence, typename Handler>
227  const ConstBufferSequence& buffers,
228  const endpoint_type& destination, socket_base::message_flags flags,
229  Handler& handler)
230  {
231  bool is_continuation =
233 
234  // Allocate and construct an operation to wrap the handler.
235  typedef reactive_socket_sendto_op<ConstBufferSequence,
236  endpoint_type, Handler> op;
237  typename op::ptr p = { asio::detail::addressof(handler),
239  sizeof(op), handler), 0 };
240  p.p = new (p.v) op(impl.socket_, buffers, destination, flags, handler);
241 
242  ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_send_to"));
243 
244  start_op(impl, reactor::write_op, p.p, is_continuation, true, false);
245  p.v = p.p = 0;
246  }
247 
248  // Start an asynchronous wait until data can be sent without blocking.
249  template <typename Handler>
251  const endpoint_type&, socket_base::message_flags, Handler& handler)
252  {
253  bool is_continuation =
255 
256  // Allocate and construct an operation to wrap the handler.
258  typename op::ptr p = { asio::detail::addressof(handler),
260  sizeof(op), handler), 0 };
261  p.p = new (p.v) op(handler);
262 
263  ASIO_HANDLER_CREATION((p.p, "socket",
264  &impl, "async_send_to(null_buffers)"));
265 
266  start_op(impl, reactor::write_op, p.p, is_continuation, false, false);
267  p.v = p.p = 0;
268  }
269 
270  // Receive a datagram with the endpoint of the sender. Returns the number of
271  // bytes received.
272  template <typename MutableBufferSequence>
274  const MutableBufferSequence& buffers,
275  endpoint_type& sender_endpoint, socket_base::message_flags flags,
276  asio::error_code& ec)
277  {
279  MutableBufferSequence> bufs(buffers);
280 
281  std::size_t addr_len = sender_endpoint.capacity();
282  std::size_t bytes_recvd = socket_ops::sync_recvfrom(
283  impl.socket_, impl.state_, bufs.buffers(), bufs.count(),
284  flags, sender_endpoint.data(), &addr_len, ec);
285 
286  if (!ec)
287  sender_endpoint.resize(addr_len);
288 
289  return bytes_recvd;
290  }
291 
292  // Wait until data can be received without blocking.
294  endpoint_type& sender_endpoint, socket_base::message_flags,
295  asio::error_code& ec)
296  {
297  // Wait for socket to become ready.
298  socket_ops::poll_read(impl.socket_, impl.state_, ec);
299 
300  // Reset endpoint since it can be given no sensible value at this time.
301  sender_endpoint = endpoint_type();
302 
303  return 0;
304  }
305 
306  // Start an asynchronous receive. The buffer for the data being received and
307  // the sender_endpoint object must both be valid for the lifetime of the
308  // asynchronous operation.
309  template <typename MutableBufferSequence, typename Handler>
311  const MutableBufferSequence& buffers, endpoint_type& sender_endpoint,
312  socket_base::message_flags flags, Handler& handler)
313  {
314  bool is_continuation =
316 
317  // Allocate and construct an operation to wrap the handler.
318  typedef reactive_socket_recvfrom_op<MutableBufferSequence,
319  endpoint_type, Handler> op;
320  typename op::ptr p = { asio::detail::addressof(handler),
322  sizeof(op), handler), 0 };
323  int protocol = impl.protocol_.type();
324  p.p = new (p.v) op(impl.socket_, protocol,
325  buffers, sender_endpoint, flags, handler);
326 
327  ASIO_HANDLER_CREATION((p.p, "socket",
328  &impl, "async_receive_from"));
329 
330  start_op(impl,
331  (flags & socket_base::message_out_of_band)
332  ? reactor::except_op : reactor::read_op,
333  p.p, is_continuation, true, false);
334  p.v = p.p = 0;
335  }
336 
337  // Wait until data can be received without blocking.
338  template <typename Handler>
340  const null_buffers&, endpoint_type& sender_endpoint,
341  socket_base::message_flags flags, Handler& handler)
342  {
343  bool is_continuation =
345 
346  // Allocate and construct an operation to wrap the handler.
348  typename op::ptr p = { asio::detail::addressof(handler),
350  sizeof(op), handler), 0 };
351  p.p = new (p.v) op(handler);
352 
353  ASIO_HANDLER_CREATION((p.p, "socket",
354  &impl, "async_receive_from(null_buffers)"));
355 
356  // Reset endpoint since it can be given no sensible value at this time.
357  sender_endpoint = endpoint_type();
358 
359  start_op(impl,
360  (flags & socket_base::message_out_of_band)
361  ? reactor::except_op : reactor::read_op,
362  p.p, is_continuation, false, false);
363  p.v = p.p = 0;
364  }
365 
366  // Accept a new connection.
367  template <typename Socket>
369  Socket& peer, endpoint_type* peer_endpoint, asio::error_code& ec)
370  {
371  // We cannot accept a socket that is already open.
372  if (peer.is_open())
373  {
375  return ec;
376  }
377 
378  std::size_t addr_len = peer_endpoint ? peer_endpoint->capacity() : 0;
380  impl.state_, peer_endpoint ? peer_endpoint->data() : 0,
381  peer_endpoint ? &addr_len : 0, ec));
382 
383  // On success, assign new connection to peer socket object.
384  if (new_socket.get() != invalid_socket)
385  {
386  if (peer_endpoint)
387  peer_endpoint->resize(addr_len);
388  if (!peer.assign(impl.protocol_, new_socket.get(), ec))
389  new_socket.release();
390  }
391 
392  return ec;
393  }
394 
395  // Start an asynchronous accept. The peer and peer_endpoint objects
396  // must be valid until the accept's handler is invoked.
397  template <typename Socket, typename Handler>
398  void async_accept(implementation_type& impl, Socket& peer,
399  endpoint_type* peer_endpoint, Handler& handler)
400  {
401  bool is_continuation =
403 
404  // Allocate and construct an operation to wrap the handler.
406  typename op::ptr p = { asio::detail::addressof(handler),
408  sizeof(op), handler), 0 };
409  p.p = new (p.v) op(impl.socket_, impl.state_, peer,
410  impl.protocol_, peer_endpoint, handler);
411 
412  ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_accept"));
413 
414  start_accept_op(impl, p.p, is_continuation, peer.is_open());
415  p.v = p.p = 0;
416  }
417 
418  // Connect the socket to the specified endpoint.
420  const endpoint_type& peer_endpoint, asio::error_code& ec)
421  {
423  peer_endpoint.data(), peer_endpoint.size(), ec);
424  return ec;
425  }
426 
427  // Start an asynchronous connect.
428  template <typename Handler>
430  const endpoint_type& peer_endpoint, Handler& handler)
431  {
432  bool is_continuation =
434 
435  // Allocate and construct an operation to wrap the handler.
437  typename op::ptr p = { asio::detail::addressof(handler),
439  sizeof(op), handler), 0 };
440  p.p = new (p.v) op(impl.socket_, handler);
441 
442  ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_connect"));
443 
444  start_connect_op(impl, p.p, is_continuation,
445  peer_endpoint.data(), peer_endpoint.size());
446  p.v = p.p = 0;
447  }
448 };
449 
450 } // namespace detail
451 } // namespace asio
452 
454 
455 #endif // !defined(ASIO_HAS_IOCP)
456 
457 #endif // ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_HPP
int message_flags
Bitmask type for flags that can be passed to send and receive operations.
Definition: socket_base.hpp:53
asio::error_code assign(implementation_type &impl, const protocol_type &protocol, const native_handle_type &native_socket, asio::error_code &ec)
socket_type get() const
asio::error_code bind(implementation_type &impl, const endpoint_type &endpoint, asio::error_code &ec)
ASIO_DECL void start_op(base_implementation_type &impl, int op_type, reactor_op *op, bool is_continuation, bool is_non_blocking, bool noop)
asio::error_code connect(implementation_type &impl, const endpoint_type &peer_endpoint, asio::error_code &ec)
Provides core I/O functionality.
Definition: io_service.hpp:184
Holds a buffer that cannot be modified.
Definition: buffer.hpp:211
asio::error_code get_option(const implementation_type &impl, Option &option, asio::error_code &ec) const
int getsockopt(socket_type s, state_type state, int level, int optname, void *optval, size_t *optlen, asio::error_code &ec)
int getsockname(socket_type s, socket_addr_type *addr, std::size_t *addrlen, asio::error_code &ec)
void async_send_to(implementation_type &impl, const null_buffers &, const endpoint_type &, socket_base::message_flags, Handler &handler)
int poll_read(socket_type s, state_type state, asio::error_code &ec)
void async_send_to(implementation_type &impl, const ConstBufferSequence &buffers, const endpoint_type &destination, socket_base::message_flags flags, Handler &handler)
void async_connect(implementation_type &impl, const endpoint_type &peer_endpoint, Handler &handler)
size_t sync_sendto(socket_type s, state_type state, const buf *bufs, size_t count, int flags, const socket_addr_type *addr, std::size_t addrlen, asio::error_code &ec)
ASIO_DECL asio::error_code do_assign(base_implementation_type &impl, int type, const native_handle_type &native_socket, asio::error_code &ec)
size_t send_to(implementation_type &impl, const null_buffers &, const endpoint_type &, socket_base::message_flags, asio::error_code &ec)
ASIO_DECL void start_connect_op(base_implementation_type &impl, reactor_op *op, bool is_continuation, const socket_addr_type *addr, size_t addrlen)
size_t send_to(implementation_type &impl, const ConstBufferSequence &buffers, const endpoint_type &destination, socket_base::message_flags flags, asio::error_code &ec)
const MutableBufferSequence & buffers
Definition: read.hpp:521
void move_assign(implementation_type &impl, reactive_socket_service_base &other_service, implementation_type &other_impl)
ASIO_DECL void base_move_construct(base_implementation_type &impl, base_implementation_type &other_impl)
int setsockopt(socket_type s, state_type &state, int level, int optname, const void *optval, std::size_t optlen, asio::error_code &ec)
endpoint_type local_endpoint(const implementation_type &impl, asio::error_code &ec) const
ASIO_DECL asio::error_code do_open(base_implementation_type &impl, int af, int type, int protocol, asio::error_code &ec)
void async_accept(implementation_type &impl, Socket &peer, endpoint_type *peer_endpoint, Handler &handler)
asio::error_code set_option(implementation_type &impl, const Option &option, asio::error_code &ec)
Holds a buffer that can be modified.
Definition: buffer.hpp:91
int poll_write(socket_type s, state_type state, asio::error_code &ec)
asio::error_code open(implementation_type &impl, const protocol_type &protocol, asio::error_code &ec)
int bind(socket_type s, const socket_addr_type *addr, std::size_t addrlen, asio::error_code &ec)
Definition: socket_ops.ipp:278
void async_receive_from(implementation_type &impl, const MutableBufferSequence &buffers, endpoint_type &sender_endpoint, socket_base::message_flags flags, Handler &handler)
bool is_continuation(Context &context)
void converting_move_construct(implementation_type &impl, typename reactive_socket_service< Protocol1 >::implementation_type &other_impl)
void move_construct(implementation_type &impl, implementation_type &other_impl)
Class to represent an error code value.
Definition: error_code.hpp:80
ASIO_DECL void base_move_assign(base_implementation_type &impl, reactive_socket_service_base &other_service, base_implementation_type &other_impl)
ASIO_DECL void start_accept_op(base_implementation_type &impl, reactor_op *op, bool is_continuation, bool peer_is_open)
void sync_connect(socket_type s, const socket_addr_type *addr, std::size_t addrlen, asio::error_code &ec)
Definition: socket_ops.ipp:495
reactive_socket_service(asio::io_service &io_service)
void * allocate(std::size_t s, Handler &h)
int getpeername(socket_type s, socket_addr_type *addr, std::size_t *addrlen, bool cached, asio::error_code &ec)
Already open.
Definition: error.hpp:214
const int invalid_socket
size_t sync_recvfrom(socket_type s, state_type state, buf *bufs, size_t count, int flags, socket_addr_type *addr, std::size_t *addrlen, asio::error_code &ec)
Definition: socket_ops.ipp:941
native_handle_type native_handle(implementation_type &impl)
size_t receive_from(implementation_type &impl, const null_buffers &, endpoint_type &sender_endpoint, socket_base::message_flags, asio::error_code &ec)
void async_receive_from(implementation_type &impl, const null_buffers &, endpoint_type &sender_endpoint, socket_base::message_flags flags, Handler &handler)
#define ASIO_HANDLER_CREATION(args)
socket_type sync_accept(socket_type s, state_type state, socket_addr_type *addr, std::size_t *addrlen, asio::error_code &ec)
Definition: socket_ops.ipp:132
endpoint_type remote_endpoint(const implementation_type &impl, asio::error_code &ec) const
asio::error_code accept(implementation_type &impl, Socket &peer, endpoint_type *peer_endpoint, asio::error_code &ec)
size_t receive_from(implementation_type &impl, const MutableBufferSequence &buffers, endpoint_type &sender_endpoint, socket_base::message_flags flags, asio::error_code &ec)