Index: ppapi/proxy/handle_converter.cc |
diff --git a/chrome/nacl/nacl_ipc_adapter.cc b/ppapi/proxy/handle_converter.cc |
similarity index 23% |
copy from chrome/nacl/nacl_ipc_adapter.cc |
copy to ppapi/proxy/handle_converter.cc |
index a50c714891433fea6708a20704dffa0b1d015d04..a6690628bbee4d590b9f6a044bd6d28f5a96b3f5 100644 |
--- a/chrome/nacl/nacl_ipc_adapter.cc |
+++ b/ppapi/proxy/handle_converter.cc |
@@ -1,98 +1,21 @@ |
-// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+// Copyright (c) 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 "chrome/nacl/nacl_ipc_adapter.h" |
+#include "ppapi/proxy/handle_converter.h" |
-#include <limits.h> |
-#include <string.h> |
- |
-#include "base/basictypes.h" |
-#include "base/bind.h" |
-#include "base/location.h" |
-#include "base/memory/scoped_ptr.h" |
-#include "base/shared_memory.h" |
-#include "build/build_config.h" |
-#include "ipc/ipc_channel.h" |
+#include "ipc/ipc_message.h" |
#include "ipc/ipc_message_macros.h" |
-#include "ipc/ipc_platform_file.h" |
-#include "native_client/src/trusted/desc/nacl_desc_custom.h" |
-#include "native_client/src/trusted/desc/nacl_desc_wrapper.h" |
#include "ppapi/proxy/ppapi_messages.h" |
#include "ppapi/proxy/resource_message_params.h" |
+#include "ppapi/proxy/serialized_handle.h" |
-namespace { |
- |
-enum BufferSizeStatus { |
- // The buffer contains a full message with no extra bytes. |
- MESSAGE_IS_COMPLETE, |
- |
- // The message doesn't fit and the buffer contains only some of it. |
- MESSAGE_IS_TRUNCATED, |
- |
- // The buffer contains a full message + extra data. |
- MESSAGE_HAS_EXTRA_DATA |
-}; |
- |
-BufferSizeStatus GetBufferStatus(const char* data, size_t len) { |
- if (len < sizeof(NaClIPCAdapter::NaClMessageHeader)) |
- return MESSAGE_IS_TRUNCATED; |
- |
- const NaClIPCAdapter::NaClMessageHeader* header = |
- reinterpret_cast<const NaClIPCAdapter::NaClMessageHeader*>(data); |
- uint32 message_size = |
- sizeof(NaClIPCAdapter::NaClMessageHeader) + header->payload_size; |
- |
- if (len == message_size) |
- return MESSAGE_IS_COMPLETE; |
- if (len > message_size) |
- return MESSAGE_HAS_EXTRA_DATA; |
- return MESSAGE_IS_TRUNCATED; |
-} |
- |
-// This object allows the NaClDesc to hold a reference to a NaClIPCAdapter and |
-// forward calls to it. |
-struct DescThunker { |
- explicit DescThunker(NaClIPCAdapter* adapter_param) |
- : adapter(adapter_param) { |
- } |
- scoped_refptr<NaClIPCAdapter> adapter; |
-}; |
- |
-NaClIPCAdapter* ToAdapter(void* handle) { |
- return static_cast<DescThunker*>(handle)->adapter.get(); |
-} |
- |
-// NaClDescCustom implementation. |
-void NaClDescCustomDestroy(void* handle) { |
- delete static_cast<DescThunker*>(handle); |
-} |
- |
-ssize_t NaClDescCustomSendMsg(void* handle, const NaClImcTypedMsgHdr* msg, |
- int /* flags */) { |
- return static_cast<ssize_t>(ToAdapter(handle)->Send(msg)); |
-} |
- |
-ssize_t NaClDescCustomRecvMsg(void* handle, NaClImcTypedMsgHdr* msg, |
- int /* flags */) { |
- return static_cast<ssize_t>(ToAdapter(handle)->BlockingReceive(msg)); |
-} |
- |
-NaClDesc* MakeNaClDescCustom(NaClIPCAdapter* adapter) { |
- NaClDescCustomFuncs funcs = NACL_DESC_CUSTOM_FUNCS_INITIALIZER; |
- funcs.Destroy = NaClDescCustomDestroy; |
- funcs.SendMsg = NaClDescCustomSendMsg; |
- funcs.RecvMsg = NaClDescCustomRecvMsg; |
- // NaClDescMakeCustomDesc gives us a reference on the returned NaClDesc. |
- return NaClDescMakeCustomDesc(new DescThunker(adapter), &funcs); |
+namespace IPC { |
+class Message; |
} |
-void DeleteChannel(IPC::Channel* channel) { |
- delete channel; |
-} |
+namespace { |
-// TODO(dmichael): Move all this handle conversion code to ppapi/proxy. |
-// crbug.com/165201 |
void WriteHandle(int handle_index, |
const ppapi::proxy::SerializedHandle& handle, |
IPC::Message* message) { |
@@ -196,9 +119,9 @@ void ConvertHandlesImpl(const Tuple4<A, B, C, D>& t1, Handles* handles, |
} |
template <class MessageType> |
-class HandleConverter { |
+class HandleConverterImpl { |
public: |
- explicit HandleConverter(const IPC::Message* msg) |
+ explicit HandleConverterImpl(const IPC::Message* msg) |
: msg_(static_cast<const MessageType*>(msg)) { |
} |
bool ConvertMessage(Handles* handles, IPC::Message* out_msg) { |
@@ -233,499 +156,103 @@ class HandleConverter { |
} // namespace |
-class NaClIPCAdapter::RewrittenMessage |
- : public base::RefCounted<RewrittenMessage> { |
- public: |
- RewrittenMessage(); |
- |
- bool is_consumed() const { return data_read_cursor_ == data_len_; } |
- |
- void SetData(const NaClIPCAdapter::NaClMessageHeader& header, |
- const void* payload, size_t payload_length); |
- |
- int Read(NaClImcTypedMsgHdr* msg); |
- |
- void AddDescriptor(nacl::DescWrapper* desc) { descs_.push_back(desc); } |
- |
- size_t desc_count() const { return descs_.size(); } |
- |
- private: |
- friend class base::RefCounted<RewrittenMessage>; |
- ~RewrittenMessage() {} |
- |
- scoped_array<char> data_; |
- size_t data_len_; |
- |
- // Offset into data where the next read will happen. This will be equal to |
- // data_len_ when all data has been consumed. |
- size_t data_read_cursor_; |
- |
- // Wrapped descriptors for transfer to untrusted code. |
- ScopedVector<nacl::DescWrapper> descs_; |
-}; |
- |
-NaClIPCAdapter::RewrittenMessage::RewrittenMessage() |
- : data_len_(0), |
- data_read_cursor_(0) { |
-} |
- |
-void NaClIPCAdapter::RewrittenMessage::SetData( |
- const NaClIPCAdapter::NaClMessageHeader& header, |
- const void* payload, |
- size_t payload_length) { |
- DCHECK(!data_.get() && data_len_ == 0); |
- size_t header_len = sizeof(NaClIPCAdapter::NaClMessageHeader); |
- data_len_ = header_len + payload_length; |
- data_.reset(new char[data_len_]); |
- |
- memcpy(data_.get(), &header, sizeof(NaClIPCAdapter::NaClMessageHeader)); |
- memcpy(&data_[header_len], payload, payload_length); |
-} |
- |
-int NaClIPCAdapter::RewrittenMessage::Read(NaClImcTypedMsgHdr* msg) { |
- CHECK(data_len_ >= data_read_cursor_); |
- char* dest_buffer = static_cast<char*>(msg->iov[0].base); |
- size_t dest_buffer_size = msg->iov[0].length; |
- size_t bytes_to_write = std::min(dest_buffer_size, |
- data_len_ - data_read_cursor_); |
- if (bytes_to_write == 0) |
- return 0; |
- |
- memcpy(dest_buffer, &data_[data_read_cursor_], bytes_to_write); |
- data_read_cursor_ += bytes_to_write; |
- |
- // Once all data has been consumed, transfer any file descriptors. |
- if (is_consumed()) { |
- nacl_abi_size_t desc_count = static_cast<nacl_abi_size_t>(descs_.size()); |
- CHECK(desc_count <= msg->ndesc_length); |
- msg->ndesc_length = desc_count; |
- for (nacl_abi_size_t i = 0; i < desc_count; i++) { |
- // Copy the NaClDesc to the buffer and add a ref so it won't be freed |
- // when we clear our ScopedVector. |
- msg->ndescv[i] = descs_[i]->desc(); |
- NaClDescRef(descs_[i]->desc()); |
- } |
- descs_.clear(); |
- } else { |
- msg->ndesc_length = 0; |
- } |
- return static_cast<int>(bytes_to_write); |
-} |
- |
-NaClIPCAdapter::LockedData::LockedData() |
- : channel_closed_(false) { |
-} |
- |
-NaClIPCAdapter::LockedData::~LockedData() { |
-} |
- |
-NaClIPCAdapter::IOThreadData::IOThreadData() { |
-} |
- |
-NaClIPCAdapter::IOThreadData::~IOThreadData() { |
-} |
- |
-NaClIPCAdapter::NaClIPCAdapter(const IPC::ChannelHandle& handle, |
- base::TaskRunner* runner) |
- : lock_(), |
- cond_var_(&lock_), |
- task_runner_(runner), |
- locked_data_() { |
- io_thread_data_.channel_.reset( |
- new IPC::Channel(handle, IPC::Channel::MODE_SERVER, this)); |
- // Note, we can not PostTask for ConnectChannelOnIOThread here. If we did, |
- // and that task ran before this constructor completes, the reference count |
- // would go to 1 and then to 0 because of the Task, before we've been returned |
- // to the owning scoped_refptr, which is supposed to give us our first |
- // ref-count. |
-} |
- |
-NaClIPCAdapter::NaClIPCAdapter(scoped_ptr<IPC::Channel> channel, |
- base::TaskRunner* runner) |
- : lock_(), |
- cond_var_(&lock_), |
- task_runner_(runner), |
- locked_data_() { |
- io_thread_data_.channel_ = channel.Pass(); |
-} |
- |
-void NaClIPCAdapter::ConnectChannel() { |
- task_runner_->PostTask(FROM_HERE, |
- base::Bind(&NaClIPCAdapter::ConnectChannelOnIOThread, this)); |
-} |
- |
-// Note that this message is controlled by the untrusted code. So we should be |
-// skeptical of anything it contains and quick to give up if anything is fishy. |
-int NaClIPCAdapter::Send(const NaClImcTypedMsgHdr* msg) { |
- if (msg->iov_length != 1) |
- return -1; |
- |
- base::AutoLock lock(lock_); |
- |
- const char* input_data = static_cast<char*>(msg->iov[0].base); |
- size_t input_data_len = msg->iov[0].length; |
- if (input_data_len > IPC::Channel::kMaximumMessageSize) { |
- ClearToBeSent(); |
- return -1; |
- } |
- |
- // current_message[_len] refers to the total input data received so far. |
- const char* current_message; |
- size_t current_message_len; |
- bool did_append_input_data; |
- if (locked_data_.to_be_sent_.empty()) { |
- // No accumulated data, we can avoid a copy by referring to the input |
- // buffer (the entire message fitting in one call is the common case). |
- current_message = input_data; |
- current_message_len = input_data_len; |
- did_append_input_data = false; |
- } else { |
- // We've already accumulated some data, accumulate this new data and |
- // point to the beginning of the buffer. |
- |
- // Make sure our accumulated message size doesn't overflow our max. Since |
- // we know that data_len < max size (checked above) and our current |
- // accumulated value is also < max size, we just need to make sure that |
- // 2x max size can never overflow. |
- COMPILE_ASSERT(IPC::Channel::kMaximumMessageSize < (UINT_MAX / 2), |
- MaximumMessageSizeWillOverflow); |
- size_t new_size = locked_data_.to_be_sent_.size() + input_data_len; |
- if (new_size > IPC::Channel::kMaximumMessageSize) { |
- ClearToBeSent(); |
- return -1; |
- } |
- |
- locked_data_.to_be_sent_.append(input_data, input_data_len); |
- current_message = &locked_data_.to_be_sent_[0]; |
- current_message_len = locked_data_.to_be_sent_.size(); |
- did_append_input_data = true; |
- } |
- |
- // Check the total data we've accumulated so far to see if it contains a full |
- // message. |
- switch (GetBufferStatus(current_message, current_message_len)) { |
- case MESSAGE_IS_COMPLETE: { |
- // Got a complete message, can send it out. This will be the common case. |
- bool success = SendCompleteMessage(current_message, current_message_len); |
- ClearToBeSent(); |
- return success ? static_cast<int>(input_data_len) : -1; |
- } |
- case MESSAGE_IS_TRUNCATED: |
- // For truncated messages, just accumulate the new data (if we didn't |
- // already do so above) and go back to waiting for more. |
- if (!did_append_input_data) |
- locked_data_.to_be_sent_.append(input_data, input_data_len); |
- return static_cast<int>(input_data_len); |
- case MESSAGE_HAS_EXTRA_DATA: |
- default: |
- // When the plugin gives us too much data, it's an error. |
- ClearToBeSent(); |
- return -1; |
- } |
-} |
- |
-int NaClIPCAdapter::BlockingReceive(NaClImcTypedMsgHdr* msg) { |
- if (msg->iov_length != 1) |
- return -1; |
- |
- int retval = 0; |
- { |
- base::AutoLock lock(lock_); |
- while (locked_data_.to_be_received_.empty() && |
- !locked_data_.channel_closed_) |
- cond_var_.Wait(); |
- if (locked_data_.channel_closed_) { |
- retval = -1; |
- } else { |
- retval = LockedReceive(msg); |
- DCHECK(retval > 0); |
- } |
- } |
- cond_var_.Signal(); |
- return retval; |
-} |
- |
-void NaClIPCAdapter::CloseChannel() { |
- { |
- base::AutoLock lock(lock_); |
- locked_data_.channel_closed_ = true; |
- } |
- cond_var_.Signal(); |
- |
- task_runner_->PostTask(FROM_HERE, |
- base::Bind(&NaClIPCAdapter::CloseChannelOnIOThread, this)); |
-} |
- |
-NaClDesc* NaClIPCAdapter::MakeNaClDesc() { |
- return MakeNaClDescCustom(this); |
-} |
- |
-#if defined(OS_POSIX) |
-int NaClIPCAdapter::TakeClientFileDescriptor() { |
- return io_thread_data_.channel_->TakeClientFileDescriptor(); |
-} |
-#endif |
- |
#define CASE_FOR_MESSAGE(MESSAGE_TYPE) \ |
case MESSAGE_TYPE::ID: { \ |
- HandleConverter<MESSAGE_TYPE> extractor(&msg); \ |
- if (!extractor.ConvertMessage(&handles, new_msg_ptr)) \ |
+ HandleConverterImpl<MESSAGE_TYPE> extractor(&msg); \ |
+ if (!extractor.ConvertMessage(handles, new_msg_ptr->get())) \ |
return false; \ |
break; \ |
} |
#define CASE_FOR_REPLY(MESSAGE_TYPE) \ |
case MESSAGE_TYPE::ID: { \ |
- HandleConverter<MESSAGE_TYPE> extractor(&msg); \ |
+ HandleConverterImpl<MESSAGE_TYPE> extractor(&msg); \ |
if (!extractor.ConvertReply( \ |
- &handles, \ |
- static_cast<IPC::SyncMessage*>(new_msg_ptr))) \ |
+ handles, \ |
+ static_cast<IPC::SyncMessage*>(new_msg_ptr->get()))) \ |
return false; \ |
break; \ |
} |
-bool NaClIPCAdapter::OnMessageReceived(const IPC::Message& msg) { |
- { |
- base::AutoLock lock(lock_); |
- |
- scoped_refptr<RewrittenMessage> rewritten_msg(new RewrittenMessage); |
- |
- // Pointer to the "new" message we will rewrite on Windows. On posix, this |
- // isn't necessary, so it will stay NULL. |
- IPC::Message* new_msg_ptr = NULL; |
- IPC::Message new_msg(msg.routing_id(), msg.type(), msg.priority()); |
+namespace ppapi { |
+namespace proxy { |
+ |
+class SerializedHandle; |
+ |
+HandleConverter::HandleConverter() { |
+} |
+ |
+bool HandleConverter::ConvertNativeHandlesToPosix( |
+ const IPC::Message& msg, |
+ std::vector<SerializedHandle>* handles, |
+ scoped_ptr<IPC::Message>* new_msg_ptr) { |
+ DCHECK(handles); |
+ DCHECK(new_msg_ptr); |
+ DCHECK(!new_msg_ptr->get()); |
+ |
+ // In Windows, we need to re-write the contents of the message. This is |
+ // because in Windows IPC code, native HANDLE values are serialized in the |
+ // body of the message. |
+ // |
+ // In POSIX, we only serialize an index in to a FileDescriptorSet, and the |
+ // actual file descriptors are sent out-of-band. So on Windows, to make a |
+ // message that's compatible with Windows, we need to write a new message that |
+ // has simple indices in the message body instead of the HANDLEs. |
+ // |
+ // NOTE: This means on Windows, new_msg_ptr's serialized contents are not |
+ // compatible with Windows IPC deserialization code; it is intended to be |
+ // passed to NaCl. |
#if defined(OS_WIN) |
- new_msg_ptr = &new_msg; |
+ new_msg_ptr->reset( |
+ new IPC::Message(msg.routing_id(), msg.type(), msg.priority())); |
#else |
- // Even on POSIX, we have to rewrite messages to create channels, because |
- // these contain a handle with an invalid (place holder) descriptor. The |
- // message sending code sees this and doesn't pass the descriptor over |
- // correctly. |
- if (msg.type() == PpapiMsg_CreateNaClChannel::ID) |
- new_msg_ptr = &new_msg; |
+ // Even on POSIX, we have to rewrite messages to create channels, because |
+ // these contain a handle with an invalid (place holder) descriptor. The |
+ // message sending code sees this and doesn't pass the descriptor over |
+ // correctly. |
+ if (msg.type() == PpapiMsg_CreateNaClChannel::ID) { |
+ new_msg_ptr->reset( |
+ new IPC::Message(msg.routing_id(), msg.type(), msg.priority())); |
+ } |
#endif |
- Handles handles; |
- switch (msg.type()) { |
- CASE_FOR_MESSAGE(PpapiMsg_CreateNaClChannel) |
- CASE_FOR_MESSAGE(PpapiMsg_PPBAudio_NotifyAudioStreamCreated) |
- CASE_FOR_MESSAGE(PpapiPluginMsg_ResourceReply) |
- case IPC_REPLY_ID: { |
- int id = IPC::SyncMessage::GetMessageId(msg); |
- LockedData::PendingSyncMsgMap::iterator iter( |
- locked_data_.pending_sync_msgs_.find(id)); |
- if (iter == locked_data_.pending_sync_msgs_.end()) { |
- NOTREACHED(); |
- return false; |
- } |
- uint32_t type = iter->second; |
- locked_data_.pending_sync_msgs_.erase(iter); |
- switch (type) { |
- CASE_FOR_REPLY(PpapiHostMsg_PPBGraphics3D_GetTransferBuffer) |
- CASE_FOR_REPLY(PpapiHostMsg_PPBImageData_CreateNaCl) |
- CASE_FOR_REPLY(PpapiHostMsg_ResourceSyncCall) |
- default: |
- // Do nothing for messages we don't know. |
- break; |
- } |
- break; |
+ switch (msg.type()) { |
+ CASE_FOR_MESSAGE(PpapiMsg_CreateNaClChannel) |
+ CASE_FOR_MESSAGE(PpapiMsg_PPBAudio_NotifyAudioStreamCreated) |
+ CASE_FOR_MESSAGE(PpapiPluginMsg_ResourceReply) |
+ case IPC_REPLY_ID: { |
+ int id = IPC::SyncMessage::GetMessageId(msg); |
+ PendingSyncMsgMap::iterator iter(pending_sync_msgs_.find(id)); |
+ if (iter == pending_sync_msgs_.end()) { |
+ NOTREACHED(); |
+ return false; |
} |
- default: |
- // Do nothing for messages we don't know. |
- break; |
- } |
- // Now add any descriptors we found to rewritten_msg. |handles| is usually |
- // empty, unless we read a message containing a FD or handle. |
- nacl::DescWrapperFactory factory; |
- for (Handles::const_iterator iter = handles.begin(); |
- iter != handles.end(); |
- ++iter) { |
- scoped_ptr<nacl::DescWrapper> nacl_desc; |
- switch (iter->type()) { |
- case ppapi::proxy::SerializedHandle::SHARED_MEMORY: { |
- const base::SharedMemoryHandle& shm_handle = iter->shmem(); |
- uint32_t size = iter->size(); |
- nacl_desc.reset(factory.ImportShmHandle( |
-#if defined(OS_WIN) |
- reinterpret_cast<const NaClHandle>(shm_handle), |
-#else |
- shm_handle.fd, |
-#endif |
- static_cast<size_t>(size))); |
- break; |
- } |
- case ppapi::proxy::SerializedHandle::SOCKET: { |
- nacl_desc.reset(factory.ImportSyncSocketHandle( |
-#if defined(OS_WIN) |
- reinterpret_cast<const NaClHandle>(iter->descriptor()) |
-#else |
- iter->descriptor().fd |
-#endif |
- )); |
- break; |
- } |
- case ppapi::proxy::SerializedHandle::CHANNEL_HANDLE: { |
- // Check that this came from a PpapiMsg_CreateNaClChannel message. |
- // This code here is only appropriate for that message. |
- DCHECK(msg.type() == PpapiMsg_CreateNaClChannel::ID); |
- IPC::ChannelHandle channel_handle = |
- IPC::Channel::GenerateVerifiedChannelID("nacl"); |
- scoped_refptr<NaClIPCAdapter> ipc_adapter( |
- new NaClIPCAdapter(channel_handle, task_runner_)); |
- ipc_adapter->ConnectChannel(); |
-#if defined(OS_POSIX) |
- channel_handle.socket = base::FileDescriptor( |
- ipc_adapter->TakeClientFileDescriptor(), true); |
-#endif |
- nacl_desc.reset(factory.MakeGeneric(ipc_adapter->MakeNaClDesc())); |
- // Send back a message that the channel was created. |
- scoped_ptr<IPC::Message> response( |
- new PpapiHostMsg_ChannelCreated(channel_handle)); |
- task_runner_->PostTask(FROM_HERE, |
- base::Bind(&NaClIPCAdapter::SendMessageOnIOThread, this, |
- base::Passed(&response))); |
- break; |
- } |
- case ppapi::proxy::SerializedHandle::FILE: |
- // TODO(raymes): Handle file handles for NaCl. |
- NOTIMPLEMENTED(); |
- break; |
- case ppapi::proxy::SerializedHandle::INVALID: { |
- // Nothing to do. TODO(dmichael): Should we log this? Or is it |
- // sometimes okay to pass an INVALID handle? |
+ uint32_t type = iter->second; |
+ pending_sync_msgs_.erase(iter); |
+ switch (type) { |
+ CASE_FOR_REPLY(PpapiHostMsg_PPBGraphics3D_GetTransferBuffer) |
+ CASE_FOR_REPLY(PpapiHostMsg_PPBImageData_CreateNaCl) |
+ CASE_FOR_REPLY(PpapiHostMsg_ResourceSyncCall) |
+ default: |
+ // Do nothing for messages we don't know. |
break; |
- } |
- // No default, so the compiler will warn us if new types get added. |
} |
- if (nacl_desc.get()) |
- rewritten_msg->AddDescriptor(nacl_desc.release()); |
+ break; |
} |
- if (new_msg_ptr && !handles.empty()) |
- SaveMessage(*new_msg_ptr, rewritten_msg.get()); |
- else |
- SaveMessage(msg, rewritten_msg.get()); |
- } |
- cond_var_.Signal(); |
- return true; |
-} |
- |
-void NaClIPCAdapter::OnChannelConnected(int32 peer_pid) { |
-} |
- |
-void NaClIPCAdapter::OnChannelError() { |
- CloseChannel(); |
-} |
- |
-NaClIPCAdapter::~NaClIPCAdapter() { |
- // Make sure the channel is deleted on the IO thread. |
- task_runner_->PostTask(FROM_HERE, |
- base::Bind(&DeleteChannel, io_thread_data_.channel_.release())); |
-} |
- |
-int NaClIPCAdapter::LockedReceive(NaClImcTypedMsgHdr* msg) { |
- lock_.AssertAcquired(); |
- |
- if (locked_data_.to_be_received_.empty()) |
- return 0; |
- scoped_refptr<RewrittenMessage> current = |
- locked_data_.to_be_received_.front(); |
- |
- int retval = current->Read(msg); |
- |
- // When a message is entirely consumed, remove if from the waiting queue. |
- if (current->is_consumed()) |
- locked_data_.to_be_received_.pop(); |
- |
- return retval; |
-} |
- |
-bool NaClIPCAdapter::SendCompleteMessage(const char* buffer, |
- size_t buffer_len) { |
- // The message will have already been validated, so we know it's large enough |
- // for our header. |
- const NaClMessageHeader* header = |
- reinterpret_cast<const NaClMessageHeader*>(buffer); |
- |
- // Length of the message not including the body. The data passed to us by the |
- // plugin should match that in the message header. This should have already |
- // been validated by GetBufferStatus. |
- int body_len = static_cast<int>(buffer_len - sizeof(NaClMessageHeader)); |
- DCHECK(body_len == static_cast<int>(header->payload_size)); |
- |
- // We actually discard the flags and only copy the ones we care about. This |
- // is just because message doesn't have a constructor that takes raw flags. |
- scoped_ptr<IPC::Message> msg( |
- new IPC::Message(header->routing, header->type, |
- IPC::Message::PRIORITY_NORMAL)); |
- if (header->flags & IPC::Message::SYNC_BIT) |
- msg->set_sync(); |
- if (header->flags & IPC::Message::REPLY_BIT) |
- msg->set_reply(); |
- if (header->flags & IPC::Message::REPLY_ERROR_BIT) |
- msg->set_reply_error(); |
- if (header->flags & IPC::Message::UNBLOCK_BIT) |
- msg->set_unblock(true); |
- |
- msg->WriteBytes(&buffer[sizeof(NaClMessageHeader)], body_len); |
- |
- // Technically we didn't have to do any of the previous work in the lock. But |
- // sometimes our buffer will point to the to_be_sent_ string which is |
- // protected by the lock, and it's messier to factor Send() such that it can |
- // unlock for us. Holding the lock for the message construction, which is |
- // just some memcpys, shouldn't be a big deal. |
- lock_.AssertAcquired(); |
- if (locked_data_.channel_closed_) |
- return false; // TODO(brettw) clean up handles here when we add support! |
- |
- // Store the type of all sync messages so that later we can translate the |
- // reply if necessary. |
- if (msg->is_sync()) { |
- int id = IPC::SyncMessage::GetMessageId(*msg); |
- locked_data_.pending_sync_msgs_[id] = msg->type(); |
+ default: |
+ // Do nothing for messages we don't know. |
+ break; |
} |
- // Actual send must be done on the I/O thread. |
- task_runner_->PostTask(FROM_HERE, |
- base::Bind(&NaClIPCAdapter::SendMessageOnIOThread, this, |
- base::Passed(&msg))); |
return true; |
} |
-void NaClIPCAdapter::ClearToBeSent() { |
- lock_.AssertAcquired(); |
- |
- // Don't let the string keep its buffer behind our back. |
- std::string empty; |
- locked_data_.to_be_sent_.swap(empty); |
-} |
- |
-void NaClIPCAdapter::ConnectChannelOnIOThread() { |
- if (!io_thread_data_.channel_->Connect()) |
- NOTREACHED(); |
-} |
- |
-void NaClIPCAdapter::CloseChannelOnIOThread() { |
- io_thread_data_.channel_->Close(); |
-} |
- |
-void NaClIPCAdapter::SendMessageOnIOThread(scoped_ptr<IPC::Message> message) { |
- io_thread_data_.channel_->Send(message.release()); |
-} |
- |
-void NaClIPCAdapter::SaveMessage(const IPC::Message& msg, |
- RewrittenMessage* rewritten_msg) { |
- lock_.AssertAcquired(); |
- // There is some padding in this structure (the "padding" member is 16 |
- // bits but this then gets padded to 32 bits). We want to be sure not to |
- // leak data to the untrusted plugin, so zero everything out first. |
- NaClMessageHeader header; |
- memset(&header, 0, sizeof(NaClMessageHeader)); |
+void HandleConverter::RegisterSyncMessageForReply(const IPC::Message& msg) { |
+ DCHECK(msg.is_sync()); |
- header.payload_size = static_cast<uint32>(msg.payload_size()); |
- header.routing = msg.routing_id(); |
- header.type = msg.type(); |
- header.flags = msg.flags(); |
- header.num_fds = static_cast<int>(rewritten_msg->desc_count()); |
+ int msg_id = IPC::SyncMessage::GetMessageId(msg); |
+ DCHECK(pending_sync_msgs_.find(msg_id) == pending_sync_msgs_.end()); |
- rewritten_msg->SetData(header, msg.payload(), msg.payload_size()); |
- locked_data_.to_be_received_.push(rewritten_msg); |
+ pending_sync_msgs_[msg_id] = msg.type(); |
} |
+} // namespace proxy |
+} // namespace ppapi |