diff options
author | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-17 17:49:53 +0000 |
---|---|---|
committer | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-17 17:49:53 +0000 |
commit | 485f9a6b002b600f86935aefc6cc4ca7e6f68763 (patch) | |
tree | 82e3bb5a8f69b2ba4ac8d16ecfb6777746175af3 /content | |
parent | dd9cc6223a64068716927bee11291cc5ae7496d4 (diff) | |
download | chromium_src-485f9a6b002b600f86935aefc6cc4ca7e6f68763.zip chromium_src-485f9a6b002b600f86935aefc6cc4ca7e6f68763.tar.gz chromium_src-485f9a6b002b600f86935aefc6cc4ca7e6f68763.tar.bz2 |
Fix P2PSocketHostTcp to handle async write correctly.
Previously P2PSocketHostTcp was calling Write() even when another write is
pending.
BUG=232046
Review URL: https://codereview.chromium.org/13926013
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@194628 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
4 files changed, 75 insertions, 5 deletions
diff --git a/content/browser/renderer_host/p2p/socket_host_tcp.cc b/content/browser/renderer_host/p2p/socket_host_tcp.cc index 834afb7..de62ffb 100644 --- a/content/browser/renderer_host/p2p/socket_host_tcp.cc +++ b/content/browser/renderer_host/p2p/socket_host_tcp.cc @@ -21,6 +21,7 @@ namespace content { P2PSocketHostTcp::P2PSocketHostTcp(IPC::Sender* message_sender, int id) : P2PSocketHost(message_sender, id), + write_pending_(false), connected_(false) { } @@ -226,7 +227,7 @@ void P2PSocketHostTcp::Send(const net::IPEndPoint& to, } void P2PSocketHostTcp::DoWrite() { - while (write_buffer_ && state_ == STATE_OPEN) { + while (write_buffer_ && state_ == STATE_OPEN && !write_pending_) { int result = socket_->Write(write_buffer_, write_buffer_->BytesRemaining(), base::Bind(&P2PSocketHostTcp::OnWritten, base::Unretained(this))); @@ -235,7 +236,10 @@ void P2PSocketHostTcp::DoWrite() { } void P2PSocketHostTcp::OnWritten(int result) { + DCHECK(write_pending_); DCHECK_NE(result, net::ERR_IO_PENDING); + + write_pending_ = false; HandleWriteResult(result); DoWrite(); } @@ -253,7 +257,9 @@ void P2PSocketHostTcp::HandleWriteResult(int result) { write_queue_.pop(); } } - } else if (result != net::ERR_IO_PENDING) { + } else if (result == net::ERR_IO_PENDING) { + write_pending_ = true; + } else { LOG(ERROR) << "Error when sending data in TCP socket: " << result; OnError(); } diff --git a/content/browser/renderer_host/p2p/socket_host_tcp.h b/content/browser/renderer_host/p2p/socket_host_tcp.h index 0b129cc..4fa3fae 100644 --- a/content/browser/renderer_host/p2p/socket_host_tcp.h +++ b/content/browser/renderer_host/p2p/socket_host_tcp.h @@ -65,6 +65,7 @@ class CONTENT_EXPORT P2PSocketHostTcp : public P2PSocketHost { std::queue<scoped_refptr<net::DrainableIOBuffer> > write_queue_; scoped_refptr<net::DrainableIOBuffer> write_buffer_; + bool write_pending_; bool connected_; diff --git a/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc b/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc index af4950c..49a7f1f 100644 --- a/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc +++ b/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc @@ -181,4 +181,34 @@ TEST_F(P2PSocketHostTcpTest, SendAfterStunRequest) { EXPECT_EQ(expected_data, sent_data_); } +// Verify that asynchronous writes are handled correctly. +TEST_F(P2PSocketHostTcpTest, AsyncWrites) { + MessageLoop message_loop; + + socket_->set_async_write(true); + + EXPECT_CALL(sender_, Send( + MatchMessage(static_cast<uint32>(P2PMsg_OnSendComplete::ID)))) + .Times(2) + .WillRepeatedly(DoAll(DeleteArg<0>(), Return(true))); + + std::vector<char> packet1; + CreateStunRequest(&packet1); + socket_host_->Send(dest_, packet1); + + std::vector<char> packet2; + CreateStunResponse(&packet2); + socket_host_->Send(dest_, packet2); + + message_loop.RunUntilIdle(); + + std::string expected_data; + expected_data.append(IntToSize(packet1.size())); + expected_data.append(packet1.begin(), packet1.end()); + expected_data.append(IntToSize(packet2.size())); + expected_data.append(packet2.begin(), packet2.end()); + + EXPECT_EQ(expected_data, sent_data_); +} + } // namespace content diff --git a/content/browser/renderer_host/p2p/socket_host_test_utils.h b/content/browser/renderer_host/p2p/socket_host_test_utils.h index 86c7414..77da0cd 100644 --- a/content/browser/renderer_host/p2p/socket_host_test_utils.h +++ b/content/browser/renderer_host/p2p/socket_host_test_utils.h @@ -7,10 +7,13 @@ #include <vector> +#include "base/location.h" +#include "base/single_thread_task_runner.h" #include "base/sys_byteorder.h" +#include "base/thread_task_runner_handle.h" #include "content/common/p2p_messages.h" -#include "ipc/ipc_sender.h" #include "ipc/ipc_message_utils.h" +#include "ipc/ipc_sender.h" #include "net/base/address_list.h" #include "net/base/completion_callback.h" #include "net/base/io_buffer.h" @@ -49,6 +52,7 @@ class FakeSocket : public net::StreamSocket { FakeSocket(std::string* written_data); virtual ~FakeSocket(); + void set_async_write(bool async_write) { async_write_ = async_write; } void AppendInputData(const char* data, int data_size); int input_pos() const { return input_pos_; } bool read_pending() const { return read_pending_; } @@ -78,15 +82,21 @@ class FakeSocket : public net::StreamSocket { virtual bool GetSSLInfo(net::SSLInfo* ssl_info) OVERRIDE; private: + void DoAsyncWrite(scoped_refptr<net::IOBuffer> buf, int buf_len, + const net::CompletionCallback& callback); + bool read_pending_; scoped_refptr<net::IOBuffer> read_buffer_; int read_buffer_size_; net::CompletionCallback read_callback_; - std::string* written_data_; std::string input_data_; int input_pos_; + std::string* written_data_; + bool async_write_; + bool write_pending_; + net::IPEndPoint peer_address_; net::IPEndPoint local_address_; @@ -95,8 +105,10 @@ class FakeSocket : public net::StreamSocket { FakeSocket::FakeSocket(std::string* written_data) : read_pending_(false), + input_pos_(0), written_data_(written_data), - input_pos_(0) { + async_write_(false), + write_pending_(false) { } FakeSocket::~FakeSocket() { } @@ -147,6 +159,17 @@ int FakeSocket::Read(net::IOBuffer* buf, int buf_len, int FakeSocket::Write(net::IOBuffer* buf, int buf_len, const net::CompletionCallback& callback) { DCHECK(buf); + DCHECK(!write_pending_); + + if (async_write_) { + + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::Bind( + &FakeSocket::DoAsyncWrite, base::Unretained(this), + scoped_refptr<net::IOBuffer>(buf), buf_len, callback)); + write_pending_ = true; + return net::ERR_IO_PENDING; + } + if (written_data_) { written_data_->insert(written_data_->end(), buf->data(), buf->data() + buf_len); @@ -154,6 +177,16 @@ int FakeSocket::Write(net::IOBuffer* buf, int buf_len, return buf_len; } +void FakeSocket::DoAsyncWrite(scoped_refptr<net::IOBuffer> buf, int buf_len, + const net::CompletionCallback& callback) { + write_pending_ = false; + + if (written_data_) { + written_data_->insert(written_data_->end(), + buf->data(), buf->data() + buf_len); + } + callback.Run(buf_len); +} bool FakeSocket::SetReceiveBufferSize(int32 size) { NOTIMPLEMENTED(); |