Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "mojo/public/cpp/bindings/message.h" | 5 #include "mojo/public/cpp/bindings/message.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 #include <stdlib.h> | 9 #include <stdlib.h> |
| 10 | 10 |
| 11 #include <algorithm> | 11 #include <algorithm> |
| 12 #include <utility> | |
| 12 | 13 |
| 13 #include "base/logging.h" | 14 #include "base/logging.h" |
| 14 | 15 |
| 15 namespace mojo { | 16 namespace mojo { |
| 16 | 17 |
| 17 Message::Message() { | 18 Message::Message() { |
| 18 } | 19 } |
| 19 | 20 |
| 20 Message::~Message() { | 21 Message::~Message() { |
| 21 CloseHandles(); | 22 CloseHandles(); |
| 22 } | 23 } |
| 23 | 24 |
| 24 void Message::Initialize(size_t capacity, bool zero_initialized) { | 25 void Message::Initialize(size_t capacity, bool zero_initialized) { |
| 25 DCHECK(!buffer_); | 26 DCHECK(!buffer_); |
| 26 buffer_.reset(new internal::PickleBuffer(capacity, zero_initialized)); | 27 buffer_.reset(new internal::MessageBuffer(capacity, zero_initialized)); |
| 28 } | |
| 29 | |
| 30 void Message::InitializeFromMojoMessage(ScopedMessageHandle message, | |
| 31 uint32_t num_bytes, | |
| 32 std::vector<Handle>* handles) { | |
| 33 DCHECK(!buffer_); | |
| 34 buffer_.reset(new internal::MessageBuffer(std::move(message), num_bytes)); | |
| 35 handles_.swap(*handles); | |
| 27 } | 36 } |
| 28 | 37 |
| 29 void Message::MoveTo(Message* destination) { | 38 void Message::MoveTo(Message* destination) { |
| 30 DCHECK(this != destination); | 39 DCHECK(this != destination); |
| 31 | 40 |
| 32 // No copy needed. | 41 // No copy needed. |
| 33 std::swap(destination->buffer_, buffer_); | 42 std::swap(destination->buffer_, buffer_); |
| 34 std::swap(destination->handles_, handles_); | 43 std::swap(destination->handles_, handles_); |
| 35 | 44 |
| 36 CloseHandles(); | 45 CloseHandles(); |
| 37 handles_.clear(); | 46 handles_.clear(); |
| 38 buffer_.reset(); | 47 buffer_.reset(); |
| 39 } | 48 } |
| 40 | 49 |
| 50 ScopedMessageHandle Message::TakeMojoMessage() { | |
| 51 if (handles_.empty()) // Fast path for the common case: No handles. | |
| 52 return buffer_->TakeMessage(); | |
| 53 | |
| 54 // Allocate a new message with space for the handles, then copy the buffer | |
| 55 // contents into it. | |
| 56 // | |
| 57 // TODO(rockot): We could avoid this copy by extending GetSerializedSize() | |
| 58 // behavior to collect handle counts. It's unoptimized for now because it's | |
|
yzshen1
2016/04/29 16:50:20
According to my understanding, it needs to collect
Ken Rockot(use gerrit already)
2016/04/29 17:37:12
Fixed comment
| |
| 59 // much more common to have messages with no handles. | |
| 60 ScopedMessageHandle new_message; | |
| 61 MojoResult rv = AllocMessage( | |
| 62 data_num_bytes(), | |
| 63 handles_.empty() ? nullptr | |
| 64 : reinterpret_cast<const MojoHandle*>(handles_.data()), | |
| 65 handles_.size(), | |
| 66 MOJO_ALLOC_MESSAGE_FLAG_NONE, | |
| 67 &new_message); | |
| 68 CHECK_EQ(rv, MOJO_RESULT_OK); | |
| 69 handles_.clear(); | |
| 70 | |
| 71 void* new_buffer = nullptr; | |
| 72 rv = GetMessageBuffer(new_message.get(), &new_buffer); | |
| 73 CHECK_EQ(rv, MOJO_RESULT_OK); | |
| 74 | |
| 75 memcpy(new_buffer, data(), data_num_bytes()); | |
| 76 buffer_.reset(); | |
| 77 | |
| 78 return new_message; | |
| 79 } | |
| 80 | |
| 41 void Message::CloseHandles() { | 81 void Message::CloseHandles() { |
| 42 for (std::vector<Handle>::iterator it = handles_.begin(); | 82 for (std::vector<Handle>::iterator it = handles_.begin(); |
| 43 it != handles_.end(); ++it) { | 83 it != handles_.end(); ++it) { |
| 44 if (it->is_valid()) | 84 if (it->is_valid()) |
| 45 CloseRaw(*it); | 85 CloseRaw(*it); |
| 46 } | 86 } |
| 47 } | 87 } |
| 48 | 88 |
| 49 MojoResult ReadMessage(MessagePipeHandle handle, Message* message) { | 89 MojoResult ReadMessage(MessagePipeHandle handle, Message* message) { |
| 50 MojoResult rv; | 90 MojoResult rv; |
| 51 | 91 |
| 92 std::vector<Handle> handles; | |
| 93 ScopedMessageHandle mojo_message; | |
| 52 uint32_t num_bytes = 0, num_handles = 0; | 94 uint32_t num_bytes = 0, num_handles = 0; |
| 53 rv = ReadMessageRaw(handle, | 95 rv = ReadMessageNew(handle, |
| 54 nullptr, | 96 &mojo_message, |
| 55 &num_bytes, | 97 &num_bytes, |
| 56 nullptr, | 98 nullptr, |
| 57 &num_handles, | 99 &num_handles, |
| 58 MOJO_READ_MESSAGE_FLAG_NONE); | 100 MOJO_READ_MESSAGE_FLAG_NONE); |
| 59 if (rv != MOJO_RESULT_RESOURCE_EXHAUSTED) | 101 if (rv == MOJO_RESULT_RESOURCE_EXHAUSTED) { |
| 102 DCHECK_GT(num_handles, 0u); | |
| 103 handles.resize(num_handles); | |
| 104 rv = ReadMessageNew(handle, | |
| 105 &mojo_message, | |
| 106 &num_bytes, | |
| 107 reinterpret_cast<MojoHandle*>(handles.data()), | |
| 108 &num_handles, | |
| 109 MOJO_READ_MESSAGE_FLAG_NONE); | |
| 110 } | |
| 111 | |
| 112 if (rv != MOJO_RESULT_OK) | |
| 60 return rv; | 113 return rv; |
| 61 | 114 |
| 62 message->Initialize(num_bytes, false /* zero_initialized */); | 115 message->InitializeFromMojoMessage( |
| 63 | 116 std::move(mojo_message), num_bytes, &handles); |
| 64 void* mutable_data = message->buffer()->Allocate(num_bytes); | 117 return MOJO_RESULT_OK; |
| 65 message->mutable_handles()->resize(num_handles); | |
| 66 | |
| 67 rv = ReadMessageRaw( | |
| 68 handle, mutable_data, &num_bytes, | |
| 69 message->mutable_handles()->empty() | |
| 70 ? nullptr | |
| 71 : reinterpret_cast<MojoHandle*>(message->mutable_handles()->data()), | |
| 72 &num_handles, MOJO_READ_MESSAGE_FLAG_NONE); | |
| 73 return rv; | |
| 74 } | 118 } |
| 75 | 119 |
| 76 } // namespace mojo | 120 } // namespace mojo |
| OLD | NEW |