diff options
author | pfeldman@chromium.org <pfeldman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-27 06:20:26 +0000 |
---|---|---|
committer | pfeldman@chromium.org <pfeldman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-27 06:20:26 +0000 |
commit | 5198e3ef3f963c877ba7db4784ee8c93ea198f22 (patch) | |
tree | 4afe184ac681c21d8a54b331c71a6d5bc691b6dd /content/browser | |
parent | 2b1da855508d76bea54d771cc714e6bd69032a28 (diff) | |
download | chromium_src-5198e3ef3f963c877ba7db4784ee8c93ea198f22.zip chromium_src-5198e3ef3f963c877ba7db4784ee8c93ea198f22.tar.gz chromium_src-5198e3ef3f963c877ba7db4784ee8c93ea198f22.tar.bz2 |
DevTools: do not close socket too early in reversed port forwarding.
R=vsevik@chromium.org
Review URL: https://codereview.chromium.org/14395003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@196953 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser')
-rw-r--r-- | content/browser/devtools/tethering_handler.cc | 70 |
1 files changed, 59 insertions, 11 deletions
diff --git a/content/browser/devtools/tethering_handler.cc b/content/browser/devtools/tethering_handler.cc index 725a2b9..bad1ded 100644 --- a/content/browser/devtools/tethering_handler.cc +++ b/content/browser/devtools/tethering_handler.cc @@ -44,13 +44,14 @@ class SocketPump : public net::StreamListenSocket::Delegate { SocketPump(DevToolsHttpHandlerDelegate* delegate, net::StreamSocket* client_socket) : client_socket_(client_socket), - delegate_(delegate) { + delegate_(delegate), + wire_buffer_size_(0), + pending_destruction_(false) { } std::string Init() { std::string channel_name; server_socket_ = delegate_->CreateSocketForTethering(this, &channel_name); - buffer_ = new net::IOBuffer(kBufferSize); if (!server_socket_ || channel_name.empty()) SelfDestruct(); return channel_name; @@ -64,6 +65,10 @@ class SocketPump : public net::StreamListenSocket::Delegate { if (accepted_socket_) return; + buffer_ = new net::IOBuffer(kBufferSize); + wire_buffer_ = new net::GrowableIOBuffer(); + wire_buffer_->SetCapacity(kBufferSize); + accepted_socket_ = socket; int result = client_socket_->Read(buffer_, kBufferSize, base::Bind(&SocketPump::OnClientRead, @@ -75,12 +80,14 @@ class SocketPump : public net::StreamListenSocket::Delegate { virtual void DidRead(net::StreamListenSocket* socket, const char* data, int len) OVERRIDE { - std::string payload = std::string(data, len); - int result = client_socket_->Write(new net::StringIOBuffer(payload), len, - base::Bind(&SocketPump::OnClientWrite, - base::Unretained(this))); - if (result < 0 && result != net::ERR_IO_PENDING) - SelfDestruct(); + int old_size = wire_buffer_size_; + wire_buffer_size_ += len; + while (wire_buffer_->capacity() < wire_buffer_size_) + wire_buffer_->SetCapacity(wire_buffer_->capacity() * 2); + memcpy(wire_buffer_->StartOfBuffer() + old_size, data, len); + if (old_size != wire_buffer_->offset()) + return; + OnClientWrite(0); } virtual void DidClose(net::StreamListenSocket* socket) OVERRIDE { @@ -94,10 +101,9 @@ class SocketPump : public net::StreamListenSocket::Delegate { } accepted_socket_->Send(buffer_->data(), result); - result = client_socket_->Read(buffer_, kBufferSize, - base::Bind(&SocketPump::OnClientRead, - base::Unretained(this))); + base::Bind(&SocketPump::OnClientRead, + base::Unretained(this))); if (result != net::ERR_IO_PENDING) OnClientRead(result); } @@ -105,9 +111,45 @@ class SocketPump : public net::StreamListenSocket::Delegate { void OnClientWrite(int result) { if (result < 0) SelfDestruct(); + + wire_buffer_->set_offset(wire_buffer_->offset() + result); + + int remaining = wire_buffer_size_ - wire_buffer_->offset(); + if (remaining == 0) { + if (pending_destruction_) + SelfDestruct(); + return; + } + + + if (remaining > kBufferSize) + remaining = kBufferSize; + + scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(remaining); + memcpy(buffer->data(), wire_buffer_->data(), remaining); + result = client_socket_->Write( + buffer, remaining, base::Bind(&SocketPump::OnClientWrite, + base::Unretained(this))); + + // Shrink buffer + int offset = wire_buffer_->offset(); + if (offset > kBufferSize) { + memcpy(wire_buffer_->StartOfBuffer(), wire_buffer_->data(), + wire_buffer_size_ - offset); + wire_buffer_size_ -= offset; + wire_buffer_->set_offset(0); + } + + if (result != net::ERR_IO_PENDING) + OnClientWrite(result); + return; } void SelfDestruct() { + if (wire_buffer_->offset() != wire_buffer_size_) { + pending_destruction_ = true; + return; + } delete this; } @@ -116,7 +158,10 @@ class SocketPump : public net::StreamListenSocket::Delegate { scoped_refptr<net::StreamListenSocket> server_socket_; scoped_refptr<net::StreamListenSocket> accepted_socket_; scoped_refptr<net::IOBuffer> buffer_; + scoped_refptr<net::GrowableIOBuffer> wire_buffer_; DevToolsHttpHandlerDelegate* delegate_; + int wire_buffer_size_; + bool pending_destruction_; }; } // namespace @@ -232,6 +277,9 @@ TetheringHandler::OnBind(DevToolsProtocol::Command* command) { if (port == 0) return command->InvalidParamResponse(kPortParam); + if (bound_sockets_.find(port) != bound_sockets_.end()) + return command->InternalErrorResponse("Port already bound"); + scoped_ptr<BoundSocket> bound_socket(new BoundSocket(this, delegate_)); if (!bound_socket->Listen(port)) return command->InternalErrorResponse("Could not bind port"); |