1// Copyright 2015 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "mojo/public/cpp/bindings/pipe_control_message_handler.h"
6
7#include "base/logging.h"
8#include "mojo/public/cpp/bindings/interface_id.h"
9#include "mojo/public/cpp/bindings/lib/message_builder.h"
10#include "mojo/public/cpp/bindings/lib/serialization.h"
11#include "mojo/public/cpp/bindings/lib/serialization_context.h"
12#include "mojo/public/cpp/bindings/lib/validation_context.h"
13#include "mojo/public/cpp/bindings/lib/validation_util.h"
14#include "mojo/public/cpp/bindings/pipe_control_message_handler_delegate.h"
15#include "mojo/public/interfaces/bindings/pipe_control_messages.mojom.h"
16
17namespace mojo {
18
19PipeControlMessageHandler::PipeControlMessageHandler(
20    PipeControlMessageHandlerDelegate* delegate)
21    : delegate_(delegate) {}
22
23PipeControlMessageHandler::~PipeControlMessageHandler() {}
24
25void PipeControlMessageHandler::SetDescription(const std::string& description) {
26  description_ = description;
27}
28
29// static
30bool PipeControlMessageHandler::IsPipeControlMessage(const Message* message) {
31  return !IsValidInterfaceId(message->interface_id());
32}
33
34bool PipeControlMessageHandler::Accept(Message* message) {
35  if (!Validate(message))
36    return false;
37
38  if (message->name() == pipe_control::kRunOrClosePipeMessageId)
39    return RunOrClosePipe(message);
40
41  NOTREACHED();
42  return false;
43}
44
45bool PipeControlMessageHandler::Validate(Message* message) {
46  internal::ValidationContext validation_context(message->payload(),
47                                                 message->payload_num_bytes(),
48                                                 0, 0, message, description_);
49
50  if (message->name() == pipe_control::kRunOrClosePipeMessageId) {
51    if (!internal::ValidateMessageIsRequestWithoutResponse(
52            message, &validation_context)) {
53      return false;
54    }
55    return internal::ValidateMessagePayload<
56        pipe_control::internal::RunOrClosePipeMessageParams_Data>(
57            message, &validation_context);
58  }
59
60  return false;
61}
62
63bool PipeControlMessageHandler::RunOrClosePipe(Message* message) {
64  internal::SerializationContext context;
65  pipe_control::internal::RunOrClosePipeMessageParams_Data* params =
66      reinterpret_cast<
67          pipe_control::internal::RunOrClosePipeMessageParams_Data*>(
68          message->mutable_payload());
69  pipe_control::RunOrClosePipeMessageParamsPtr params_ptr;
70  internal::Deserialize<pipe_control::RunOrClosePipeMessageParamsDataView>(
71      params, &params_ptr, &context);
72
73  if (params_ptr->input->is_peer_associated_endpoint_closed_event()) {
74    const auto& event =
75        params_ptr->input->get_peer_associated_endpoint_closed_event();
76
77    base::Optional<DisconnectReason> reason;
78    if (event->disconnect_reason) {
79      reason.emplace(event->disconnect_reason->custom_reason,
80                     event->disconnect_reason->description);
81    }
82    return delegate_->OnPeerAssociatedEndpointClosed(event->id, reason);
83  }
84
85  DVLOG(1) << "Unsupported command in a RunOrClosePipe message pipe control "
86           << "message. Closing the pipe.";
87  return false;
88}
89
90}  // namespace mojo
91