Realistic 3D camera system
3D camera system components
win_iocp_socket_service.hpp
Go to the documentation of this file.
1 //
2 // detail/win_iocp_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_WIN_IOCP_SOCKET_SERVICE_HPP
12 #define ASIO_DETAIL_WIN_IOCP_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 <cstring>
23 #include "asio/error.hpp"
24 #include "asio/io_service.hpp"
25 #include "asio/socket_base.hpp"
32 #include "asio/detail/mutex.hpp"
34 #include "asio/detail/reactor.hpp"
46 
48 
49 namespace asio {
50 namespace detail {
51 
52 template <typename Protocol>
53 class win_iocp_socket_service : public win_iocp_socket_service_base
54 {
55 public:
56  // The protocol type.
57  typedef Protocol protocol_type;
58 
59  // The endpoint type.
60  typedef typename Protocol::endpoint endpoint_type;
61 
62  // The native type of a socket.
63  class native_handle_type
64  {
65  public:
66  native_handle_type(socket_type s)
67  : socket_(s),
68  have_remote_endpoint_(false)
69  {
70  }
71 
72  native_handle_type(socket_type s, const endpoint_type& ep)
73  : socket_(s),
74  have_remote_endpoint_(true),
75  remote_endpoint_(ep)
76  {
77  }
78 
79  void operator=(socket_type s)
80  {
81  socket_ = s;
82  have_remote_endpoint_ = false;
83  remote_endpoint_ = endpoint_type();
84  }
85 
86  operator socket_type() const
87  {
88  return socket_;
89  }
90 
91  bool have_remote_endpoint() const
92  {
93  return have_remote_endpoint_;
94  }
95 
96  endpoint_type remote_endpoint() const
97  {
98  return remote_endpoint_;
99  }
100 
101  private:
102  socket_type socket_;
103  bool have_remote_endpoint_;
104  endpoint_type remote_endpoint_;
105  };
106 
107  // The implementation type of the socket.
108  struct implementation_type :
109  win_iocp_socket_service_base::base_implementation_type
110  {
111  // Default constructor.
112  implementation_type()
113  : protocol_(endpoint_type().protocol()),
114  have_remote_endpoint_(false),
115  remote_endpoint_()
116  {
117  }
118 
119  // The protocol associated with the socket.
120  protocol_type protocol_;
121 
122  // Whether we have a cached remote endpoint.
123  bool have_remote_endpoint_;
124 
125  // A cached remote endpoint.
126  endpoint_type remote_endpoint_;
127  };
128 
129  // Constructor.
130  win_iocp_socket_service(asio::io_service& io_service)
131  : win_iocp_socket_service_base(io_service)
132  {
133  }
134 
135  // Move-construct a new socket implementation.
136  void move_construct(implementation_type& impl,
137  implementation_type& other_impl)
138  {
139  this->base_move_construct(impl, other_impl);
140 
141  impl.protocol_ = other_impl.protocol_;
142  other_impl.protocol_ = endpoint_type().protocol();
143 
144  impl.have_remote_endpoint_ = other_impl.have_remote_endpoint_;
145  other_impl.have_remote_endpoint_ = false;
146 
147  impl.remote_endpoint_ = other_impl.remote_endpoint_;
148  other_impl.remote_endpoint_ = endpoint_type();
149  }
150 
151  // Move-assign from another socket implementation.
152  void move_assign(implementation_type& impl,
153  win_iocp_socket_service_base& other_service,
154  implementation_type& other_impl)
155  {
156  this->base_move_assign(impl, other_service, other_impl);
157 
158  impl.protocol_ = other_impl.protocol_;
159  other_impl.protocol_ = endpoint_type().protocol();
160 
161  impl.have_remote_endpoint_ = other_impl.have_remote_endpoint_;
162  other_impl.have_remote_endpoint_ = false;
163 
164  impl.remote_endpoint_ = other_impl.remote_endpoint_;
165  other_impl.remote_endpoint_ = endpoint_type();
166  }
167 
168  // Move-construct a new socket implementation from another protocol type.
169  template <typename Protocol1>
170  void converting_move_construct(implementation_type& impl,
171  typename win_iocp_socket_service<
172  Protocol1>::implementation_type& other_impl)
173  {
174  this->base_move_construct(impl, other_impl);
175 
176  impl.protocol_ = protocol_type(other_impl.protocol_);
177  other_impl.protocol_ = typename Protocol1::endpoint().protocol();
178 
179  impl.have_remote_endpoint_ = other_impl.have_remote_endpoint_;
180  other_impl.have_remote_endpoint_ = false;
181 
182  impl.remote_endpoint_ = other_impl.remote_endpoint_;
183  other_impl.remote_endpoint_ = typename Protocol1::endpoint();
184  }
185 
186  // Open a new socket implementation.
187  asio::error_code open(implementation_type& impl,
188  const protocol_type& protocol, asio::error_code& ec)
189  {
190  if (!do_open(impl, protocol.family(),
191  protocol.type(), protocol.protocol(), ec))
192  {
193  impl.protocol_ = protocol;
194  impl.have_remote_endpoint_ = false;
195  impl.remote_endpoint_ = endpoint_type();
196  }
197  return ec;
198  }
199 
200  // Assign a native socket to a socket implementation.
201  asio::error_code assign(implementation_type& impl,
202  const protocol_type& protocol, const native_handle_type& native_socket,
203  asio::error_code& ec)
204  {
205  if (!do_assign(impl, protocol.type(), native_socket, ec))
206  {
207  impl.protocol_ = protocol;
208  impl.have_remote_endpoint_ = native_socket.have_remote_endpoint();
209  impl.remote_endpoint_ = native_socket.remote_endpoint();
210  }
211  return ec;
212  }
213 
214  // Get the native socket representation.
215  native_handle_type native_handle(implementation_type& impl)
216  {
217  if (impl.have_remote_endpoint_)
218  return native_handle_type(impl.socket_, impl.remote_endpoint_);
219  return native_handle_type(impl.socket_);
220  }
221 
222  // Bind the socket to the specified local endpoint.
223  asio::error_code bind(implementation_type& impl,
224  const endpoint_type& endpoint, asio::error_code& ec)
225  {
226  socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec);
227  return ec;
228  }
229 
230  // Set a socket option.
231  template <typename Option>
232  asio::error_code set_option(implementation_type& impl,
233  const Option& option, asio::error_code& ec)
234  {
235  socket_ops::setsockopt(impl.socket_, impl.state_,
236  option.level(impl.protocol_), option.name(impl.protocol_),
237  option.data(impl.protocol_), option.size(impl.protocol_), ec);
238  return ec;
239  }
240 
241  // Set a socket option.
242  template <typename Option>
243  asio::error_code get_option(const implementation_type& impl,
244  Option& option, asio::error_code& ec) const
245  {
246  std::size_t size = option.size(impl.protocol_);
247  socket_ops::getsockopt(impl.socket_, impl.state_,
248  option.level(impl.protocol_), option.name(impl.protocol_),
249  option.data(impl.protocol_), &size, ec);
250  if (!ec)
251  option.resize(impl.protocol_, size);
252  return ec;
253  }
254 
255  // Get the local endpoint.
256  endpoint_type local_endpoint(const implementation_type& impl,
257  asio::error_code& ec) const
258  {
259  endpoint_type endpoint;
260  std::size_t addr_len = endpoint.capacity();
261  if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec))
262  return endpoint_type();
263  endpoint.resize(addr_len);
264  return endpoint;
265  }
266 
267  // Get the remote endpoint.
268  endpoint_type remote_endpoint(const implementation_type& impl,
269  asio::error_code& ec) const
270  {
271  endpoint_type endpoint = impl.remote_endpoint_;
272  std::size_t addr_len = endpoint.capacity();
273  if (socket_ops::getpeername(impl.socket_, endpoint.data(),
274  &addr_len, impl.have_remote_endpoint_, ec))
275  return endpoint_type();
276  endpoint.resize(addr_len);
277  return endpoint;
278  }
279 
280  // Send a datagram to the specified endpoint. Returns the number of bytes
281  // sent.
282  template <typename ConstBufferSequence>
283  size_t send_to(implementation_type& impl, const ConstBufferSequence& buffers,
284  const endpoint_type& destination, socket_base::message_flags flags,
285  asio::error_code& ec)
286  {
287  buffer_sequence_adapter<asio::const_buffer,
288  ConstBufferSequence> bufs(buffers);
289 
290  return socket_ops::sync_sendto(impl.socket_, impl.state_,
291  bufs.buffers(), bufs.count(), flags,
292  destination.data(), destination.size(), ec);
293  }
294 
295  // Wait until data can be sent without blocking.
296  size_t send_to(implementation_type& impl, const null_buffers&,
297  const endpoint_type&, socket_base::message_flags,
298  asio::error_code& ec)
299  {
300  // Wait for socket to become ready.
301  socket_ops::poll_write(impl.socket_, impl.state_, ec);
302 
303  return 0;
304  }
305 
306  // Start an asynchronous send. The data being sent must be valid for the
307  // lifetime of the asynchronous operation.
308  template <typename ConstBufferSequence, typename Handler>
309  void async_send_to(implementation_type& impl,
310  const ConstBufferSequence& buffers, const endpoint_type& destination,
311  socket_base::message_flags flags, Handler& handler)
312  {
313  // Allocate and construct an operation to wrap the handler.
314  typedef win_iocp_socket_send_op<ConstBufferSequence, Handler> op;
315  typename op::ptr p = { asio::detail::addressof(handler),
317  sizeof(op), handler), 0 };
318  p.p = new (p.v) op(impl.cancel_token_, buffers, handler);
319 
320  ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_send_to"));
321 
322  buffer_sequence_adapter<asio::const_buffer,
323  ConstBufferSequence> bufs(buffers);
324 
325  start_send_to_op(impl, bufs.buffers(), bufs.count(),
326  destination.data(), static_cast<int>(destination.size()),
327  flags, p.p);
328  p.v = p.p = 0;
329  }
330 
331  // Start an asynchronous wait until data can be sent without blocking.
332  template <typename Handler>
333  void async_send_to(implementation_type& impl, const null_buffers&,
334  const endpoint_type&, socket_base::message_flags, Handler& handler)
335  {
336  // Allocate and construct an operation to wrap the handler.
337  typedef win_iocp_null_buffers_op<Handler> op;
338  typename op::ptr p = { asio::detail::addressof(handler),
340  sizeof(op), handler), 0 };
341  p.p = new (p.v) op(impl.cancel_token_, handler);
342 
343  ASIO_HANDLER_CREATION((p.p, "socket",
344  &impl, "async_send_to(null_buffers)"));
345 
346  start_reactor_op(impl, reactor::write_op, p.p);
347  p.v = p.p = 0;
348  }
349 
350  // Receive a datagram with the endpoint of the sender. Returns the number of
351  // bytes received.
352  template <typename MutableBufferSequence>
353  size_t receive_from(implementation_type& impl,
354  const MutableBufferSequence& buffers,
355  endpoint_type& sender_endpoint, socket_base::message_flags flags,
356  asio::error_code& ec)
357  {
358  buffer_sequence_adapter<asio::mutable_buffer,
359  MutableBufferSequence> bufs(buffers);
360 
361  std::size_t addr_len = sender_endpoint.capacity();
362  std::size_t bytes_recvd = socket_ops::sync_recvfrom(
363  impl.socket_, impl.state_, bufs.buffers(), bufs.count(),
364  flags, sender_endpoint.data(), &addr_len, ec);
365 
366  if (!ec)
367  sender_endpoint.resize(addr_len);
368 
369  return bytes_recvd;
370  }
371 
372  // Wait until data can be received without blocking.
373  size_t receive_from(implementation_type& impl,
374  const null_buffers&, endpoint_type& sender_endpoint,
376  {
377  // Wait for socket to become ready.
378  socket_ops::poll_read(impl.socket_, impl.state_, ec);
379 
380  // Reset endpoint since it can be given no sensible value at this time.
381  sender_endpoint = endpoint_type();
382 
383  return 0;
384  }
385 
386  // Start an asynchronous receive. The buffer for the data being received and
387  // the sender_endpoint object must both be valid for the lifetime of the
388  // asynchronous operation.
389  template <typename MutableBufferSequence, typename Handler>
390  void async_receive_from(implementation_type& impl,
391  const MutableBufferSequence& buffers, endpoint_type& sender_endp,
392  socket_base::message_flags flags, Handler& handler)
393  {
394  // Allocate and construct an operation to wrap the handler.
395  typedef win_iocp_socket_recvfrom_op<
396  MutableBufferSequence, endpoint_type, Handler> op;
397  typename op::ptr p = { asio::detail::addressof(handler),
399  sizeof(op), handler), 0 };
400  p.p = new (p.v) op(sender_endp, impl.cancel_token_, buffers, handler);
401 
402  ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_receive_from"));
403 
404  buffer_sequence_adapter<asio::mutable_buffer,
405  MutableBufferSequence> bufs(buffers);
406 
407  start_receive_from_op(impl, bufs.buffers(), bufs.count(),
408  sender_endp.data(), flags, &p.p->endpoint_size(), p.p);
409  p.v = p.p = 0;
410  }
411 
412  // Wait until data can be received without blocking.
413  template <typename Handler>
414  void async_receive_from(implementation_type& impl,
415  const null_buffers&, endpoint_type& sender_endpoint,
416  socket_base::message_flags flags, Handler& handler)
417  {
418  // Allocate and construct an operation to wrap the handler.
419  typedef win_iocp_null_buffers_op<Handler> op;
420  typename op::ptr p = { asio::detail::addressof(handler),
422  sizeof(op), handler), 0 };
423  p.p = new (p.v) op(impl.cancel_token_, handler);
424 
425  ASIO_HANDLER_CREATION((p.p, "socket", &impl,
426  "async_receive_from(null_buffers)"));
427 
428  // Reset endpoint since it can be given no sensible value at this time.
429  sender_endpoint = endpoint_type();
430 
431  start_null_buffers_receive_op(impl, flags, p.p);
432  p.v = p.p = 0;
433  }
434 
435  // Accept a new connection.
436  template <typename Socket>
437  asio::error_code accept(implementation_type& impl, Socket& peer,
438  endpoint_type* peer_endpoint, asio::error_code& ec)
439  {
440  // We cannot accept a socket that is already open.
441  if (peer.is_open())
442  {
444  return ec;
445  }
446 
447  std::size_t addr_len = peer_endpoint ? peer_endpoint->capacity() : 0;
448  socket_holder new_socket(socket_ops::sync_accept(impl.socket_,
449  impl.state_, peer_endpoint ? peer_endpoint->data() : 0,
450  peer_endpoint ? &addr_len : 0, ec));
451 
452  // On success, assign new connection to peer socket object.
453  if (new_socket.get() != invalid_socket)
454  {
455  if (peer_endpoint)
456  peer_endpoint->resize(addr_len);
457  if (!peer.assign(impl.protocol_, new_socket.get(), ec))
458  new_socket.release();
459  }
460 
461  return ec;
462  }
463 
464  // Start an asynchronous accept. The peer and peer_endpoint objects
465  // must be valid until the accept's handler is invoked.
466  template <typename Socket, typename Handler>
467  void async_accept(implementation_type& impl, Socket& peer,
468  endpoint_type* peer_endpoint, Handler& handler)
469  {
470  // Allocate and construct an operation to wrap the handler.
471  typedef win_iocp_socket_accept_op<Socket, protocol_type, Handler> op;
472  typename op::ptr p = { asio::detail::addressof(handler),
474  sizeof(op), handler), 0 };
476  (impl.state_ & socket_ops::enable_connection_aborted) != 0;
477  p.p = new (p.v) op(*this, impl.socket_, peer, impl.protocol_,
478  peer_endpoint, enable_connection_aborted, handler);
479 
480  ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_accept"));
481 
482  start_accept_op(impl, peer.is_open(), p.p->new_socket(),
483  impl.protocol_.family(), impl.protocol_.type(),
484  impl.protocol_.protocol(), p.p->output_buffer(),
485  p.p->address_length(), p.p);
486  p.v = p.p = 0;
487  }
488 
489  // Connect the socket to the specified endpoint.
490  asio::error_code connect(implementation_type& impl,
491  const endpoint_type& peer_endpoint, asio::error_code& ec)
492  {
493  socket_ops::sync_connect(impl.socket_,
494  peer_endpoint.data(), peer_endpoint.size(), ec);
495  return ec;
496  }
497 
498  // Start an asynchronous connect.
499  template <typename Handler>
500  void async_connect(implementation_type& impl,
501  const endpoint_type& peer_endpoint, Handler& handler)
502  {
503  // Allocate and construct an operation to wrap the handler.
504  typedef win_iocp_socket_connect_op<Handler> op;
505  typename op::ptr p = { asio::detail::addressof(handler),
507  sizeof(op), handler), 0 };
508  p.p = new (p.v) op(impl.socket_, handler);
509 
510  ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_connect"));
511 
512  start_connect_op(impl, impl.protocol_.family(), impl.protocol_.type(),
513  peer_endpoint.data(), static_cast<int>(peer_endpoint.size()), p.p);
514  p.v = p.p = 0;
515  }
516 };
517 
518 } // namespace detail
519 } // namespace asio
520 
522 
523 #endif // defined(ASIO_HAS_IOCP)
524 
525 #endif // ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_HPP
int message_flags
Bitmask type for flags that can be passed to send and receive operations.
Definition: socket_base.hpp:53
Provides core I/O functionality.
Definition: io_service.hpp:184
Holds a buffer that cannot be modified.
Definition: buffer.hpp:211
SocketService & s
Definition: connect.hpp:521
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)
Iterator connect(basic_socket< Protocol, SocketService > &s, Iterator begin)
Establishes a socket connection by trying each endpoint in a sequence.
Definition: connect.hpp:44
int poll_read(socket_type s, state_type state, asio::error_code &ec)
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)
const MutableBufferSequence & buffers
Definition: read.hpp:521
int setsockopt(socket_type s, state_type &state, int level, int optname, const void *optval, std::size_t optlen, 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)
int bind(socket_type s, const socket_addr_type *addr, std::size_t addrlen, asio::error_code &ec)
Definition: socket_ops.ipp:278
Class to represent an error code value.
Definition: error_code.hpp:80
socket_type accept(socket_type s, socket_addr_type *addr, std::size_t *addrlen, asio::error_code &ec)
Definition: socket_ops.ipp:101
void sync_connect(socket_type s, const socket_addr_type *addr, std::size_t addrlen, asio::error_code &ec)
Definition: socket_ops.ipp:495
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
ASIO_DECL int open(const char *path, int flags, asio::error_code &ec)
#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