• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 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/message.h"
6 
7 #include <stddef.h>
8 #include <stdint.h>
9 #include <stdlib.h>
10 
11 #include <algorithm>
12 #include <utility>
13 
14 #include "base/logging.h"
15 #include "base/strings/stringprintf.h"
16 
17 namespace mojo {
18 
Message()19 Message::Message() {
20 }
21 
~Message()22 Message::~Message() {
23   CloseHandles();
24 }
25 
Initialize(size_t capacity,bool zero_initialized)26 void Message::Initialize(size_t capacity, bool zero_initialized) {
27   DCHECK(!buffer_);
28   buffer_.reset(new internal::MessageBuffer(capacity, zero_initialized));
29 }
30 
InitializeFromMojoMessage(ScopedMessageHandle message,uint32_t num_bytes,std::vector<Handle> * handles)31 void Message::InitializeFromMojoMessage(ScopedMessageHandle message,
32                                         uint32_t num_bytes,
33                                         std::vector<Handle>* handles) {
34   DCHECK(!buffer_);
35   buffer_.reset(new internal::MessageBuffer(std::move(message), num_bytes));
36   handles_.swap(*handles);
37 }
38 
MoveTo(Message * destination)39 void Message::MoveTo(Message* destination) {
40   DCHECK(this != destination);
41 
42   // No copy needed.
43   std::swap(destination->buffer_, buffer_);
44   std::swap(destination->handles_, handles_);
45 
46   CloseHandles();
47   handles_.clear();
48   buffer_.reset();
49 }
50 
TakeMojoMessage()51 ScopedMessageHandle Message::TakeMojoMessage() {
52   if (handles_.empty())  // Fast path for the common case: No handles.
53     return buffer_->TakeMessage();
54 
55   // Allocate a new message with space for the handles, then copy the buffer
56   // contents into it.
57   //
58   // TODO(rockot): We could avoid this copy by extending GetSerializedSize()
59   // behavior to collect handles. It's unoptimized for now because it's much
60   // more common to have messages with no handles.
61   ScopedMessageHandle new_message;
62   MojoResult rv = AllocMessage(
63       data_num_bytes(),
64       handles_.empty() ? nullptr
65                        : reinterpret_cast<const MojoHandle*>(handles_.data()),
66       handles_.size(),
67       MOJO_ALLOC_MESSAGE_FLAG_NONE,
68       &new_message);
69   CHECK_EQ(rv, MOJO_RESULT_OK);
70   handles_.clear();
71 
72   void* new_buffer = nullptr;
73   rv = GetMessageBuffer(new_message.get(), &new_buffer);
74   CHECK_EQ(rv, MOJO_RESULT_OK);
75 
76   memcpy(new_buffer, data(), data_num_bytes());
77   buffer_.reset();
78 
79   return new_message;
80 }
81 
NotifyBadMessage(const std::string & error)82 void Message::NotifyBadMessage(const std::string& error) {
83   buffer_->NotifyBadMessage(error);
84 }
85 
CloseHandles()86 void Message::CloseHandles() {
87   for (std::vector<Handle>::iterator it = handles_.begin();
88        it != handles_.end(); ++it) {
89     if (it->is_valid())
90       CloseRaw(*it);
91   }
92 }
93 
ReadMessage(MessagePipeHandle handle,Message * message)94 MojoResult ReadMessage(MessagePipeHandle handle, Message* message) {
95   MojoResult rv;
96 
97   std::vector<Handle> handles;
98   ScopedMessageHandle mojo_message;
99   uint32_t num_bytes = 0, num_handles = 0;
100   rv = ReadMessageNew(handle,
101                       &mojo_message,
102                       &num_bytes,
103                       nullptr,
104                       &num_handles,
105                       MOJO_READ_MESSAGE_FLAG_NONE);
106   if (rv == MOJO_RESULT_RESOURCE_EXHAUSTED) {
107     DCHECK_GT(num_handles, 0u);
108     handles.resize(num_handles);
109     rv = ReadMessageNew(handle,
110                         &mojo_message,
111                         &num_bytes,
112                         reinterpret_cast<MojoHandle*>(handles.data()),
113                         &num_handles,
114                         MOJO_READ_MESSAGE_FLAG_NONE);
115   }
116 
117   if (rv != MOJO_RESULT_OK)
118     return rv;
119 
120   message->InitializeFromMojoMessage(
121       std::move(mojo_message), num_bytes, &handles);
122   return MOJO_RESULT_OK;
123 }
124 
125 }  // namespace mojo
126