| 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 |