diff --git a/libtorrent/include/libtorrent/asio/basic_datagram_socket.hpp b/libtorrent/include/libtorrent/asio/basic_datagram_socket.hpp index 1a521628f..64d4d7244 100644 --- a/libtorrent/include/libtorrent/asio/basic_datagram_socket.hpp +++ b/libtorrent/include/libtorrent/asio/basic_datagram_socket.hpp @@ -732,8 +732,8 @@ public: * completes. Copies will be made of the handler as required. The function * signature of the handler must be: * @code void handler( - * const asio::system_error& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes received. + * const asio::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes received. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or * not, the handler will not be invoked from within this function. Invocation diff --git a/libtorrent/include/libtorrent/asio/basic_io_object.hpp b/libtorrent/include/libtorrent/asio/basic_io_object.hpp index 9291ff5da..5b1f94b8e 100644 --- a/libtorrent/include/libtorrent/asio/basic_io_object.hpp +++ b/libtorrent/include/libtorrent/asio/basic_io_object.hpp @@ -34,7 +34,8 @@ public: /// The underlying implementation type of I/O object. typedef typename service_type::implementation_type implementation_type; - /// Get the io_service associated with the object. + /// (Deprecated: use get_io_service().) Get the io_service associated with + /// the object. /** * This function may be used to obtain the io_service object that the I/O * object uses to dispatch handlers for asynchronous operations. @@ -44,7 +45,20 @@ public: */ asio::io_service& io_service() { - return service.io_service(); + return service.get_io_service(); + } + + /// Get the io_service associated with the object. + /** + * This function may be used to obtain the io_service object that the I/O + * object uses to dispatch handlers for asynchronous operations. + * + * @return A reference to the io_service object that the I/O object will use + * to dispatch handlers. Ownership is not transferred to the caller. + */ + asio::io_service& get_io_service() + { + return service.get_io_service(); } protected: diff --git a/libtorrent/include/libtorrent/asio/basic_socket.hpp b/libtorrent/include/libtorrent/asio/basic_socket.hpp index 2b2521b69..fbacf940d 100644 --- a/libtorrent/include/libtorrent/asio/basic_socket.hpp +++ b/libtorrent/include/libtorrent/asio/basic_socket.hpp @@ -564,7 +564,8 @@ public: if (this->service.open(this->implementation, peer_endpoint.protocol(), ec)) { - this->io_service().post(asio::detail::bind_handler(handler, ec)); + this->get_io_service().post( + asio::detail::bind_handler(handler, ec)); return; } } diff --git a/libtorrent/include/libtorrent/asio/buffered_read_stream.hpp b/libtorrent/include/libtorrent/asio/buffered_read_stream.hpp index 5cf5d688e..bd9169b8f 100644 --- a/libtorrent/include/libtorrent/asio/buffered_read_stream.hpp +++ b/libtorrent/include/libtorrent/asio/buffered_read_stream.hpp @@ -93,10 +93,17 @@ public: return next_layer_.lowest_layer(); } - /// Get the io_service associated with the object. + /// (Deprecated: use get_io_service().) Get the io_service associated with + /// the object. asio::io_service& io_service() { - return next_layer_.io_service(); + return next_layer_.get_io_service(); + } + + /// Get the io_service associated with the object. + asio::io_service& get_io_service() + { + return next_layer_.get_io_service(); } /// Close the stream. @@ -207,7 +214,7 @@ public: buffer( storage_.data() + previous_size, storage_.size() - previous_size), - fill_handler(io_service(), + fill_handler(get_io_service(), storage_, previous_size, handler)); } @@ -295,12 +302,12 @@ public: if (storage_.empty()) { async_fill(read_some_handler( - io_service(), storage_, buffers, handler)); + get_io_service(), storage_, buffers, handler)); } else { std::size_t length = copy(buffers); - io_service().post(detail::bind_handler( + get_io_service().post(detail::bind_handler( handler, asio::error_code(), length)); } } diff --git a/libtorrent/include/libtorrent/asio/buffered_stream.hpp b/libtorrent/include/libtorrent/asio/buffered_stream.hpp index b6901a6d4..57959059e 100644 --- a/libtorrent/include/libtorrent/asio/buffered_stream.hpp +++ b/libtorrent/include/libtorrent/asio/buffered_stream.hpp @@ -83,10 +83,17 @@ public: return stream_impl_.lowest_layer(); } - /// Get the io_service associated with the object. + /// (Deprecated: use get_io_service().) Get the io_service associated with + /// the object. asio::io_service& io_service() { - return stream_impl_.io_service(); + return stream_impl_.get_io_service(); + } + + /// Get the io_service associated with the object. + asio::io_service& get_io_service() + { + return stream_impl_.get_io_service(); } /// Close the stream. diff --git a/libtorrent/include/libtorrent/asio/buffered_write_stream.hpp b/libtorrent/include/libtorrent/asio/buffered_write_stream.hpp index ffe3a2ee7..d06787091 100644 --- a/libtorrent/include/libtorrent/asio/buffered_write_stream.hpp +++ b/libtorrent/include/libtorrent/asio/buffered_write_stream.hpp @@ -94,10 +94,17 @@ public: return next_layer_.lowest_layer(); } - /// Get the io_service associated with the object. + /// (Deprecated: use get_io_service().) Get the io_service associated with + /// the object. asio::io_service& io_service() { - return next_layer_.io_service(); + return next_layer_.get_io_service(); + } + + /// Get the io_service associated with the object. + asio::io_service& get_io_service() + { + return next_layer_.get_io_service(); } /// Close the stream. @@ -165,7 +172,7 @@ public: void async_flush(WriteHandler handler) { async_write(next_layer_, buffer(storage_.data(), storage_.size()), - flush_handler(io_service(), storage_, handler)); + flush_handler(get_io_service(), storage_, handler)); } /// Write the given data to the stream. Returns the number of bytes written. @@ -253,12 +260,12 @@ public: if (storage_.size() == storage_.capacity()) { async_flush(write_some_handler( - io_service(), storage_, buffers, handler)); + get_io_service(), storage_, buffers, handler)); } else { std::size_t bytes_copied = copy(buffers); - io_service().post(detail::bind_handler( + get_io_service().post(detail::bind_handler( handler, asio::error_code(), bytes_copied)); } } diff --git a/libtorrent/include/libtorrent/asio/detail/deadline_timer_service.hpp b/libtorrent/include/libtorrent/asio/detail/deadline_timer_service.hpp index c22c5a7b7..06b90b5eb 100644 --- a/libtorrent/include/libtorrent/asio/detail/deadline_timer_service.hpp +++ b/libtorrent/include/libtorrent/asio/detail/deadline_timer_service.hpp @@ -180,7 +180,7 @@ public: { impl.might_have_pending_waits = true; scheduler_.schedule_timer(timer_queue_, impl.expiry, - wait_handler(this->io_service(), handler), &impl); + wait_handler(this->get_io_service(), handler), &impl); } private: diff --git a/libtorrent/include/libtorrent/asio/detail/pipe_select_interrupter.hpp b/libtorrent/include/libtorrent/asio/detail/pipe_select_interrupter.hpp index e203669cb..c85765cc3 100644 --- a/libtorrent/include/libtorrent/asio/detail/pipe_select_interrupter.hpp +++ b/libtorrent/include/libtorrent/asio/detail/pipe_select_interrupter.hpp @@ -19,6 +19,7 @@ #include "asio/detail/push_options.hpp" #include +#include #include "asio/detail/pop_options.hpp" #if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) @@ -27,6 +28,8 @@ #include #include "asio/detail/pop_options.hpp" +#include "asio/error.hpp" +#include "asio/system_error.hpp" #include "asio/detail/socket_types.hpp" namespace asio { @@ -46,6 +49,12 @@ public: write_descriptor_ = pipe_fds[1]; ::fcntl(write_descriptor_, F_SETFL, O_NONBLOCK); } + else + { + asio::error_code ec(errno, asio::error::system_category); + asio::system_error e(ec, "pipe_select_interrupter"); + boost::throw_exception(e); + } } // Destructor. diff --git a/libtorrent/include/libtorrent/asio/detail/posix_fd_set_adapter.hpp b/libtorrent/include/libtorrent/asio/detail/posix_fd_set_adapter.hpp index ae5bf6642..c43904f4d 100644 --- a/libtorrent/include/libtorrent/asio/detail/posix_fd_set_adapter.hpp +++ b/libtorrent/include/libtorrent/asio/detail/posix_fd_set_adapter.hpp @@ -58,7 +58,7 @@ public: } private: - fd_set fd_set_; + mutable fd_set fd_set_; socket_type max_descriptor_; }; diff --git a/libtorrent/include/libtorrent/asio/detail/reactive_socket_service.hpp b/libtorrent/include/libtorrent/asio/detail/reactive_socket_service.hpp index 6b03c6bc5..0d272c578 100644 --- a/libtorrent/include/libtorrent/asio/detail/reactive_socket_service.hpp +++ b/libtorrent/include/libtorrent/asio/detail/reactive_socket_service.hpp @@ -624,7 +624,7 @@ public: { if (!is_open(impl)) { - this->io_service().post(bind_handler(handler, + this->get_io_service().post(bind_handler(handler, asio::error::bad_descriptor, 0)); } else @@ -645,7 +645,7 @@ public: // A request to receive 0 bytes on a stream socket is a no-op. if (total_buffer_size == 0) { - this->io_service().post(bind_handler(handler, + this->get_io_service().post(bind_handler(handler, asio::error_code(), 0)); return; } @@ -658,7 +658,7 @@ public: asio::error_code ec; if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) { - this->io_service().post(bind_handler(handler, ec, 0)); + this->get_io_service().post(bind_handler(handler, ec, 0)); return; } impl.flags_ |= implementation_type::internal_non_blocking; @@ -666,7 +666,7 @@ public: reactor_.start_write_op(impl.socket_, send_handler( - impl.socket_, this->io_service(), buffers, flags, handler)); + impl.socket_, this->get_io_service(), buffers, flags, handler)); } } @@ -804,7 +804,7 @@ public: { if (!is_open(impl)) { - this->io_service().post(bind_handler(handler, + this->get_io_service().post(bind_handler(handler, asio::error::bad_descriptor, 0)); } else @@ -816,7 +816,7 @@ public: asio::error_code ec; if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) { - this->io_service().post(bind_handler(handler, ec, 0)); + this->get_io_service().post(bind_handler(handler, ec, 0)); return; } impl.flags_ |= implementation_type::internal_non_blocking; @@ -824,7 +824,7 @@ public: reactor_.start_write_op(impl.socket_, send_to_handler( - impl.socket_, this->io_service(), buffers, + impl.socket_, this->get_io_service(), buffers, destination, flags, handler)); } } @@ -975,7 +975,7 @@ public: { if (!is_open(impl)) { - this->io_service().post(bind_handler(handler, + this->get_io_service().post(bind_handler(handler, asio::error::bad_descriptor, 0)); } else @@ -996,7 +996,7 @@ public: // A request to receive 0 bytes on a stream socket is a no-op. if (total_buffer_size == 0) { - this->io_service().post(bind_handler(handler, + this->get_io_service().post(bind_handler(handler, asio::error_code(), 0)); return; } @@ -1009,7 +1009,7 @@ public: asio::error_code ec; if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) { - this->io_service().post(bind_handler(handler, ec, 0)); + this->get_io_service().post(bind_handler(handler, ec, 0)); return; } impl.flags_ |= implementation_type::internal_non_blocking; @@ -1019,13 +1019,13 @@ public: { reactor_.start_except_op(impl.socket_, receive_handler( - impl.socket_, this->io_service(), buffers, flags, handler)); + impl.socket_, this->get_io_service(), buffers, flags, handler)); } else { reactor_.start_read_op(impl.socket_, receive_handler( - impl.socket_, this->io_service(), buffers, flags, handler)); + impl.socket_, this->get_io_service(), buffers, flags, handler)); } } } @@ -1181,7 +1181,7 @@ public: { if (!is_open(impl)) { - this->io_service().post(bind_handler(handler, + this->get_io_service().post(bind_handler(handler, asio::error::bad_descriptor, 0)); } else @@ -1193,7 +1193,7 @@ public: asio::error_code ec; if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) { - this->io_service().post(bind_handler(handler, ec, 0)); + this->get_io_service().post(bind_handler(handler, ec, 0)); return; } impl.flags_ |= implementation_type::internal_non_blocking; @@ -1201,7 +1201,7 @@ public: reactor_.start_read_op(impl.socket_, receive_from_handler( - impl.socket_, this->io_service(), buffers, + impl.socket_, this->get_io_service(), buffers, sender_endpoint, flags, handler)); } } @@ -1384,12 +1384,12 @@ public: { if (!is_open(impl)) { - this->io_service().post(bind_handler(handler, + this->get_io_service().post(bind_handler(handler, asio::error::bad_descriptor)); } else if (peer.is_open()) { - this->io_service().post(bind_handler(handler, + this->get_io_service().post(bind_handler(handler, asio::error::already_open)); } else @@ -1401,7 +1401,7 @@ public: asio::error_code ec; if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) { - this->io_service().post(bind_handler(handler, ec)); + this->get_io_service().post(bind_handler(handler, ec)); return; } impl.flags_ |= implementation_type::internal_non_blocking; @@ -1409,7 +1409,7 @@ public: reactor_.start_read_op(impl.socket_, accept_handler( - impl.socket_, this->io_service(), + impl.socket_, this->get_io_service(), peer, impl.protocol_, peer_endpoint, (impl.flags_ & implementation_type::enable_connection_aborted) != 0, handler)); @@ -1515,7 +1515,7 @@ public: { if (!is_open(impl)) { - this->io_service().post(bind_handler(handler, + this->get_io_service().post(bind_handler(handler, asio::error::bad_descriptor)); return; } @@ -1527,7 +1527,7 @@ public: asio::error_code ec; if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) { - this->io_service().post(bind_handler(handler, ec)); + this->get_io_service().post(bind_handler(handler, ec)); return; } impl.flags_ |= implementation_type::internal_non_blocking; @@ -1541,7 +1541,7 @@ public: { // The connect operation has finished successfully so we need to post the // handler immediately. - this->io_service().post(bind_handler(handler, + this->get_io_service().post(bind_handler(handler, asio::error_code())); } else if (ec == asio::error::in_progress @@ -1551,13 +1551,13 @@ public: // until the socket becomes writeable. boost::shared_ptr completed(new bool(false)); reactor_.start_write_and_except_ops(impl.socket_, - connect_handler( - impl.socket_, completed, this->io_service(), reactor_, handler)); + connect_handler(impl.socket_, completed, + this->get_io_service(), reactor_, handler)); } else { // The connect operation has failed, so post the handler immediately. - this->io_service().post(bind_handler(handler, ec)); + this->get_io_service().post(bind_handler(handler, ec)); } } diff --git a/libtorrent/include/libtorrent/asio/detail/resolver_service.hpp b/libtorrent/include/libtorrent/asio/detail/resolver_service.hpp index c820b75f3..dab6340a5 100644 --- a/libtorrent/include/libtorrent/asio/detail/resolver_service.hpp +++ b/libtorrent/include/libtorrent/asio/detail/resolver_service.hpp @@ -213,7 +213,7 @@ public: start_work_thread(); work_io_service_->post( resolve_query_handler( - impl, query, this->io_service(), handler)); + impl, query, this->get_io_service(), handler)); } } @@ -309,7 +309,7 @@ public: start_work_thread(); work_io_service_->post( resolve_endpoint_handler( - impl, endpoint, this->io_service(), handler)); + impl, endpoint, this->get_io_service(), handler)); } } diff --git a/libtorrent/include/libtorrent/asio/detail/socket_ops.hpp b/libtorrent/include/libtorrent/asio/detail/socket_ops.hpp index 105f309b8..92826d89e 100644 --- a/libtorrent/include/libtorrent/asio/detail/socket_ops.hpp +++ b/libtorrent/include/libtorrent/asio/detail/socket_ops.hpp @@ -39,6 +39,13 @@ namespace socket_ops { struct msghdr { int msg_namelen; }; #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) +#if defined(__hpux) +// HP-UX doesn't declare these functions extern "C", so they are declared again +// here to avoid linker errors about undefined symbols. +extern "C" char* if_indextoname(unsigned int, char*); +extern "C" unsigned int if_nametoindex(const char*); +#endif // defined(__hpux) + inline void clear_error(asio::error_code& ec) { errno = 0; @@ -542,10 +549,12 @@ inline int select(int nfds, fd_set* readfds, fd_set* writefds, timeout->tv_usec = 1000; #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) -#if defined(__hpux) && defined(__HP_aCC) && !defined(_XOPEN_SOURCE_EXTENDED) - return error_wrapper(::select(nfds, - reinterpret_cast(readfds), reinterpret_cast(writefds), - reinterpret_cast(exceptfds), timeout), ec); +#if defined(__hpux) && defined(__HP_aCC) + timespec ts; + ts.tv_sec = timeout ? timeout->tv_sec : 0; + ts.tv_nsec = timeout ? timeout->tv_usec * 1000 : 0; + return error_wrapper(::pselect(nfds, readfds, + writefds, exceptfds, timeout ? &ts : 0, 0), ec); #else return error_wrapper(::select(nfds, readfds, writefds, exceptfds, timeout), ec); diff --git a/libtorrent/include/libtorrent/asio/detail/socket_types.hpp b/libtorrent/include/libtorrent/asio/detail/socket_types.hpp index 4e1c68792..f16bba747 100644 --- a/libtorrent/include/libtorrent/asio/detail/socket_types.hpp +++ b/libtorrent/include/libtorrent/asio/detail/socket_types.hpp @@ -29,12 +29,12 @@ # if !defined(_WIN32_WINNT) && !defined(_WIN32_WINDOWS) # if defined(_MSC_VER) || defined(__BORLANDC__) # pragma message("Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately") -# pragma message("Assuming _WIN32_WINNT=0x0500 (i.e. Windows 2000 target)") +# pragma message("Assuming _WIN32_WINNT=0x0501 (i.e. Windows XP target)") # else // defined(_MSC_VER) || defined(__BORLANDC__) # warning Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately -# warning Assuming _WIN32_WINNT=0x0500 (i.e. Windows 2000 target) +# warning Assuming _WIN32_WINNT=0x0501 (i.e. Windows XP target) # endif // defined(_MSC_VER) || defined(__BORLANDC__) -# define _WIN32_WINNT 0x0500 +# define _WIN32_WINNT 0x0501 # endif // !defined(_WIN32_WINNT) && !defined(_WIN32_WINDOWS) # if defined(_MSC_VER) # if defined(_WIN32) && !defined(WIN32) diff --git a/libtorrent/include/libtorrent/asio/detail/strand_service.hpp b/libtorrent/include/libtorrent/asio/detail/strand_service.hpp index 8e3c183d0..598b79dcc 100644 --- a/libtorrent/include/libtorrent/asio/detail/strand_service.hpp +++ b/libtorrent/include/libtorrent/asio/detail/strand_service.hpp @@ -276,7 +276,7 @@ public: if (impl_->first_waiter_ == 0) impl_->last_waiter_ = 0; lock.unlock(); - service_impl_.io_service().post( + service_impl_.get_io_service().post( invoke_current_handler(service_impl_, impl_)); } } @@ -429,7 +429,7 @@ public: // This handler now has the lock, so can be dispatched immediately. impl->current_handler_ = ptr.get(); lock.unlock(); - this->io_service().dispatch(invoke_current_handler(*this, impl)); + this->get_io_service().dispatch(invoke_current_handler(*this, impl)); ptr.release(); } else @@ -469,7 +469,7 @@ public: // This handler now has the lock, so can be dispatched immediately. impl->current_handler_ = ptr.get(); lock.unlock(); - this->io_service().post(invoke_current_handler(*this, impl)); + this->get_io_service().post(invoke_current_handler(*this, impl)); ptr.release(); } else diff --git a/libtorrent/include/libtorrent/asio/detail/task_io_service.hpp b/libtorrent/include/libtorrent/asio/detail/task_io_service.hpp index 33934cf88..ffadb620b 100644 --- a/libtorrent/include/libtorrent/asio/detail/task_io_service.hpp +++ b/libtorrent/include/libtorrent/asio/detail/task_io_service.hpp @@ -225,16 +225,18 @@ private: { bool more_handlers = (!handler_queue_.empty()); task_interrupted_ = more_handlers || polling; - lock.unlock(); // If the task has already run and we're polling then we're done. if (task_has_run && polling) { + task_interrupted_ = true; + handler_queue_.push(&task_handler_); ec = asio::error_code(); return 0; } task_has_run = true; - + + lock.unlock(); task_cleanup c(lock, *this); // Run the task. May throw an exception. Only block if the handler @@ -316,6 +318,8 @@ private: } // Helper class to perform task-related operations on block exit. + class task_cleanup; + friend class task_cleanup; class task_cleanup { public: diff --git a/libtorrent/include/libtorrent/asio/detail/win_iocp_socket_service.hpp b/libtorrent/include/libtorrent/asio/detail/win_iocp_socket_service.hpp index ece098f7b..2b6ee80e8 100644 --- a/libtorrent/include/libtorrent/asio/detail/win_iocp_socket_service.hpp +++ b/libtorrent/include/libtorrent/asio/detail/win_iocp_socket_service.hpp @@ -327,7 +327,7 @@ public: ec = asio::error::bad_descriptor; } else if (FARPROC cancel_io_ex_ptr = ::GetProcAddress( - ::GetModuleHandle("KERNEL32"), "CancelIoEx")) + ::GetModuleHandleA("KERNEL32"), "CancelIoEx")) { // The version of Windows supports cancellation from any thread. typedef BOOL (WINAPI* cancel_io_ex_t)(HANDLE, LPOVERLAPPED); @@ -767,7 +767,7 @@ public: { if (!is_open(impl)) { - this->io_service().post(bind_handler(handler, + this->get_io_service().post(bind_handler(handler, asio::error::bad_descriptor, 0)); return; } @@ -783,7 +783,7 @@ public: typedef handler_alloc_traits alloc_traits; raw_handler_ptr raw_ptr(handler); handler_ptr ptr(raw_ptr, - this->io_service(), impl.cancel_token_, buffers, handler); + this->get_io_service(), impl.cancel_token_, buffers, handler); // Copy buffers into WSABUF array. ::WSABUF bufs[max_buffers]; @@ -803,7 +803,7 @@ public: // A request to receive 0 bytes on a stream socket is a no-op. if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0) { - asio::io_service::work work(this->io_service()); + asio::io_service::work work(this->get_io_service()); ptr.reset(); asio::error_code error; iocp_service_.post(bind_handler(handler, error, 0)); @@ -819,7 +819,7 @@ public: // Check if the operation completed immediately. if (result != 0 && last_error != WSA_IO_PENDING) { - asio::io_service::work work(this->io_service()); + asio::io_service::work work(this->get_io_service()); ptr.reset(); asio::error_code ec(last_error, asio::error::system_category); @@ -958,7 +958,7 @@ public: { if (!is_open(impl)) { - this->io_service().post(bind_handler(handler, + this->get_io_service().post(bind_handler(handler, asio::error::bad_descriptor, 0)); return; } @@ -974,7 +974,7 @@ public: typedef handler_alloc_traits alloc_traits; raw_handler_ptr raw_ptr(handler); handler_ptr ptr(raw_ptr, - this->io_service(), buffers, handler); + this->get_io_service(), buffers, handler); // Copy buffers into WSABUF array. ::WSABUF bufs[max_buffers]; @@ -998,7 +998,7 @@ public: // Check if the operation completed immediately. if (result != 0 && last_error != WSA_IO_PENDING) { - asio::io_service::work work(this->io_service()); + asio::io_service::work work(this->get_io_service()); ptr.reset(); asio::error_code ec(last_error, asio::error::system_category); @@ -1170,7 +1170,7 @@ public: { if (!is_open(impl)) { - this->io_service().post(bind_handler(handler, + this->get_io_service().post(bind_handler(handler, asio::error::bad_descriptor, 0)); return; } @@ -1186,7 +1186,7 @@ public: typedef handler_alloc_traits alloc_traits; raw_handler_ptr raw_ptr(handler); handler_ptr ptr(raw_ptr, - this->io_service(), impl.cancel_token_, buffers, handler); + this->get_io_service(), impl.cancel_token_, buffers, handler); // Copy buffers into WSABUF array. ::WSABUF bufs[max_buffers]; @@ -1205,7 +1205,7 @@ public: // A request to receive 0 bytes on a stream socket is a no-op. if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0) { - asio::io_service::work work(this->io_service()); + asio::io_service::work work(this->get_io_service()); ptr.reset(); asio::error_code error; iocp_service_.post(bind_handler(handler, error, 0)); @@ -1220,7 +1220,7 @@ public: DWORD last_error = ::WSAGetLastError(); if (result != 0 && last_error != WSA_IO_PENDING) { - asio::io_service::work work(this->io_service()); + asio::io_service::work work(this->get_io_service()); ptr.reset(); asio::error_code ec(last_error, asio::error::system_category); @@ -1390,7 +1390,7 @@ public: { if (!is_open(impl)) { - this->io_service().post(bind_handler(handler, + this->get_io_service().post(bind_handler(handler, asio::error::bad_descriptor, 0)); return; } @@ -1406,7 +1406,7 @@ public: typedef handler_alloc_traits alloc_traits; raw_handler_ptr raw_ptr(handler); handler_ptr ptr(raw_ptr, - this->io_service(), sender_endp, buffers, handler); + this->get_io_service(), sender_endp, buffers, handler); // Copy buffers into WSABUF array. ::WSABUF bufs[max_buffers]; @@ -1429,7 +1429,7 @@ public: DWORD last_error = ::WSAGetLastError(); if (result != 0 && last_error != WSA_IO_PENDING) { - asio::io_service::work work(this->io_service()); + asio::io_service::work work(this->get_io_service()); ptr.reset(); asio::error_code ec(last_error, asio::error::system_category); @@ -1517,7 +1517,7 @@ public: peer_(peer), protocol_(protocol), peer_endpoint_(peer_endpoint), - work_(io_service.io_service()), + work_(io_service.get_io_service()), enable_connection_aborted_(enable_connection_aborted), handler_(handler) { @@ -1706,7 +1706,7 @@ public: // Check whether acceptor has been initialised. if (!is_open(impl)) { - this->io_service().post(bind_handler(handler, + this->get_io_service().post(bind_handler(handler, asio::error::bad_descriptor)); return; } @@ -1714,7 +1714,7 @@ public: // Check that peer socket has not already been opened. if (peer.is_open()) { - this->io_service().post(bind_handler(handler, + this->get_io_service().post(bind_handler(handler, asio::error::already_open)); return; } @@ -1731,7 +1731,7 @@ public: impl.protocol_.type(), impl.protocol_.protocol(), ec)); if (sock.get() == invalid_socket) { - this->io_service().post(bind_handler(handler, ec)); + this->get_io_service().post(bind_handler(handler, ec)); return; } @@ -1769,7 +1769,7 @@ public: } else { - asio::io_service::work work(this->io_service()); + asio::io_service::work work(this->get_io_service()); ptr.reset(); asio::error_code ec(last_error, asio::error::system_category); @@ -1888,7 +1888,7 @@ public: { if (!is_open(impl)) { - this->io_service().post(bind_handler(handler, + this->get_io_service().post(bind_handler(handler, asio::error::bad_descriptor)); return; } @@ -1905,7 +1905,8 @@ public: reinterpret_cast(&reactor_), 0, 0)); if (!reactor) { - reactor = &(asio::use_service(this->io_service())); + reactor = &(asio::use_service( + this->get_io_service())); interlocked_exchange_pointer( reinterpret_cast(&reactor_), reactor); } @@ -1916,7 +1917,7 @@ public: asio::error_code ec; if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) { - this->io_service().post(bind_handler(handler, ec)); + this->get_io_service().post(bind_handler(handler, ec)); return; } @@ -1933,7 +1934,7 @@ public: // The connect operation has finished successfully so we need to post the // handler immediately. - this->io_service().post(bind_handler(handler, ec)); + this->get_io_service().post(bind_handler(handler, ec)); } else if (ec == asio::error::in_progress || ec == asio::error::would_block) @@ -1945,7 +1946,7 @@ public: connect_handler( impl.socket_, (impl.flags_ & implementation_type::user_set_non_blocking) != 0, - completed, this->io_service(), *reactor, handler)); + completed, this->get_io_service(), *reactor, handler)); } else { @@ -1958,7 +1959,7 @@ public: } // The connect operation has failed, so post the handler immediately. - this->io_service().post(bind_handler(handler, ec)); + this->get_io_service().post(bind_handler(handler, ec)); } } diff --git a/libtorrent/include/libtorrent/asio/error.hpp b/libtorrent/include/libtorrent/asio/error.hpp index a8316be2c..9cc7818e8 100644 --- a/libtorrent/include/libtorrent/asio/error.hpp +++ b/libtorrent/include/libtorrent/asio/error.hpp @@ -61,7 +61,7 @@ enum basic_errors /// Address family not supported by protocol. address_family_not_supported = ASIO_SOCKET_ERROR(EAFNOSUPPORT), - /// Address already in use. + /// Port already in use. address_in_use = ASIO_SOCKET_ERROR(EADDRINUSE), /// Transport endpoint is already connected. @@ -82,7 +82,7 @@ enum basic_errors /// Bad file descriptor. bad_descriptor = ASIO_SOCKET_ERROR(EBADF), - /// Bad address. + /// Bad port. fault = ASIO_SOCKET_ERROR(EFAULT), /// No route to host. @@ -197,6 +197,10 @@ enum misc_errors not_found }; +enum ssl_errors +{ +}; + // boostify: error category definitions go here. inline asio::error_code make_error_code(basic_errors e) @@ -219,6 +223,11 @@ inline asio::error_code make_error_code(misc_errors e) return asio::error_code(static_cast(e), misc_category); } +inline asio::error_code make_error_code(ssl_errors e) +{ + return asio::error_code(static_cast(e), ssl_category); +} + } // namespace error } // namespace asio diff --git a/libtorrent/include/libtorrent/asio/impl/error_code.ipp b/libtorrent/include/libtorrent/asio/impl/error_code.ipp index f66b6fd94..aaef231eb 100644 --- a/libtorrent/include/libtorrent/asio/impl/error_code.ipp +++ b/libtorrent/include/libtorrent/asio/impl/error_code.ipp @@ -84,7 +84,7 @@ inline std::string error_code::message() const return strerror(value_); #elif defined(__MACH__) && defined(__APPLE__) \ || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) \ -|| defined(_AIX) +|| defined(_AIX) || defined(__hpux) || defined(__osf__) char buf[256] = ""; strerror_r(value_, buf, sizeof(buf)); return buf; diff --git a/libtorrent/include/libtorrent/asio/impl/io_service.ipp b/libtorrent/include/libtorrent/asio/impl/io_service.ipp index db79e9c05..8ebc2643c 100644 --- a/libtorrent/include/libtorrent/asio/impl/io_service.ipp +++ b/libtorrent/include/libtorrent/asio/impl/io_service.ipp @@ -158,6 +158,11 @@ inline asio::io_service& io_service::work::io_service() return io_service_; } +inline asio::io_service& io_service::work::get_io_service() +{ + return io_service_; +} + inline io_service::service::service(asio::io_service& owner) : owner_(owner), type_info_(0), @@ -174,6 +179,11 @@ inline asio::io_service& io_service::service::io_service() return owner_; } +inline asio::io_service& io_service::service::get_io_service() +{ + return owner_; +} + template inline Service& use_service(io_service& ios) { diff --git a/libtorrent/include/libtorrent/asio/impl/read.ipp b/libtorrent/include/libtorrent/asio/impl/read.ipp index f30f50fb0..53a92b734 100644 --- a/libtorrent/include/libtorrent/asio/impl/read.ipp +++ b/libtorrent/include/libtorrent/asio/impl/read.ipp @@ -19,6 +19,7 @@ #include "asio/detail/push_options.hpp" #include +#include #include "asio/detail/pop_options.hpp" #include "asio/buffer.hpp" @@ -138,23 +139,25 @@ namespace detail std::size_t bytes_transferred) { total_transferred_ += bytes_transferred; - buffers_.consume(bytes_transferred); - if (completion_condition_(ec, total_transferred_) - || buffers_.begin() == buffers_.end()) + buffers_->consume(bytes_transferred); + if ((*completion_condition_)(ec, total_transferred_) + || buffers_->begin() == buffers_->end()) { + buffers_.reset(); + completion_condition_.reset(); handler_(ec, total_transferred_); } else { - stream_.async_read_some(buffers_, *this); + stream_.async_read_some(*buffers_, *this); } } //private: AsyncReadStream& stream_; - buffers_type buffers_; + boost::optional buffers_; std::size_t total_transferred_; - CompletionCondition completion_condition_; + boost::optional completion_condition_; ReadHandler handler_; }; @@ -235,8 +238,9 @@ namespace detail total_transferred_ += bytes_transferred; streambuf_.commit(bytes_transferred); if (streambuf_.size() == streambuf_.max_size() - || completion_condition_(ec, total_transferred_)) + || (*completion_condition_)(ec, total_transferred_)) { + completion_condition_.reset(); handler_(ec, total_transferred_); } else @@ -251,7 +255,7 @@ namespace detail AsyncReadStream& stream_; asio::basic_streambuf& streambuf_; std::size_t total_transferred_; - CompletionCondition completion_condition_; + boost::optional completion_condition_; ReadHandler handler_; }; diff --git a/libtorrent/include/libtorrent/asio/impl/write.ipp b/libtorrent/include/libtorrent/asio/impl/write.ipp index 8c2d1d33f..c8d221e12 100644 --- a/libtorrent/include/libtorrent/asio/impl/write.ipp +++ b/libtorrent/include/libtorrent/asio/impl/write.ipp @@ -17,6 +17,10 @@ #include "asio/detail/push_options.hpp" +#include "asio/detail/push_options.hpp" +#include +#include "asio/detail/pop_options.hpp" + #include "asio/buffer.hpp" #include "asio/completion_condition.hpp" #include "asio/detail/bind_handler.hpp" @@ -124,23 +128,25 @@ namespace detail std::size_t bytes_transferred) { total_transferred_ += bytes_transferred; - buffers_.consume(bytes_transferred); - if (completion_condition_(ec, total_transferred_) - || buffers_.begin() == buffers_.end()) + buffers_->consume(bytes_transferred); + if ((*completion_condition_)(ec, total_transferred_) + || buffers_->begin() == buffers_->end()) { + buffers_.reset(); + completion_condition_.reset(); handler_(ec, total_transferred_); } else { - stream_.async_write_some(buffers_, *this); + stream_.async_write_some(*buffers_, *this); } } //private: AsyncWriteStream& stream_; - buffers_type buffers_; + boost::optional buffers_; std::size_t total_transferred_; - CompletionCondition completion_condition_; + boost::optional completion_condition_; WriteHandler handler_; }; diff --git a/libtorrent/include/libtorrent/asio/io_service.hpp b/libtorrent/include/libtorrent/asio/io_service.hpp index 76cac4e0b..984a63e18 100644 --- a/libtorrent/include/libtorrent/asio/io_service.hpp +++ b/libtorrent/include/libtorrent/asio/io_service.hpp @@ -381,7 +381,8 @@ public: private: #if defined(BOOST_WINDOWS) || defined(__CYGWIN__) detail::winsock_init<> init_; -#elif defined(__sun) || defined(__QNX__) || defined(__hpux) || defined(_AIX) +#elif defined(__sun) || defined(__QNX__) || defined(__hpux) || defined(_AIX) \ + || defined(__osf__) detail::signal_init<> init_; #endif @@ -429,9 +430,13 @@ public: */ ~work(); - /// Get the io_service associated with the work. + /// (Deprecated: use get_io_service().) Get the io_service associated with the + /// work. asio::io_service& io_service(); + /// Get the io_service associated with the work. + asio::io_service& get_io_service(); + private: // Prevent assignment. void operator=(const work& other); @@ -454,9 +459,13 @@ class io_service::service : private noncopyable { public: - /// Get the io_service object that owns the service. + /// (Deprecated: use get_io_service().) Get the io_service object that owns + /// the service. asio::io_service& io_service(); + /// Get the io_service object that owns the service. + asio::io_service& get_io_service(); + protected: /// Constructor. /** diff --git a/libtorrent/include/libtorrent/asio/ip/address_v6.hpp b/libtorrent/include/libtorrent/asio/ip/address_v6.hpp index 87bb6d459..ce5eeb00b 100644 --- a/libtorrent/include/libtorrent/asio/ip/address_v6.hpp +++ b/libtorrent/include/libtorrent/asio/ip/address_v6.hpp @@ -300,7 +300,7 @@ public: { using namespace std; // For memcmp. int memcmp_result = memcmp(&a1.addr_, &a2.addr_, - sizeof(asio::detail::in6_addr_type)) < 0; + sizeof(asio::detail::in6_addr_type)); if (memcmp_result < 0) return true; if (memcmp_result > 0) diff --git a/libtorrent/include/libtorrent/asio/ip/detail/socket_option.hpp b/libtorrent/include/libtorrent/asio/ip/detail/socket_option.hpp index a46ad2bce..f564ba2c5 100644 --- a/libtorrent/include/libtorrent/asio/ip/detail/socket_option.hpp +++ b/libtorrent/include/libtorrent/asio/ip/detail/socket_option.hpp @@ -32,52 +32,60 @@ namespace ip { namespace detail { namespace socket_option { -// Helper template for implementing boolean-based options. +// Helper template for implementing multicast enable loopback options. template -class boolean +class multicast_enable_loopback { public: -#if defined(__sun) || defined(_AIX) || defined(__osf__) - typedef unsigned char value_type; +#if defined(__sun) || defined(__osf__) + typedef unsigned char ipv4_value_type; + typedef unsigned char ipv6_value_type; +#elif defined(_AIX) || defined(__hpux) + typedef unsigned char ipv4_value_type; + typedef unsigned int ipv6_value_type; #else - typedef int value_type; + typedef int ipv4_value_type; + typedef int ipv6_value_type; #endif // Default constructor. - boolean() - : value_(0) + multicast_enable_loopback() + : ipv4_value_(0), + ipv6_value_(0) { } // Construct with a specific option value. - explicit boolean(bool v) - : value_(v ? 1 : 0) + explicit multicast_enable_loopback(bool v) + : ipv4_value_(v ? 1 : 0), + ipv6_value_(v ? 1 : 0) { } // Set the value of the boolean. - boolean& operator=(bool v) + multicast_enable_loopback& operator=(bool v) { - value_ = v ? 1 : 0; + ipv4_value_ = v ? 1 : 0; + ipv6_value_ = v ? 1 : 0; return *this; } // Get the current value of the boolean. bool value() const { - return !!value_; + return !!ipv4_value_; } // Convert to bool. operator bool() const { - return !!value_; + return !!ipv4_value_; } // Test for false. bool operator!() const { - return !value_; + return !ipv4_value_; } // Get the level of the socket option. @@ -100,35 +108,58 @@ public: // Get the address of the boolean data. template - value_type* data(const Protocol&) + void* data(const Protocol& protocol) { - return &value_; + if (protocol.family() == PF_INET6) + return &ipv6_value_; + return &ipv4_value_; } // Get the address of the boolean data. template - const value_type* data(const Protocol&) const + const void* data(const Protocol& protocol) const { - return &value_; + if (protocol.family() == PF_INET6) + return &ipv6_value_; + return &ipv4_value_; } // Get the size of the boolean data. template - std::size_t size(const Protocol&) const + std::size_t size(const Protocol& protocol) const { - return sizeof(value_); + if (protocol.family() == PF_INET6) + return sizeof(ipv6_value_); + return sizeof(ipv4_value_); } // Set the size of the boolean data. template - void resize(const Protocol&, std::size_t s) + void resize(const Protocol& protocol, std::size_t s) { - if (s != sizeof(value_)) - throw std::length_error("boolean socket option resize"); + if (protocol.family() == PF_INET6) + { + if (s != sizeof(ipv6_value_)) + { + throw std::length_error( + "multicast_enable_loopback socket option resize"); + } + ipv4_value_ = ipv6_value_ ? 1 : 0; + } + else + { + if (s != sizeof(ipv4_value_)) + { + throw std::length_error( + "multicast_enable_loopback socket option resize"); + } + ipv6_value_ = ipv4_value_ ? 1 : 0; + } } private: - value_type value_; + ipv4_value_type ipv4_value_; + ipv6_value_type ipv6_value_; }; // Helper template for implementing unicast hops options. @@ -206,6 +237,10 @@ public: { if (s != sizeof(value_)) throw std::length_error("unicast hops socket option resize"); +#if defined(__hpux) + if (value_ < 0) + value_ = value_ & 0xFF; +#endif } private: @@ -477,7 +512,7 @@ public: } // Construct with IPv6 interface. - explicit network_interface(unsigned long ipv6_interface) + explicit network_interface(unsigned int ipv6_interface) { ipv4_value_.s_addr = asio::detail::socket_ops::host_to_network_long( @@ -523,7 +558,7 @@ public: private: asio::detail::in4_addr_type ipv4_value_; - unsigned long ipv6_value_; + unsigned int ipv6_value_; }; } // namespace socket_option diff --git a/libtorrent/include/libtorrent/asio/ip/multicast.hpp b/libtorrent/include/libtorrent/asio/ip/multicast.hpp index 0d90659ca..8b48687f1 100644 --- a/libtorrent/include/libtorrent/asio/ip/multicast.hpp +++ b/libtorrent/include/libtorrent/asio/ip/multicast.hpp @@ -167,7 +167,7 @@ typedef asio::ip::detail::socket_option::multicast_hops< #if defined(GENERATING_DOCUMENTATION) typedef implementation_defined enable_loopback; #else -typedef asio::ip::detail::socket_option::boolean< +typedef asio::ip::detail::socket_option::multicast_enable_loopback< IPPROTO_IP, IP_MULTICAST_LOOP, IPPROTO_IPV6, IPV6_MULTICAST_LOOP> enable_loopback; #endif diff --git a/libtorrent/include/libtorrent/asio/placeholders.hpp b/libtorrent/include/libtorrent/asio/placeholders.hpp index 0c1b6b4a6..9309fc0b4 100644 --- a/libtorrent/include/libtorrent/asio/placeholders.hpp +++ b/libtorrent/include/libtorrent/asio/placeholders.hpp @@ -27,17 +27,17 @@ namespace placeholders { #if defined(GENERATING_DOCUMENTATION) -/// An argument placeholder, for use with @ref boost_bind, that corresponds to +/// An argument placeholder, for use with boost::bind(), that corresponds to /// the error argument of a handler for any of the asynchronous functions. unspecified error; -/// An argument placeholder, for use with @ref boost_bind, that corresponds to +/// An argument placeholder, for use with boost::bind(), that corresponds to /// the bytes_transferred argument of a handler for asynchronous functions such /// as asio::basic_stream_socket::async_write_some or /// asio::async_write. unspecified bytes_transferred; -/// An argument placeholder, for use with @ref boost_bind, that corresponds to +/// An argument placeholder, for use with boost::bind(), that corresponds to /// the iterator argument of a handler for asynchronous functions such as /// asio::basic_resolver::resolve. unspecified iterator; diff --git a/libtorrent/include/libtorrent/asio/ssl/detail/openssl_stream_service.hpp b/libtorrent/include/libtorrent/asio/ssl/detail/openssl_stream_service.hpp index d90b588ef..3812deb80 100644 --- a/libtorrent/include/libtorrent/asio/ssl/detail/openssl_stream_service.hpp +++ b/libtorrent/include/libtorrent/asio/ssl/detail/openssl_stream_service.hpp @@ -238,7 +238,7 @@ public: typedef handshake_handler connect_handler; connect_handler* local_handler = - new connect_handler(handler, io_service()); + new connect_handler(handler, get_io_service()); openssl_operation* op = new openssl_operation ( @@ -259,7 +259,7 @@ public: ); local_handler->set_operation(op); - io_service().post(boost::bind(&openssl_operation::start, op)); + get_io_service().post(boost::bind(&openssl_operation::start, op)); } // Shut down SSL on the stream. @@ -294,7 +294,7 @@ public: typedef shutdown_handler disconnect_handler; disconnect_handler* local_handler = - new disconnect_handler(handler, io_service()); + new disconnect_handler(handler, get_io_service()); openssl_operation* op = new openssl_operation ( @@ -313,7 +313,7 @@ public: ); local_handler->set_operation(op); - io_service().post(boost::bind(&openssl_operation::start, op)); + get_io_service().post(boost::bind(&openssl_operation::start, op)); } // Write some data to the stream. @@ -354,7 +354,7 @@ public: { typedef io_handler send_handler; - send_handler* local_handler = new send_handler(handler, io_service()); + send_handler* local_handler = new send_handler(handler, get_io_service()); boost::function send_func = boost::bind(&::SSL_write, boost::arg<1>(), @@ -378,7 +378,7 @@ public: ); local_handler->set_operation(op); - io_service().post(boost::bind(&openssl_operation::start, op)); + get_io_service().post(boost::bind(&openssl_operation::start, op)); } // Read some data from the stream. @@ -419,7 +419,7 @@ public: { typedef io_handler recv_handler; - recv_handler* local_handler = new recv_handler(handler, io_service()); + recv_handler* local_handler = new recv_handler(handler, get_io_service()); boost::function recv_func = boost::bind(&::SSL_read, boost::arg<1>(), @@ -443,7 +443,7 @@ public: ); local_handler->set_operation(op); - io_service().post(boost::bind(&openssl_operation::start, op)); + get_io_service().post(boost::bind(&openssl_operation::start, op)); } // Peek at the incoming data on the stream. diff --git a/libtorrent/include/libtorrent/asio/ssl/stream.hpp b/libtorrent/include/libtorrent/asio/ssl/stream.hpp index a6af16101..9ee48fef1 100644 --- a/libtorrent/include/libtorrent/asio/ssl/stream.hpp +++ b/libtorrent/include/libtorrent/asio/ssl/stream.hpp @@ -85,7 +85,7 @@ public: template explicit stream(Arg& arg, basic_context& context) : next_layer_(arg), - service_(asio::use_service(next_layer_.io_service())), + service_(asio::use_service(next_layer_.get_io_service())), impl_(service_.null()) { service_.create(impl_, next_layer_, context); @@ -97,7 +97,8 @@ public: service_.destroy(impl_, next_layer_); } - /// Get the io_service associated with the object. + /// (Deprecated: use get_io_service().) Get the io_service associated with + /// the object. /** * This function may be used to obtain the io_service object that the stream * uses to dispatch handlers for asynchronous operations. @@ -107,7 +108,20 @@ public: */ asio::io_service& io_service() { - return next_layer_.io_service(); + return next_layer_.get_io_service(); + } + + /// Get the io_service associated with the object. + /** + * This function may be used to obtain the io_service object that the stream + * uses to dispatch handlers for asynchronous operations. + * + * @return A reference to the io_service object that stream will use to + * dispatch handlers. Ownership is not transferred to the caller. + */ + asio::io_service& get_io_service() + { + return next_layer_.get_io_service(); } /// Get a reference to the next layer. diff --git a/libtorrent/include/libtorrent/asio/strand.hpp b/libtorrent/include/libtorrent/asio/strand.hpp index d0869d95d..ff76415a2 100644 --- a/libtorrent/include/libtorrent/asio/strand.hpp +++ b/libtorrent/include/libtorrent/asio/strand.hpp @@ -65,7 +65,8 @@ public: service_.destroy(impl_); } - /// Get the io_service associated with the strand. + /// (Deprecated: use get_io_service().) Get the io_service associated with + /// the strand. /** * This function may be used to obtain the io_service object that the strand * uses to dispatch handlers for asynchronous operations. @@ -75,7 +76,20 @@ public: */ asio::io_service& io_service() { - return service_.io_service(); + return service_.get_io_service(); + } + + /// Get the io_service associated with the strand. + /** + * This function may be used to obtain the io_service object that the strand + * uses to dispatch handlers for asynchronous operations. + * + * @return A reference to the io_service object that the strand will use to + * dispatch handlers. Ownership is not transferred to the caller. + */ + asio::io_service& get_io_service() + { + return service_.get_io_service(); } /// Request the strand to invoke the given handler.