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.h"
8 #include "base/bind_helpers.h"
9 #include "base/lazy_instance.h"
10 #include "ipc/ipc_listener.h"
11 #include "mojo/embedder/embedder.h"
13 #if defined(OS_POSIX) && !defined(OS_NACL)
14 #include "ipc/file_descriptor_set_posix.h"
21 // IPC::Listener for bootstrap channels.
22 // It should never receive any message.
23 class NullListener
: public Listener
{
25 virtual bool OnMessageReceived(const Message
&) OVERRIDE
{
30 virtual void OnChannelConnected(int32 peer_pid
) OVERRIDE
{
34 virtual void OnChannelError() OVERRIDE
{
38 virtual void OnBadMessageReceived(const Message
& message
) OVERRIDE
{
43 base::LazyInstance
<NullListener
> g_null_listener
= LAZY_INSTANCE_INITIALIZER
;
45 class MojoChannelFactory
: public ChannelFactory
{
48 ChannelHandle channel_handle
,
50 scoped_refptr
<base::TaskRunner
> io_thread_task_runner
)
51 : channel_handle_(channel_handle
),
53 io_thread_task_runner_(io_thread_task_runner
) {
56 virtual std::string
GetName() const OVERRIDE
{
57 return channel_handle_
.name
;
60 virtual scoped_ptr
<Channel
> BuildChannel(Listener
* listener
) OVERRIDE
{
61 return ChannelMojo::Create(
65 io_thread_task_runner_
).PassAs
<Channel
>();
69 ChannelHandle channel_handle_
;
71 scoped_refptr
<base::TaskRunner
> io_thread_task_runner_
;
74 mojo::embedder::PlatformHandle
ToPlatformHandle(
75 const ChannelHandle
& handle
) {
76 #if defined(OS_POSIX) && !defined(OS_NACL)
77 return mojo::embedder::PlatformHandle(handle
.socket
.fd
);
79 return mojo::embedder::PlatformHandle(handle
.pipe
.handle
);
81 #error "Unsupported Platform!"
85 //------------------------------------------------------------------------------
87 // TODO(morrita): This should be built using higher-level Mojo construct
88 // for clarity and extensibility.
91 static Pickle
CreateRequest(int32 pid
) {
93 request
.WriteString(kHelloRequestMagic
);
94 request
.WriteInt(pid
);
98 static bool ReadRequest(Pickle
& pickle
, int32
* pid
) {
99 PickleIterator
iter(pickle
);
101 if (!iter
.ReadString(&hello
)) {
102 DLOG(WARNING
) << "Failed to Read magic string.";
106 if (hello
!= kHelloRequestMagic
) {
107 DLOG(WARNING
) << "Magic mismatch:" << hello
;
112 if (!iter
.ReadInt(&read_pid
)) {
113 DLOG(WARNING
) << "Failed to Read PID.";
121 static Pickle
CreateResponse(int32 pid
) {
123 request
.WriteString(kHelloResponseMagic
);
124 request
.WriteInt(pid
);
128 static bool ReadResponse(Pickle
& pickle
, int32
* pid
) {
129 PickleIterator
iter(pickle
);
131 if (!iter
.ReadString(&hello
)) {
132 DLOG(WARNING
) << "Failed to read magic string.";
136 if (hello
!= kHelloResponseMagic
) {
137 DLOG(WARNING
) << "Magic mismatch:" << hello
;
142 if (!iter
.ReadInt(&read_pid
)) {
143 DLOG(WARNING
) << "Failed to read PID.";
152 static const char* kHelloRequestMagic
;
153 static const char* kHelloResponseMagic
;
156 const char* HelloMessage::kHelloRequestMagic
= "MREQ";
157 const char* HelloMessage::kHelloResponseMagic
= "MRES";
161 //------------------------------------------------------------------------------
163 // A MessagePipeReader implemenation for IPC::Message communication.
164 class ChannelMojo::MessageReader
: public internal::MessagePipeReader
{
166 MessageReader(mojo::ScopedMessagePipeHandle pipe
, ChannelMojo
* owner
)
167 : internal::MessagePipeReader(pipe
.Pass()),
170 bool Send(scoped_ptr
<Message
> message
);
171 virtual void OnMessageReceived() OVERRIDE
;
172 virtual void OnPipeClosed() OVERRIDE
;
173 virtual void OnPipeError(MojoResult error
) OVERRIDE
;
179 void ChannelMojo::MessageReader::OnMessageReceived() {
180 Message
message(data_buffer().empty() ? "" : &data_buffer()[0],
181 static_cast<uint32
>(data_buffer().size()));
183 std::vector
<MojoHandle
> handle_buffer
;
184 TakeHandleBuffer(&handle_buffer
);
185 #if defined(OS_POSIX) && !defined(OS_NACL)
186 for (size_t i
= 0; i
< handle_buffer
.size(); ++i
) {
187 mojo::embedder::ScopedPlatformHandle platform_handle
;
188 MojoResult unwrap_result
= mojo::embedder::PassWrappedPlatformHandle(
189 handle_buffer
[i
], &platform_handle
);
190 if (unwrap_result
!= MOJO_RESULT_OK
) {
191 DLOG(WARNING
) << "Pipe failed to covert handles. Closing: "
193 CloseWithError(unwrap_result
);
197 bool ok
= message
.file_descriptor_set()->Add(platform_handle
.release().fd
);
201 DCHECK(handle_buffer
.empty());
204 message
.TraceMessageEnd();
205 owner_
->OnMessageReceived(message
);
208 void ChannelMojo::MessageReader::OnPipeClosed() {
211 owner_
->OnPipeClosed(this);
215 void ChannelMojo::MessageReader::OnPipeError(MojoResult error
) {
218 owner_
->OnPipeError(this);
221 bool ChannelMojo::MessageReader::Send(scoped_ptr
<Message
> message
) {
224 message
->TraceMessageBegin();
225 std::vector
<MojoHandle
> handles
;
226 #if defined(OS_POSIX) && !defined(OS_NACL)
227 // We dup() the handles in IPC::Message to transmit.
228 // IPC::FileDescriptorSet has intricate lifecycle semantics
229 // of FDs, so just to dup()-and-own them is the safest option.
230 if (message
->HasFileDescriptors()) {
231 FileDescriptorSet
* fdset
= message
->file_descriptor_set();
232 for (size_t i
= 0; i
< fdset
->size(); ++i
) {
233 int fd_to_send
= dup(fdset
->GetDescriptorAt(i
));
234 if (-1 == fd_to_send
) {
235 DPLOG(WARNING
) << "Failed to dup FD to transmit.";
236 std::for_each(handles
.begin(), handles
.end(), &MojoClose
);
237 CloseWithError(MOJO_RESULT_UNKNOWN
);
241 MojoHandle wrapped_handle
;
242 MojoResult wrap_result
= CreatePlatformHandleWrapper(
243 mojo::embedder::ScopedPlatformHandle(
244 mojo::embedder::PlatformHandle(fd_to_send
)),
246 if (MOJO_RESULT_OK
!= wrap_result
) {
247 DLOG(WARNING
) << "Pipe failed to wrap handles. Closing: "
249 std::for_each(handles
.begin(), handles
.end(), &MojoClose
);
250 CloseWithError(wrap_result
);
254 handles
.push_back(wrapped_handle
);
258 MojoResult write_result
= MojoWriteMessage(
260 message
->data(), static_cast<uint32
>(message
->size()),
261 handles
.empty() ? NULL
: &handles
[0],
262 static_cast<uint32
>(handles
.size()),
263 MOJO_WRITE_MESSAGE_FLAG_NONE
);
264 if (MOJO_RESULT_OK
!= write_result
) {
265 std::for_each(handles
.begin(), handles
.end(), &MojoClose
);
266 CloseWithError(write_result
);
273 //------------------------------------------------------------------------------
275 // MessagePipeReader implementation for control messages.
276 // Actual message handling is implemented by sublcasses.
277 class ChannelMojo::ControlReader
: public internal::MessagePipeReader
{
279 ControlReader(mojo::ScopedMessagePipeHandle pipe
, ChannelMojo
* owner
)
280 : internal::MessagePipeReader(pipe
.Pass()),
283 virtual bool Connect() { return true; }
284 virtual void OnPipeClosed() OVERRIDE
;
285 virtual void OnPipeError(MojoResult error
) OVERRIDE
;
291 void ChannelMojo::ControlReader::OnPipeClosed() {
294 owner_
->OnPipeClosed(this);
298 void ChannelMojo::ControlReader::OnPipeError(MojoResult error
) {
301 owner_
->OnPipeError(this);
304 //------------------------------------------------------------------------------
306 // ControlReader for server-side ChannelMojo.
307 class ChannelMojo::ServerControlReader
: public ChannelMojo::ControlReader
{
309 ServerControlReader(mojo::ScopedMessagePipeHandle pipe
, ChannelMojo
* owner
)
310 : ControlReader(pipe
.Pass(), owner
) { }
312 virtual bool Connect() OVERRIDE
;
313 virtual void OnMessageReceived() OVERRIDE
;
316 MojoResult
SendHelloRequest();
317 MojoResult
RespondHelloResponse();
319 mojo::ScopedMessagePipeHandle message_pipe_
;
322 bool ChannelMojo::ServerControlReader::Connect() {
323 MojoResult result
= SendHelloRequest();
324 if (result
!= MOJO_RESULT_OK
) {
325 CloseWithError(result
);
332 MojoResult
ChannelMojo::ServerControlReader::SendHelloRequest() {
334 DCHECK(!message_pipe_
.is_valid());
336 mojo::ScopedMessagePipeHandle self
;
337 mojo::ScopedMessagePipeHandle peer
;
338 MojoResult create_result
= mojo::CreateMessagePipe(
339 NULL
, &message_pipe_
, &peer
);
340 if (MOJO_RESULT_OK
!= create_result
) {
341 DLOG(WARNING
) << "mojo::CreateMessagePipe failed: " << create_result
;
342 return create_result
;
345 MojoHandle peer_to_send
= peer
.get().value();
346 Pickle request
= HelloMessage::CreateRequest(owner_
->GetSelfPID());
347 MojoResult write_result
= MojoWriteMessage(
349 request
.data(), static_cast<uint32
>(request
.size()),
351 MOJO_WRITE_MESSAGE_FLAG_NONE
);
352 if (MOJO_RESULT_OK
!= write_result
) {
353 DLOG(WARNING
) << "Writing Hello request failed: " << create_result
;
357 // |peer| is sent and no longer owned by |this|.
358 (void)peer
.release();
359 return MOJO_RESULT_OK
;
362 MojoResult
ChannelMojo::ServerControlReader::RespondHelloResponse() {
363 Pickle
request(data_buffer().empty() ? "" : &data_buffer()[0],
364 static_cast<uint32
>(data_buffer().size()));
367 if (!HelloMessage::ReadResponse(request
, &read_pid
)) {
368 DLOG(ERROR
) << "Failed to parse Hello response.";
369 return MOJO_RESULT_UNKNOWN
;
372 base::ProcessId pid
= static_cast<base::ProcessId
>(read_pid
);
373 owner_
->set_peer_pid(pid
);
374 owner_
->OnConnected(message_pipe_
.Pass());
375 return MOJO_RESULT_OK
;
378 void ChannelMojo::ServerControlReader::OnMessageReceived() {
379 MojoResult result
= RespondHelloResponse();
380 if (result
!= MOJO_RESULT_OK
)
381 CloseWithError(result
);
384 //------------------------------------------------------------------------------
386 // ControlReader for client-side ChannelMojo.
387 class ChannelMojo::ClientControlReader
: public ChannelMojo::ControlReader
{
389 ClientControlReader(mojo::ScopedMessagePipeHandle pipe
, ChannelMojo
* owner
)
390 : ControlReader(pipe
.Pass(), owner
) {}
392 virtual void OnMessageReceived() OVERRIDE
;
395 MojoResult
RespondHelloRequest(MojoHandle message_channel
);
398 MojoResult
ChannelMojo::ClientControlReader::RespondHelloRequest(
399 MojoHandle message_channel
) {
402 mojo::ScopedMessagePipeHandle
received_pipe(
403 (mojo::MessagePipeHandle(message_channel
)));
405 int32 read_request
= 0;
406 Pickle
request(data_buffer().empty() ? "" : &data_buffer()[0],
407 static_cast<uint32
>(data_buffer().size()));
408 if (!HelloMessage::ReadRequest(request
, &read_request
)) {
409 DLOG(ERROR
) << "Hello request has wrong magic.";
410 return MOJO_RESULT_UNKNOWN
;
413 base::ProcessId pid
= read_request
;
414 Pickle response
= HelloMessage::CreateResponse(owner_
->GetSelfPID());
415 MojoResult write_result
= MojoWriteMessage(
417 response
.data(), static_cast<uint32
>(response
.size()),
419 MOJO_WRITE_MESSAGE_FLAG_NONE
);
420 if (MOJO_RESULT_OK
!= write_result
) {
421 DLOG(ERROR
) << "Writing Hello response failed: " << write_result
;
425 owner_
->set_peer_pid(pid
);
426 owner_
->OnConnected(received_pipe
.Pass());
427 return MOJO_RESULT_OK
;
430 void ChannelMojo::ClientControlReader::OnMessageReceived() {
431 std::vector
<MojoHandle
> handle_buffer
;
432 TakeHandleBuffer(&handle_buffer
);
433 if (handle_buffer
.size() != 1) {
434 DLOG(ERROR
) << "Hello request doesn't contains required handle: "
435 << handle_buffer
.size();
436 CloseWithError(MOJO_RESULT_UNKNOWN
);
440 MojoResult result
= RespondHelloRequest(handle_buffer
[0]);
441 if (result
!= MOJO_RESULT_OK
) {
442 DLOG(ERROR
) << "Failed to respond Hello request. Closing: "
444 CloseWithError(result
);
448 //------------------------------------------------------------------------------
450 void ChannelMojo::ChannelInfoDeleter::operator()(
451 mojo::embedder::ChannelInfo
* ptr
) const {
452 mojo::embedder::DestroyChannelOnIOThread(ptr
);
455 //------------------------------------------------------------------------------
458 scoped_ptr
<ChannelMojo
> ChannelMojo::Create(
459 scoped_ptr
<Channel
> bootstrap
, Mode mode
, Listener
* listener
,
460 scoped_refptr
<base::TaskRunner
> io_thread_task_runner
) {
461 return make_scoped_ptr(new ChannelMojo(
462 bootstrap
.Pass(), mode
, listener
, io_thread_task_runner
));
466 scoped_ptr
<ChannelMojo
> ChannelMojo::Create(
467 const ChannelHandle
&channel_handle
, Mode mode
, Listener
* listener
,
468 scoped_refptr
<base::TaskRunner
> io_thread_task_runner
) {
470 Channel::Create(channel_handle
, mode
, g_null_listener
.Pointer()),
471 mode
, listener
, io_thread_task_runner
);
475 scoped_ptr
<ChannelFactory
> ChannelMojo::CreateFactory(
476 const ChannelHandle
&channel_handle
, Mode mode
,
477 scoped_refptr
<base::TaskRunner
> io_thread_task_runner
) {
478 return make_scoped_ptr(
479 new MojoChannelFactory(
480 channel_handle
, mode
,
481 io_thread_task_runner
)).PassAs
<ChannelFactory
>();
484 ChannelMojo::ChannelMojo(
485 scoped_ptr
<Channel
> bootstrap
, Mode mode
, Listener
* listener
,
486 scoped_refptr
<base::TaskRunner
> io_thread_task_runner
)
487 : bootstrap_(bootstrap
.Pass()),
488 mode_(mode
), listener_(listener
),
489 peer_pid_(base::kNullProcessId
),
490 weak_factory_(this) {
491 if (base::MessageLoopProxy::current() == io_thread_task_runner
.get()) {
494 io_thread_task_runner
->PostTask(FROM_HERE
,
495 base::Bind(&ChannelMojo::InitOnIOThread
,
496 weak_factory_
.GetWeakPtr()));
500 ChannelMojo::~ChannelMojo() {
504 void ChannelMojo::InitOnIOThread() {
505 mojo::embedder::ChannelInfo
* channel_info
;
506 mojo::ScopedMessagePipeHandle control_pipe
=
507 mojo::embedder::CreateChannelOnIOThread(
508 mojo::embedder::ScopedPlatformHandle(
509 ToPlatformHandle(bootstrap_
->TakePipeHandle())),
511 channel_info_
.reset(channel_info
);
515 control_reader_
.reset(new ServerControlReader(control_pipe
.Pass(), this));
518 control_reader_
.reset(new ClientControlReader(control_pipe
.Pass(), this));
526 bool ChannelMojo::Connect() {
527 DCHECK(!message_reader_
);
528 return control_reader_
->Connect();
531 void ChannelMojo::Close() {
532 control_reader_
.reset();
533 message_reader_
.reset();
534 channel_info_
.reset();
537 void ChannelMojo::OnConnected(mojo::ScopedMessagePipeHandle pipe
) {
538 message_reader_
= make_scoped_ptr(new MessageReader(pipe
.Pass(), this));
540 for (size_t i
= 0; i
< pending_messages_
.size(); ++i
) {
541 message_reader_
->Send(make_scoped_ptr(pending_messages_
[i
]));
542 pending_messages_
[i
] = NULL
;
545 pending_messages_
.clear();
547 listener_
->OnChannelConnected(GetPeerPID());
550 void ChannelMojo::OnPipeClosed(internal::MessagePipeReader
* reader
) {
554 void ChannelMojo::OnPipeError(internal::MessagePipeReader
* reader
) {
555 listener_
->OnChannelError();
559 bool ChannelMojo::Send(Message
* message
) {
560 if (!message_reader_
) {
561 pending_messages_
.push_back(message
);
565 return message_reader_
->Send(make_scoped_ptr(message
));
568 base::ProcessId
ChannelMojo::GetPeerPID() const {
572 base::ProcessId
ChannelMojo::GetSelfPID() const {
573 return bootstrap_
->GetSelfPID();
576 ChannelHandle
ChannelMojo::TakePipeHandle() {
577 return bootstrap_
->TakePipeHandle();
580 void ChannelMojo::OnMessageReceived(Message
& message
) {
581 listener_
->OnMessageReceived(message
);
582 if (message
.dispatch_error())
583 listener_
->OnBadMessageReceived(message
);
586 #if defined(OS_POSIX) && !defined(OS_NACL)
587 int ChannelMojo::GetClientFileDescriptor() const {
588 return bootstrap_
->GetClientFileDescriptor();
591 int ChannelMojo::TakeClientFileDescriptor() {
592 return bootstrap_
->TakeClientFileDescriptor();
594 #endif // defined(OS_POSIX) && !defined(OS_NACL)