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/system/raw_channel.h" | 5 #include "mojo/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 | 13 |
13 #include "base/basictypes.h" | 14 #include "base/basictypes.h" |
14 #include "base/bind.h" | 15 #include "base/bind.h" |
15 #include "base/compiler_specific.h" | 16 #include "base/compiler_specific.h" |
16 #include "base/location.h" | 17 #include "base/location.h" |
17 #include "base/logging.h" | 18 #include "base/logging.h" |
18 #include "base/memory/scoped_ptr.h" | 19 #include "base/memory/scoped_ptr.h" |
19 #include "base/memory/weak_ptr.h" | 20 #include "base/memory/weak_ptr.h" |
20 #include "base/message_loop/message_loop.h" | 21 #include "base/message_loop/message_loop.h" |
21 #include "base/synchronization/lock.h" | 22 #include "base/synchronization/lock.h" |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
61 void WaitToWrite(); | 62 void WaitToWrite(); |
62 | 63 |
63 embedder::ScopedPlatformHandle fd_; | 64 embedder::ScopedPlatformHandle fd_; |
64 | 65 |
65 // The following members are only used on the I/O thread: | 66 // The following members are only used on the I/O thread: |
66 scoped_ptr<base::MessageLoopForIO::FileDescriptorWatcher> read_watcher_; | 67 scoped_ptr<base::MessageLoopForIO::FileDescriptorWatcher> read_watcher_; |
67 scoped_ptr<base::MessageLoopForIO::FileDescriptorWatcher> write_watcher_; | 68 scoped_ptr<base::MessageLoopForIO::FileDescriptorWatcher> write_watcher_; |
68 | 69 |
69 bool pending_read_; | 70 bool pending_read_; |
70 | 71 |
71 embedder::ScopedPlatformHandleVectorPtr read_platform_handles_; | 72 std::deque<embedder::PlatformHandle> read_platform_handles_; |
72 | 73 |
73 // The following members are used on multiple threads and protected by | 74 // The following members are used on multiple threads and protected by |
74 // |write_lock()|: | 75 // |write_lock()|: |
75 bool pending_write_; | 76 bool pending_write_; |
76 | 77 |
77 // This is used for posting tasks from write threads to the I/O thread. It | 78 // This is used for posting tasks from write threads to the I/O thread. It |
78 // must only be accessed under |write_lock_|. The weak pointers it produces | 79 // must only be accessed under |write_lock_|. The weak pointers it produces |
79 // are only used/invalidated on the I/O thread. | 80 // are only used/invalidated on the I/O thread. |
80 base::WeakPtrFactory<RawChannelPosix> weak_ptr_factory_; | 81 base::WeakPtrFactory<RawChannelPosix> weak_ptr_factory_; |
81 | 82 |
(...skipping 13 matching lines...) Expand all Loading... |
95 DCHECK(!pending_write_); | 96 DCHECK(!pending_write_); |
96 | 97 |
97 // No need to take the |write_lock()| here -- if there are still weak pointers | 98 // No need to take the |write_lock()| here -- if there are still weak pointers |
98 // outstanding, then we're hosed anyway (since we wouldn't be able to | 99 // outstanding, then we're hosed anyway (since we wouldn't be able to |
99 // invalidate them cleanly, since we might not be on the I/O thread). | 100 // invalidate them cleanly, since we might not be on the I/O thread). |
100 DCHECK(!weak_ptr_factory_.HasWeakPtrs()); | 101 DCHECK(!weak_ptr_factory_.HasWeakPtrs()); |
101 | 102 |
102 // These must have been shut down/destroyed on the I/O thread. | 103 // These must have been shut down/destroyed on the I/O thread. |
103 DCHECK(!read_watcher_.get()); | 104 DCHECK(!read_watcher_.get()); |
104 DCHECK(!write_watcher_.get()); | 105 DCHECK(!write_watcher_.get()); |
| 106 |
| 107 embedder::CloseAllPlatformHandles(&read_platform_handles_); |
105 } | 108 } |
106 | 109 |
107 size_t RawChannelPosix::GetSerializedPlatformHandleSize() const { | 110 size_t RawChannelPosix::GetSerializedPlatformHandleSize() const { |
108 // We don't actually need any space on POSIX (since we just send FDs). | 111 // We don't actually need any space on POSIX (since we just send FDs). |
109 return 0; | 112 return 0; |
110 } | 113 } |
111 | 114 |
112 RawChannel::IOResult RawChannelPosix::Read(size_t* bytes_read) { | 115 RawChannel::IOResult RawChannelPosix::Read(size_t* bytes_read) { |
113 DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); | 116 DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); |
114 DCHECK(!pending_read_); | 117 DCHECK(!pending_read_); |
115 | 118 |
116 char* buffer = NULL; | 119 char* buffer = NULL; |
117 size_t bytes_to_read = 0; | 120 size_t bytes_to_read = 0; |
118 read_buffer()->GetBuffer(&buffer, &bytes_to_read); | 121 read_buffer()->GetBuffer(&buffer, &bytes_to_read); |
119 | 122 |
120 size_t old_num_platform_handles = | 123 size_t old_num_platform_handles = read_platform_handles_.size(); |
121 read_platform_handles_ ? read_platform_handles_->size() : 0; | |
122 ssize_t read_result = | 124 ssize_t read_result = |
123 embedder::PlatformChannelRecvmsg(fd_.get(), | 125 embedder::PlatformChannelRecvmsg(fd_.get(), |
124 buffer, | 126 buffer, |
125 bytes_to_read, | 127 bytes_to_read, |
126 &read_platform_handles_); | 128 &read_platform_handles_); |
127 if (read_platform_handles_ && | 129 if (read_platform_handles_.size() > old_num_platform_handles) { |
128 read_platform_handles_->size() > old_num_platform_handles) { | 130 DCHECK_LE(read_platform_handles_.size() - old_num_platform_handles, |
| 131 embedder::kPlatformChannelMaxNumHandles); |
| 132 |
129 if (read_result != 1) { | 133 if (read_result != 1) { |
130 LOG(WARNING) << "Invalid control message with platform handles"; | 134 LOG(WARNING) << "Invalid control message with platform handles"; |
131 return IO_FAILED; | 135 return IO_FAILED; |
132 } | 136 } |
133 | 137 |
134 if (read_platform_handles_->size() > TransportData::kMaxPlatformHandles) { | 138 // We should never accumulate more than |TransportData::kMaxPlatformHandles |
| 139 // + embedder::kPlatformChannelMaxNumHandles| handles. (The latter part is |
| 140 // possible because we could have accumulated all the handles for a message, |
| 141 // then received the message data plus the first set of handles for the next |
| 142 // message in the subsequent |recvmsg()|.) |
| 143 if (read_platform_handles_.size() > (TransportData::kMaxPlatformHandles + |
| 144 embedder::kPlatformChannelMaxNumHandles)) { |
135 LOG(WARNING) << "Received too many platform handles"; | 145 LOG(WARNING) << "Received too many platform handles"; |
136 read_platform_handles_.reset(); | 146 embedder::CloseAllPlatformHandles(&read_platform_handles_); |
| 147 read_platform_handles_.clear(); |
137 return IO_FAILED; | 148 return IO_FAILED; |
138 } | 149 } |
139 | 150 |
140 // This wasn't a data read (platform handles just get stashed). | 151 // This wasn't a data read (platform handles just get stashed). |
141 return ScheduleRead(); | 152 return ScheduleRead(); |
142 } | 153 } |
143 | 154 |
144 if (read_result > 0) { | 155 if (read_result > 0) { |
145 *bytes_read = static_cast<size_t>(read_result); | 156 *bytes_read = static_cast<size_t>(read_result); |
146 return IO_SUCCEEDED; | 157 return IO_SUCCEEDED; |
(...skipping 19 matching lines...) Expand all Loading... |
166 pending_read_ = true; | 177 pending_read_ = true; |
167 | 178 |
168 return IO_PENDING; | 179 return IO_PENDING; |
169 } | 180 } |
170 | 181 |
171 embedder::ScopedPlatformHandleVectorPtr RawChannelPosix::GetReadPlatformHandles( | 182 embedder::ScopedPlatformHandleVectorPtr RawChannelPosix::GetReadPlatformHandles( |
172 size_t num_platform_handles, | 183 size_t num_platform_handles, |
173 const void* /*platform_handle_table*/) { | 184 const void* /*platform_handle_table*/) { |
174 DCHECK_GT(num_platform_handles, 0u); | 185 DCHECK_GT(num_platform_handles, 0u); |
175 | 186 |
176 if (!read_platform_handles_ || | 187 if (read_platform_handles_.size() < num_platform_handles) { |
177 read_platform_handles_->size() != num_platform_handles) { | 188 embedder::CloseAllPlatformHandles(&read_platform_handles_); |
178 read_platform_handles_.reset(); | 189 read_platform_handles_.clear(); |
179 return embedder::ScopedPlatformHandleVectorPtr(); | 190 return embedder::ScopedPlatformHandleVectorPtr(); |
180 } | 191 } |
181 | 192 |
182 return read_platform_handles_.Pass(); | 193 embedder::ScopedPlatformHandleVectorPtr rv( |
| 194 new embedder::PlatformHandleVector(num_platform_handles)); |
| 195 rv->assign(read_platform_handles_.begin(), |
| 196 read_platform_handles_.begin() + num_platform_handles); |
| 197 read_platform_handles_.erase( |
| 198 read_platform_handles_.begin(), |
| 199 read_platform_handles_.begin() + num_platform_handles); |
| 200 return rv.Pass(); |
183 } | 201 } |
184 | 202 |
185 RawChannel::IOResult RawChannelPosix::WriteNoLock( | 203 RawChannel::IOResult RawChannelPosix::WriteNoLock( |
186 size_t* platform_handles_written, | 204 size_t* platform_handles_written, |
187 size_t* bytes_written) { | 205 size_t* bytes_written) { |
188 write_lock().AssertAcquired(); | 206 write_lock().AssertAcquired(); |
189 | 207 |
190 DCHECK(!pending_write_); | 208 DCHECK(!pending_write_); |
191 | 209 |
192 if (write_buffer_no_lock()->HavePlatformHandlesToSend()) { | 210 if (write_buffer_no_lock()->HavePlatformHandlesToSend()) { |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
385 | 403 |
386 // Static factory method declared in raw_channel.h. | 404 // Static factory method declared in raw_channel.h. |
387 // static | 405 // static |
388 scoped_ptr<RawChannel> RawChannel::Create( | 406 scoped_ptr<RawChannel> RawChannel::Create( |
389 embedder::ScopedPlatformHandle handle) { | 407 embedder::ScopedPlatformHandle handle) { |
390 return scoped_ptr<RawChannel>(new RawChannelPosix(handle.Pass())); | 408 return scoped_ptr<RawChannel>(new RawChannelPosix(handle.Pass())); |
391 } | 409 } |
392 | 410 |
393 } // namespace system | 411 } // namespace system |
394 } // namespace mojo | 412 } // namespace mojo |
OLD | NEW |