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 3 // found in the LICENSE file. 4 5 #include "base/async_socket_io_handler.h" 6 7 namespace base { 8 9 AsyncSocketIoHandler::AsyncSocketIoHandler() 10 : socket_(base::SyncSocket::kInvalidHandle), 11 context_(NULL), 12 is_pending_(false) {} 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_) { 20 if (is_pending_) { 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. 30 void AsyncSocketIoHandler::OnIOCompleted( 31 base::MessageLoopForIO::IOContext* context, 32 DWORD bytes_transfered, 33 DWORD error) { 34 DCHECK(CalledOnValidThread()); 35 DCHECK_EQ(context_, context); 36 DCHECK(!read_complete_.is_null()); 37 is_pending_ = false; 38 read_complete_.Run(error == ERROR_SUCCESS ? bytes_transfered : 0); 39 } 40 41 bool AsyncSocketIoHandler::Read(char* buffer, int buffer_len) { 42 DCHECK(CalledOnValidThread()); 43 DCHECK(!read_complete_.is_null()); 44 DCHECK(!is_pending_); 45 DCHECK_NE(socket_, base::SyncSocket::kInvalidHandle); 46 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. 54 is_pending_ = !ok && (GetLastError() == ERROR_IO_PENDING); 55 return ok || is_pending_; 56 } 57 58 bool AsyncSocketIoHandler::Initialize(base::SyncSocket::Handle socket, 59 const ReadCompleteCallback& callback) { 60 DCHECK(!context_); 61 DCHECK_EQ(socket_, base::SyncSocket::kInvalidHandle); 62 63 DetachFromThread(); 64 65 socket_ = socket; 66 read_complete_ = callback; 67 68 base::MessageLoopForIO::current()->RegisterIOHandler(socket, this); 69 70 context_ = new base::MessageLoopForIO::IOContext(); 71 context_->handler = this; 72 memset(&context_->overlapped, 0, sizeof(context_->overlapped)); 73 74 return true; 75 } 76 77 } // namespace base. 78