Home | History | Annotate | Download | only in base
      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