Skip to content

Commit

Permalink
Mojo bindings: add message pipe control message definition and C++ he…
Browse files Browse the repository at this point in the history
…lpers.

These control messages are necessary for managing associated interfaces running on the pipe.

BUG=546067

Review URL: https://codereview.chromium.org/1453553002

Cr-Commit-Position: refs/heads/master@{#360259}
  • Loading branch information
yzshen authored and Commit bot committed Nov 18, 2015
1 parent de9e5ea commit 8cbbbf3
Show file tree
Hide file tree
Showing 14 changed files with 378 additions and 8 deletions.
7 changes: 7 additions & 0 deletions mojo/public/cpp/bindings/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ source_set("bindings") {
"lib/filter_chain.h",
"lib/fixed_buffer.cc",
"lib/fixed_buffer.h",
"lib/interface_id.h",
"lib/interface_ptr_internal.h",
"lib/map_data_internal.h",
"lib/map_internal.h",
Expand All @@ -42,6 +43,11 @@ source_set("bindings") {
"lib/message_header_validator.h",
"lib/message_internal.h",
"lib/no_interface.cc",
"lib/pipe_control_message_handler.cc",
"lib/pipe_control_message_handler.h",
"lib/pipe_control_message_handler_delegate.h",
"lib/pipe_control_message_proxy.cc",
"lib/pipe_control_message_proxy.h",
"lib/router.cc",
"lib/router.h",
"lib/string_serialization.cc",
Expand Down Expand Up @@ -69,6 +75,7 @@ source_set("bindings") {
]

deps = [
"//base",
"//mojo/public/cpp/environment",
"//mojo/public/interfaces/bindings:bindings_cpp_sources",
]
Expand Down
5 changes: 3 additions & 2 deletions mojo/public/cpp/bindings/lib/bindings_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDINGS_INTERNAL_H_
#define MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDINGS_INTERNAL_H_

#include "mojo/public/cpp/bindings/lib/interface_id.h"
#include "mojo/public/cpp/bindings/lib/template_util.h"
#include "mojo/public/cpp/bindings/struct_ptr.h"
#include "mojo/public/cpp/system/core.h"
Expand Down Expand Up @@ -64,13 +65,13 @@ struct Interface_Data {
static_assert(sizeof(Interface_Data) == 8, "Bad_sizeof(Interface_Data)");

struct AssociatedInterface_Data {
uint32_t interface_id;
InterfaceId interface_id;
uint32_t version;
};
static_assert(sizeof(AssociatedInterface_Data) == 8,
"Bad_sizeof(AssociatedInterface_Data)");

using AssociatedInterfaceRequest_Data = uint32_t;
using AssociatedInterfaceRequest_Data = InterfaceId;

#pragma pack(pop)

Expand Down
37 changes: 37 additions & 0 deletions mojo/public/cpp/bindings/lib/interface_id.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright 2015 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.

#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_INTERFACE_ID_H_
#define MOJO_PUBLIC_CPP_BINDINGS_LIB_INTERFACE_ID_H_

#include <stdint.h>

namespace mojo {
namespace internal {

// The size of the type matters because it is directly used in messages.
using InterfaceId = uint32_t;

// IDs of associated interface can be generated at both sides of the message
// pipe. In order to avoid collision, the highest bit is used as namespace bit:
// at the side where the client-side of the master interface lives, IDs are
// generated with the namespace bit set to 1; at the opposite side IDs are
// generated with the namespace bit set to 0.
const uint32_t kInterfaceIdNamespaceMask = 0x80000000;

const InterfaceId kMasterInterfaceId = 0x00000000;
const InterfaceId kInvalidInterfaceId = 0xFFFFFFFF;

inline bool IsMasterInterfaceId(InterfaceId id) {
return id == kMasterInterfaceId;
}

inline bool IsValidInterfaceId(InterfaceId id) {
return id != kInvalidInterfaceId;
}

} // namespace internal
} // namespace mojo

#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_INTERFACE_ID_H_
75 changes: 75 additions & 0 deletions mojo/public/cpp/bindings/lib/pipe_control_message_handler.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Copyright 2015 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 "mojo/public/cpp/bindings/lib/pipe_control_message_handler.h"

#include "base/logging.h"
#include "mojo/public/cpp/bindings/lib/message_builder.h"
#include "mojo/public/cpp/bindings/lib/pipe_control_message_handler_delegate.h"
#include "mojo/public/cpp/bindings/lib/validation_util.h"
#include "mojo/public/interfaces/bindings/pipe_control_messages.mojom.h"

namespace mojo {
namespace internal {

PipeControlMessageHandler::PipeControlMessageHandler(
PipeControlMessageHandlerDelegate* delegate)
: delegate_(delegate) {}

PipeControlMessageHandler::~PipeControlMessageHandler() {}

// static
bool PipeControlMessageHandler::IsPipeControlMessage(const Message* message) {
return !IsValidInterfaceId(message->interface_id());
}

bool PipeControlMessageHandler::Accept(Message* message) {
if (!Validate(message))
return false;

if (message->name() == pipe_control::kRunOrClosePipeMessageId)
return RunOrClosePipe(message);

NOTREACHED();
return false;
}

bool PipeControlMessageHandler::Validate(const Message* message) {
if (message->name() == pipe_control::kRunOrClosePipeMessageId) {
if (!ValidateMessageIsRequestWithoutResponse(message))
return false;
return ValidateMessagePayload<
pipe_control::internal::RunOrClosePipeMessageParams_Data>(message);
}

return false;
}

bool PipeControlMessageHandler::RunOrClosePipe(Message* message) {
pipe_control::internal::RunOrClosePipeMessageParams_Data* params =
reinterpret_cast<
pipe_control::internal::RunOrClosePipeMessageParams_Data*>(
message->mutable_payload());
params->DecodePointersAndHandles(message->mutable_handles());

pipe_control::RunOrClosePipeMessageParamsPtr params_ptr;
Deserialize_(params, &params_ptr);

if (params_ptr->input->is_peer_associated_endpoint_closed_event()) {
return delegate_->OnPeerAssociatedEndpointClosed(
params_ptr->input->get_peer_associated_endpoint_closed_event()->id);
}
if (params_ptr->input->is_associated_endpoint_closed_before_sent_event()) {
return delegate_->OnAssociatedEndpointClosedBeforeSent(
params_ptr->input->get_associated_endpoint_closed_before_sent_event()
->id);
}

DVLOG(1) << "Unsupported command in a RunOrClosePipe message pipe control "
<< "message. Closing the pipe.";
return false;
}

} // namespace internal
} // namespace mojo
48 changes: 48 additions & 0 deletions mojo/public/cpp/bindings/lib/pipe_control_message_handler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright 2015 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.

#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_PIPE_CONTROL_MESSAGE_HANDLER_H_
#define MOJO_PUBLIC_CPP_BINDINGS_LIB_PIPE_CONTROL_MESSAGE_HANDLER_H_

#include "base/macros.h"
#include "mojo/public/cpp/bindings/lib/interface_id.h"
#include "mojo/public/cpp/bindings/message.h"

namespace mojo {
namespace internal {

class PipeControlMessageHandlerDelegate;

// Handler for messages defined in pipe_control_messages.mojom.
class PipeControlMessageHandler : public MessageReceiver {
public:
explicit PipeControlMessageHandler(
PipeControlMessageHandlerDelegate* delegate);
~PipeControlMessageHandler() override;

// NOTE: |message| must have passed message header validation.
static bool IsPipeControlMessage(const Message* message);

// MessageReceiver implementation:

// NOTE: |message| must:
// - have passed message header validation; and
// - be a pipe control message (i.e., IsPipeControlMessage() returns true).
// If the method returns false, the message pipe should be closed.
bool Accept(Message* message) override;

private:
// |message| must have passed message header validation.
bool Validate(const Message* message);
bool RunOrClosePipe(Message* message);

PipeControlMessageHandlerDelegate* const delegate_;

DISALLOW_COPY_AND_ASSIGN(PipeControlMessageHandler);
};

} // namespace internal
} // namespace mojo

#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_PIPE_CONTROL_MESSAGE_HANDLER_H_
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright 2015 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.

#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_PIPE_CONTROL_MESSAGE_HANDLER_DELEGATE_H_
#define MOJO_PUBLIC_CPP_BINDINGS_LIB_PIPE_CONTROL_MESSAGE_HANDLER_DELEGATE_H_

#include "mojo/public/cpp/bindings/lib/interface_id.h"

namespace mojo {
namespace internal {

class PipeControlMessageHandlerDelegate {
public:
// The implementation of the following methods should return false if the
// notification is unexpected. In that case, the user of this delegate is
// expected to close the message pipe.
virtual bool OnPeerAssociatedEndpointClosed(InterfaceId id) = 0;
virtual bool OnAssociatedEndpointClosedBeforeSent(InterfaceId id) = 0;

protected:
virtual ~PipeControlMessageHandlerDelegate() {}
};

} // namespace internal
} // namespace mojo

#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_PIPE_CONTROL_MESSAGE_HANDLER_DELEGATE_H_
65 changes: 65 additions & 0 deletions mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Copyright 2015 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 "mojo/public/cpp/bindings/lib/pipe_control_message_proxy.h"

#include "base/compiler_specific.h"
#include "mojo/public/cpp/bindings/lib/message_builder.h"
#include "mojo/public/cpp/bindings/message.h"
#include "mojo/public/interfaces/bindings/pipe_control_messages.mojom.h"

namespace mojo {
namespace internal {
namespace {

void SendRunOrClosePipeMessage(MessageReceiver* receiver,
pipe_control::RunOrClosePipeInputPtr input) {
pipe_control::RunOrClosePipeMessageParamsPtr params_ptr(
pipe_control::RunOrClosePipeMessageParams::New());
params_ptr->input = input.Pass();

size_t size = GetSerializedSize_(params_ptr);
MessageBuilder builder(pipe_control::kRunOrClosePipeMessageId, size);

pipe_control::internal::RunOrClosePipeMessageParams_Data* params = nullptr;
Serialize_(params_ptr.Pass(), builder.buffer(), &params);
params->EncodePointersAndHandles(builder.message()->mutable_handles());
builder.message()->set_interface_id(kInvalidInterfaceId);
bool ok = receiver->Accept(builder.message());
// This return value may be ignored as !ok implies the underlying message pipe
// has encountered an error, which will be visible through other means.
ALLOW_UNUSED_LOCAL(ok);
}

} // namespace

PipeControlMessageProxy::PipeControlMessageProxy(MessageReceiver* receiver)
: receiver_(receiver) {}

void PipeControlMessageProxy::NotifyPeerEndpointClosed(InterfaceId id) {
pipe_control::PeerAssociatedEndpointClosedEventPtr event(
pipe_control::PeerAssociatedEndpointClosedEvent::New());
event->id = id;

pipe_control::RunOrClosePipeInputPtr input(
pipe_control::RunOrClosePipeInput::New());
input->set_peer_associated_endpoint_closed_event(event.Pass());

SendRunOrClosePipeMessage(receiver_, input.Pass());
}

void PipeControlMessageProxy::NotifyEndpointClosedBeforeSent(InterfaceId id) {
pipe_control::AssociatedEndpointClosedBeforeSentEventPtr event(
pipe_control::AssociatedEndpointClosedBeforeSentEvent::New());
event->id = id;

pipe_control::RunOrClosePipeInputPtr input(
pipe_control::RunOrClosePipeInput::New());
input->set_associated_endpoint_closed_before_sent_event(event.Pass());

SendRunOrClosePipeMessage(receiver_, input.Pass());
}

} // namespace internal
} // namespace mojo
36 changes: 36 additions & 0 deletions mojo/public/cpp/bindings/lib/pipe_control_message_proxy.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright 2015 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.

#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_PIPE_CONTROL_MESSAGE_PROXY_H_
#define MOJO_PUBLIC_CPP_BINDINGS_LIB_PIPE_CONTROL_MESSAGE_PROXY_H_

#include "base/macros.h"
#include "mojo/public/cpp/bindings/lib/interface_id.h"

namespace mojo {

class MessageReceiver;

namespace internal {

// Proxy for request messages defined in pipe_control_messages.mojom.
class PipeControlMessageProxy {
public:
// Doesn't take ownership of |receiver|. It must outlive this object.
explicit PipeControlMessageProxy(MessageReceiver* receiver);

void NotifyPeerEndpointClosed(InterfaceId id);
void NotifyEndpointClosedBeforeSent(InterfaceId id);

private:
// Not owned.
MessageReceiver* receiver_;

DISALLOW_COPY_AND_ASSIGN(PipeControlMessageProxy);
};

} // namespace internal
} // namespace mojo

#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_PIPE_CONTROL_MESSAGE_PROXY_H_
3 changes: 3 additions & 0 deletions mojo/public/cpp/bindings/message.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ class Message {
// Access the header.
const internal::MessageHeader* header() const { return &data_->header; }

uint32_t interface_id() const { return data_->header.interface_id; }
void set_interface_id(uint32_t id) { data_->header.interface_id = id; }

uint32_t name() const { return data_->header.name; }
bool has_flag(uint32_t flag) const { return !!(data_->header.flags & flag); }

Expand Down
1 change: 1 addition & 0 deletions mojo/public/interfaces/bindings/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import("../../tools/bindings/mojom.gni")
mojom("bindings") {
sources = [
"interface_control_messages.mojom",
"pipe_control_messages.mojom",
]

with_environment = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

[DartPackage="mojo", JavaPackage="org.chromium.mojo.bindings"]
[JavaPackage="org.chromium.mojo.bindings"]
module mojo;

// For each message pipe representing a user-defined interface, some control
// functions are provided at the same end of the message pipe as the
// user-defined interface, providing information about the user-defined
// interface and controlling behavior of the message pipe.
// For each user-defined interface, some control functions are provided at the
// same end of the message pipe as the user-defined interface, providing
// information about the user-defined interface.

////////////////////////////////////////////////////////////////////////////////
// Run@0xFFFFFFFF(RunInput input) => (RunOutput? output);
Expand Down
Loading

0 comments on commit 8cbbbf3

Please sign in to comment.