| 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 | 12 |
| 13 #include "base/basictypes.h" | 13 #include "base/basictypes.h" |
| 14 #include "base/bind.h" | 14 #include "base/bind.h" |
| 15 #include "base/compiler_specific.h" | 15 #include "base/compiler_specific.h" |
| 16 #include "base/location.h" | 16 #include "base/location.h" |
| 17 #include "base/logging.h" | 17 #include "base/logging.h" |
| 18 #include "base/memory/scoped_ptr.h" | 18 #include "base/memory/scoped_ptr.h" |
| 19 #include "base/memory/weak_ptr.h" | 19 #include "base/memory/weak_ptr.h" |
| 20 #include "base/message_loop/message_loop.h" | 20 #include "base/message_loop/message_loop.h" |
| 21 #include "base/synchronization/lock.h" | 21 #include "base/synchronization/lock.h" |
| 22 #include "mojo/embedder/platform_channel_utils_posix.h" | 22 #include "mojo/embedder/platform_channel_utils_posix.h" |
| 23 #include "mojo/embedder/platform_handle.h" | 23 #include "mojo/embedder/platform_handle.h" |
| 24 #include "mojo/embedder/platform_handle_vector.h" |
| 25 #include "mojo/system/transport_data.h" |
| 24 | 26 |
| 25 namespace mojo { | 27 namespace mojo { |
| 26 namespace system { | 28 namespace system { |
| 27 | 29 |
| 28 namespace { | 30 namespace { |
| 29 | 31 |
| 30 class RawChannelPosix : public RawChannel, | 32 class RawChannelPosix : public RawChannel, |
| 31 public base::MessageLoopForIO::Watcher { | 33 public base::MessageLoopForIO::Watcher { |
| 32 public: | 34 public: |
| 33 RawChannelPosix(embedder::ScopedPlatformHandle handle); | 35 RawChannelPosix(embedder::ScopedPlatformHandle handle); |
| 34 virtual ~RawChannelPosix(); | 36 virtual ~RawChannelPosix(); |
| 35 | 37 |
| 36 // |RawChannel| public methods: | 38 // |RawChannel| public methods: |
| 37 virtual size_t GetSerializedPlatformHandleSize() const OVERRIDE; | 39 virtual size_t GetSerializedPlatformHandleSize() const OVERRIDE; |
| 38 | 40 |
| 39 private: | 41 private: |
| 40 // |RawChannel| protected methods: | 42 // |RawChannel| protected methods: |
| 41 virtual IOResult Read(size_t* bytes_read) OVERRIDE; | 43 virtual IOResult Read(size_t* bytes_read) OVERRIDE; |
| 42 virtual IOResult ScheduleRead() OVERRIDE; | 44 virtual IOResult ScheduleRead() OVERRIDE; |
| 45 virtual scoped_ptr<embedder::PlatformHandleVector> GetReadPlatformHandles( |
| 46 size_t num_platform_handles, |
| 47 const void* platform_handle_table) OVERRIDE; |
| 43 virtual IOResult WriteNoLock(size_t* platform_handles_written, | 48 virtual IOResult WriteNoLock(size_t* platform_handles_written, |
| 44 size_t* bytes_written) OVERRIDE; | 49 size_t* bytes_written) OVERRIDE; |
| 45 virtual IOResult ScheduleWriteNoLock() OVERRIDE; | 50 virtual IOResult ScheduleWriteNoLock() OVERRIDE; |
| 46 virtual bool OnInit() OVERRIDE; | 51 virtual bool OnInit() OVERRIDE; |
| 47 virtual void OnShutdownNoLock( | 52 virtual void OnShutdownNoLock( |
| 48 scoped_ptr<ReadBuffer> read_buffer, | 53 scoped_ptr<ReadBuffer> read_buffer, |
| 49 scoped_ptr<WriteBuffer> write_buffer) OVERRIDE; | 54 scoped_ptr<WriteBuffer> write_buffer) OVERRIDE; |
| 50 | 55 |
| 51 // |base::MessageLoopForIO::Watcher| implementation: | 56 // |base::MessageLoopForIO::Watcher| implementation: |
| 52 virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE; | 57 virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE; |
| 53 virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE; | 58 virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE; |
| 54 | 59 |
| 55 // Watches for |fd_| to become writable. Must be called on the I/O thread. | 60 // Watches for |fd_| to become writable. Must be called on the I/O thread. |
| 56 void WaitToWrite(); | 61 void WaitToWrite(); |
| 57 | 62 |
| 58 embedder::ScopedPlatformHandle fd_; | 63 embedder::ScopedPlatformHandle fd_; |
| 59 | 64 |
| 60 // The following members are only used on the I/O thread: | 65 // The following members are only used on the I/O thread: |
| 61 scoped_ptr<base::MessageLoopForIO::FileDescriptorWatcher> read_watcher_; | 66 scoped_ptr<base::MessageLoopForIO::FileDescriptorWatcher> read_watcher_; |
| 62 scoped_ptr<base::MessageLoopForIO::FileDescriptorWatcher> write_watcher_; | 67 scoped_ptr<base::MessageLoopForIO::FileDescriptorWatcher> write_watcher_; |
| 63 | 68 |
| 64 bool pending_read_; | 69 bool pending_read_; |
| 65 | 70 |
| 71 scoped_ptr<embedder::PlatformHandleVector> read_platform_handles_; |
| 72 |
| 66 // The following members are used on multiple threads and protected by | 73 // The following members are used on multiple threads and protected by |
| 67 // |write_lock()|: | 74 // |write_lock()|: |
| 68 bool pending_write_; | 75 bool pending_write_; |
| 69 | 76 |
| 70 // This is used for posting tasks from write threads to the I/O thread. It | 77 // This is used for posting tasks from write threads to the I/O thread. It |
| 71 // must only be accessed under |write_lock_|. The weak pointers it produces | 78 // must only be accessed under |write_lock_|. The weak pointers it produces |
| 72 // are only used/invalidated on the I/O thread. | 79 // are only used/invalidated on the I/O thread. |
| 73 base::WeakPtrFactory<RawChannelPosix> weak_ptr_factory_; | 80 base::WeakPtrFactory<RawChannelPosix> weak_ptr_factory_; |
| 74 | 81 |
| 75 DISALLOW_COPY_AND_ASSIGN(RawChannelPosix); | 82 DISALLOW_COPY_AND_ASSIGN(RawChannelPosix); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 103 } | 110 } |
| 104 | 111 |
| 105 RawChannel::IOResult RawChannelPosix::Read(size_t* bytes_read) { | 112 RawChannel::IOResult RawChannelPosix::Read(size_t* bytes_read) { |
| 106 DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); | 113 DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); |
| 107 DCHECK(!pending_read_); | 114 DCHECK(!pending_read_); |
| 108 | 115 |
| 109 char* buffer = NULL; | 116 char* buffer = NULL; |
| 110 size_t bytes_to_read = 0; | 117 size_t bytes_to_read = 0; |
| 111 read_buffer()->GetBuffer(&buffer, &bytes_to_read); | 118 read_buffer()->GetBuffer(&buffer, &bytes_to_read); |
| 112 | 119 |
| 113 scoped_ptr<embedder::PlatformHandleVector> handles; | 120 size_t old_num_platform_handles = |
| 114 ssize_t read_result = embedder::PlatformChannelRecvmsg(fd_.get(), | 121 read_platform_handles_ ? read_platform_handles_->size() : 0; |
| 115 buffer, | 122 ssize_t read_result = |
| 116 bytes_to_read, | 123 embedder::PlatformChannelRecvmsg(fd_.get(), |
| 117 &handles); | 124 buffer, |
| 125 bytes_to_read, |
| 126 &read_platform_handles_); |
| 118 if (read_result > 0) { | 127 if (read_result > 0) { |
| 119 *bytes_read = static_cast<size_t>(read_result); | 128 *bytes_read = static_cast<size_t>(read_result); |
| 120 return IO_SUCCEEDED; | 129 return IO_SUCCEEDED; |
| 121 } | 130 } |
| 122 | 131 |
| 123 if (handles) { | 132 if (read_platform_handles_ && |
| 133 read_platform_handles_->size() > old_num_platform_handles) { |
| 124 if (read_result != 1) { | 134 if (read_result != 1) { |
| 125 LOG(WARNING) << "Invalid control message with handles"; | 135 LOG(WARNING) << "Invalid control message with platform handles"; |
| 126 return IO_FAILED; | 136 return IO_FAILED; |
| 127 } | 137 } |
| 128 | 138 |
| 129 // TODO(vtl): Implement this ("buffer" received handles). For now, just drop | 139 if (read_platform_handles_->size() > TransportData::kMaxPlatformHandles) { |
| 130 // them on the floor. (Discard this message entirely.) | 140 LOG(WARNING) << "Received too many platform handles"; |
| 131 NOTIMPLEMENTED(); | 141 embedder::CloseAllHandlesAndClear(read_platform_handles_.get()); |
| 132 for (size_t i = 0; i < handles->size(); i++) | 142 read_platform_handles_.reset(); |
| 133 (*handles)[i].CloseIfNecessary(); | 143 return IO_FAILED; |
| 134 return ScheduleRead(); | 144 } |
| 135 } | 145 } |
| 136 | 146 |
| 137 // |read_result == 0| means "end of file". | 147 // |read_result == 0| means "end of file". |
| 138 if (read_result == 0 || (errno != EAGAIN && errno != EWOULDBLOCK)) { | 148 if (read_result == 0 || (errno != EAGAIN && errno != EWOULDBLOCK)) { |
| 139 PLOG_IF(ERROR, read_result != 0) << "recvmsg"; | 149 PLOG_IF(ERROR, read_result != 0) << "recvmsg"; |
| 140 | 150 |
| 141 // Make sure that |OnFileCanReadWithoutBlocking()| won't be called again. | 151 // Make sure that |OnFileCanReadWithoutBlocking()| won't be called again. |
| 142 read_watcher_.reset(); | 152 read_watcher_.reset(); |
| 143 | 153 |
| 144 return IO_FAILED; | 154 return IO_FAILED; |
| 145 } | 155 } |
| 146 | 156 |
| 147 return ScheduleRead(); | 157 return ScheduleRead(); |
| 148 } | 158 } |
| 149 | 159 |
| 150 RawChannel::IOResult RawChannelPosix::ScheduleRead() { | 160 RawChannel::IOResult RawChannelPosix::ScheduleRead() { |
| 151 DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); | 161 DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); |
| 152 DCHECK(!pending_read_); | 162 DCHECK(!pending_read_); |
| 153 | 163 |
| 154 pending_read_ = true; | 164 pending_read_ = true; |
| 155 | 165 |
| 156 return IO_PENDING; | 166 return IO_PENDING; |
| 157 } | 167 } |
| 158 | 168 |
| 169 scoped_ptr<embedder::PlatformHandleVector> |
| 170 RawChannelPosix::GetReadPlatformHandles( |
| 171 size_t num_platform_handles, |
| 172 const void* /*platform_handle_table*/) { |
| 173 DCHECK_GT(num_platform_handles, 0u); |
| 174 |
| 175 if (!read_platform_handles_ || |
| 176 read_platform_handles_->size() != num_platform_handles) { |
| 177 embedder::CloseAllHandlesAndClear(read_platform_handles_.get()); |
| 178 read_platform_handles_.reset(); |
| 179 return scoped_ptr<embedder::PlatformHandleVector>(); |
| 180 } |
| 181 |
| 182 return read_platform_handles_.Pass(); |
| 183 } |
| 184 |
| 159 RawChannel::IOResult RawChannelPosix::WriteNoLock( | 185 RawChannel::IOResult RawChannelPosix::WriteNoLock( |
| 160 size_t* platform_handles_written, | 186 size_t* platform_handles_written, |
| 161 size_t* bytes_written) { | 187 size_t* bytes_written) { |
| 162 write_lock().AssertAcquired(); | 188 write_lock().AssertAcquired(); |
| 163 | 189 |
| 164 DCHECK(!pending_write_); | 190 DCHECK(!pending_write_); |
| 165 | 191 |
| 166 if (write_buffer_no_lock()->HavePlatformHandlesToSend()) { | 192 if (write_buffer_no_lock()->HavePlatformHandlesToSend()) { |
| 167 size_t num_platform_handles; | 193 size_t num_platform_handles; |
| 168 embedder::PlatformHandle* platform_handles; | 194 embedder::PlatformHandle* platform_handles; |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 359 | 385 |
| 360 // Static factory method declared in raw_channel.h. | 386 // Static factory method declared in raw_channel.h. |
| 361 // static | 387 // static |
| 362 scoped_ptr<RawChannel> RawChannel::Create( | 388 scoped_ptr<RawChannel> RawChannel::Create( |
| 363 embedder::ScopedPlatformHandle handle) { | 389 embedder::ScopedPlatformHandle handle) { |
| 364 return scoped_ptr<RawChannel>(new RawChannelPosix(handle.Pass())); | 390 return scoped_ptr<RawChannel>(new RawChannelPosix(handle.Pass())); |
| 365 } | 391 } |
| 366 | 392 |
| 367 } // namespace system | 393 } // namespace system |
| 368 } // namespace mojo | 394 } // namespace mojo |
| OLD | NEW |