$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r60689 - in trunk: boost/asio/detail libs/asio/test/ip
From: chris_at_[hidden]
Date: 2010-03-18 07:08:20
Author: chris_kohlhoff
Date: 2010-03-18 07:08:19 EDT (Thu, 18 Mar 2010)
New Revision: 60689
URL: http://svn.boost.org/trac/boost/changeset/60689
Log:
Fix bug where 0-byte reads were incorrectly passing an eof error_code to the handler. Refs #4023.
Text files modified: 
   trunk/boost/asio/detail/win_iocp_socket_service.hpp |     2                                         
   trunk/libs/asio/test/ip/tcp.cpp                     |   144 ++++++++++++++++++++++++++++++++++++++++
   2 files changed, 146 insertions(+), 0 deletions(-)
Modified: trunk/boost/asio/detail/win_iocp_socket_service.hpp
==============================================================================
--- trunk/boost/asio/detail/win_iocp_socket_service.hpp	(original)
+++ trunk/boost/asio/detail/win_iocp_socket_service.hpp	2010-03-18 07:08:19 EDT (Thu, 18 Mar 2010)
@@ -1059,6 +1059,8 @@
         // Check for connection closed.
         else if (!ec && bytes_transferred == 0
             && o->protocol_type_ == SOCK_STREAM
+            && !buffer_sequence_adapter<boost::asio::mutable_buffer,
+                MutableBufferSequence>::all_empty(o->buffers_)
             && !boost::is_same<MutableBufferSequence, null_buffers>::value)
         {
           ec = boost::asio::error::eof;
Modified: trunk/libs/asio/test/ip/tcp.cpp
==============================================================================
--- trunk/libs/asio/test/ip/tcp.cpp	(original)
+++ trunk/libs/asio/test/ip/tcp.cpp	2010-03-18 07:08:19 EDT (Thu, 18 Mar 2010)
@@ -19,6 +19,9 @@
 #include <boost/bind.hpp>
 #include <cstring>
 #include <boost/asio/io_service.hpp>
+#include <boost/asio/placeholders.hpp>
+#include <boost/asio/read.hpp>
+#include <boost/asio/write.hpp>
 #include "../unit_test.hpp"
 #include "../archetypes/io_control_command.hpp"
 
@@ -300,6 +303,146 @@
 
 //------------------------------------------------------------------------------
 
+// ip_tcp_socket_runtime test
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+// The following test checks the runtime operation of the ip::tcp::socket class.
+
+namespace ip_tcp_socket_runtime {
+
+static const char write_data[]
+  = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+void handle_read_noop(const boost::system::error_code& err,
+    size_t bytes_transferred, bool* called)
+{
+  *called = true;
+  BOOST_CHECK(!err);
+  BOOST_CHECK(bytes_transferred == 0);
+}
+
+void handle_write_noop(const boost::system::error_code& err,
+    size_t bytes_transferred, bool* called)
+{
+  *called = true;
+  BOOST_CHECK(!err);
+  BOOST_CHECK(bytes_transferred == 0);
+}
+
+void handle_read(const boost::system::error_code& err,
+    size_t bytes_transferred, bool* called)
+{
+  *called = true;
+  BOOST_CHECK(!err);
+  BOOST_CHECK(bytes_transferred == sizeof(write_data));
+}
+
+void handle_write(const boost::system::error_code& err,
+    size_t bytes_transferred, bool* called)
+{
+  *called = true;
+  BOOST_CHECK(!err);
+  BOOST_CHECK(bytes_transferred == sizeof(write_data));
+}
+
+void handle_read_eof(const boost::system::error_code& err,
+    size_t bytes_transferred, bool* called)
+{
+  *called = true;
+  BOOST_CHECK(err == boost::asio::error::eof);
+  BOOST_CHECK(bytes_transferred == 0);
+}
+
+void test()
+{
+  using namespace std; // For memcmp.
+  using namespace boost::asio;
+  namespace ip = boost::asio::ip;
+
+  io_service ios;
+
+  ip::tcp::acceptor acceptor(ios, ip::tcp::endpoint(ip::tcp::v4(), 0));
+  ip::tcp::endpoint server_endpoint = acceptor.local_endpoint();
+  server_endpoint.address(ip::address_v4::loopback());
+
+  ip::tcp::socket client_side_socket(ios);
+  ip::tcp::socket server_side_socket(ios);
+
+  client_side_socket.connect(server_endpoint);
+  acceptor.accept(server_side_socket);
+
+  // No-op read.
+
+  bool read_noop_completed = false;
+  client_side_socket.async_read_some(
+      boost::asio::mutable_buffers_1(0, 0),
+      boost::bind(handle_read_noop,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        &read_noop_completed));
+
+  ios.run();
+  BOOST_CHECK(read_noop_completed);
+
+  // No-op write.
+
+  bool write_noop_completed = false;
+  client_side_socket.async_write_some(
+      boost::asio::const_buffers_1(0, 0),
+      boost::bind(handle_write_noop,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        &write_noop_completed));
+
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(write_noop_completed);
+
+  // Read and write to transfer data.
+
+  char read_buffer[sizeof(write_data)];
+  bool read_completed = false;
+  boost::asio::async_read(client_side_socket,
+      boost::asio::buffer(read_buffer),
+      boost::bind(handle_read,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        &read_completed));
+
+  bool write_completed = false;
+  boost::asio::async_write(server_side_socket,
+      boost::asio::buffer(write_data),
+      boost::bind(handle_write,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        &write_completed));
+
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(read_completed);
+  BOOST_CHECK(write_completed);
+  BOOST_CHECK(memcmp(read_buffer, write_data, sizeof(write_data)) == 0);
+
+  // A read when the peer closes socket should fail with eof.
+
+  bool read_eof_completed = false;
+  boost::asio::async_read(client_side_socket,
+      boost::asio::buffer(read_buffer),
+      boost::bind(handle_read_eof,
+        boost::asio::placeholders::error,
+        boost::asio::placeholders::bytes_transferred,
+        &read_eof_completed));
+
+  server_side_socket.close();
+
+  ios.reset();
+  ios.run();
+  BOOST_CHECK(read_eof_completed);
+}
+
+} // namespace ip_tcp_socket_runtime
+
+//------------------------------------------------------------------------------
+
 // ip_tcp_acceptor_runtime test
 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // The following test checks the runtime operation of the ip::tcp::acceptor
@@ -383,6 +526,7 @@
   test->add(BOOST_TEST_CASE(&ip_tcp_compile::test));
   test->add(BOOST_TEST_CASE(&ip_tcp_runtime::test));
   test->add(BOOST_TEST_CASE(&ip_tcp_socket_compile::test));
+  test->add(BOOST_TEST_CASE(&ip_tcp_socket_runtime::test));
   test->add(BOOST_TEST_CASE(&ip_tcp_acceptor_runtime::test));
   return test;
 }