| Index: remoting/protocol/channel_multiplexer.cc
|
| diff --git a/remoting/protocol/channel_multiplexer.cc b/remoting/protocol/channel_multiplexer.cc
|
| index 3ad87bcf0d80ac60a4ee08a8eeb8f2552549f5e1..e14b2b37a152b65c89b8bd41b6e21dacc974d269 100644
|
| --- a/remoting/protocol/channel_multiplexer.cc
|
| +++ b/remoting/protocol/channel_multiplexer.cc
|
| @@ -9,7 +9,9 @@
|
| #include "base/bind.h"
|
| #include "base/callback.h"
|
| #include "base/location.h"
|
| +#include "base/single_thread_task_runner.h"
|
| #include "base/stl_util.h"
|
| +#include "base/thread_task_runner_handle.h"
|
| #include "net/base/net_errors.h"
|
| #include "net/socket/stream_socket.h"
|
| #include "remoting/protocol/util.h"
|
| @@ -364,7 +366,7 @@ ChannelMultiplexer::ChannelMultiplexer(ChannelFactory* factory,
|
| : base_channel_factory_(factory),
|
| base_channel_name_(base_channel_name),
|
| next_channel_id_(0),
|
| - destroyed_flag_(NULL) {
|
| + ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
|
| }
|
|
|
| ChannelMultiplexer::~ChannelMultiplexer() {
|
| @@ -374,9 +376,6 @@ ChannelMultiplexer::~ChannelMultiplexer() {
|
| // Cancel creation of the base channel if it hasn't finished.
|
| if (base_channel_factory_)
|
| base_channel_factory_->CancelChannelCreation(base_channel_name_);
|
| -
|
| - if (destroyed_flag_)
|
| - *destroyed_flag_ = true;
|
| }
|
|
|
| void ChannelMultiplexer::CreateStreamChannel(
|
| @@ -425,30 +424,37 @@ void ChannelMultiplexer::OnBaseChannelReady(
|
| base_channel_factory_ = NULL;
|
| base_channel_ = socket.Pass();
|
|
|
| - if (!base_channel_.get()) {
|
| - // Notify all callers that we can't create any channels.
|
| - for (std::list<PendingChannel>::iterator it = pending_channels_.begin();
|
| - it != pending_channels_.end(); ++it) {
|
| - it->callback.Run(scoped_ptr<net::StreamSocket>());
|
| - }
|
| - pending_channels_.clear();
|
| - return;
|
| + if (base_channel_.get()) {
|
| + // Initialize reader and writer.
|
| + reader_.Init(base_channel_.get(),
|
| + base::Bind(&ChannelMultiplexer::OnIncomingPacket,
|
| + base::Unretained(this)));
|
| + writer_.Init(base_channel_.get(),
|
| + base::Bind(&ChannelMultiplexer::OnWriteFailed,
|
| + base::Unretained(this)));
|
| }
|
|
|
| - // Initialize reader and writer.
|
| - reader_.Init(base_channel_.get(),
|
| - base::Bind(&ChannelMultiplexer::OnIncomingPacket,
|
| - base::Unretained(this)));
|
| - writer_.Init(base_channel_.get(),
|
| - base::Bind(&ChannelMultiplexer::OnWriteFailed,
|
| - base::Unretained(this)));
|
| + DoCreatePendingChannels();
|
| +}
|
|
|
| - // Now create all pending channels.
|
| - for (std::list<PendingChannel>::iterator it = pending_channels_.begin();
|
| - it != pending_channels_.end(); ++it) {
|
| - it->callback.Run(GetOrCreateChannel(it->name)->CreateSocket());
|
| - }
|
| - pending_channels_.clear();
|
| +void ChannelMultiplexer::DoCreatePendingChannels() {
|
| + if (pending_channels_.empty())
|
| + return;
|
| +
|
| + // Every time this function is called it connects a single channel and posts a
|
| + // separate task to connect other channels. This is necessary because the
|
| + // callback may destroy the multiplexer or somehow else modify
|
| + // |pending_channels_| list (e.g. call CancelChannelCreation()).
|
| + base::ThreadTaskRunnerHandle::Get()->PostTask(
|
| + FROM_HERE, base::Bind(&ChannelMultiplexer::DoCreatePendingChannels,
|
| + weak_factory_.GetWeakPtr()));
|
| +
|
| + PendingChannel c = pending_channels_.front();
|
| + pending_channels_.erase(pending_channels_.begin());
|
| + scoped_ptr<net::StreamSocket> socket;
|
| + if (base_channel_.get())
|
| + socket = GetOrCreateChannel(c.name)->CreateSocket();
|
| + c.callback.Run(socket.Pass());
|
| }
|
|
|
| ChannelMultiplexer::MuxChannel* ChannelMultiplexer::GetOrCreateChannel(
|
| @@ -467,15 +473,19 @@ ChannelMultiplexer::MuxChannel* ChannelMultiplexer::GetOrCreateChannel(
|
|
|
|
|
| void ChannelMultiplexer::OnWriteFailed(int error) {
|
| - bool destroyed = false;
|
| - destroyed_flag_ = &destroyed;
|
| 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()));
|
| + }
|
| +}
|
| +
|
| +void ChannelMultiplexer::NotifyWriteFailed(const std::string& name) {
|
| + std::map<std::string, MuxChannel*>::iterator it = channels_.find(name);
|
| + if (it != channels_.end()) {
|
| it->second->OnWriteFailed();
|
| - if (destroyed)
|
| - return;
|
| }
|
| - destroyed_flag_ = NULL;
|
| }
|
|
|
| void ChannelMultiplexer::OnIncomingPacket(scoped_ptr<MultiplexPacket> packet,
|
|
|