| Index: third_party/mojo/src/mojo/edk/system/channel_endpoint.cc
|
| diff --git a/third_party/mojo/src/mojo/edk/system/channel_endpoint.cc b/third_party/mojo/src/mojo/edk/system/channel_endpoint.cc
|
| deleted file mode 100644
|
| index 78504216ec8bef134178ae0667bd5931546bc3de..0000000000000000000000000000000000000000
|
| --- a/third_party/mojo/src/mojo/edk/system/channel_endpoint.cc
|
| +++ /dev/null
|
| @@ -1,226 +0,0 @@
|
| -// Copyright 2014 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "third_party/mojo/src/mojo/edk/system/channel_endpoint.h"
|
| -
|
| -#include <utility>
|
| -
|
| -#include "base/logging.h"
|
| -#include "base/threading/platform_thread.h"
|
| -#include "mojo/public/cpp/system/macros.h"
|
| -#include "third_party/mojo/src/mojo/edk/system/channel.h"
|
| -#include "third_party/mojo/src/mojo/edk/system/channel_endpoint_client.h"
|
| -
|
| -namespace mojo {
|
| -namespace system {
|
| -
|
| -ChannelEndpoint::ChannelEndpoint(ChannelEndpointClient* client,
|
| - unsigned client_port,
|
| - MessageInTransitQueue* message_queue)
|
| - : state_(State::PAUSED),
|
| - client_(client),
|
| - client_port_(client_port),
|
| - channel_(nullptr) {
|
| - DCHECK(client_ || message_queue);
|
| -
|
| - if (message_queue)
|
| - channel_message_queue_.Swap(message_queue);
|
| -}
|
| -
|
| -bool ChannelEndpoint::EnqueueMessage(scoped_ptr<MessageInTransit> message) {
|
| - DCHECK(message);
|
| -
|
| - MutexLocker locker(&mutex_);
|
| -
|
| - switch (state_) {
|
| - case State::PAUSED:
|
| - channel_message_queue_.AddMessage(std::move(message));
|
| - return true;
|
| - case State::RUNNING:
|
| - return WriteMessageNoLock(std::move(message));
|
| - case State::DEAD:
|
| - return false;
|
| - }
|
| -
|
| - NOTREACHED();
|
| - return false;
|
| -}
|
| -
|
| -bool ChannelEndpoint::ReplaceClient(ChannelEndpointClient* client,
|
| - unsigned client_port) {
|
| - DCHECK(client);
|
| -
|
| - MutexLocker locker(&mutex_);
|
| - DCHECK(client_);
|
| - DCHECK(client != client_.get() || client_port != client_port_);
|
| - client_ = client;
|
| - client_port_ = client_port;
|
| - return state_ != State::DEAD;
|
| -}
|
| -
|
| -void ChannelEndpoint::DetachFromClient() {
|
| - MutexLocker locker(&mutex_);
|
| - DCHECK(client_);
|
| - client_ = nullptr;
|
| -
|
| - if (!channel_)
|
| - return;
|
| - channel_->DetachEndpoint(this, local_id_, remote_id_);
|
| - DieNoLock();
|
| -}
|
| -
|
| -void ChannelEndpoint::AttachAndRun(Channel* channel,
|
| - ChannelEndpointId local_id,
|
| - ChannelEndpointId remote_id) {
|
| - DCHECK(channel);
|
| - DCHECK(local_id.is_valid());
|
| - DCHECK(remote_id.is_valid());
|
| -
|
| - MutexLocker locker(&mutex_);
|
| - DCHECK(state_ == State::PAUSED);
|
| - DCHECK(!channel_);
|
| - DCHECK(!local_id_.is_valid());
|
| - DCHECK(!remote_id_.is_valid());
|
| - state_ = State::RUNNING;
|
| - channel_ = channel;
|
| - local_id_ = local_id;
|
| - remote_id_ = remote_id;
|
| -
|
| - while (!channel_message_queue_.IsEmpty()) {
|
| - bool ok = WriteMessageNoLock(channel_message_queue_.GetMessage());
|
| - LOG_IF(WARNING, !ok) << "Failed to write enqueue message to channel";
|
| - }
|
| -
|
| - if (!client_) {
|
| - channel_->DetachEndpoint(this, local_id_, remote_id_);
|
| - DieNoLock();
|
| - }
|
| -}
|
| -
|
| -void ChannelEndpoint::OnReadMessage(scoped_ptr<MessageInTransit> message) {
|
| - if (message->type() == MessageInTransit::Type::ENDPOINT_CLIENT) {
|
| - OnReadMessageForClient(std::move(message));
|
| - return;
|
| - }
|
| -
|
| - DCHECK_EQ(message->type(), MessageInTransit::Type::ENDPOINT);
|
| -
|
| - // TODO(vtl)
|
| - // Note that this won't crash on Release builds, which is important (since the
|
| - // other side may be malicious). Doing nothing is safe and will dispose of the
|
| - // message.
|
| - NOTREACHED();
|
| -}
|
| -
|
| -void ChannelEndpoint::DetachFromChannel() {
|
| - scoped_refptr<ChannelEndpointClient> client;
|
| - unsigned client_port = 0;
|
| - {
|
| - MutexLocker locker(&mutex_);
|
| -
|
| - if (client_) {
|
| - // Take a ref, and call |OnDetachFromChannel()| outside the lock.
|
| - client = client_;
|
| - client_port = client_port_;
|
| - }
|
| -
|
| - // |channel_| may already be null if we already detached from the channel in
|
| - // |DetachFromClient()| by calling |Channel::DetachEndpoint()| (and there
|
| - // are racing detaches).
|
| - if (channel_)
|
| - DieNoLock();
|
| - else
|
| - DCHECK(state_ != State::RUNNING);
|
| - }
|
| -
|
| - // If |ReplaceClient()| is called (from another thread) after the above locked
|
| - // section but before we call |OnDetachFromChannel()|, |ReplaceClient()|
|
| - // returns false to notify the caller that the channel was already detached.
|
| - // (The old client has to accept the arguably-spurious call to
|
| - // |OnDetachFromChannel()|.)
|
| - if (client)
|
| - client->OnDetachFromChannel(client_port);
|
| -}
|
| -
|
| -ChannelEndpoint::~ChannelEndpoint() {
|
| - DCHECK(!client_);
|
| - DCHECK(!channel_);
|
| - DCHECK(!local_id_.is_valid());
|
| - DCHECK(!remote_id_.is_valid());
|
| -}
|
| -
|
| -bool ChannelEndpoint::WriteMessageNoLock(scoped_ptr<MessageInTransit> message) {
|
| - DCHECK(message);
|
| -
|
| - mutex_.AssertHeld();
|
| -
|
| - DCHECK(channel_);
|
| - DCHECK(local_id_.is_valid());
|
| - DCHECK(remote_id_.is_valid());
|
| -
|
| - message->SerializeAndCloseDispatchers(channel_);
|
| - message->set_source_id(local_id_);
|
| - message->set_destination_id(remote_id_);
|
| - return channel_->WriteMessage(std::move(message));
|
| -}
|
| -
|
| -void ChannelEndpoint::OnReadMessageForClient(
|
| - scoped_ptr<MessageInTransit> message) {
|
| - DCHECK_EQ(message->type(), MessageInTransit::Type::ENDPOINT_CLIENT);
|
| -
|
| - scoped_refptr<ChannelEndpointClient> client;
|
| - unsigned client_port = 0;
|
| -
|
| - // This loop is to make |ReplaceClient()| work. We can't call the client's
|
| - // |OnReadMessage()| under our lock, so by the time we do that, |client| may
|
| - // no longer be our client.
|
| - //
|
| - // In that case, |client| must return false. We'll then yield, and retry with
|
| - // the new client. (Theoretically, the client could be replaced again.)
|
| - //
|
| - // This solution isn't terribly elegant, but it's the least costly way of
|
| - // handling/avoiding this (very unlikely) race. (Other solutions -- e.g.,
|
| - // adding a client message queue, which the client only fetches messages from
|
| - // -- impose significant cost in the common case.)
|
| - for (;;) {
|
| - {
|
| - MutexLocker locker(&mutex_);
|
| - if (!channel_ || !client_) {
|
| - // This isn't a failure per se. (It just means that, e.g., the other end
|
| - // of the message pipe closed first.)
|
| - return;
|
| - }
|
| -
|
| - // If we get here in a second (third, etc.) iteration of the loop, it's
|
| - // because |ReplaceClient()| was called.
|
| - DCHECK(client_ != client || client_port_ != client_port);
|
| -
|
| - // Take a ref, and call |OnReadMessage()| outside the lock.
|
| - client = client_;
|
| - client_port = client_port_;
|
| - }
|
| -
|
| - if (client->OnReadMessage(client_port, message.get())) {
|
| - ignore_result(message.release());
|
| - break;
|
| - }
|
| -
|
| - base::PlatformThread::YieldCurrentThread();
|
| - }
|
| -}
|
| -
|
| -void ChannelEndpoint::DieNoLock() {
|
| - DCHECK(state_ == State::RUNNING);
|
| - DCHECK(channel_);
|
| - DCHECK(local_id_.is_valid());
|
| - DCHECK(remote_id_.is_valid());
|
| -
|
| - state_ = State::DEAD;
|
| - channel_ = nullptr;
|
| - local_id_ = ChannelEndpointId();
|
| - remote_id_ = ChannelEndpointId();
|
| -}
|
| -
|
| -} // namespace system
|
| -} // namespace mojo
|
|
|