| Index: mojo/edk/system/channel.cc
|
| diff --git a/mojo/edk/system/channel.cc b/mojo/edk/system/channel.cc
|
| index 0582b23301006f1b716849037340f3040b9de000..f008bec2cc7a2e1159414be721ed379d55f0fab3 100644
|
| --- a/mojo/edk/system/channel.cc
|
| +++ b/mojo/edk/system/channel.cc
|
| @@ -12,7 +12,6 @@
|
| #include "base/macros.h"
|
| #include "base/strings/stringprintf.h"
|
| #include "mojo/edk/embedder/platform_handle_vector.h"
|
| -#include "mojo/edk/system/message_pipe_endpoint.h"
|
| #include "mojo/edk/system/transport_data.h"
|
|
|
| namespace mojo {
|
| @@ -125,8 +124,9 @@ void Channel::RunEndpoint(scoped_refptr<ChannelEndpoint> endpoint,
|
| endpoint->Run(remote_id);
|
| }
|
|
|
| -void Channel::AttachAndRunEndpoint(scoped_refptr<ChannelEndpoint> endpoint,
|
| - bool is_bootstrap) {
|
| +ChannelEndpointId Channel::AttachAndRunEndpoint(
|
| + scoped_refptr<ChannelEndpoint> endpoint,
|
| + bool is_bootstrap) {
|
| DCHECK(endpoint.get());
|
|
|
| ChannelEndpointId local_id;
|
| @@ -144,8 +144,6 @@ void Channel::AttachAndRunEndpoint(scoped_refptr<ChannelEndpoint> endpoint,
|
|
|
| remote_id = ChannelEndpointId::GetBootstrap();
|
| } else {
|
| - // TODO(vtl): More work needs to be done to enable the non-bootstrap case.
|
| - NOTREACHED() << "Non-bootstrap case not yet fully implemented";
|
| do {
|
| local_id = local_id_generator_.GetNext();
|
| } while (local_id_to_endpoint_map_.find(local_id) !=
|
| @@ -158,29 +156,22 @@ void Channel::AttachAndRunEndpoint(scoped_refptr<ChannelEndpoint> endpoint,
|
| local_id_to_endpoint_map_[local_id] = endpoint;
|
| }
|
|
|
| - endpoint->AttachAndRun(this, local_id, remote_id);
|
| -}
|
| -
|
| -void Channel::RunRemoteMessagePipeEndpoint(ChannelEndpointId local_id,
|
| - ChannelEndpointId remote_id) {
|
| -#if DCHECK_IS_ON
|
| - {
|
| - base::AutoLock locker(lock_);
|
| - DCHECK(local_id_to_endpoint_map_.find(local_id) !=
|
| - local_id_to_endpoint_map_.end());
|
| + if (!is_bootstrap) {
|
| + if (!SendControlMessage(
|
| + MessageInTransit::kSubtypeChannelAttachAndRunEndpoint,
|
| + local_id,
|
| + remote_id)) {
|
| + HandleLocalError(base::StringPrintf(
|
| + "Failed to send message to run remote message pipe endpoint (local "
|
| + "ID %u, remote ID %u)",
|
| + static_cast<unsigned>(local_id.value()),
|
| + static_cast<unsigned>(remote_id.value())));
|
| + // TODO(vtl): Should we continue on to |AttachAndRun()|?
|
| + }
|
| }
|
| -#endif
|
|
|
| - if (!SendControlMessage(
|
| - MessageInTransit::kSubtypeChannelRunMessagePipeEndpoint,
|
| - local_id,
|
| - remote_id)) {
|
| - HandleLocalError(base::StringPrintf(
|
| - "Failed to send message to run remote message pipe endpoint (local ID "
|
| - "%u, remote ID %u)",
|
| - static_cast<unsigned>(local_id.value()),
|
| - static_cast<unsigned>(remote_id.value())));
|
| - }
|
| + endpoint->AttachAndRun(this, local_id, remote_id);
|
| + return remote_id;
|
| }
|
|
|
| bool Channel::WriteMessage(scoped_ptr<MessageInTransit> message) {
|
| @@ -243,6 +234,25 @@ void Channel::DetachEndpoint(ChannelEndpoint* endpoint,
|
| }
|
| }
|
|
|
| +scoped_refptr<MessagePipe> Channel::PassIncomingMessagePipe(
|
| + ChannelEndpointId local_id) {
|
| + // No need to check the validity of |local_id| -- if it's not valid, it simply
|
| + // won't be in |incoming_message_pipes_|.
|
| + DVLOG_IF(2, !local_id.is_valid() || !local_id.is_remote())
|
| + << "Attempt to get invalid incoming message pipe for ID " << local_id;
|
| +
|
| + base::AutoLock locker(lock_);
|
| +
|
| + auto it = incoming_message_pipes_.find(local_id);
|
| + if (it == incoming_message_pipes_.end())
|
| + return scoped_refptr<MessagePipe>();
|
| +
|
| + scoped_refptr<MessagePipe> rv;
|
| + rv.swap(it->second);
|
| + incoming_message_pipes_.erase(it);
|
| + return rv;
|
| +}
|
| +
|
| size_t Channel::GetSerializedPlatformHandleSize() const {
|
| return raw_channel_->GetSerializedPlatformHandleSize();
|
| }
|
| @@ -375,14 +385,14 @@ void Channel::OnReadMessageForChannel(
|
| }
|
|
|
| switch (message_view.subtype()) {
|
| - case MessageInTransit::kSubtypeChannelRunMessagePipeEndpoint:
|
| - DVLOG(2) << "Handling channel message to run message pipe (local ID "
|
| - << message_view.destination_id() << ", remote ID "
|
| - << message_view.source_id() << ")";
|
| - if (!OnRunMessagePipeEndpoint(message_view.destination_id(),
|
| - message_view.source_id())) {
|
| + case MessageInTransit::kSubtypeChannelAttachAndRunEndpoint:
|
| + DVLOG(2) << "Handling channel message to attach and run message pipe "
|
| + "(local ID " << message_view.destination_id()
|
| + << ", remote ID " << message_view.source_id() << ")";
|
| + if (!OnAttachAndRunEndpoint(message_view.destination_id(),
|
| + message_view.source_id())) {
|
| HandleRemoteError(
|
| - "Received invalid channel message to run message pipe");
|
| + "Received invalid channel message to attach and run message pipe");
|
| }
|
| break;
|
| case MessageInTransit::kSubtypeChannelRemoveMessagePipeEndpoint:
|
| @@ -411,20 +421,51 @@ void Channel::OnReadMessageForChannel(
|
| }
|
| }
|
|
|
| -bool Channel::OnRunMessagePipeEndpoint(ChannelEndpointId local_id,
|
| - ChannelEndpointId remote_id) {
|
| +bool Channel::OnAttachAndRunEndpoint(ChannelEndpointId local_id,
|
| + ChannelEndpointId remote_id) {
|
| + // We should only get this for remotely-created local endpoints, so our local
|
| + // ID should be "remote".
|
| + if (!local_id.is_valid() || !local_id.is_remote()) {
|
| + DVLOG(2) << "Received attach and run endpoint with invalid local ID";
|
| + return false;
|
| + }
|
| +
|
| + // Conversely, the remote end should be "local".
|
| + if (!remote_id.is_valid() || remote_id.is_remote()) {
|
| + DVLOG(2) << "Received attach and run endpoint with invalid remote ID";
|
| + return false;
|
| + }
|
| +
|
| + // Create a message pipe and thus an endpoint (outside the lock).
|
| scoped_refptr<ChannelEndpoint> endpoint;
|
| + scoped_refptr<MessagePipe> message_pipe(
|
| + MessagePipe::CreateLocalProxy(&endpoint));
|
| +
|
| + bool success = true;
|
| {
|
| base::AutoLock locker(lock_);
|
|
|
| - IdToEndpointMap::iterator it = local_id_to_endpoint_map_.find(local_id);
|
| - if (it == local_id_to_endpoint_map_.end())
|
| - return false;
|
| + if (local_id_to_endpoint_map_.find(local_id) ==
|
| + local_id_to_endpoint_map_.end()) {
|
| + DCHECK(incoming_message_pipes_.find(local_id) ==
|
| + incoming_message_pipes_.end());
|
|
|
| - endpoint = it->second;
|
| + // TODO(vtl): Use emplace when we move to C++11 unordered_maps. (It'll
|
| + // avoid some refcount churn.)
|
| + local_id_to_endpoint_map_[local_id] = endpoint;
|
| + incoming_message_pipes_[local_id] = message_pipe;
|
| + } else {
|
| + // We need to call |Close()| on the message pipe outside the lock.
|
| + success = false;
|
| + }
|
| + }
|
| + if (!success) {
|
| + DVLOG(2) << "Received attach and run endpoint for existing local ID";
|
| + message_pipe->Close(0);
|
| + return false;
|
| }
|
|
|
| - RunEndpoint(endpoint, remote_id);
|
| + endpoint->AttachAndRun(this, local_id, remote_id);
|
| return true;
|
| }
|
|
|
|
|