00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #ifndef ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_HPP
00012 #define ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_HPP
00013
00014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
00015 # pragma once
00016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
00017
00018 #include "asio/detail/push_options.hpp"
00019
00020 #include "asio/detail/win_iocp_io_service_fwd.hpp"
00021
00022 #if defined(ASIO_HAS_IOCP)
00023
00024 #include "asio/detail/push_options.hpp"
00025 #include <cstring>
00026 #include <boost/shared_ptr.hpp>
00027 #include <boost/weak_ptr.hpp>
00028 #include "asio/detail/pop_options.hpp"
00029
00030 #include "asio/buffer.hpp"
00031 #include "asio/error.hpp"
00032 #include "asio/io_service.hpp"
00033 #include "asio/socket_base.hpp"
00034 #include "asio/detail/bind_handler.hpp"
00035 #include "asio/detail/handler_alloc_helpers.hpp"
00036 #include "asio/detail/handler_invoke_helpers.hpp"
00037 #include "asio/detail/mutex.hpp"
00038 #include "asio/detail/select_reactor.hpp"
00039 #include "asio/detail/socket_holder.hpp"
00040 #include "asio/detail/socket_ops.hpp"
00041 #include "asio/detail/socket_types.hpp"
00042 #include "asio/detail/win_iocp_io_service.hpp"
00043
00044 namespace asio {
00045 namespace detail {
00046
00047 template <typename Protocol>
00048 class win_iocp_socket_service
00049 : public asio::detail::service_base<win_iocp_socket_service<Protocol> >
00050 {
00051 public:
00052
00053 typedef Protocol protocol_type;
00054
00055
00056 typedef typename Protocol::endpoint endpoint_type;
00057
00058
00059 typedef win_iocp_operation operation;
00060
00061 struct noop_deleter { void operator()(void*) {} };
00062 typedef boost::shared_ptr<void> shared_cancel_token_type;
00063 typedef boost::weak_ptr<void> weak_cancel_token_type;
00064
00065
00066 class native_type
00067 {
00068 public:
00069 native_type(socket_type s)
00070 : socket_(s),
00071 have_remote_endpoint_(false)
00072 {
00073 }
00074
00075 native_type(socket_type s, const endpoint_type& ep)
00076 : socket_(s),
00077 have_remote_endpoint_(true),
00078 remote_endpoint_(ep)
00079 {
00080 }
00081
00082 void operator=(socket_type s)
00083 {
00084 socket_ = s;
00085 have_remote_endpoint_ = false;
00086 remote_endpoint_ = endpoint_type();
00087 }
00088
00089 operator socket_type() const
00090 {
00091 return socket_;
00092 }
00093
00094 HANDLE as_handle() const
00095 {
00096 return reinterpret_cast<HANDLE>(socket_);
00097 }
00098
00099 bool have_remote_endpoint() const
00100 {
00101 return have_remote_endpoint_;
00102 }
00103
00104 endpoint_type remote_endpoint() const
00105 {
00106 return remote_endpoint_;
00107 }
00108
00109 private:
00110 socket_type socket_;
00111 bool have_remote_endpoint_;
00112 endpoint_type remote_endpoint_;
00113 };
00114
00115
00116 class implementation_type
00117 {
00118 public:
00119
00120 implementation_type()
00121 : socket_(invalid_socket),
00122 flags_(0),
00123 cancel_token_(),
00124 protocol_(endpoint_type().protocol()),
00125 next_(0),
00126 prev_(0)
00127 {
00128 }
00129
00130 private:
00131
00132 friend class win_iocp_socket_service;
00133
00134
00135 native_type socket_;
00136
00137 enum
00138 {
00139 enable_connection_aborted = 1,
00140 user_set_linger = 2
00141 };
00142
00143
00144 unsigned char flags_;
00145
00146
00147
00148
00149
00150
00151
00152 shared_cancel_token_type cancel_token_;
00153
00154
00155 protocol_type protocol_;
00156
00157
00158
00159
00160
00161 DWORD safe_cancellation_thread_id_;
00162
00163
00164 implementation_type* next_;
00165 implementation_type* prev_;
00166 };
00167
00168
00169 typedef detail::select_reactor<true> reactor_type;
00170
00171
00172 enum { max_buffers = 16 };
00173
00174
00175 win_iocp_socket_service(asio::io_service& io_service)
00176 : asio::detail::service_base<
00177 win_iocp_socket_service<Protocol> >(io_service),
00178 iocp_service_(asio::use_service<win_iocp_io_service>(io_service)),
00179 reactor_(0),
00180 mutex_(),
00181 impl_list_(0)
00182 {
00183 }
00184
00185
00186 void shutdown_service()
00187 {
00188
00189 asio::detail::mutex::scoped_lock lock(mutex_);
00190 implementation_type* impl = impl_list_;
00191 while (impl)
00192 {
00193 asio::error_code ignored_ec;
00194 close(*impl, ignored_ec);
00195 impl = impl->next_;
00196 }
00197 }
00198
00199
00200 void construct(implementation_type& impl)
00201 {
00202 impl.socket_ = invalid_socket;
00203 impl.cancel_token_.reset();
00204 impl.safe_cancellation_thread_id_ = 0;
00205
00206
00207 asio::detail::mutex::scoped_lock lock(mutex_);
00208 impl.next_ = impl_list_;
00209 impl.prev_ = 0;
00210 if (impl_list_)
00211 impl_list_->prev_ = &impl;
00212 impl_list_ = &impl;
00213 }
00214
00215
00216 void destroy(implementation_type& impl)
00217 {
00218 if (impl.socket_ != invalid_socket)
00219 {
00220
00221
00222
00223 reactor_type* reactor = static_cast<reactor_type*>(
00224 interlocked_compare_exchange_pointer(
00225 reinterpret_cast<void**>(&reactor_), 0, 0));
00226 if (reactor)
00227 reactor->close_descriptor(impl.socket_);
00228
00229 if (impl.flags_ & implementation_type::user_set_linger)
00230 {
00231 ::linger opt;
00232 opt.l_onoff = 0;
00233 opt.l_linger = 0;
00234 asio::error_code ignored_ec;
00235 socket_ops::setsockopt(impl.socket_,
00236 SOL_SOCKET, SO_LINGER, &opt, sizeof(opt), ignored_ec);
00237 }
00238
00239 asio::error_code ignored_ec;
00240 socket_ops::close(impl.socket_, ignored_ec);
00241 impl.socket_ = invalid_socket;
00242 impl.cancel_token_.reset();
00243 impl.safe_cancellation_thread_id_ = 0;
00244 }
00245
00246
00247 asio::detail::mutex::scoped_lock lock(mutex_);
00248 if (impl_list_ == &impl)
00249 impl_list_ = impl.next_;
00250 if (impl.prev_)
00251 impl.prev_->next_ = impl.next_;
00252 if (impl.next_)
00253 impl.next_->prev_= impl.prev_;
00254 impl.next_ = 0;
00255 impl.prev_ = 0;
00256 }
00257
00258
00259 asio::error_code open(implementation_type& impl,
00260 const protocol_type& protocol, asio::error_code& ec)
00261 {
00262 if (is_open(impl))
00263 {
00264 ec = asio::error::already_open;
00265 return ec;
00266 }
00267
00268 socket_holder sock(socket_ops::socket(protocol.family(), protocol.type(),
00269 protocol.protocol(), ec));
00270 if (sock.get() == invalid_socket)
00271 return ec;
00272
00273 HANDLE sock_as_handle = reinterpret_cast<HANDLE>(sock.get());
00274 iocp_service_.register_handle(sock_as_handle);
00275
00276 impl.socket_ = sock.release();
00277 impl.cancel_token_.reset(static_cast<void*>(0), noop_deleter());
00278 impl.protocol_ = protocol;
00279 ec = asio::error_code();
00280 return ec;
00281 }
00282
00283
00284 asio::error_code assign(implementation_type& impl,
00285 const protocol_type& protocol, const native_type& native_socket,
00286 asio::error_code& ec)
00287 {
00288 if (is_open(impl))
00289 {
00290 ec = asio::error::already_open;
00291 return ec;
00292 }
00293
00294 iocp_service_.register_handle(native_socket.as_handle());
00295
00296 impl.socket_ = native_socket;
00297 impl.cancel_token_.reset(static_cast<void*>(0), noop_deleter());
00298 impl.protocol_ = protocol;
00299 ec = asio::error_code();
00300 return ec;
00301 }
00302
00303
00304 bool is_open(const implementation_type& impl) const
00305 {
00306 return impl.socket_ != invalid_socket;
00307 }
00308
00309
00310 asio::error_code close(implementation_type& impl,
00311 asio::error_code& ec)
00312 {
00313 if (is_open(impl))
00314 {
00315
00316
00317
00318 reactor_type* reactor = static_cast<reactor_type*>(
00319 interlocked_compare_exchange_pointer(
00320 reinterpret_cast<void**>(&reactor_), 0, 0));
00321 if (reactor)
00322 reactor->close_descriptor(impl.socket_);
00323
00324 if (socket_ops::close(impl.socket_, ec) == socket_error_retval)
00325 return ec;
00326
00327 impl.socket_ = invalid_socket;
00328 impl.cancel_token_.reset();
00329 impl.safe_cancellation_thread_id_ = 0;
00330 }
00331
00332 ec = asio::error_code();
00333 return ec;
00334 }
00335
00336
00337 native_type native(implementation_type& impl)
00338 {
00339 return impl.socket_;
00340 }
00341
00342
00343 asio::error_code cancel(implementation_type& impl,
00344 asio::error_code& ec)
00345 {
00346 if (!is_open(impl))
00347 {
00348 ec = asio::error::bad_descriptor;
00349 }
00350 else if (impl.safe_cancellation_thread_id_ == 0)
00351 {
00352
00353 ec = asio::error_code();
00354 }
00355 else if (impl.safe_cancellation_thread_id_ == ::GetCurrentThreadId())
00356 {
00357
00358
00359 socket_type sock = impl.socket_;
00360 HANDLE sock_as_handle = reinterpret_cast<HANDLE>(sock);
00361 if (!::CancelIo(sock_as_handle))
00362 {
00363 DWORD last_error = ::GetLastError();
00364 ec = asio::error_code(last_error, asio::native_ecat);
00365 }
00366 else
00367 {
00368 ec = asio::error_code();
00369 }
00370 }
00371 else
00372 {
00373
00374
00375 ec = asio::error::operation_not_supported;
00376 }
00377
00378 return ec;
00379 }
00380
00381
00382 bool at_mark(const implementation_type& impl,
00383 asio::error_code& ec) const
00384 {
00385 if (!is_open(impl))
00386 {
00387 ec = asio::error::bad_descriptor;
00388 return false;
00389 }
00390
00391 asio::detail::ioctl_arg_type value = 0;
00392 socket_ops::ioctl(impl.socket_, SIOCATMARK, &value, ec);
00393 return ec ? false : value != 0;
00394 }
00395
00396
00397 std::size_t available(const implementation_type& impl,
00398 asio::error_code& ec) const
00399 {
00400 if (!is_open(impl))
00401 {
00402 ec = asio::error::bad_descriptor;
00403 return 0;
00404 }
00405
00406 asio::detail::ioctl_arg_type value = 0;
00407 socket_ops::ioctl(impl.socket_, FIONREAD, &value, ec);
00408 return ec ? static_cast<std::size_t>(0) : static_cast<std::size_t>(value);
00409 }
00410
00411
00412 asio::error_code bind(implementation_type& impl,
00413 const endpoint_type& endpoint, asio::error_code& ec)
00414 {
00415 if (!is_open(impl))
00416 {
00417 ec = asio::error::bad_descriptor;
00418 return ec;
00419 }
00420
00421 socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec);
00422 return ec;
00423 }
00424
00425
00426 asio::error_code listen(implementation_type& impl, int backlog,
00427 asio::error_code& ec)
00428 {
00429 if (!is_open(impl))
00430 {
00431 ec = asio::error::bad_descriptor;
00432 return ec;
00433 }
00434
00435 socket_ops::listen(impl.socket_, backlog, ec);
00436 return ec;
00437 }
00438
00439
00440 template <typename Option>
00441 asio::error_code set_option(implementation_type& impl,
00442 const Option& option, asio::error_code& ec)
00443 {
00444 if (!is_open(impl))
00445 {
00446 ec = asio::error::bad_descriptor;
00447 return ec;
00448 }
00449
00450 if (option.level(impl.protocol_) == custom_socket_option_level
00451 && option.name(impl.protocol_) == enable_connection_aborted_option)
00452 {
00453 if (option.size(impl.protocol_) != sizeof(int))
00454 {
00455 ec = asio::error::invalid_argument;
00456 }
00457 else
00458 {
00459 if (*reinterpret_cast<const int*>(option.data(impl.protocol_)))
00460 impl.flags_ |= implementation_type::enable_connection_aborted;
00461 else
00462 impl.flags_ &= ~implementation_type::enable_connection_aborted;
00463 ec = asio::error_code();
00464 }
00465 return ec;
00466 }
00467 else
00468 {
00469 if (option.level(impl.protocol_) == SOL_SOCKET
00470 && option.name(impl.protocol_) == SO_LINGER)
00471 {
00472 impl.flags_ |= implementation_type::user_set_linger;
00473 }
00474
00475 socket_ops::setsockopt(impl.socket_,
00476 option.level(impl.protocol_), option.name(impl.protocol_),
00477 option.data(impl.protocol_), option.size(impl.protocol_), ec);
00478 return ec;
00479 }
00480 }
00481
00482
00483 template <typename Option>
00484 asio::error_code get_option(const implementation_type& impl,
00485 Option& option, asio::error_code& ec) const
00486 {
00487 if (!is_open(impl))
00488 {
00489 ec = asio::error::bad_descriptor;
00490 return ec;
00491 }
00492
00493 if (option.level(impl.protocol_) == custom_socket_option_level
00494 && option.name(impl.protocol_) == enable_connection_aborted_option)
00495 {
00496 if (option.size(impl.protocol_) != sizeof(int))
00497 {
00498 ec = asio::error::invalid_argument;
00499 }
00500 else
00501 {
00502 int* target = reinterpret_cast<int*>(option.data(impl.protocol_));
00503 if (impl.flags_ & implementation_type::enable_connection_aborted)
00504 *target = 1;
00505 else
00506 *target = 0;
00507 option.resize(impl.protocol_, sizeof(int));
00508 ec = asio::error_code();
00509 }
00510 return ec;
00511 }
00512 else
00513 {
00514 size_t size = option.size(impl.protocol_);
00515 socket_ops::getsockopt(impl.socket_,
00516 option.level(impl.protocol_), option.name(impl.protocol_),
00517 option.data(impl.protocol_), &size, ec);
00518 if (!ec)
00519 option.resize(impl.protocol_, size);
00520 return ec;
00521 }
00522 }
00523
00524
00525 template <typename IO_Control_Command>
00526 asio::error_code io_control(implementation_type& impl,
00527 IO_Control_Command& command, asio::error_code& ec)
00528 {
00529 if (!is_open(impl))
00530 {
00531 ec = asio::error::bad_descriptor;
00532 return ec;
00533 }
00534
00535 socket_ops::ioctl(impl.socket_, command.name(),
00536 static_cast<ioctl_arg_type*>(command.data()), ec);
00537 return ec;
00538 }
00539
00540
00541 endpoint_type local_endpoint(const implementation_type& impl,
00542 asio::error_code& ec) const
00543 {
00544 if (!is_open(impl))
00545 {
00546 ec = asio::error::bad_descriptor;
00547 return endpoint_type();
00548 }
00549
00550 endpoint_type endpoint;
00551 socket_addr_len_type addr_len = endpoint.capacity();
00552 if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec))
00553 return endpoint_type();
00554 endpoint.resize(addr_len);
00555 return endpoint;
00556 }
00557
00558
00559 endpoint_type remote_endpoint(const implementation_type& impl,
00560 asio::error_code& ec) const
00561 {
00562 if (!is_open(impl))
00563 {
00564 ec = asio::error::bad_descriptor;
00565 return endpoint_type();
00566 }
00567
00568 if (impl.socket_.have_remote_endpoint())
00569 {
00570
00571 DWORD connect_time = 0;
00572 size_t connect_time_len = sizeof(connect_time);
00573 if (socket_ops::getsockopt(impl.socket_, SOL_SOCKET, SO_CONNECT_TIME,
00574 &connect_time, &connect_time_len, ec) == socket_error_retval)
00575 {
00576 return endpoint_type();
00577 }
00578 if (connect_time == 0xFFFFFFFF)
00579 {
00580 ec = asio::error::not_connected;
00581 return endpoint_type();
00582 }
00583
00584 ec = asio::error_code();
00585 return impl.socket_.remote_endpoint();
00586 }
00587 else
00588 {
00589 endpoint_type endpoint;
00590 socket_addr_len_type addr_len = endpoint.capacity();
00591 if (socket_ops::getpeername(impl.socket_, endpoint.data(), &addr_len, ec))
00592 return endpoint_type();
00593 endpoint.resize(addr_len);
00594 return endpoint;
00595 }
00596 }
00597
00599 asio::error_code shutdown(implementation_type& impl,
00600 socket_base::shutdown_type what, asio::error_code& ec)
00601 {
00602 if (!is_open(impl))
00603 {
00604 ec = asio::error::bad_descriptor;
00605 return ec;
00606 }
00607
00608 socket_ops::shutdown(impl.socket_, what, ec);
00609 return ec;
00610 }
00611
00612
00613 template <typename ConstBufferSequence>
00614 size_t send(implementation_type& impl, const ConstBufferSequence& buffers,
00615 socket_base::message_flags flags, asio::error_code& ec)
00616 {
00617 if (!is_open(impl))
00618 {
00619 ec = asio::error::bad_descriptor;
00620 return 0;
00621 }
00622
00623
00624 ::WSABUF bufs[max_buffers];
00625 typename ConstBufferSequence::const_iterator iter = buffers.begin();
00626 typename ConstBufferSequence::const_iterator end = buffers.end();
00627 DWORD i = 0;
00628 size_t total_buffer_size = 0;
00629 for (; iter != end && i < max_buffers; ++iter, ++i)
00630 {
00631 asio::const_buffer buffer(*iter);
00632 bufs[i].len = static_cast<u_long>(asio::buffer_size(buffer));
00633 bufs[i].buf = const_cast<char*>(
00634 asio::buffer_cast<const char*>(buffer));
00635 total_buffer_size += asio::buffer_size(buffer);
00636 }
00637
00638
00639 if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0)
00640 {
00641 ec = asio::error_code();
00642 return 0;
00643 }
00644
00645
00646 DWORD bytes_transferred = 0;
00647 int result = ::WSASend(impl.socket_, bufs,
00648 i, &bytes_transferred, flags, 0, 0);
00649 if (result != 0)
00650 {
00651 DWORD last_error = ::WSAGetLastError();
00652 if (last_error == ERROR_NETNAME_DELETED)
00653 last_error = WSAECONNRESET;
00654 else if (last_error == ERROR_PORT_UNREACHABLE)
00655 last_error = WSAECONNREFUSED;
00656 ec = asio::error_code(last_error, asio::native_ecat);
00657 return 0;
00658 }
00659
00660 ec = asio::error_code();
00661 return bytes_transferred;
00662 }
00663
00664 template <typename ConstBufferSequence, typename Handler>
00665 class send_operation
00666 : public operation
00667 {
00668 public:
00669 send_operation(asio::io_service& io_service,
00670 weak_cancel_token_type cancel_token,
00671 const ConstBufferSequence& buffers, Handler handler)
00672 : operation(
00673 &send_operation<ConstBufferSequence, Handler>::do_completion_impl,
00674 &send_operation<ConstBufferSequence, Handler>::destroy_impl),
00675 work_(io_service),
00676 cancel_token_(cancel_token),
00677 buffers_(buffers),
00678 handler_(handler)
00679 {
00680 }
00681
00682 private:
00683 static void do_completion_impl(operation* op,
00684 DWORD last_error, size_t bytes_transferred)
00685 {
00686
00687 typedef send_operation<ConstBufferSequence, Handler> op_type;
00688 op_type* handler_op(static_cast<op_type*>(op));
00689 typedef handler_alloc_traits<Handler, op_type> alloc_traits;
00690 handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
00691
00692 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
00693
00694 typename ConstBufferSequence::const_iterator iter
00695 = handler_op->buffers_.begin();
00696 typename ConstBufferSequence::const_iterator end
00697 = handler_op->buffers_.end();
00698 while (iter != end)
00699 {
00700 asio::const_buffer buffer(*iter);
00701 asio::buffer_cast<const char*>(buffer);
00702 ++iter;
00703 }
00704 #endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
00705
00706
00707 asio::error_code ec(last_error, asio::native_ecat);
00708 if (ec.value() == ERROR_NETNAME_DELETED)
00709 {
00710 if (handler_op->cancel_token_.expired())
00711 ec = asio::error::operation_aborted;
00712 else
00713 ec = asio::error::connection_reset;
00714 }
00715 else if (ec.value() == ERROR_PORT_UNREACHABLE)
00716 {
00717 ec = asio::error::connection_refused;
00718 }
00719
00720
00721
00722 Handler handler(handler_op->handler_);
00723
00724
00725 ptr.reset();
00726
00727
00728 asio_handler_invoke_helpers::invoke(
00729 detail::bind_handler(handler, ec, bytes_transferred), &handler);
00730 }
00731
00732 static void destroy_impl(operation* op)
00733 {
00734
00735 typedef send_operation<ConstBufferSequence, Handler> op_type;
00736 op_type* handler_op(static_cast<op_type*>(op));
00737 typedef handler_alloc_traits<Handler, op_type> alloc_traits;
00738 handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
00739 }
00740
00741 asio::io_service::work work_;
00742 weak_cancel_token_type cancel_token_;
00743 ConstBufferSequence buffers_;
00744 Handler handler_;
00745 };
00746
00747
00748
00749 template <typename ConstBufferSequence, typename Handler>
00750 void async_send(implementation_type& impl, const ConstBufferSequence& buffers,
00751 socket_base::message_flags flags, Handler handler)
00752 {
00753 if (!is_open(impl))
00754 {
00755 this->io_service().post(bind_handler(handler,
00756 asio::error::bad_descriptor, 0));
00757 return;
00758 }
00759
00760
00761 if (impl.safe_cancellation_thread_id_ == 0)
00762 impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();
00763 else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())
00764 impl.safe_cancellation_thread_id_ = ~DWORD(0);
00765
00766
00767 typedef send_operation<ConstBufferSequence, Handler> value_type;
00768 typedef handler_alloc_traits<Handler, value_type> alloc_traits;
00769 raw_handler_ptr<alloc_traits> raw_ptr(handler);
00770 handler_ptr<alloc_traits> ptr(raw_ptr,
00771 this->io_service(), impl.cancel_token_, buffers, handler);
00772
00773
00774 ::WSABUF bufs[max_buffers];
00775 typename ConstBufferSequence::const_iterator iter = buffers.begin();
00776 typename ConstBufferSequence::const_iterator end = buffers.end();
00777 DWORD i = 0;
00778 size_t total_buffer_size = 0;
00779 for (; iter != end && i < max_buffers; ++iter, ++i)
00780 {
00781 asio::const_buffer buffer(*iter);
00782 bufs[i].len = static_cast<u_long>(asio::buffer_size(buffer));
00783 bufs[i].buf = const_cast<char*>(
00784 asio::buffer_cast<const char*>(buffer));
00785 total_buffer_size += asio::buffer_size(buffer);
00786 }
00787
00788
00789 if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0)
00790 {
00791 asio::io_service::work work(this->io_service());
00792 ptr.reset();
00793 asio::error_code error;
00794 iocp_service_.post(bind_handler(handler, error, 0));
00795 return;
00796 }
00797
00798
00799 DWORD bytes_transferred = 0;
00800 int result = ::WSASend(impl.socket_, bufs, i,
00801 &bytes_transferred, flags, ptr.get(), 0);
00802 DWORD last_error = ::WSAGetLastError();
00803
00804
00805 if (result != 0 && last_error != WSA_IO_PENDING)
00806 {
00807 asio::io_service::work work(this->io_service());
00808 ptr.reset();
00809 asio::error_code ec(last_error, asio::native_ecat);
00810 iocp_service_.post(bind_handler(handler, ec, bytes_transferred));
00811 }
00812 else
00813 {
00814 ptr.release();
00815 }
00816 }
00817
00818
00819
00820 template <typename ConstBufferSequence>
00821 size_t send_to(implementation_type& impl, const ConstBufferSequence& buffers,
00822 const endpoint_type& destination, socket_base::message_flags flags,
00823 asio::error_code& ec)
00824 {
00825 if (!is_open(impl))
00826 {
00827 ec = asio::error::bad_descriptor;
00828 return 0;
00829 }
00830
00831
00832 ::WSABUF bufs[max_buffers];
00833 typename ConstBufferSequence::const_iterator iter = buffers.begin();
00834 typename ConstBufferSequence::const_iterator end = buffers.end();
00835 DWORD i = 0;
00836 for (; iter != end && i < max_buffers; ++iter, ++i)
00837 {
00838 asio::const_buffer buffer(*iter);
00839 bufs[i].len = static_cast<u_long>(asio::buffer_size(buffer));
00840 bufs[i].buf = const_cast<char*>(
00841 asio::buffer_cast<const char*>(buffer));
00842 }
00843
00844
00845 DWORD bytes_transferred = 0;
00846 int result = ::WSASendTo(impl.socket_, bufs, i, &bytes_transferred,
00847 flags, destination.data(), destination.size(), 0, 0);
00848 if (result != 0)
00849 {
00850 DWORD last_error = ::WSAGetLastError();
00851 if (last_error == ERROR_PORT_UNREACHABLE)
00852 last_error = WSAECONNREFUSED;
00853 ec = asio::error_code(last_error, asio::native_ecat);
00854 return 0;
00855 }
00856
00857 ec = asio::error_code();
00858 return bytes_transferred;
00859 }
00860
00861 template <typename ConstBufferSequence, typename Handler>
00862 class send_to_operation
00863 : public operation
00864 {
00865 public:
00866 send_to_operation(asio::io_service& io_service,
00867 const ConstBufferSequence& buffers, Handler handler)
00868 : operation(
00869 &send_to_operation<ConstBufferSequence, Handler>::do_completion_impl,
00870 &send_to_operation<ConstBufferSequence, Handler>::destroy_impl),
00871 work_(io_service),
00872 buffers_(buffers),
00873 handler_(handler)
00874 {
00875 }
00876
00877 private:
00878 static void do_completion_impl(operation* op,
00879 DWORD last_error, size_t bytes_transferred)
00880 {
00881
00882 typedef send_to_operation<ConstBufferSequence, Handler> op_type;
00883 op_type* handler_op(static_cast<op_type*>(op));
00884 typedef handler_alloc_traits<Handler, op_type> alloc_traits;
00885 handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
00886
00887 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
00888
00889 typename ConstBufferSequence::const_iterator iter
00890 = handler_op->buffers_.begin();
00891 typename ConstBufferSequence::const_iterator end
00892 = handler_op->buffers_.end();
00893 while (iter != end)
00894 {
00895 asio::const_buffer buffer(*iter);
00896 asio::buffer_cast<const char*>(buffer);
00897 ++iter;
00898 }
00899 #endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
00900
00901
00902 asio::error_code ec(last_error, asio::native_ecat);
00903 if (ec.value() == ERROR_PORT_UNREACHABLE)
00904 {
00905 ec = asio::error::connection_refused;
00906 }
00907
00908
00909
00910 Handler handler(handler_op->handler_);
00911
00912
00913 ptr.reset();
00914
00915
00916 asio_handler_invoke_helpers::invoke(
00917 detail::bind_handler(handler, ec, bytes_transferred), &handler);
00918 }
00919
00920 static void destroy_impl(operation* op)
00921 {
00922
00923 typedef send_to_operation<ConstBufferSequence, Handler> op_type;
00924 op_type* handler_op(static_cast<op_type*>(op));
00925 typedef handler_alloc_traits<Handler, op_type> alloc_traits;
00926 handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
00927 }
00928
00929 asio::io_service::work work_;
00930 ConstBufferSequence buffers_;
00931 Handler handler_;
00932 };
00933
00934
00935
00936 template <typename ConstBufferSequence, typename Handler>
00937 void async_send_to(implementation_type& impl,
00938 const ConstBufferSequence& buffers, const endpoint_type& destination,
00939 socket_base::message_flags flags, Handler handler)
00940 {
00941 if (!is_open(impl))
00942 {
00943 this->io_service().post(bind_handler(handler,
00944 asio::error::bad_descriptor, 0));
00945 return;
00946 }
00947
00948
00949 if (impl.safe_cancellation_thread_id_ == 0)
00950 impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();
00951 else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())
00952 impl.safe_cancellation_thread_id_ = ~DWORD(0);
00953
00954
00955 typedef send_to_operation<ConstBufferSequence, Handler> value_type;
00956 typedef handler_alloc_traits<Handler, value_type> alloc_traits;
00957 raw_handler_ptr<alloc_traits> raw_ptr(handler);
00958 handler_ptr<alloc_traits> ptr(raw_ptr,
00959 this->io_service(), buffers, handler);
00960
00961
00962 ::WSABUF bufs[max_buffers];
00963 typename ConstBufferSequence::const_iterator iter = buffers.begin();
00964 typename ConstBufferSequence::const_iterator end = buffers.end();
00965 DWORD i = 0;
00966 for (; iter != end && i < max_buffers; ++iter, ++i)
00967 {
00968 asio::const_buffer buffer(*iter);
00969 bufs[i].len = static_cast<u_long>(asio::buffer_size(buffer));
00970 bufs[i].buf = const_cast<char*>(
00971 asio::buffer_cast<const char*>(buffer));
00972 }
00973
00974
00975 DWORD bytes_transferred = 0;
00976 int result = ::WSASendTo(impl.socket_, bufs, i, &bytes_transferred,
00977 flags, destination.data(), destination.size(), ptr.get(), 0);
00978 DWORD last_error = ::WSAGetLastError();
00979
00980
00981 if (result != 0 && last_error != WSA_IO_PENDING)
00982 {
00983 asio::io_service::work work(this->io_service());
00984 ptr.reset();
00985 asio::error_code ec(last_error, asio::native_ecat);
00986 iocp_service_.post(bind_handler(handler, ec, bytes_transferred));
00987 }
00988 else
00989 {
00990 ptr.release();
00991 }
00992 }
00993
00994
00995 template <typename MutableBufferSequence>
00996 size_t receive(implementation_type& impl,
00997 const MutableBufferSequence& buffers,
00998 socket_base::message_flags flags, asio::error_code& ec)
00999 {
01000 if (!is_open(impl))
01001 {
01002 ec = asio::error::bad_descriptor;
01003 return 0;
01004 }
01005
01006
01007 ::WSABUF bufs[max_buffers];
01008 typename MutableBufferSequence::const_iterator iter = buffers.begin();
01009 typename MutableBufferSequence::const_iterator end = buffers.end();
01010 DWORD i = 0;
01011 size_t total_buffer_size = 0;
01012 for (; iter != end && i < max_buffers; ++iter, ++i)
01013 {
01014 asio::mutable_buffer buffer(*iter);
01015 bufs[i].len = static_cast<u_long>(asio::buffer_size(buffer));
01016 bufs[i].buf = asio::buffer_cast<char*>(buffer);
01017 total_buffer_size += asio::buffer_size(buffer);
01018 }
01019
01020
01021 if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0)
01022 {
01023 ec = asio::error_code();
01024 return 0;
01025 }
01026
01027
01028 DWORD bytes_transferred = 0;
01029 DWORD recv_flags = flags;
01030 int result = ::WSARecv(impl.socket_, bufs, i,
01031 &bytes_transferred, &recv_flags, 0, 0);
01032 if (result != 0)
01033 {
01034 DWORD last_error = ::WSAGetLastError();
01035 if (last_error == ERROR_NETNAME_DELETED)
01036 last_error = WSAECONNRESET;
01037 else if (last_error == ERROR_PORT_UNREACHABLE)
01038 last_error = WSAECONNREFUSED;
01039 ec = asio::error_code(last_error, asio::native_ecat);
01040 return 0;
01041 }
01042 if (bytes_transferred == 0)
01043 {
01044 ec = asio::error::eof;
01045 return 0;
01046 }
01047
01048 ec = asio::error_code();
01049 return bytes_transferred;
01050 }
01051
01052 template <typename MutableBufferSequence, typename Handler>
01053 class receive_operation
01054 : public operation
01055 {
01056 public:
01057 receive_operation(asio::io_service& io_service,
01058 weak_cancel_token_type cancel_token,
01059 const MutableBufferSequence& buffers, Handler handler)
01060 : operation(
01061 &receive_operation<
01062 MutableBufferSequence, Handler>::do_completion_impl,
01063 &receive_operation<
01064 MutableBufferSequence, Handler>::destroy_impl),
01065 work_(io_service),
01066 cancel_token_(cancel_token),
01067 buffers_(buffers),
01068 handler_(handler)
01069 {
01070 }
01071
01072 private:
01073 static void do_completion_impl(operation* op,
01074 DWORD last_error, size_t bytes_transferred)
01075 {
01076
01077 typedef receive_operation<MutableBufferSequence, Handler> op_type;
01078 op_type* handler_op(static_cast<op_type*>(op));
01079 typedef handler_alloc_traits<Handler, op_type> alloc_traits;
01080 handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
01081
01082 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
01083
01084 typename MutableBufferSequence::const_iterator iter
01085 = handler_op->buffers_.begin();
01086 typename MutableBufferSequence::const_iterator end
01087 = handler_op->buffers_.end();
01088 while (iter != end)
01089 {
01090 asio::mutable_buffer buffer(*iter);
01091 asio::buffer_cast<char*>(buffer);
01092 ++iter;
01093 }
01094 #endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
01095
01096
01097 asio::error_code ec(last_error, asio::native_ecat);
01098 if (ec.value() == ERROR_NETNAME_DELETED)
01099 {
01100 if (handler_op->cancel_token_.expired())
01101 ec = asio::error::operation_aborted;
01102 else
01103 ec = asio::error::connection_reset;
01104 }
01105 else if (ec.value() == ERROR_PORT_UNREACHABLE)
01106 {
01107 ec = asio::error::connection_refused;
01108 }
01109
01110
01111 else if (!ec && bytes_transferred == 0)
01112 {
01113 ec = asio::error::eof;
01114 }
01115
01116
01117
01118 Handler handler(handler_op->handler_);
01119
01120
01121 ptr.reset();
01122
01123
01124 asio_handler_invoke_helpers::invoke(
01125 detail::bind_handler(handler, ec, bytes_transferred), &handler);
01126 }
01127
01128 static void destroy_impl(operation* op)
01129 {
01130
01131 typedef receive_operation<MutableBufferSequence, Handler> op_type;
01132 op_type* handler_op(static_cast<op_type*>(op));
01133 typedef handler_alloc_traits<Handler, op_type> alloc_traits;
01134 handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
01135 }
01136
01137 asio::io_service::work work_;
01138 weak_cancel_token_type cancel_token_;
01139 MutableBufferSequence buffers_;
01140 Handler handler_;
01141 };
01142
01143
01144
01145 template <typename MutableBufferSequence, typename Handler>
01146 void async_receive(implementation_type& impl,
01147 const MutableBufferSequence& buffers,
01148 socket_base::message_flags flags, Handler handler)
01149 {
01150 if (!is_open(impl))
01151 {
01152 this->io_service().post(bind_handler(handler,
01153 asio::error::bad_descriptor, 0));
01154 return;
01155 }
01156
01157
01158 if (impl.safe_cancellation_thread_id_ == 0)
01159 impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();
01160 else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())
01161 impl.safe_cancellation_thread_id_ = ~DWORD(0);
01162
01163
01164 typedef receive_operation<MutableBufferSequence, Handler> value_type;
01165 typedef handler_alloc_traits<Handler, value_type> alloc_traits;
01166 raw_handler_ptr<alloc_traits> raw_ptr(handler);
01167 handler_ptr<alloc_traits> ptr(raw_ptr,
01168 this->io_service(), impl.cancel_token_, buffers, handler);
01169
01170
01171 ::WSABUF bufs[max_buffers];
01172 typename MutableBufferSequence::const_iterator iter = buffers.begin();
01173 typename MutableBufferSequence::const_iterator end = buffers.end();
01174 DWORD i = 0;
01175 size_t total_buffer_size = 0;
01176 for (; iter != end && i < max_buffers; ++iter, ++i)
01177 {
01178 asio::mutable_buffer buffer(*iter);
01179 bufs[i].len = static_cast<u_long>(asio::buffer_size(buffer));
01180 bufs[i].buf = asio::buffer_cast<char*>(buffer);
01181 total_buffer_size += asio::buffer_size(buffer);
01182 }
01183
01184
01185 if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0)
01186 {
01187 asio::io_service::work work(this->io_service());
01188 ptr.reset();
01189 asio::error_code error;
01190 iocp_service_.post(bind_handler(handler, error, 0));
01191 return;
01192 }
01193
01194
01195 DWORD bytes_transferred = 0;
01196 DWORD recv_flags = flags;
01197 int result = ::WSARecv(impl.socket_, bufs, i,
01198 &bytes_transferred, &recv_flags, ptr.get(), 0);
01199 DWORD last_error = ::WSAGetLastError();
01200 if (result != 0 && last_error != WSA_IO_PENDING)
01201 {
01202 asio::io_service::work work(this->io_service());
01203 ptr.reset();
01204 asio::error_code ec(last_error, asio::native_ecat);
01205 iocp_service_.post(bind_handler(handler, ec, bytes_transferred));
01206 }
01207 else
01208 {
01209 ptr.release();
01210 }
01211 }
01212
01213
01214
01215 template <typename MutableBufferSequence>
01216 size_t receive_from(implementation_type& impl,
01217 const MutableBufferSequence& buffers,
01218 endpoint_type& sender_endpoint, socket_base::message_flags flags,
01219 asio::error_code& ec)
01220 {
01221 if (!is_open(impl))
01222 {
01223 ec = asio::error::bad_descriptor;
01224 return 0;
01225 }
01226
01227
01228 ::WSABUF bufs[max_buffers];
01229 typename MutableBufferSequence::const_iterator iter = buffers.begin();
01230 typename MutableBufferSequence::const_iterator end = buffers.end();
01231 DWORD i = 0;
01232 for (; iter != end && i < max_buffers; ++iter, ++i)
01233 {
01234 asio::mutable_buffer buffer(*iter);
01235 bufs[i].len = static_cast<u_long>(asio::buffer_size(buffer));
01236 bufs[i].buf = asio::buffer_cast<char*>(buffer);
01237 }
01238
01239
01240 DWORD bytes_transferred = 0;
01241 DWORD recv_flags = flags;
01242 int endpoint_size = sender_endpoint.capacity();
01243 int result = ::WSARecvFrom(impl.socket_, bufs, i, &bytes_transferred,
01244 &recv_flags, sender_endpoint.data(), &endpoint_size, 0, 0);
01245 if (result != 0)
01246 {
01247 DWORD last_error = ::WSAGetLastError();
01248 if (last_error == ERROR_PORT_UNREACHABLE)
01249 last_error = WSAECONNREFUSED;
01250 ec = asio::error_code(last_error, asio::native_ecat);
01251 return 0;
01252 }
01253 if (bytes_transferred == 0)
01254 {
01255 ec = asio::error::eof;
01256 return 0;
01257 }
01258
01259 sender_endpoint.resize(endpoint_size);
01260
01261 ec = asio::error_code();
01262 return bytes_transferred;
01263 }
01264
01265 template <typename MutableBufferSequence, typename Handler>
01266 class receive_from_operation
01267 : public operation
01268 {
01269 public:
01270 receive_from_operation(asio::io_service& io_service,
01271 endpoint_type& endpoint, const MutableBufferSequence& buffers,
01272 Handler handler)
01273 : operation(
01274 &receive_from_operation<
01275 MutableBufferSequence, Handler>::do_completion_impl,
01276 &receive_from_operation<
01277 MutableBufferSequence, Handler>::destroy_impl),
01278 endpoint_(endpoint),
01279 endpoint_size_(endpoint.capacity()),
01280 work_(io_service),
01281 buffers_(buffers),
01282 handler_(handler)
01283 {
01284 }
01285
01286 int& endpoint_size()
01287 {
01288 return endpoint_size_;
01289 }
01290
01291 private:
01292 static void do_completion_impl(operation* op,
01293 DWORD last_error, size_t bytes_transferred)
01294 {
01295
01296 typedef receive_from_operation<MutableBufferSequence, Handler> op_type;
01297 op_type* handler_op(static_cast<op_type*>(op));
01298 typedef handler_alloc_traits<Handler, op_type> alloc_traits;
01299 handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
01300
01301 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
01302
01303 typename MutableBufferSequence::const_iterator iter
01304 = handler_op->buffers_.begin();
01305 typename MutableBufferSequence::const_iterator end
01306 = handler_op->buffers_.end();
01307 while (iter != end)
01308 {
01309 asio::mutable_buffer buffer(*iter);
01310 asio::buffer_cast<char*>(buffer);
01311 ++iter;
01312 }
01313 #endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
01314
01315
01316 asio::error_code ec(last_error, asio::native_ecat);
01317 if (ec.value() == ERROR_PORT_UNREACHABLE)
01318 {
01319 ec = asio::error::connection_refused;
01320 }
01321
01322
01323 if (!ec && bytes_transferred == 0)
01324 {
01325 ec = asio::error::eof;
01326 }
01327
01328
01329 handler_op->endpoint_.resize(handler_op->endpoint_size_);
01330
01331
01332
01333 Handler handler(handler_op->handler_);
01334
01335
01336 ptr.reset();
01337
01338
01339 asio_handler_invoke_helpers::invoke(
01340 detail::bind_handler(handler, ec, bytes_transferred), &handler);
01341 }
01342
01343 static void destroy_impl(operation* op)
01344 {
01345
01346 typedef receive_from_operation<MutableBufferSequence, Handler> op_type;
01347 op_type* handler_op(static_cast<op_type*>(op));
01348 typedef handler_alloc_traits<Handler, op_type> alloc_traits;
01349 handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
01350 }
01351
01352 endpoint_type& endpoint_;
01353 int endpoint_size_;
01354 asio::io_service::work work_;
01355 MutableBufferSequence buffers_;
01356 Handler handler_;
01357 };
01358
01359
01360
01361
01362 template <typename MutableBufferSequence, typename Handler>
01363 void async_receive_from(implementation_type& impl,
01364 const MutableBufferSequence& buffers, endpoint_type& sender_endp,
01365 socket_base::message_flags flags, Handler handler)
01366 {
01367 if (!is_open(impl))
01368 {
01369 this->io_service().post(bind_handler(handler,
01370 asio::error::bad_descriptor, 0));
01371 return;
01372 }
01373
01374
01375 if (impl.safe_cancellation_thread_id_ == 0)
01376 impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();
01377 else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())
01378 impl.safe_cancellation_thread_id_ = ~DWORD(0);
01379
01380
01381 typedef receive_from_operation<MutableBufferSequence, Handler> value_type;
01382 typedef handler_alloc_traits<Handler, value_type> alloc_traits;
01383 raw_handler_ptr<alloc_traits> raw_ptr(handler);
01384 handler_ptr<alloc_traits> ptr(raw_ptr,
01385 this->io_service(), sender_endp, buffers, handler);
01386
01387
01388 ::WSABUF bufs[max_buffers];
01389 typename MutableBufferSequence::const_iterator iter = buffers.begin();
01390 typename MutableBufferSequence::const_iterator end = buffers.end();
01391 DWORD i = 0;
01392 for (; iter != end && i < max_buffers; ++iter, ++i)
01393 {
01394 asio::mutable_buffer buffer(*iter);
01395 bufs[i].len = static_cast<u_long>(asio::buffer_size(buffer));
01396 bufs[i].buf = asio::buffer_cast<char*>(buffer);
01397 }
01398
01399
01400 DWORD bytes_transferred = 0;
01401 DWORD recv_flags = flags;
01402 int result = ::WSARecvFrom(impl.socket_, bufs, i, &bytes_transferred,
01403 &recv_flags, sender_endp.data(), &ptr.get()->endpoint_size(),
01404 ptr.get(), 0);
01405 DWORD last_error = ::WSAGetLastError();
01406 if (result != 0 && last_error != WSA_IO_PENDING)
01407 {
01408 asio::io_service::work work(this->io_service());
01409 ptr.reset();
01410 asio::error_code ec(last_error, asio::native_ecat);
01411 iocp_service_.post(bind_handler(handler, ec, bytes_transferred));
01412 }
01413 else
01414 {
01415 ptr.release();
01416 }
01417 }
01418
01419
01420 template <typename Socket>
01421 asio::error_code accept(implementation_type& impl, Socket& peer,
01422 endpoint_type* peer_endpoint, asio::error_code& ec)
01423 {
01424 if (!is_open(impl))
01425 {
01426 ec = asio::error::bad_descriptor;
01427 return ec;
01428 }
01429
01430
01431 if (peer.is_open())
01432 {
01433 ec = asio::error::already_open;
01434 return ec;
01435 }
01436
01437 for (;;)
01438 {
01439 asio::error_code ec;
01440 socket_holder new_socket;
01441 socket_addr_len_type addr_len = 0;
01442 if (peer_endpoint)
01443 {
01444 addr_len = peer_endpoint->capacity();
01445 new_socket.reset(socket_ops::accept(impl.socket_,
01446 peer_endpoint->data(), &addr_len, ec));
01447 }
01448 else
01449 {
01450 new_socket.reset(socket_ops::accept(impl.socket_, 0, 0, ec));
01451 }
01452
01453 if (ec)
01454 {
01455 if (ec == asio::error::connection_aborted
01456 && !(impl.flags_ & implementation_type::enable_connection_aborted))
01457 {
01458
01459 continue;
01460 }
01461 else
01462 {
01463 return ec;
01464 }
01465 }
01466
01467 if (peer_endpoint)
01468 peer_endpoint->resize(addr_len);
01469
01470 peer.assign(impl.protocol_, new_socket.get(), ec);
01471 if (!ec)
01472 new_socket.release();
01473 return ec;
01474 }
01475 }
01476
01477 template <typename Socket, typename Handler>
01478 class accept_operation
01479 : public operation
01480 {
01481 public:
01482 accept_operation(win_iocp_io_service& io_service,
01483 socket_type socket, socket_type new_socket, Socket& peer,
01484 const protocol_type& protocol, endpoint_type* peer_endpoint,
01485 bool enable_connection_aborted, Handler handler)
01486 : operation(
01487 &accept_operation<Socket, Handler>::do_completion_impl,
01488 &accept_operation<Socket, Handler>::destroy_impl),
01489 io_service_(io_service),
01490 socket_(socket),
01491 new_socket_(new_socket),
01492 peer_(peer),
01493 protocol_(protocol),
01494 peer_endpoint_(peer_endpoint),
01495 work_(io_service.io_service()),
01496 enable_connection_aborted_(enable_connection_aborted),
01497 handler_(handler)
01498 {
01499 }
01500
01501 socket_type new_socket()
01502 {
01503 return new_socket_.get();
01504 }
01505
01506 void* output_buffer()
01507 {
01508 return output_buffer_;
01509 }
01510
01511 DWORD address_length()
01512 {
01513 return sizeof(sockaddr_storage_type) + 16;
01514 }
01515
01516 private:
01517 static void do_completion_impl(operation* op,
01518 DWORD last_error, size_t bytes_transferred)
01519 {
01520
01521 typedef accept_operation<Socket, Handler> op_type;
01522 op_type* handler_op(static_cast<op_type*>(op));
01523 typedef handler_alloc_traits<Handler, op_type> alloc_traits;
01524 handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
01525
01526
01527 if (last_error == ERROR_NETNAME_DELETED)
01528 {
01529 last_error = WSAECONNABORTED;
01530 }
01531
01532
01533
01534 if (last_error == WSAECONNABORTED
01535 && !ptr.get()->enable_connection_aborted_)
01536 {
01537
01538 ptr.get()->Internal = 0;
01539 ptr.get()->InternalHigh = 0;
01540 ptr.get()->Offset = 0;
01541 ptr.get()->OffsetHigh = 0;
01542 ptr.get()->hEvent = 0;
01543
01544
01545
01546 asio::error_code ec;
01547 ptr.get()->new_socket_.reset();
01548 ptr.get()->new_socket_.reset(socket_ops::socket(
01549 ptr.get()->protocol_.family(), ptr.get()->protocol_.type(),
01550 ptr.get()->protocol_.protocol(), ec));
01551 if (ptr.get()->new_socket() != invalid_socket)
01552 {
01553
01554 DWORD bytes_read = 0;
01555 BOOL result = ::AcceptEx(ptr.get()->socket_, ptr.get()->new_socket(),
01556 ptr.get()->output_buffer(), 0, ptr.get()->address_length(),
01557 ptr.get()->address_length(), &bytes_read, ptr.get());
01558 last_error = ::WSAGetLastError();
01559
01560
01561 if (!result && last_error != WSA_IO_PENDING)
01562 {
01563 if (last_error == ERROR_NETNAME_DELETED
01564 || last_error == WSAECONNABORTED)
01565 {
01566
01567 ptr.get()->io_service_.post_completion(ptr.get(), last_error, 0);
01568 ptr.release();
01569 return;
01570 }
01571 else
01572 {
01573
01574 }
01575 }
01576 else
01577 {
01578
01579 ptr.release();
01580 return;
01581 }
01582 }
01583 }
01584
01585
01586 endpoint_type peer_endpoint;
01587 if (last_error == 0)
01588 {
01589 LPSOCKADDR local_addr = 0;
01590 int local_addr_length = 0;
01591 LPSOCKADDR remote_addr = 0;
01592 int remote_addr_length = 0;
01593 GetAcceptExSockaddrs(handler_op->output_buffer(), 0,
01594 handler_op->address_length(), handler_op->address_length(),
01595 &local_addr, &local_addr_length, &remote_addr, &remote_addr_length);
01596 if (remote_addr_length > peer_endpoint.capacity())
01597 {
01598 last_error = WSAEINVAL;
01599 }
01600 else
01601 {
01602 using namespace std;
01603 memcpy(peer_endpoint.data(), remote_addr, remote_addr_length);
01604 peer_endpoint.resize(remote_addr_length);
01605 }
01606 }
01607
01608
01609
01610 if (last_error == 0)
01611 {
01612 SOCKET update_ctx_param = handler_op->socket_;
01613 asio::error_code ec;
01614 if (socket_ops::setsockopt(handler_op->new_socket_.get(),
01615 SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
01616 &update_ctx_param, sizeof(SOCKET), ec) != 0)
01617 {
01618 last_error = ec.value();
01619 }
01620 }
01621
01622
01623
01624 if (last_error == 0)
01625 {
01626 asio::error_code ec;
01627 handler_op->peer_.assign(handler_op->protocol_,
01628 native_type(handler_op->new_socket_.get(), peer_endpoint), ec);
01629 if (ec)
01630 last_error = ec.value();
01631 else
01632 handler_op->new_socket_.release();
01633 }
01634
01635
01636 if (handler_op->peer_endpoint_)
01637 *handler_op->peer_endpoint_ = peer_endpoint;
01638
01639
01640
01641 Handler handler(handler_op->handler_);
01642
01643
01644 ptr.reset();
01645
01646
01647 asio::error_code ec(last_error, asio::native_ecat);
01648 asio_handler_invoke_helpers::invoke(
01649 detail::bind_handler(handler, ec), &handler);
01650 }
01651
01652 static void destroy_impl(operation* op)
01653 {
01654
01655 typedef accept_operation<Socket, Handler> op_type;
01656 op_type* handler_op(static_cast<op_type*>(op));
01657 typedef handler_alloc_traits<Handler, op_type> alloc_traits;
01658 handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
01659 }
01660
01661 win_iocp_io_service& io_service_;
01662 socket_type socket_;
01663 socket_holder new_socket_;
01664 Socket& peer_;
01665 protocol_type protocol_;
01666 endpoint_type* peer_endpoint_;
01667 asio::io_service::work work_;
01668 unsigned char output_buffer_[(sizeof(sockaddr_storage_type) + 16) * 2];
01669 bool enable_connection_aborted_;
01670 Handler handler_;
01671 };
01672
01673
01674
01675 template <typename Socket, typename Handler>
01676 void async_accept(implementation_type& impl, Socket& peer,
01677 endpoint_type* peer_endpoint, Handler handler)
01678 {
01679
01680 if (!is_open(impl))
01681 {
01682 this->io_service().post(bind_handler(handler,
01683 asio::error::bad_descriptor));
01684 return;
01685 }
01686
01687
01688 if (peer.is_open())
01689 {
01690 this->io_service().post(bind_handler(handler,
01691 asio::error::already_open));
01692 return;
01693 }
01694
01695
01696 if (impl.safe_cancellation_thread_id_ == 0)
01697 impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();
01698 else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())
01699 impl.safe_cancellation_thread_id_ = ~DWORD(0);
01700
01701
01702 asio::error_code ec;
01703 socket_holder sock(socket_ops::socket(impl.protocol_.family(),
01704 impl.protocol_.type(), impl.protocol_.protocol(), ec));
01705 if (sock.get() == invalid_socket)
01706 {
01707 this->io_service().post(bind_handler(handler, ec));
01708 return;
01709 }
01710
01711
01712 typedef accept_operation<Socket, Handler> value_type;
01713 typedef handler_alloc_traits<Handler, value_type> alloc_traits;
01714 raw_handler_ptr<alloc_traits> raw_ptr(handler);
01715 socket_type new_socket = sock.get();
01716 bool enable_connection_aborted =
01717 (impl.flags_ & implementation_type::enable_connection_aborted);
01718 handler_ptr<alloc_traits> ptr(raw_ptr,
01719 iocp_service_, impl.socket_, new_socket, peer, impl.protocol_,
01720 peer_endpoint, enable_connection_aborted, handler);
01721 sock.release();
01722
01723
01724 DWORD bytes_read = 0;
01725 BOOL result = ::AcceptEx(impl.socket_, ptr.get()->new_socket(),
01726 ptr.get()->output_buffer(), 0, ptr.get()->address_length(),
01727 ptr.get()->address_length(), &bytes_read, ptr.get());
01728 DWORD last_error = ::WSAGetLastError();
01729
01730
01731 if (!result && last_error != WSA_IO_PENDING)
01732 {
01733 if (!enable_connection_aborted
01734 && (last_error == ERROR_NETNAME_DELETED
01735 || last_error == WSAECONNABORTED))
01736 {
01737
01738
01739
01740 iocp_service_.post_completion(ptr.get(), last_error, 0);
01741 ptr.release();
01742 }
01743 else
01744 {
01745 asio::io_service::work work(this->io_service());
01746 ptr.reset();
01747 asio::error_code ec(last_error, asio::native_ecat);
01748 iocp_service_.post(bind_handler(handler, ec));
01749 }
01750 }
01751 else
01752 {
01753 ptr.release();
01754 }
01755 }
01756
01757
01758 asio::error_code connect(implementation_type& impl,
01759 const endpoint_type& peer_endpoint, asio::error_code& ec)
01760 {
01761 if (!is_open(impl))
01762 {
01763 ec = asio::error::bad_descriptor;
01764 return ec;
01765 }
01766
01767
01768 socket_ops::connect(impl.socket_,
01769 peer_endpoint.data(), peer_endpoint.size(), ec);
01770 return ec;
01771 }
01772
01773 template <typename Handler>
01774 class connect_handler
01775 {
01776 public:
01777 connect_handler(socket_type socket,
01778 boost::shared_ptr<bool> completed,
01779 asio::io_service& io_service,
01780 reactor_type& reactor, Handler handler)
01781 : socket_(socket),
01782 completed_(completed),
01783 io_service_(io_service),
01784 reactor_(reactor),
01785 work_(io_service),
01786 handler_(handler)
01787 {
01788 }
01789
01790 bool operator()(const asio::error_code& result)
01791 {
01792
01793
01794 if (*completed_)
01795 return true;
01796
01797
01798 *completed_ = true;
01799 reactor_.enqueue_cancel_ops_unlocked(socket_);
01800
01801
01802 if (result)
01803 {
01804 io_service_.post(bind_handler(handler_, result));
01805 return true;
01806 }
01807
01808
01809 int connect_error = 0;
01810 size_t connect_error_len = sizeof(connect_error);
01811 asio::error_code ec;
01812 if (socket_ops::getsockopt(socket_, SOL_SOCKET, SO_ERROR,
01813 &connect_error, &connect_error_len, ec) == socket_error_retval)
01814 {
01815 io_service_.post(bind_handler(handler_, ec));
01816 return true;
01817 }
01818
01819
01820 if (connect_error)
01821 {
01822 ec = asio::error_code(
01823 connect_error, asio::native_ecat);
01824 io_service_.post(bind_handler(handler_, ec));
01825 return true;
01826 }
01827
01828
01829 ioctl_arg_type non_blocking = 0;
01830 if (socket_ops::ioctl(socket_, FIONBIO, &non_blocking, ec))
01831 {
01832 io_service_.post(bind_handler(handler_, ec));
01833 return true;
01834 }
01835
01836
01837 ec = asio::error_code();
01838 io_service_.post(bind_handler(handler_, ec));
01839 return true;
01840 }
01841
01842 private:
01843 socket_type socket_;
01844 boost::shared_ptr<bool> completed_;
01845 asio::io_service& io_service_;
01846 reactor_type& reactor_;
01847 asio::io_service::work work_;
01848 Handler handler_;
01849 };
01850
01851
01852 template <typename Handler>
01853 void async_connect(implementation_type& impl,
01854 const endpoint_type& peer_endpoint, Handler handler)
01855 {
01856 if (!is_open(impl))
01857 {
01858 this->io_service().post(bind_handler(handler,
01859 asio::error::bad_descriptor));
01860 return;
01861 }
01862
01863
01864 if (impl.safe_cancellation_thread_id_ == 0)
01865 impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();
01866 else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())
01867 impl.safe_cancellation_thread_id_ = ~DWORD(0);
01868
01869
01870 reactor_type* reactor = static_cast<reactor_type*>(
01871 interlocked_compare_exchange_pointer(
01872 reinterpret_cast<void**>(&reactor_), 0, 0));
01873 if (!reactor)
01874 {
01875 reactor = &(asio::use_service<reactor_type>(this->io_service()));
01876 interlocked_exchange_pointer(
01877 reinterpret_cast<void**>(&reactor_), reactor);
01878 }
01879
01880
01881
01882 ioctl_arg_type non_blocking = 1;
01883 asio::error_code ec;
01884 if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
01885 {
01886 this->io_service().post(bind_handler(handler, ec));
01887 return;
01888 }
01889
01890
01891 if (socket_ops::connect(impl.socket_, peer_endpoint.data(),
01892 peer_endpoint.size(), ec) == 0)
01893 {
01894
01895
01896 this->io_service().post(bind_handler(handler, ec));
01897 }
01898 else if (ec == asio::error::in_progress
01899 || ec == asio::error::would_block)
01900 {
01901
01902
01903 boost::shared_ptr<bool> completed(new bool(false));
01904 reactor->start_write_and_except_ops(impl.socket_,
01905 connect_handler<Handler>(
01906 impl.socket_, completed, this->io_service(), *reactor, handler));
01907 }
01908 else
01909 {
01910
01911 this->io_service().post(bind_handler(handler, ec));
01912 }
01913 }
01914
01915 private:
01916
01917
01918 void* interlocked_compare_exchange_pointer(void** dest, void* exch, void* cmp)
01919 {
01920 #if defined(_WIN32_WINNT) && (_WIN32_WINNT <= 0x400) && (_M_IX86)
01921 return reinterpret_cast<void*>(InterlockedCompareExchange(
01922 reinterpret_cast<LONG*>(dest), reinterpret_cast<LONG>(exch),
01923 reinterpret_cast<LONG>(cmp)));
01924 #else
01925 return InterlockedCompareExchangePointer(dest, exch, cmp);
01926 #endif
01927 }
01928
01929
01930
01931 void* interlocked_exchange_pointer(void** dest, void* val)
01932 {
01933 #if defined(_WIN32_WINNT) && (_WIN32_WINNT <= 0x400) && (_M_IX86)
01934 return reinterpret_cast<void*>(InterlockedExchange(
01935 reinterpret_cast<LONG*>(dest), reinterpret_cast<LONG>(val)));
01936 #else
01937 return InterlockedExchangePointer(dest, val);
01938 #endif
01939 }
01940
01941
01942
01943 win_iocp_io_service& iocp_service_;
01944
01945
01946
01947 reactor_type* reactor_;
01948
01949
01950 asio::detail::mutex mutex_;
01951
01952
01953 implementation_type* impl_list_;
01954 };
01955
01956 }
01957 }
01958
01959 #endif // defined(ASIO_HAS_IOCP)
01960
01961 #include "asio/detail/pop_options.hpp"
01962
01963 #endif // ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_HPP