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 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
56 size_t* bytes_written) OVERRIDE; | 56 size_t* bytes_written) OVERRIDE; |
57 virtual IOResult ScheduleWriteNoLock() OVERRIDE; | 57 virtual IOResult ScheduleWriteNoLock() OVERRIDE; |
58 virtual bool OnInit() OVERRIDE; | 58 virtual bool OnInit() OVERRIDE; |
59 virtual void OnShutdownNoLock(scoped_ptr<ReadBuffer> read_buffer, | 59 virtual void OnShutdownNoLock(scoped_ptr<ReadBuffer> read_buffer, |
60 scoped_ptr<WriteBuffer> write_buffer) OVERRIDE; | 60 scoped_ptr<WriteBuffer> write_buffer) OVERRIDE; |
61 | 61 |
62 // |base::MessageLoopForIO::Watcher| implementation: | 62 // |base::MessageLoopForIO::Watcher| implementation: |
63 virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE; | 63 virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE; |
64 virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE; | 64 virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE; |
65 | 65 |
66 // Implements most of |Read()| (except for a bit of clean-up): | |
67 IOResult ReadImpl(size_t* bytes_read); | |
68 | |
66 // Watches for |fd_| to become writable. Must be called on the I/O thread. | 69 // Watches for |fd_| to become writable. Must be called on the I/O thread. |
67 void WaitToWrite(); | 70 void WaitToWrite(); |
68 | 71 |
69 embedder::ScopedPlatformHandle fd_; | 72 embedder::ScopedPlatformHandle fd_; |
70 | 73 |
71 // The following members are only used on the I/O thread: | 74 // The following members are only used on the I/O thread: |
72 scoped_ptr<base::MessageLoopForIO::FileDescriptorWatcher> read_watcher_; | 75 scoped_ptr<base::MessageLoopForIO::FileDescriptorWatcher> read_watcher_; |
73 scoped_ptr<base::MessageLoopForIO::FileDescriptorWatcher> write_watcher_; | 76 scoped_ptr<base::MessageLoopForIO::FileDescriptorWatcher> write_watcher_; |
74 | 77 |
75 bool pending_read_; | 78 bool pending_read_; |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
166 return true; | 169 return true; |
167 } | 170 } |
168 | 171 |
169 return RawChannel::OnReadMessageForRawChannel(message_view); | 172 return RawChannel::OnReadMessageForRawChannel(message_view); |
170 } | 173 } |
171 | 174 |
172 RawChannel::IOResult RawChannelPosix::Read(size_t* bytes_read) { | 175 RawChannel::IOResult RawChannelPosix::Read(size_t* bytes_read) { |
173 DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); | 176 DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); |
174 DCHECK(!pending_read_); | 177 DCHECK(!pending_read_); |
175 | 178 |
176 char* buffer = NULL; | 179 IOResult rv = ReadImpl(bytes_read); |
yzshen1
2014/08/12 21:21:17
optional: I think for windows code, sometimes we u
| |
177 size_t bytes_to_read = 0; | 180 if (rv != IO_SUCCEEDED && rv != IO_PENDING) { |
178 read_buffer()->GetBuffer(&buffer, &bytes_to_read); | |
179 | |
180 size_t old_num_platform_handles = read_platform_handles_.size(); | |
181 ssize_t read_result = embedder::PlatformChannelRecvmsg( | |
182 fd_.get(), buffer, bytes_to_read, &read_platform_handles_); | |
183 if (read_platform_handles_.size() > old_num_platform_handles) { | |
184 DCHECK_LE(read_platform_handles_.size() - old_num_platform_handles, | |
185 embedder::kPlatformChannelMaxNumHandles); | |
186 | |
187 // We should never accumulate more than |TransportData::kMaxPlatformHandles | |
188 // + embedder::kPlatformChannelMaxNumHandles| handles. (The latter part is | |
189 // possible because we could have accumulated all the handles for a message, | |
190 // then received the message data plus the first set of handles for the next | |
191 // message in the subsequent |recvmsg()|.) | |
192 if (read_platform_handles_.size() > | |
193 (TransportData::kMaxPlatformHandles + | |
194 embedder::kPlatformChannelMaxNumHandles)) { | |
195 LOG(ERROR) << "Received too many platform handles"; | |
196 embedder::CloseAllPlatformHandles(&read_platform_handles_); | |
197 read_platform_handles_.clear(); | |
198 return IO_FAILED_UNKNOWN; | |
199 } | |
200 } | |
201 | |
202 if (read_result > 0) { | |
203 *bytes_read = static_cast<size_t>(read_result); | |
204 return IO_SUCCEEDED; | |
205 } | |
206 | |
207 // |read_result == 0| means "end of file". | |
208 if (read_result == 0) { | |
209 // Make sure that |OnFileCanReadWithoutBlocking()| won't be called again. | 181 // Make sure that |OnFileCanReadWithoutBlocking()| won't be called again. |
210 read_watcher_.reset(); | 182 read_watcher_.reset(); |
211 return IO_FAILED_SHUTDOWN; | |
212 } | 183 } |
213 | |
214 if (errno == EAGAIN || errno == EWOULDBLOCK) | |
215 return ScheduleRead(); | |
216 | |
217 IOResult rv = IO_FAILED_UNKNOWN; | |
218 if (errno == ECONNRESET) | |
219 rv = IO_FAILED_BROKEN; | |
220 else | |
221 PLOG(WARNING) << "recvmsg"; | |
222 | |
223 // Make sure that |OnFileCanReadWithoutBlocking()| won't be called again. | |
224 read_watcher_.reset(); | |
225 return rv; | 184 return rv; |
226 } | 185 } |
227 | 186 |
228 RawChannel::IOResult RawChannelPosix::ScheduleRead() { | 187 RawChannel::IOResult RawChannelPosix::ScheduleRead() { |
229 DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); | 188 DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); |
230 DCHECK(!pending_read_); | 189 DCHECK(!pending_read_); |
231 | 190 |
232 pending_read_ = true; | 191 pending_read_ = true; |
233 | 192 |
234 return IO_PENDING; | 193 return IO_PENDING; |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
438 DCHECK(pending_write_); | 397 DCHECK(pending_write_); |
439 | 398 |
440 pending_write_ = false; | 399 pending_write_ = false; |
441 io_result = WriteNoLock(&platform_handles_written, &bytes_written); | 400 io_result = WriteNoLock(&platform_handles_written, &bytes_written); |
442 } | 401 } |
443 | 402 |
444 if (io_result != IO_PENDING) | 403 if (io_result != IO_PENDING) |
445 OnWriteCompleted(io_result, platform_handles_written, bytes_written); | 404 OnWriteCompleted(io_result, platform_handles_written, bytes_written); |
446 } | 405 } |
447 | 406 |
407 RawChannel::IOResult RawChannelPosix::ReadImpl(size_t* bytes_read) { | |
408 char* buffer = NULL; | |
409 size_t bytes_to_read = 0; | |
410 read_buffer()->GetBuffer(&buffer, &bytes_to_read); | |
411 | |
412 size_t old_num_platform_handles = read_platform_handles_.size(); | |
413 ssize_t read_result = embedder::PlatformChannelRecvmsg( | |
414 fd_.get(), buffer, bytes_to_read, &read_platform_handles_); | |
415 if (read_platform_handles_.size() > old_num_platform_handles) { | |
416 DCHECK_LE(read_platform_handles_.size() - old_num_platform_handles, | |
417 embedder::kPlatformChannelMaxNumHandles); | |
418 | |
419 // We should never accumulate more than |TransportData::kMaxPlatformHandles | |
420 // + embedder::kPlatformChannelMaxNumHandles| handles. (The latter part is | |
421 // possible because we could have accumulated all the handles for a message, | |
422 // then received the message data plus the first set of handles for the next | |
423 // message in the subsequent |recvmsg()|.) | |
424 if (read_platform_handles_.size() > | |
425 (TransportData::kMaxPlatformHandles + | |
426 embedder::kPlatformChannelMaxNumHandles)) { | |
427 LOG(ERROR) << "Received too many platform handles"; | |
428 embedder::CloseAllPlatformHandles(&read_platform_handles_); | |
429 read_platform_handles_.clear(); | |
430 return IO_FAILED_UNKNOWN; | |
431 } | |
432 } | |
433 | |
434 if (read_result > 0) { | |
435 *bytes_read = static_cast<size_t>(read_result); | |
436 return IO_SUCCEEDED; | |
437 } | |
438 | |
439 // |read_result == 0| means "end of file". | |
440 if (read_result == 0) | |
441 return IO_FAILED_SHUTDOWN; | |
442 | |
443 if (errno == EAGAIN || errno == EWOULDBLOCK) | |
444 return ScheduleRead(); | |
445 | |
446 if (errno == ECONNRESET) | |
447 return IO_FAILED_BROKEN; | |
448 | |
449 PLOG(WARNING) << "recvmsg"; | |
450 return IO_FAILED_UNKNOWN; | |
451 } | |
452 | |
448 void RawChannelPosix::WaitToWrite() { | 453 void RawChannelPosix::WaitToWrite() { |
449 DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); | 454 DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); |
450 | 455 |
451 DCHECK(write_watcher_); | 456 DCHECK(write_watcher_); |
452 | 457 |
453 if (!message_loop_for_io()->WatchFileDescriptor( | 458 if (!message_loop_for_io()->WatchFileDescriptor( |
454 fd_.get().fd, | 459 fd_.get().fd, |
455 false, | 460 false, |
456 base::MessageLoopForIO::WATCH_WRITE, | 461 base::MessageLoopForIO::WATCH_WRITE, |
457 write_watcher_.get(), | 462 write_watcher_.get(), |
(...skipping 14 matching lines...) Expand all Loading... | |
472 | 477 |
473 // Static factory method declared in raw_channel.h. | 478 // Static factory method declared in raw_channel.h. |
474 // static | 479 // static |
475 scoped_ptr<RawChannel> RawChannel::Create( | 480 scoped_ptr<RawChannel> RawChannel::Create( |
476 embedder::ScopedPlatformHandle handle) { | 481 embedder::ScopedPlatformHandle handle) { |
477 return scoped_ptr<RawChannel>(new RawChannelPosix(handle.Pass())); | 482 return scoped_ptr<RawChannel>(new RawChannelPosix(handle.Pass())); |
478 } | 483 } |
479 | 484 |
480 } // namespace system | 485 } // namespace system |
481 } // namespace mojo | 486 } // namespace mojo |
OLD | NEW |