| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "mojo/edk/system/raw_channel.h" | 5 #include "mojo/edk/system/raw_channel.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <sys/uio.h> | 8 #include <sys/uio.h> |
| 9 #include <unistd.h> | 9 #include <unistd.h> |
| 10 | 10 |
| 11 #include <algorithm> | 11 #include <algorithm> |
| 12 #include <deque> | 12 #include <deque> |
| 13 #include <iterator> |
| 13 #include <memory> | 14 #include <memory> |
| 14 #include <utility> | 15 #include <utility> |
| 16 #include <vector> |
| 15 | 17 |
| 16 #include "base/bind.h" | 18 #include "base/bind.h" |
| 17 #include "base/location.h" | 19 #include "base/location.h" |
| 18 #include "base/logging.h" | 20 #include "base/logging.h" |
| 19 #include "base/memory/weak_ptr.h" | 21 #include "base/memory/weak_ptr.h" |
| 20 #include "base/message_loop/message_loop.h" | 22 #include "base/message_loop/message_loop.h" |
| 21 #include "mojo/edk/embedder/platform_channel_utils.h" | 23 #include "mojo/edk/embedder/platform_channel_utils.h" |
| 22 #include "mojo/edk/embedder/platform_handle.h" | 24 #include "mojo/edk/embedder/platform_handle.h" |
| 23 #include "mojo/edk/embedder/platform_handle_vector.h" | 25 #include "mojo/edk/embedder/scoped_platform_handle.h" |
| 24 #include "mojo/edk/system/transport_data.h" | 26 #include "mojo/edk/system/transport_data.h" |
| 25 #include "mojo/edk/util/make_unique.h" | 27 #include "mojo/edk/util/make_unique.h" |
| 26 #include "mojo/public/cpp/system/macros.h" | 28 #include "mojo/public/cpp/system/macros.h" |
| 27 | 29 |
| 30 using mojo::embedder::ScopedPlatformHandle; |
| 31 using mojo::util::MakeUnique; |
| 28 using mojo::util::MutexLocker; | 32 using mojo::util::MutexLocker; |
| 29 | 33 |
| 30 namespace mojo { | 34 namespace mojo { |
| 31 namespace system { | 35 namespace system { |
| 32 | 36 |
| 33 namespace { | 37 namespace { |
| 34 | 38 |
| 35 class RawChannelPosix final : public RawChannel, | 39 class RawChannelPosix final : public RawChannel, |
| 36 public base::MessageLoopForIO::Watcher { | 40 public base::MessageLoopForIO::Watcher { |
| 37 public: | 41 public: |
| 38 explicit RawChannelPosix(embedder::ScopedPlatformHandle handle); | 42 explicit RawChannelPosix(embedder::ScopedPlatformHandle handle); |
| 39 ~RawChannelPosix() override; | 43 ~RawChannelPosix() override; |
| 40 | 44 |
| 41 // |RawChannel| public methods: | 45 // |RawChannel| public methods: |
| 42 size_t GetSerializedPlatformHandleSize() const override; | 46 size_t GetSerializedPlatformHandleSize() const override; |
| 43 | 47 |
| 44 private: | 48 private: |
| 45 // |RawChannel| protected methods: | 49 // |RawChannel| protected methods: |
| 46 // Actually override this so that we can send multiple messages with (only) | 50 // Actually override this so that we can send multiple messages with (only) |
| 47 // FDs if necessary. | 51 // FDs if necessary. |
| 48 void EnqueueMessageNoLock(std::unique_ptr<MessageInTransit> message) override | 52 void EnqueueMessageNoLock(std::unique_ptr<MessageInTransit> message) override |
| 49 MOJO_EXCLUSIVE_LOCKS_REQUIRED(write_mutex()); | 53 MOJO_EXCLUSIVE_LOCKS_REQUIRED(write_mutex()); |
| 50 // Override this to handle those extra FD-only messages. | 54 // Override this to handle those extra FD-only messages. |
| 51 bool OnReadMessageForRawChannel( | 55 bool OnReadMessageForRawChannel( |
| 52 const MessageInTransit::View& message_view) override; | 56 const MessageInTransit::View& message_view) override; |
| 53 IOResult Read(size_t* bytes_read) override; | 57 IOResult Read(size_t* bytes_read) override; |
| 54 IOResult ScheduleRead() override; | 58 IOResult ScheduleRead() override; |
| 55 embedder::ScopedPlatformHandleVectorPtr GetReadPlatformHandles( | 59 std::unique_ptr<std::vector<ScopedPlatformHandle>> GetReadPlatformHandles( |
| 56 size_t num_platform_handles, | 60 size_t num_platform_handles, |
| 57 const void* platform_handle_table) override; | 61 const void* platform_handle_table) override; |
| 58 IOResult WriteNoLock(size_t* platform_handles_written, | 62 IOResult WriteNoLock(size_t* platform_handles_written, |
| 59 size_t* bytes_written) override; | 63 size_t* bytes_written) override; |
| 60 IOResult ScheduleWriteNoLock() override; | 64 IOResult ScheduleWriteNoLock() override; |
| 61 void OnInit() override; | 65 void OnInit() override; |
| 62 void OnShutdownNoLock(std::unique_ptr<ReadBuffer> read_buffer, | 66 void OnShutdownNoLock(std::unique_ptr<ReadBuffer> read_buffer, |
| 63 std::unique_ptr<WriteBuffer> write_buffer) override; | 67 std::unique_ptr<WriteBuffer> write_buffer) override; |
| 64 | 68 |
| 65 // |base::MessageLoopForIO::Watcher| implementation: | 69 // |base::MessageLoopForIO::Watcher| implementation: |
| 66 void OnFileCanReadWithoutBlocking(int fd) override; | 70 void OnFileCanReadWithoutBlocking(int fd) override; |
| 67 void OnFileCanWriteWithoutBlocking(int fd) override; | 71 void OnFileCanWriteWithoutBlocking(int fd) override; |
| 68 | 72 |
| 69 // Implements most of |Read()| (except for a bit of clean-up): | 73 // Implements most of |Read()| (except for a bit of clean-up): |
| 70 IOResult ReadImpl(size_t* bytes_read); | 74 IOResult ReadImpl(size_t* bytes_read); |
| 71 | 75 |
| 72 // Watches for |fd_| to become writable. Must be called on the I/O thread. | 76 // Watches for |fd_| to become writable. Must be called on the I/O thread. |
| 73 void WaitToWrite(); | 77 void WaitToWrite(); |
| 74 | 78 |
| 75 embedder::ScopedPlatformHandle fd_; | 79 embedder::ScopedPlatformHandle fd_; |
| 76 | 80 |
| 77 // The following members are only used on the I/O thread: | 81 // The following members are only used on the I/O thread: |
| 78 std::unique_ptr<base::MessageLoopForIO::FileDescriptorWatcher> read_watcher_; | 82 std::unique_ptr<base::MessageLoopForIO::FileDescriptorWatcher> read_watcher_; |
| 79 std::unique_ptr<base::MessageLoopForIO::FileDescriptorWatcher> write_watcher_; | 83 std::unique_ptr<base::MessageLoopForIO::FileDescriptorWatcher> write_watcher_; |
| 80 | 84 |
| 81 bool pending_read_; | 85 bool pending_read_; |
| 82 | 86 |
| 83 std::deque<embedder::PlatformHandle> read_platform_handles_; | 87 std::deque<embedder::ScopedPlatformHandle> read_platform_handles_; |
| 84 | 88 |
| 85 bool pending_write_ MOJO_GUARDED_BY(write_mutex()); | 89 bool pending_write_ MOJO_GUARDED_BY(write_mutex()); |
| 86 | 90 |
| 87 // This is used for posting tasks from write threads to the I/O thread. The | 91 // This is used for posting tasks from write threads to the I/O thread. The |
| 88 // weak pointers it produces are only used/invalidated on the I/O thread. | 92 // weak pointers it produces are only used/invalidated on the I/O thread. |
| 89 base::WeakPtrFactory<RawChannelPosix> weak_ptr_factory_ | 93 base::WeakPtrFactory<RawChannelPosix> weak_ptr_factory_ |
| 90 MOJO_GUARDED_BY(write_mutex()); | 94 MOJO_GUARDED_BY(write_mutex()); |
| 91 | 95 |
| 92 MOJO_DISALLOW_COPY_AND_ASSIGN(RawChannelPosix); | 96 MOJO_DISALLOW_COPY_AND_ASSIGN(RawChannelPosix); |
| 93 }; | 97 }; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 105 DCHECK(!pending_write_); | 109 DCHECK(!pending_write_); |
| 106 | 110 |
| 107 // No need to take |write_mutex()| here -- if there are still weak pointers | 111 // No need to take |write_mutex()| here -- if there are still weak pointers |
| 108 // outstanding, then we're hosed anyway (since we wouldn't be able to | 112 // outstanding, then we're hosed anyway (since we wouldn't be able to |
| 109 // invalidate them cleanly, since we might not be on the I/O thread). | 113 // invalidate them cleanly, since we might not be on the I/O thread). |
| 110 DCHECK(!weak_ptr_factory_.HasWeakPtrs()); | 114 DCHECK(!weak_ptr_factory_.HasWeakPtrs()); |
| 111 | 115 |
| 112 // These must have been shut down/destroyed on the I/O thread. | 116 // These must have been shut down/destroyed on the I/O thread. |
| 113 DCHECK(!read_watcher_); | 117 DCHECK(!read_watcher_); |
| 114 DCHECK(!write_watcher_); | 118 DCHECK(!write_watcher_); |
| 115 | |
| 116 embedder::CloseAllPlatformHandles(&read_platform_handles_); | |
| 117 } | 119 } |
| 118 | 120 |
| 119 size_t RawChannelPosix::GetSerializedPlatformHandleSize() const { | 121 size_t RawChannelPosix::GetSerializedPlatformHandleSize() const { |
| 120 // We don't actually need any space on POSIX (since we just send FDs). | 122 // We don't actually need any space on POSIX (since we just send FDs). |
| 121 return 0; | 123 return 0; |
| 122 } | 124 } |
| 123 | 125 |
| 124 void RawChannelPosix::EnqueueMessageNoLock( | 126 void RawChannelPosix::EnqueueMessageNoLock( |
| 125 std::unique_ptr<MessageInTransit> message) { | 127 std::unique_ptr<MessageInTransit> message) { |
| 126 if (message->transport_data()) { | 128 if (message->transport_data()) { |
| 127 embedder::PlatformHandleVector* const platform_handles = | 129 std::vector<ScopedPlatformHandle>* const platform_handles = |
| 128 message->transport_data()->platform_handles(); | 130 message->transport_data()->platform_handles(); |
| 129 if (platform_handles && | 131 if (platform_handles && |
| 130 platform_handles->size() > embedder::kPlatformChannelMaxNumHandles) { | 132 platform_handles->size() > embedder::kPlatformChannelMaxNumHandles) { |
| 131 // We can't attach all the FDs to a single message, so we have to "split" | 133 // We can't attach all the FDs to a single message, so we have to "split" |
| 132 // the message. Send as many control messages as needed first with FDs | 134 // the message. Send as many control messages as needed first with FDs |
| 133 // attached (and no data). | 135 // attached (and no data). |
| 134 size_t i = 0; | 136 size_t i = 0; |
| 135 for (; platform_handles->size() - i > | 137 for (; platform_handles->size() - i > |
| 136 embedder::kPlatformChannelMaxNumHandles; | 138 embedder::kPlatformChannelMaxNumHandles; |
| 137 i += embedder::kPlatformChannelMaxNumHandles) { | 139 i += embedder::kPlatformChannelMaxNumHandles) { |
| 138 std::unique_ptr<MessageInTransit> fd_message(new MessageInTransit( | 140 std::unique_ptr<MessageInTransit> fd_message(new MessageInTransit( |
| 139 MessageInTransit::Type::RAW_CHANNEL, | 141 MessageInTransit::Type::RAW_CHANNEL, |
| 140 MessageInTransit::Subtype::RAW_CHANNEL_POSIX_EXTRA_PLATFORM_HANDLES, | 142 MessageInTransit::Subtype::RAW_CHANNEL_POSIX_EXTRA_PLATFORM_HANDLES, |
| 141 0, nullptr)); | 143 0, nullptr)); |
| 142 embedder::ScopedPlatformHandleVectorPtr fds( | 144 using IteratorType = std::vector<ScopedPlatformHandle>::iterator; |
| 143 new embedder::PlatformHandleVector( | 145 std::unique_ptr<std::vector<ScopedPlatformHandle>> fds( |
| 144 platform_handles->begin() + i, | 146 MakeUnique<std::vector<ScopedPlatformHandle>>( |
| 145 platform_handles->begin() + i + | 147 std::move_iterator<IteratorType>(platform_handles->begin() + i), |
| 146 embedder::kPlatformChannelMaxNumHandles)); | 148 std::move_iterator<IteratorType>( |
| 149 platform_handles->begin() + i + |
| 150 embedder::kPlatformChannelMaxNumHandles))); |
| 147 fd_message->SetTransportData(util::MakeUnique<TransportData>( | 151 fd_message->SetTransportData(util::MakeUnique<TransportData>( |
| 148 std::move(fds), GetSerializedPlatformHandleSize())); | 152 std::move(fds), GetSerializedPlatformHandleSize())); |
| 149 RawChannel::EnqueueMessageNoLock(std::move(fd_message)); | 153 RawChannel::EnqueueMessageNoLock(std::move(fd_message)); |
| 150 } | 154 } |
| 151 | 155 |
| 152 // Remove the handles that we "moved" into the other messages. | 156 // Remove the handles that we "moved" into the other messages. |
| 153 platform_handles->erase(platform_handles->begin(), | 157 platform_handles->erase(platform_handles->begin(), |
| 154 platform_handles->begin() + i); | 158 platform_handles->begin() + i); |
| 155 } | 159 } |
| 156 } | 160 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 186 | 190 |
| 187 RawChannel::IOResult RawChannelPosix::ScheduleRead() { | 191 RawChannel::IOResult RawChannelPosix::ScheduleRead() { |
| 188 DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); | 192 DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); |
| 189 DCHECK(!pending_read_); | 193 DCHECK(!pending_read_); |
| 190 | 194 |
| 191 pending_read_ = true; | 195 pending_read_ = true; |
| 192 | 196 |
| 193 return IO_PENDING; | 197 return IO_PENDING; |
| 194 } | 198 } |
| 195 | 199 |
| 196 embedder::ScopedPlatformHandleVectorPtr RawChannelPosix::GetReadPlatformHandles( | 200 std::unique_ptr<std::vector<ScopedPlatformHandle>> |
| 197 size_t num_platform_handles, | 201 RawChannelPosix::GetReadPlatformHandles(size_t num_platform_handles, |
| 198 const void* /*platform_handle_table*/) { | 202 const void* /*platform_handle_table*/) { |
| 199 DCHECK_GT(num_platform_handles, 0u); | 203 DCHECK_GT(num_platform_handles, 0u); |
| 200 | 204 |
| 201 if (read_platform_handles_.size() < num_platform_handles) { | 205 if (read_platform_handles_.size() < num_platform_handles) { |
| 202 embedder::CloseAllPlatformHandles(&read_platform_handles_); | |
| 203 read_platform_handles_.clear(); | 206 read_platform_handles_.clear(); |
| 204 return embedder::ScopedPlatformHandleVectorPtr(); | 207 return nullptr; |
| 205 } | 208 } |
| 206 | 209 |
| 207 embedder::ScopedPlatformHandleVectorPtr rv( | 210 auto rv = MakeUnique<std::vector<ScopedPlatformHandle>>(num_platform_handles); |
| 208 new embedder::PlatformHandleVector(num_platform_handles)); | 211 using IteratorType = std::deque<ScopedPlatformHandle>::iterator; |
| 209 rv->assign(read_platform_handles_.begin(), | 212 rv->assign(std::move_iterator<IteratorType>(read_platform_handles_.begin()), |
| 210 read_platform_handles_.begin() + num_platform_handles); | 213 std::move_iterator<IteratorType>(read_platform_handles_.begin() + |
| 214 num_platform_handles)); |
| 211 read_platform_handles_.erase( | 215 read_platform_handles_.erase( |
| 212 read_platform_handles_.begin(), | 216 read_platform_handles_.begin(), |
| 213 read_platform_handles_.begin() + num_platform_handles); | 217 read_platform_handles_.begin() + num_platform_handles); |
| 214 return rv; | 218 return rv; |
| 215 } | 219 } |
| 216 | 220 |
| 217 RawChannel::IOResult RawChannelPosix::WriteNoLock( | 221 RawChannel::IOResult RawChannelPosix::WriteNoLock( |
| 218 size_t* platform_handles_written, | 222 size_t* platform_handles_written, |
| 219 size_t* bytes_written) { | 223 size_t* bytes_written) { |
| 220 write_mutex().AssertHeld(); | 224 write_mutex().AssertHeld(); |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 415 | 419 |
| 416 // We should never accumulate more than |TransportData::kMaxPlatformHandles | 420 // We should never accumulate more than |TransportData::kMaxPlatformHandles |
| 417 // + embedder::kPlatformChannelMaxNumHandles| handles. (The latter part is | 421 // + embedder::kPlatformChannelMaxNumHandles| handles. (The latter part is |
| 418 // possible because we could have accumulated all the handles for a message, | 422 // possible because we could have accumulated all the handles for a message, |
| 419 // then received the message data plus the first set of handles for the next | 423 // then received the message data plus the first set of handles for the next |
| 420 // message in the subsequent |recvmsg()|.) | 424 // message in the subsequent |recvmsg()|.) |
| 421 if (read_platform_handles_.size() > | 425 if (read_platform_handles_.size() > |
| 422 (TransportData::GetMaxPlatformHandles() + | 426 (TransportData::GetMaxPlatformHandles() + |
| 423 embedder::kPlatformChannelMaxNumHandles)) { | 427 embedder::kPlatformChannelMaxNumHandles)) { |
| 424 LOG(ERROR) << "Received too many platform handles"; | 428 LOG(ERROR) << "Received too many platform handles"; |
| 425 embedder::CloseAllPlatformHandles(&read_platform_handles_); | |
| 426 read_platform_handles_.clear(); | 429 read_platform_handles_.clear(); |
| 427 return IO_FAILED_UNKNOWN; | 430 return IO_FAILED_UNKNOWN; |
| 428 } | 431 } |
| 429 } | 432 } |
| 430 | 433 |
| 431 if (read_result > 0) { | 434 if (read_result > 0) { |
| 432 *bytes_read = static_cast<size_t>(read_result); | 435 *bytes_read = static_cast<size_t>(read_result); |
| 433 return IO_SUCCEEDED; | 436 return IO_SUCCEEDED; |
| 434 } | 437 } |
| 435 | 438 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 472 | 475 |
| 473 // Static factory method declared in raw_channel.h. | 476 // Static factory method declared in raw_channel.h. |
| 474 // static | 477 // static |
| 475 std::unique_ptr<RawChannel> RawChannel::Create( | 478 std::unique_ptr<RawChannel> RawChannel::Create( |
| 476 embedder::ScopedPlatformHandle handle) { | 479 embedder::ScopedPlatformHandle handle) { |
| 477 return util::MakeUnique<RawChannelPosix>(handle.Pass()); | 480 return util::MakeUnique<RawChannelPosix>(handle.Pass()); |
| 478 } | 481 } |
| 479 | 482 |
| 480 } // namespace system | 483 } // namespace system |
| 481 } // namespace mojo | 484 } // namespace mojo |
| OLD | NEW |