Index: remoting/protocol/channel_multiplexer.cc |
diff --git a/remoting/protocol/channel_multiplexer.cc b/remoting/protocol/channel_multiplexer.cc |
index 8d885fe28f05765d7c697f01138a0f86688f2e2f..832fba39894897d5cb4917095d77cef2526df258 100644 |
--- a/remoting/protocol/channel_multiplexer.cc |
+++ b/remoting/protocol/channel_multiplexer.cc |
@@ -8,6 +8,7 @@ |
#include "base/bind.h" |
#include "base/callback.h" |
+#include "base/callback_helpers.h" |
#include "base/location.h" |
#include "base/single_thread_task_runner.h" |
#include "base/stl_util.h" |
@@ -79,7 +80,7 @@ class ChannelMultiplexer::MuxChannel { |
scoped_ptr<net::StreamSocket> CreateSocket(); |
void OnIncomingPacket(scoped_ptr<MultiplexPacket> packet, |
const base::Closure& done_task); |
- void OnWriteFailed(); |
+ void OnBaseChannelError(int error); |
// Called by MuxSocket. |
void OnSocketDestroyed(); |
@@ -107,7 +108,7 @@ class ChannelMultiplexer::MuxSocket : public net::StreamSocket, |
~MuxSocket() override; |
void OnWriteComplete(); |
- void OnWriteFailed(); |
+ void OnBaseChannelError(int error); |
void OnPacketReceived(); |
// net::StreamSocket interface. |
@@ -168,6 +169,8 @@ class ChannelMultiplexer::MuxSocket : public net::StreamSocket, |
private: |
MuxChannel* channel_; |
+ int base_channel_error_ = net::OK; |
+ |
net::CompletionCallback read_callback_; |
scoped_refptr<net::IOBuffer> read_buffer_; |
int read_buffer_size_; |
@@ -220,9 +223,9 @@ void ChannelMultiplexer::MuxChannel::OnIncomingPacket( |
} |
} |
-void ChannelMultiplexer::MuxChannel::OnWriteFailed() { |
+void ChannelMultiplexer::MuxChannel::OnBaseChannelError(int error) { |
if (socket_) |
- socket_->OnWriteFailed(); |
+ socket_->OnBaseChannelError(error); |
} |
void ChannelMultiplexer::MuxChannel::OnSocketDestroyed() { |
@@ -276,6 +279,9 @@ int ChannelMultiplexer::MuxSocket::Read( |
DCHECK(CalledOnValidThread()); |
DCHECK(read_callback_.is_null()); |
+ if (base_channel_error_ != net::OK) |
+ return base_channel_error_; |
+ |
int result = channel_->DoRead(buffer, buffer_len); |
if (result == 0) { |
read_buffer_ = buffer; |
@@ -290,6 +296,10 @@ int ChannelMultiplexer::MuxSocket::Write( |
net::IOBuffer* buffer, int buffer_len, |
const net::CompletionCallback& callback) { |
DCHECK(CalledOnValidThread()); |
+ DCHECK(write_callback_.is_null()); |
+ |
+ if (base_channel_error_ != net::OK) |
+ return base_channel_error_; |
scoped_ptr<MultiplexPacket> packet(new MultiplexPacket()); |
size_t size = std::min(kMaxPacketSize, buffer_len); |
@@ -317,19 +327,28 @@ int ChannelMultiplexer::MuxSocket::Write( |
void ChannelMultiplexer::MuxSocket::OnWriteComplete() { |
write_pending_ = false; |
- if (!write_callback_.is_null()) { |
- net::CompletionCallback cb; |
- std::swap(cb, write_callback_); |
- cb.Run(write_result_); |
- } |
+ if (!write_callback_.is_null()) |
+ base::ResetAndReturn(&write_callback_).Run(write_result_); |
+ |
} |
-void ChannelMultiplexer::MuxSocket::OnWriteFailed() { |
- if (!write_callback_.is_null()) { |
- net::CompletionCallback cb; |
- std::swap(cb, write_callback_); |
- cb.Run(net::ERR_FAILED); |
+void ChannelMultiplexer::MuxSocket::OnBaseChannelError(int error) { |
+ base_channel_error_ = error; |
+ |
+ // Here only one of the read and write callbacks is called if both of them are |
+ // pending. Ideally both of them should be called in that case, but that would |
+ // require the second one to be called asynchronously which would complicate |
+ // this code. Channels handle read and write errors the same way (see |
+ // ChannelDispatcherBase::OnReadWriteFailed) so calling only one of the |
+ // callbacks is enough. |
+ |
+ if (!read_callback_.is_null()) { |
+ base::ResetAndReturn(&read_callback_).Run(error); |
+ return; |
} |
+ |
+ if (!write_callback_.is_null()) |
+ base::ResetAndReturn(&write_callback_).Run(error); |
} |
void ChannelMultiplexer::MuxSocket::OnPacketReceived() { |
@@ -337,9 +356,7 @@ void ChannelMultiplexer::MuxSocket::OnPacketReceived() { |
int result = channel_->DoRead(read_buffer_.get(), read_buffer_size_); |
read_buffer_ = nullptr; |
DCHECK_GT(result, 0); |
- net::CompletionCallback cb; |
- std::swap(cb, read_callback_); |
- cb.Run(result); |
+ base::ResetAndReturn(&read_callback_).Run(result); |
} |
} |
@@ -403,9 +420,11 @@ void ChannelMultiplexer::OnBaseChannelReady( |
if (base_channel_.get()) { |
// Initialize reader and writer. |
- reader_.StartReading(base_channel_.get()); |
+ reader_.StartReading(base_channel_.get(), |
+ base::Bind(&ChannelMultiplexer::OnBaseChannelError, |
+ base::Unretained(this))); |
writer_.Init(base_channel_.get(), |
- base::Bind(&ChannelMultiplexer::OnWriteFailed, |
+ base::Bind(&ChannelMultiplexer::OnBaseChannelError, |
base::Unretained(this))); |
} |
@@ -447,20 +466,21 @@ ChannelMultiplexer::MuxChannel* ChannelMultiplexer::GetOrCreateChannel( |
} |
-void ChannelMultiplexer::OnWriteFailed(int error) { |
+void ChannelMultiplexer::OnBaseChannelError(int error) { |
for (std::map<std::string, MuxChannel*>::iterator it = channels_.begin(); |
it != channels_.end(); ++it) { |
base::ThreadTaskRunnerHandle::Get()->PostTask( |
- FROM_HERE, base::Bind(&ChannelMultiplexer::NotifyWriteFailed, |
- weak_factory_.GetWeakPtr(), it->second->name())); |
+ FROM_HERE, |
+ base::Bind(&ChannelMultiplexer::NotifyBaseChannelError, |
+ weak_factory_.GetWeakPtr(), it->second->name(), error)); |
} |
} |
-void ChannelMultiplexer::NotifyWriteFailed(const std::string& name) { |
+void ChannelMultiplexer::NotifyBaseChannelError(const std::string& name, |
+ int error) { |
std::map<std::string, MuxChannel*>::iterator it = channels_.find(name); |
- if (it != channels_.end()) { |
- it->second->OnWriteFailed(); |
- } |
+ if (it != channels_.end()) |
+ it->second->OnBaseChannelError(error); |
} |
void ChannelMultiplexer::OnIncomingPacket(scoped_ptr<MultiplexPacket> packet, |