[email protected] | 39cb64f | 2013-08-22 12:39:33 | [diff] [blame] | 1 | // Copyright 2013 The Chromium Authors. All rights reserved. |
[email protected] | a0e3f0f | 2012-06-07 12:45:51 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
[email protected] | 39cb64f | 2013-08-22 12:39:33 | [diff] [blame] | 5 | #include "base/async_socket_io_handler.h" |
[email protected] | a0e3f0f | 2012-06-07 12:45:51 | [diff] [blame] | 6 | |
[email protected] | f1b96af | 2013-08-23 15:56:33 | [diff] [blame] | 7 | namespace base { |
[email protected] | a0e3f0f | 2012-06-07 12:45:51 | [diff] [blame] | 8 | |
| 9 | AsyncSocketIoHandler::AsyncSocketIoHandler() |
| 10 | : socket_(base::SyncSocket::kInvalidHandle), |
[email protected] | 26195ea | 2012-07-04 13:34:21 | [diff] [blame] | 11 | context_(NULL), |
| 12 | is_pending_(false) {} |
[email protected] | a0e3f0f | 2012-06-07 12:45:51 | [diff] [blame] | 13 | |
| 14 | AsyncSocketIoHandler::~AsyncSocketIoHandler() { |
| 15 | // We need to be deleted on the correct thread to avoid racing with the |
| 16 | // message loop thread. |
| 17 | DCHECK(CalledOnValidThread()); |
| 18 | |
| 19 | if (context_) { |
[email protected] | 26195ea | 2012-07-04 13:34:21 | [diff] [blame] | 20 | if (is_pending_) { |
[email protected] | a0e3f0f | 2012-06-07 12:45:51 | [diff] [blame] | 21 | // Make the context be deleted by the message pump when done. |
| 22 | context_->handler = NULL; |
| 23 | } else { |
| 24 | delete context_; |
| 25 | } |
| 26 | } |
| 27 | } |
| 28 | |
| 29 | // Implementation of IOHandler on Windows. |
[email protected] | fb5af23 | 2013-04-22 22:40:03 | [diff] [blame] | 30 | void AsyncSocketIoHandler::OnIOCompleted( |
| 31 | base::MessageLoopForIO::IOContext* context, |
| 32 | DWORD bytes_transfered, |
| 33 | DWORD error) { |
[email protected] | a0e3f0f | 2012-06-07 12:45:51 | [diff] [blame] | 34 | DCHECK(CalledOnValidThread()); |
| 35 | DCHECK_EQ(context_, context); |
[email protected] | 26195ea | 2012-07-04 13:34:21 | [diff] [blame] | 36 | DCHECK(!read_complete_.is_null()); |
| 37 | is_pending_ = false; |
| 38 | read_complete_.Run(error == ERROR_SUCCESS ? bytes_transfered : 0); |
[email protected] | a0e3f0f | 2012-06-07 12:45:51 | [diff] [blame] | 39 | } |
| 40 | |
[email protected] | 26195ea | 2012-07-04 13:34:21 | [diff] [blame] | 41 | bool AsyncSocketIoHandler::Read(char* buffer, int buffer_len) { |
[email protected] | a0e3f0f | 2012-06-07 12:45:51 | [diff] [blame] | 42 | DCHECK(CalledOnValidThread()); |
[email protected] | 26195ea | 2012-07-04 13:34:21 | [diff] [blame] | 43 | DCHECK(!read_complete_.is_null()); |
| 44 | DCHECK(!is_pending_); |
[email protected] | a0e3f0f | 2012-06-07 12:45:51 | [diff] [blame] | 45 | DCHECK_NE(socket_, base::SyncSocket::kInvalidHandle); |
| 46 | |
[email protected] | a0e3f0f | 2012-06-07 12:45:51 | [diff] [blame] | 47 | DWORD bytes_read = 0; |
| 48 | BOOL ok = ::ReadFile(socket_, buffer, buffer_len, &bytes_read, |
| 49 | &context_->overlapped); |
| 50 | // The completion port will be signaled regardless of completing the read |
| 51 | // straight away or asynchronously (ERROR_IO_PENDING). OnIOCompleted() will |
| 52 | // be called regardless and we don't need to explicitly run the callback |
| 53 | // in the case where ok is FALSE and GLE==ERROR_IO_PENDING. |
[email protected] | 26195ea | 2012-07-04 13:34:21 | [diff] [blame] | 54 | is_pending_ = !ok && (GetLastError() == ERROR_IO_PENDING); |
| 55 | return ok || is_pending_; |
[email protected] | a0e3f0f | 2012-06-07 12:45:51 | [diff] [blame] | 56 | } |
| 57 | |
[email protected] | 26195ea | 2012-07-04 13:34:21 | [diff] [blame] | 58 | bool AsyncSocketIoHandler::Initialize(base::SyncSocket::Handle socket, |
| 59 | const ReadCompleteCallback& callback) { |
[email protected] | a0e3f0f | 2012-06-07 12:45:51 | [diff] [blame] | 60 | DCHECK(!context_); |
| 61 | DCHECK_EQ(socket_, base::SyncSocket::kInvalidHandle); |
| 62 | |
| 63 | DetachFromThread(); |
| 64 | |
| 65 | socket_ = socket; |
[email protected] | 26195ea | 2012-07-04 13:34:21 | [diff] [blame] | 66 | read_complete_ = callback; |
| 67 | |
[email protected] | fb5af23 | 2013-04-22 22:40:03 | [diff] [blame] | 68 | base::MessageLoopForIO::current()->RegisterIOHandler(socket, this); |
[email protected] | a0e3f0f | 2012-06-07 12:45:51 | [diff] [blame] | 69 | |
[email protected] | fb5af23 | 2013-04-22 22:40:03 | [diff] [blame] | 70 | context_ = new base::MessageLoopForIO::IOContext(); |
[email protected] | a0e3f0f | 2012-06-07 12:45:51 | [diff] [blame] | 71 | context_->handler = this; |
| 72 | memset(&context_->overlapped, 0, sizeof(context_->overlapped)); |
| 73 | |
| 74 | return true; |
| 75 | } |
| 76 | |
[email protected] | f1b96af | 2013-08-23 15:56:33 | [diff] [blame] | 77 | } // namespace base. |