1 // Copyright 2014 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.
5 #include "ipc/mojo/ipc_message_pipe_reader.h"
8 #include "base/bind_helpers.h"
9 #include "base/location.h"
10 #include "base/logging.h"
11 #include "base/message_loop/message_loop_proxy.h"
12 #include "mojo/public/cpp/environment/environment.h"
17 MessagePipeReader::MessagePipeReader(mojo::ScopedMessagePipeHandle handle
)
19 pipe_(handle
.Pass()) {
23 MessagePipeReader::~MessagePipeReader() {
27 void MessagePipeReader::Close() {
33 void MessagePipeReader::CloseWithError(MojoResult error
) {
39 void MessagePipeReader::InvokePipeIsReady(void* closure
, MojoResult result
) {
40 reinterpret_cast<MessagePipeReader
*>(closure
)->PipeIsReady(result
);
43 void MessagePipeReader::StartWaiting() {
44 DCHECK(pipe_
.is_valid());
45 DCHECK(!pipe_wait_id_
);
46 // Not using MOJO_HANDLE_SIGNAL_WRITABLE here, expecting buffer in
49 // TODO(morrita): Should we re-set the signal when we get new
51 pipe_wait_id_
= mojo::Environment::GetDefaultAsyncWaiter()->AsyncWait(
53 MOJO_HANDLE_SIGNAL_READABLE
,
54 MOJO_DEADLINE_INDEFINITE
,
59 void MessagePipeReader::StopWaiting() {
62 mojo::Environment::GetDefaultAsyncWaiter()->CancelWait(pipe_wait_id_
);
66 void MessagePipeReader::PipeIsReady(MojoResult wait_result
) {
69 if (wait_result
!= MOJO_RESULT_OK
) {
70 if (wait_result
!= MOJO_RESULT_ABORTED
) {
71 // FAILED_PRECONDITION happens every time the peer is dead so
72 // it isn't worth polluting the log message.
73 DLOG_IF(WARNING
, wait_result
!= MOJO_RESULT_FAILED_PRECONDITION
)
74 << "Pipe got error from the waiter. Closing: "
76 OnPipeError(wait_result
);
83 while (pipe_
.is_valid()) {
84 MojoResult read_result
= ReadMessageBytes();
85 if (read_result
== MOJO_RESULT_SHOULD_WAIT
)
87 if (read_result
!= MOJO_RESULT_OK
) {
88 // FAILED_PRECONDITION means that all the received messages
89 // got consumed and the peer is already closed.
90 if (read_result
!= MOJO_RESULT_FAILED_PRECONDITION
) {
92 << "Pipe got error from ReadMessage(). Closing: " << read_result
;
93 OnPipeError(read_result
);
103 if (pipe_
.is_valid())
107 MojoResult
MessagePipeReader::ReadMessageBytes() {
108 DCHECK(handle_buffer_
.empty());
110 uint32_t num_bytes
= static_cast<uint32_t>(data_buffer_
.size());
111 uint32_t num_handles
= 0;
112 MojoResult result
= MojoReadMessage(pipe_
.get().value(),
113 num_bytes
? &data_buffer_
[0] : NULL
,
117 MOJO_READ_MESSAGE_FLAG_NONE
);
118 data_buffer_
.resize(num_bytes
);
119 handle_buffer_
.resize(num_handles
);
120 if (result
== MOJO_RESULT_RESOURCE_EXHAUSTED
) {
121 // MOJO_RESULT_RESOURCE_EXHAUSTED was asking the caller that
122 // it needs more bufer. So we re-read it with resized buffers.
123 result
= MojoReadMessage(pipe_
.get().value(),
124 num_bytes
? &data_buffer_
[0] : NULL
,
126 num_handles
? &handle_buffer_
[0] : NULL
,
128 MOJO_READ_MESSAGE_FLAG_NONE
);
131 DCHECK(0 == num_bytes
|| data_buffer_
.size() == num_bytes
);
132 DCHECK(0 == num_handles
|| handle_buffer_
.size() == num_handles
);
136 void MessagePipeReader::DelayedDeleter::operator()(
137 MessagePipeReader
* ptr
) const {
139 base::MessageLoopProxy::current()->PostTask(
140 FROM_HERE
, base::Bind(&DeleteNow
, ptr
));
143 } // namespace internal