summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authorsergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-17 17:49:53 +0000
committersergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-17 17:49:53 +0000
commit485f9a6b002b600f86935aefc6cc4ca7e6f68763 (patch)
tree82e3bb5a8f69b2ba4ac8d16ecfb6777746175af3 /content
parentdd9cc6223a64068716927bee11291cc5ae7496d4 (diff)
downloadchromium_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')
-rw-r--r--content/browser/renderer_host/p2p/socket_host_tcp.cc10
-rw-r--r--content/browser/renderer_host/p2p/socket_host_tcp.h1
-rw-r--r--content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc30
-rw-r--r--content/browser/renderer_host/p2p/socket_host_test_utils.h39
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();