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_channel_mojo_readers.h"
7 #include "ipc/mojo/ipc_channel_mojo.h"
8 #include "mojo/embedder/embedder.h"
10 #if defined(OS_POSIX) && !defined(OS_NACL)
11 #include "ipc/file_descriptor_set_posix.h"
19 // TODO(morrita): This should be built using higher-level Mojo construct
20 // for clarity and extensibility.
23 static Pickle
CreateRequest(int32 pid
) {
25 request
.WriteString(kHelloRequestMagic
);
26 request
.WriteInt(pid
);
30 static bool ReadRequest(Pickle
& pickle
, int32
* pid
) {
31 PickleIterator
iter(pickle
);
33 if (!iter
.ReadString(&hello
)) {
34 DLOG(WARNING
) << "Failed to Read magic string.";
38 if (hello
!= kHelloRequestMagic
) {
39 DLOG(WARNING
) << "Magic mismatch:" << hello
;
44 if (!iter
.ReadInt(&read_pid
)) {
45 DLOG(WARNING
) << "Failed to Read PID.";
53 static Pickle
CreateResponse(int32 pid
) {
55 request
.WriteString(kHelloResponseMagic
);
56 request
.WriteInt(pid
);
60 static bool ReadResponse(Pickle
& pickle
, int32
* pid
) {
61 PickleIterator
iter(pickle
);
63 if (!iter
.ReadString(&hello
)) {
64 DLOG(WARNING
) << "Failed to read magic string.";
68 if (hello
!= kHelloResponseMagic
) {
69 DLOG(WARNING
) << "Magic mismatch:" << hello
;
74 if (!iter
.ReadInt(&read_pid
)) {
75 DLOG(WARNING
) << "Failed to read PID.";
84 static const char* kHelloRequestMagic
;
85 static const char* kHelloResponseMagic
;
88 const char* HelloMessage::kHelloRequestMagic
= "MREQ";
89 const char* HelloMessage::kHelloResponseMagic
= "MRES";
93 //------------------------------------------------------------------------------
95 MessageReader::MessageReader(mojo::ScopedMessagePipeHandle pipe
,
97 : internal::MessagePipeReader(pipe
.Pass()), owner_(owner
) {
100 void MessageReader::OnMessageReceived() {
101 Message
message(data_buffer().empty() ? "" : &data_buffer()[0],
102 static_cast<uint32
>(data_buffer().size()));
104 std::vector
<MojoHandle
> handle_buffer
;
105 TakeHandleBuffer(&handle_buffer
);
106 #if defined(OS_POSIX) && !defined(OS_NACL)
107 MojoResult write_result
=
108 ChannelMojo::WriteToFileDescriptorSet(handle_buffer
, &message
);
109 if (write_result
!= MOJO_RESULT_OK
) {
110 CloseWithError(write_result
);
114 DCHECK(handle_buffer
.empty());
117 message
.TraceMessageEnd();
118 owner_
->OnMessageReceived(message
);
121 void MessageReader::OnPipeClosed() {
124 owner_
->OnPipeClosed(this);
128 void MessageReader::OnPipeError(MojoResult error
) {
131 owner_
->OnPipeError(this);
134 bool MessageReader::Send(scoped_ptr
<Message
> message
) {
137 message
->TraceMessageBegin();
138 std::vector
<MojoHandle
> handles
;
139 #if defined(OS_POSIX) && !defined(OS_NACL)
140 MojoResult read_result
=
141 ChannelMojo::ReadFromFileDescriptorSet(*message
, &handles
);
142 if (read_result
!= MOJO_RESULT_OK
) {
143 std::for_each(handles
.begin(), handles
.end(), &MojoClose
);
144 CloseWithError(read_result
);
148 MojoResult write_result
=
149 MojoWriteMessage(handle(),
151 static_cast<uint32
>(message
->size()),
152 handles
.empty() ? NULL
: &handles
[0],
153 static_cast<uint32
>(handles
.size()),
154 MOJO_WRITE_MESSAGE_FLAG_NONE
);
155 if (MOJO_RESULT_OK
!= write_result
) {
156 std::for_each(handles
.begin(), handles
.end(), &MojoClose
);
157 CloseWithError(write_result
);
164 //------------------------------------------------------------------------------
166 ControlReader::ControlReader(mojo::ScopedMessagePipeHandle pipe
,
168 : internal::MessagePipeReader(pipe
.Pass()), owner_(owner
) {
171 void ControlReader::OnPipeClosed() {
174 owner_
->OnPipeClosed(this);
178 void ControlReader::OnPipeError(MojoResult error
) {
181 owner_
->OnPipeError(this);
184 bool ControlReader::Connect() {
188 //------------------------------------------------------------------------------
190 ServerControlReader::ServerControlReader(mojo::ScopedMessagePipeHandle pipe
,
192 : ControlReader(pipe
.Pass(), owner
) {
195 ServerControlReader::~ServerControlReader() {
198 bool ServerControlReader::Connect() {
199 MojoResult result
= SendHelloRequest();
200 if (result
!= MOJO_RESULT_OK
) {
201 CloseWithError(result
);
208 MojoResult
ServerControlReader::SendHelloRequest() {
210 DCHECK(!message_pipe_
.is_valid());
212 mojo::ScopedMessagePipeHandle self
;
213 mojo::ScopedMessagePipeHandle peer
;
214 MojoResult create_result
=
215 mojo::CreateMessagePipe(NULL
, &message_pipe_
, &peer
);
216 if (MOJO_RESULT_OK
!= create_result
) {
217 DLOG(WARNING
) << "mojo::CreateMessagePipe failed: " << create_result
;
218 return create_result
;
221 MojoHandle peer_to_send
= peer
.get().value();
222 Pickle request
= HelloMessage::CreateRequest(owner_
->GetSelfPID());
223 MojoResult write_result
=
224 MojoWriteMessage(handle(),
226 static_cast<uint32
>(request
.size()),
229 MOJO_WRITE_MESSAGE_FLAG_NONE
);
230 if (MOJO_RESULT_OK
!= write_result
) {
231 DLOG(WARNING
) << "Writing Hello request failed: " << create_result
;
235 // |peer| is sent and no longer owned by |this|.
236 (void)peer
.release();
237 return MOJO_RESULT_OK
;
240 MojoResult
ServerControlReader::RespondHelloResponse() {
241 Pickle
request(data_buffer().empty() ? "" : &data_buffer()[0],
242 static_cast<uint32
>(data_buffer().size()));
245 if (!HelloMessage::ReadResponse(request
, &read_pid
)) {
246 DLOG(ERROR
) << "Failed to parse Hello response.";
247 return MOJO_RESULT_UNKNOWN
;
250 base::ProcessId pid
= static_cast<base::ProcessId
>(read_pid
);
251 owner_
->set_peer_pid(pid
);
252 owner_
->OnConnected(message_pipe_
.Pass());
253 return MOJO_RESULT_OK
;
256 void ServerControlReader::OnMessageReceived() {
257 MojoResult result
= RespondHelloResponse();
258 if (result
!= MOJO_RESULT_OK
)
259 CloseWithError(result
);
262 //------------------------------------------------------------------------------
264 ClientControlReader::ClientControlReader(mojo::ScopedMessagePipeHandle pipe
,
266 : ControlReader(pipe
.Pass(), owner
) {
269 MojoResult
ClientControlReader::RespondHelloRequest(
270 MojoHandle message_channel
) {
273 mojo::ScopedMessagePipeHandle
received_pipe(
274 (mojo::MessagePipeHandle(message_channel
)));
276 int32 read_request
= 0;
277 Pickle
request(data_buffer().empty() ? "" : &data_buffer()[0],
278 static_cast<uint32
>(data_buffer().size()));
279 if (!HelloMessage::ReadRequest(request
, &read_request
)) {
280 DLOG(ERROR
) << "Hello request has wrong magic.";
281 return MOJO_RESULT_UNKNOWN
;
284 base::ProcessId pid
= read_request
;
285 Pickle response
= HelloMessage::CreateResponse(owner_
->GetSelfPID());
286 MojoResult write_result
=
287 MojoWriteMessage(handle(),
289 static_cast<uint32
>(response
.size()),
292 MOJO_WRITE_MESSAGE_FLAG_NONE
);
293 if (MOJO_RESULT_OK
!= write_result
) {
294 DLOG(ERROR
) << "Writing Hello response failed: " << write_result
;
298 owner_
->set_peer_pid(pid
);
299 owner_
->OnConnected(received_pipe
.Pass());
300 return MOJO_RESULT_OK
;
303 void ClientControlReader::OnMessageReceived() {
304 std::vector
<MojoHandle
> handle_buffer
;
305 TakeHandleBuffer(&handle_buffer
);
306 if (handle_buffer
.size() != 1) {
307 DLOG(ERROR
) << "Hello request doesn't contains required handle: "
308 << handle_buffer
.size();
309 CloseWithError(MOJO_RESULT_UNKNOWN
);
313 MojoResult result
= RespondHelloRequest(handle_buffer
[0]);
314 if (result
!= MOJO_RESULT_OK
) {
315 DLOG(ERROR
) << "Failed to respond Hello request. Closing: " << result
;
316 CloseWithError(result
);
320 } // namespace internal