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 c43904f4d..28e717bb1 100644 --- a/libtorrent/include/libtorrent/asio/detail/posix_fd_set_adapter.hpp +++ b/libtorrent/include/libtorrent/asio/detail/posix_fd_set_adapter.hpp @@ -35,11 +35,16 @@ public: FD_ZERO(&fd_set_); } - void set(socket_type descriptor) + bool set(socket_type descriptor) { - if (max_descriptor_ == invalid_socket || descriptor > max_descriptor_) - max_descriptor_ = descriptor; - FD_SET(descriptor, &fd_set_); + if (descriptor < (socket_type)FD_SETSIZE) + { + if (max_descriptor_ == invalid_socket || descriptor > max_descriptor_) + max_descriptor_ = descriptor; + FD_SET(descriptor, &fd_set_); + return true; + } + return false; } bool is_set(socket_type descriptor) const diff --git a/libtorrent/include/libtorrent/asio/detail/reactor_op_queue.hpp b/libtorrent/include/libtorrent/asio/detail/reactor_op_queue.hpp index b2d1054c6..583636047 100644 --- a/libtorrent/include/libtorrent/asio/detail/reactor_op_queue.hpp +++ b/libtorrent/include/libtorrent/asio/detail/reactor_op_queue.hpp @@ -173,8 +173,13 @@ public: typename operation_map::iterator i = operations_.begin(); while (i != operations_.end()) { - descriptors.set(i->first); + Descriptor descriptor = i->first; ++i; + if (!descriptors.set(descriptor)) + { + asio::error_code ec(error::fd_set_failure); + dispatch_all_operations(descriptor, ec); + } } } diff --git a/libtorrent/include/libtorrent/asio/detail/socket_ops.hpp b/libtorrent/include/libtorrent/asio/detail/socket_ops.hpp index ee0b4b582..b99383a80 100644 --- a/libtorrent/include/libtorrent/asio/detail/socket_ops.hpp +++ b/libtorrent/include/libtorrent/asio/detail/socket_ops.hpp @@ -1124,8 +1124,12 @@ inline void gai_free(void* p) inline void gai_strcpy(char* target, const char* source, std::size_t max_size) { using namespace std; +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE) + strcpy_s(target, max_size, source); +#else *target = 0; strncat(target, source, max_size); +#endif } enum { gai_clone_flag = 1 << 30 }; @@ -1658,7 +1662,11 @@ inline asio::error_code getnameinfo_emulation( { return ec = asio::error::no_buffer_space; } +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE) + sprintf_s(serv, servlen, "%u", ntohs(port)); +#else sprintf(serv, "%u", ntohs(port)); +#endif } else { @@ -1677,7 +1685,11 @@ inline asio::error_code getnameinfo_emulation( { return ec = asio::error::no_buffer_space; } +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE) + sprintf_s(serv, servlen, "%u", ntohs(port)); +#else sprintf(serv, "%u", ntohs(port)); +#endif } #if defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS) ::pthread_mutex_unlock(&mutex); diff --git a/libtorrent/include/libtorrent/asio/detail/socket_types.hpp b/libtorrent/include/libtorrent/asio/detail/socket_types.hpp index e2b68910c..4ff207f57 100644 --- a/libtorrent/include/libtorrent/asio/detail/socket_types.hpp +++ b/libtorrent/include/libtorrent/asio/detail/socket_types.hpp @@ -92,7 +92,11 @@ # include # include # include -# include +# if defined(__hpux) +# include +# else +# include +# endif # include # include # include @@ -156,7 +160,16 @@ const int max_addr_v4_str_len = INET_ADDRSTRLEN; const int max_addr_v6_str_len = INET6_ADDRSTRLEN + 1 + IF_NAMESIZE; typedef sockaddr socket_addr_type; typedef in_addr in4_addr_type; +# if defined(__hpux) +// HP-UX doesn't provide ip_mreq when _XOPEN_SOURCE_EXTENDED is defined. +struct in4_mreq_type +{ + struct in_addr imr_multiaddr; + struct in_addr imr_interface; +}; +# else typedef ip_mreq in4_mreq_type; +# endif typedef sockaddr_in sockaddr_in4_type; typedef in6_addr in6_addr_type; typedef ipv6_mreq in6_mreq_type; diff --git a/libtorrent/include/libtorrent/asio/detail/win_fd_set_adapter.hpp b/libtorrent/include/libtorrent/asio/detail/win_fd_set_adapter.hpp index f2632c4d0..c97063a53 100644 --- a/libtorrent/include/libtorrent/asio/detail/win_fd_set_adapter.hpp +++ b/libtorrent/include/libtorrent/asio/detail/win_fd_set_adapter.hpp @@ -36,13 +36,17 @@ public: fd_set_.fd_count = 0; } - void set(socket_type descriptor) + bool set(socket_type descriptor) { for (u_int i = 0; i < fd_set_.fd_count; ++i) if (fd_set_.fd_array[i] == descriptor) - return; + return true; if (fd_set_.fd_count < win_fd_set_size) + { fd_set_.fd_array[fd_set_.fd_count++] = descriptor; + return true; + } + return false; } bool is_set(socket_type descriptor) const diff --git a/libtorrent/include/libtorrent/asio/error.hpp b/libtorrent/include/libtorrent/asio/error.hpp index c65599c91..4fd47d2d4 100644 --- a/libtorrent/include/libtorrent/asio/error.hpp +++ b/libtorrent/include/libtorrent/asio/error.hpp @@ -194,7 +194,10 @@ enum misc_errors eof, /// Element not found. - not_found + not_found, + + /// The descriptor cannot fit into the select system call's fd_set. + fd_set_failure }; enum ssl_errors diff --git a/libtorrent/include/libtorrent/asio/error_code.hpp b/libtorrent/include/libtorrent/asio/error_code.hpp index 516d599d7..6c8370d42 100644 --- a/libtorrent/include/libtorrent/asio/error_code.hpp +++ b/libtorrent/include/libtorrent/asio/error_code.hpp @@ -112,7 +112,11 @@ public: { }; - typedef unspecified_bool_type_t* unspecified_bool_type; + typedef void (*unspecified_bool_type)(unspecified_bool_type_t); + + static void unspecified_bool_true(unspecified_bool_type_t) + { + } /// Operator returns non-null if there is a non-success error code. operator unspecified_bool_type() const @@ -120,7 +124,7 @@ public: if (value_ == 0) return 0; else - return reinterpret_cast(1); + return &error_code::unspecified_bool_true; } /// Operator to test if the error represents success. diff --git a/libtorrent/include/libtorrent/asio/impl/error_code.ipp b/libtorrent/include/libtorrent/asio/impl/error_code.ipp index 9925cb484..52aef2851 100644 --- a/libtorrent/include/libtorrent/asio/impl/error_code.ipp +++ b/libtorrent/include/libtorrent/asio/impl/error_code.ipp @@ -35,6 +35,8 @@ inline std::string error_code::message() const return "Already open."; if (*this == error::not_found) return "Not found."; + if (*this == error::fd_set_failure) + return "The descriptor does not fit into the select call's fd_set."; if (category_ == error::get_ssl_category()) return "SSL error."; #if defined(BOOST_WINDOWS) || defined(__CYGWIN__) diff --git a/libtorrent/include/libtorrent/asio/ssl/detail/openssl_operation.hpp b/libtorrent/include/libtorrent/asio/ssl/detail/openssl_operation.hpp index c254aceb2..f9ca336df 100755 --- a/libtorrent/include/libtorrent/asio/ssl/detail/openssl_operation.hpp +++ b/libtorrent/include/libtorrent/asio/ssl/detail/openssl_operation.hpp @@ -100,6 +100,10 @@ public: &openssl_operation::do_async_write, this, boost::arg<1>(), boost::arg<2>() ); + read_ = boost::bind( + &openssl_operation::do_async_read, + this + ); handler_= boost::bind( &openssl_operation::async_user_handler, this, boost::arg<1>(), boost::arg<2>() @@ -122,6 +126,10 @@ public: &openssl_operation::do_sync_write, this, boost::arg<1>(), boost::arg<2>() ); + read_ = boost::bind( + &openssl_operation::do_sync_read, + this + ); handler_ = boost::bind( &openssl_operation::sync_user_handler, this, boost::arg<1>(), boost::arg<2>() @@ -134,7 +142,7 @@ public: int start() { int rc = primitive_( session_ ); - int sys_error_code = ERR_get_error(); + bool is_operation_done = (rc > 0); // For connect/accept/shutdown, the operation // is done, when return code is 1 @@ -144,6 +152,8 @@ public: int error_code = !is_operation_done ? ::SSL_get_error( session_, rc ) : 0; + int sys_error_code = ERR_get_error(); + bool is_read_needed = (error_code == SSL_ERROR_WANT_READ); bool is_write_needed = (error_code == SSL_ERROR_WANT_WRITE || ::BIO_ctrl_pending( ssl_bio_ )); @@ -211,6 +221,10 @@ public: return start(); } + else if (is_read_needed) + { + return read_(); + } } // Continue with operation, flush any SSL data out to network... @@ -222,10 +236,12 @@ private: typedef boost::function int_handler_func; typedef boost::function write_func; + typedef boost::function read_func; ssl_primitive_func primitive_; user_handler_func user_handler_; write_func write_; + read_func read_; int_handler_func handler_; net_buffer send_buf_; // buffers for network IO @@ -249,8 +265,15 @@ private: throw asio::system_error(error); } - int async_user_handler(const asio::error_code& error, int rc) + int async_user_handler(asio::error_code error, int rc) { + if (rc < 0) + { + if (!error) + error = asio::error::no_recovery; + rc = 0; + } + user_handler_(error, rc); return 0; } @@ -315,8 +338,8 @@ private: } // OPeration is not done and writing to net has been made... - // start reading... - do_async_read(); + // start operation again + start(); return 0; } @@ -339,7 +362,7 @@ private: handler_(error, rc); } - void do_async_read() + int do_async_read() { // Wait for new data socket_.async_read_some @@ -354,6 +377,7 @@ private: asio::placeholders::bytes_transferred ) ); + return 0; } void async_read_handler(const asio::error_code& error, @@ -432,8 +456,8 @@ private: // Finish the operation, with success return rc; - // Operation is not finished, read data from net... - return do_sync_read(); + // Operation is not finished, start again. + return start(); } int do_sync_read() diff --git a/libtorrent/include/libtorrent/asio/ssl/stream.hpp b/libtorrent/include/libtorrent/asio/ssl/stream.hpp index 9ee48fef1..e22f6b06c 100644 --- a/libtorrent/include/libtorrent/asio/ssl/stream.hpp +++ b/libtorrent/include/libtorrent/asio/ssl/stream.hpp @@ -44,16 +44,15 @@ namespace ssl { * @e Shared @e objects: Unsafe. * * @par Example - * To use the SSL stream template with a stream_socket, you would write: + * To use the SSL stream template with an ip::tcp::socket, you would write: * @code * asio::io_service io_service; * asio::ssl::context context(io_service, asio::ssl::context::sslv23); - * asio::ssl::stream sock(io_service, context); + * asio::ssl::stream sock(io_service, context); * @endcode * * @par Concepts: - * Async_Object, Async_Read_Stream, Async_Write_Stream, Error_Source, Stream, - * Sync_Read_Stream, Sync_Write_Stream. + * AsyncReadStream, AsyncWriteStream, Stream, SyncRead_Stream, SyncWriteStream. */ template class stream diff --git a/libtorrent/include/libtorrent/asio/version.hpp b/libtorrent/include/libtorrent/asio/version.hpp index 82cf4e15a..f2d68f986 100644 --- a/libtorrent/include/libtorrent/asio/version.hpp +++ b/libtorrent/include/libtorrent/asio/version.hpp @@ -18,6 +18,6 @@ // ASIO_VERSION % 100 is the sub-minor version // ASIO_VERSION / 100 % 1000 is the minor version // ASIO_VERSION / 100000 is the major version -#define ASIO_VERSION 308 // 0.3.8 +#define ASIO_VERSION 309 // 0.3.9 #endif // ASIO_VERSION_HPP