| // Copyright 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "mojo/system/message_pipe_dispatcher.h" |
| |
| #include "base/logging.h" |
| #include "mojo/system/limits.h" |
| #include "mojo/system/memory.h" |
| #include "mojo/system/message_pipe.h" |
| |
| namespace mojo { |
| namespace system { |
| |
| const unsigned kInvalidPort = static_cast<unsigned>(-1); |
| |
| MessagePipeDispatcher::MessagePipeDispatcher() |
| : port_(kInvalidPort) { |
| } |
| |
| void MessagePipeDispatcher::Init(scoped_refptr<MessagePipe> message_pipe, |
| unsigned port) { |
| DCHECK(message_pipe.get()); |
| DCHECK(port == 0 || port == 1); |
| |
| message_pipe_ = message_pipe; |
| port_ = port; |
| } |
| |
| MessagePipeDispatcher::~MessagePipeDispatcher() { |
| // |Close()|/|CloseImplNoLock()| should have taken care of the pipe. |
| DCHECK(!message_pipe_.get()); |
| } |
| |
| void MessagePipeDispatcher::CancelAllWaitersNoLock() { |
| lock().AssertAcquired(); |
| message_pipe_->CancelAllWaiters(port_); |
| } |
| |
| MojoResult MessagePipeDispatcher::CloseImplNoLock() { |
| lock().AssertAcquired(); |
| message_pipe_->Close(port_); |
| message_pipe_ = NULL; |
| port_ = kInvalidPort; |
| return MOJO_RESULT_OK; |
| } |
| |
| MojoResult MessagePipeDispatcher::WriteMessageImplNoLock( |
| const void* bytes, uint32_t num_bytes, |
| const std::vector<Dispatcher*>* dispatchers, |
| MojoWriteMessageFlags flags) { |
| DCHECK(!dispatchers || (dispatchers->size() > 0 && |
| dispatchers->size() <= kMaxMessageNumHandles)); |
| |
| lock().AssertAcquired(); |
| |
| if (!VerifyUserPointer<void>(bytes, num_bytes)) |
| return MOJO_RESULT_INVALID_ARGUMENT; |
| if (num_bytes > kMaxMessageNumBytes) |
| return MOJO_RESULT_RESOURCE_EXHAUSTED; |
| |
| return message_pipe_->WriteMessage(port_, |
| bytes, num_bytes, |
| dispatchers, |
| flags); |
| } |
| |
| MojoResult MessagePipeDispatcher::ReadMessageImplNoLock( |
| void* bytes, uint32_t* num_bytes, |
| std::vector<scoped_refptr<Dispatcher> >* dispatchers, |
| uint32_t* num_dispatchers, |
| MojoReadMessageFlags flags) { |
| lock().AssertAcquired(); |
| |
| if (num_bytes) { |
| if (!VerifyUserPointer<uint32_t>(num_bytes, 1)) |
| return MOJO_RESULT_INVALID_ARGUMENT; |
| if (!VerifyUserPointer<void>(bytes, *num_bytes)) |
| return MOJO_RESULT_INVALID_ARGUMENT; |
| } |
| |
| return message_pipe_->ReadMessage(port_, |
| bytes, num_bytes, |
| dispatchers, num_dispatchers, |
| flags); |
| } |
| |
| MojoResult MessagePipeDispatcher::AddWaiterImplNoLock(Waiter* waiter, |
| MojoWaitFlags flags, |
| MojoResult wake_result) { |
| lock().AssertAcquired(); |
| return message_pipe_->AddWaiter(port_, waiter, flags, wake_result); |
| } |
| |
| void MessagePipeDispatcher::RemoveWaiterImplNoLock(Waiter* waiter) { |
| lock().AssertAcquired(); |
| message_pipe_->RemoveWaiter(port_, waiter); |
| } |
| |
| scoped_refptr<Dispatcher> |
| MessagePipeDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock() { |
| lock().AssertAcquired(); |
| |
| scoped_refptr<MessagePipeDispatcher> rv = new MessagePipeDispatcher; |
| rv->Init(message_pipe_, port_); |
| message_pipe_ = NULL; |
| port_ = kInvalidPort; |
| return scoped_refptr<Dispatcher>(rv.get()); |
| } |
| |
| } // namespace system |
| } // namespace mojo |