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 |