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 read_platform_handles_.reset(); |
yzshen1
2014/05/11 07:16:59
The handles need to be closed? (here and line 176)
viettrungluu
2014/05/12 17:33:28
Done.
| |
132 for (size_t i = 0; i < handles->size(); i++) | 142 return IO_FAILED; |
133 (*handles)[i].CloseIfNecessary(); | 143 } |
134 return ScheduleRead(); | |
135 } | 144 } |
136 | 145 |
137 // |read_result == 0| means "end of file". | 146 // |read_result == 0| means "end of file". |
138 if (read_result == 0 || (errno != EAGAIN && errno != EWOULDBLOCK)) { | 147 if (read_result == 0 || (errno != EAGAIN && errno != EWOULDBLOCK)) { |
139 PLOG_IF(ERROR, read_result != 0) << "recvmsg"; | 148 PLOG_IF(ERROR, read_result != 0) << "recvmsg"; |
140 | 149 |
141 // Make sure that |OnFileCanReadWithoutBlocking()| won't be called again. | 150 // Make sure that |OnFileCanReadWithoutBlocking()| won't be called again. |
142 read_watcher_.reset(); | 151 read_watcher_.reset(); |
143 | 152 |
144 return IO_FAILED; | 153 return IO_FAILED; |
145 } | 154 } |
146 | 155 |
147 return ScheduleRead(); | 156 return ScheduleRead(); |
148 } | 157 } |
149 | 158 |
150 RawChannel::IOResult RawChannelPosix::ScheduleRead() { | 159 RawChannel::IOResult RawChannelPosix::ScheduleRead() { |
151 DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); | 160 DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); |
152 DCHECK(!pending_read_); | 161 DCHECK(!pending_read_); |
153 | 162 |
154 pending_read_ = true; | 163 pending_read_ = true; |
155 | 164 |
156 return IO_PENDING; | 165 return IO_PENDING; |
157 } | 166 } |
158 | 167 |
168 scoped_ptr<embedder::PlatformHandleVector> | |
169 RawChannelPosix::GetReadPlatformHandles( | |
170 size_t num_platform_handles, | |
171 const void* /*platform_handle_table*/) { | |
172 DCHECK_GT(num_platform_handles, 0u); | |
173 | |
174 if (!read_platform_handles_ || | |
175 read_platform_handles_->size() != num_platform_handles) { | |
176 read_platform_handles_.reset(); | |
177 return scoped_ptr<embedder::PlatformHandleVector>(); | |
178 } | |
179 | |
180 return read_platform_handles_.Pass(); | |
181 } | |
182 | |
159 RawChannel::IOResult RawChannelPosix::WriteNoLock( | 183 RawChannel::IOResult RawChannelPosix::WriteNoLock( |
160 size_t* platform_handles_written, | 184 size_t* platform_handles_written, |
161 size_t* bytes_written) { | 185 size_t* bytes_written) { |
162 write_lock().AssertAcquired(); | 186 write_lock().AssertAcquired(); |
163 | 187 |
164 DCHECK(!pending_write_); | 188 DCHECK(!pending_write_); |
165 | 189 |
166 if (write_buffer_no_lock()->HavePlatformHandlesToSend()) { | 190 if (write_buffer_no_lock()->HavePlatformHandlesToSend()) { |
167 size_t num_platform_handles; | 191 size_t num_platform_handles; |
168 embedder::PlatformHandle* platform_handles; | 192 embedder::PlatformHandle* platform_handles; |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
359 | 383 |
360 // Static factory method declared in raw_channel.h. | 384 // Static factory method declared in raw_channel.h. |
361 // static | 385 // static |
362 scoped_ptr<RawChannel> RawChannel::Create( | 386 scoped_ptr<RawChannel> RawChannel::Create( |
363 embedder::ScopedPlatformHandle handle) { | 387 embedder::ScopedPlatformHandle handle) { |
364 return scoped_ptr<RawChannel>(new RawChannelPosix(handle.Pass())); | 388 return scoped_ptr<RawChannel>(new RawChannelPosix(handle.Pass())); |
365 } | 389 } |
366 | 390 |
367 } // namespace system | 391 } // namespace system |
368 } // namespace mojo | 392 } // namespace mojo |
OLD | NEW |