blob: e1d215c980af69eec8e1358452a6f53d4b73fa32 [file] [log] [blame]
[email protected]39cb64f2013-08-22 12:39:331// Copyright 2013 The Chromium Authors. All rights reserved.
[email protected]a0e3f0f2012-06-07 12:45:512// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]39cb64f2013-08-22 12:39:335#include "base/async_socket_io_handler.h"
[email protected]a0e3f0f2012-06-07 12:45:516
[email protected]f1b96af2013-08-23 15:56:337namespace base {
[email protected]a0e3f0f2012-06-07 12:45:518
9AsyncSocketIoHandler::AsyncSocketIoHandler()
10 : socket_(base::SyncSocket::kInvalidHandle),
[email protected]26195ea2012-07-04 13:34:2111 context_(NULL),
12 is_pending_(false) {}
[email protected]a0e3f0f2012-06-07 12:45:5113
14AsyncSocketIoHandler::~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]26195ea2012-07-04 13:34:2120 if (is_pending_) {
[email protected]a0e3f0f2012-06-07 12:45:5121 // 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]fb5af232013-04-22 22:40:0330void AsyncSocketIoHandler::OnIOCompleted(
31 base::MessageLoopForIO::IOContext* context,
32 DWORD bytes_transfered,
33 DWORD error) {
[email protected]a0e3f0f2012-06-07 12:45:5134 DCHECK(CalledOnValidThread());
35 DCHECK_EQ(context_, context);
[email protected]26195ea2012-07-04 13:34:2136 DCHECK(!read_complete_.is_null());
37 is_pending_ = false;
38 read_complete_.Run(error == ERROR_SUCCESS ? bytes_transfered : 0);
[email protected]a0e3f0f2012-06-07 12:45:5139}
40
[email protected]26195ea2012-07-04 13:34:2141bool AsyncSocketIoHandler::Read(char* buffer, int buffer_len) {
[email protected]a0e3f0f2012-06-07 12:45:5142 DCHECK(CalledOnValidThread());
[email protected]26195ea2012-07-04 13:34:2143 DCHECK(!read_complete_.is_null());
44 DCHECK(!is_pending_);
[email protected]a0e3f0f2012-06-07 12:45:5145 DCHECK_NE(socket_, base::SyncSocket::kInvalidHandle);
46
[email protected]a0e3f0f2012-06-07 12:45:5147 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]26195ea2012-07-04 13:34:2154 is_pending_ = !ok && (GetLastError() == ERROR_IO_PENDING);
55 return ok || is_pending_;
[email protected]a0e3f0f2012-06-07 12:45:5156}
57
[email protected]26195ea2012-07-04 13:34:2158bool AsyncSocketIoHandler::Initialize(base::SyncSocket::Handle socket,
59 const ReadCompleteCallback& callback) {
[email protected]a0e3f0f2012-06-07 12:45:5160 DCHECK(!context_);
61 DCHECK_EQ(socket_, base::SyncSocket::kInvalidHandle);
62
63 DetachFromThread();
64
65 socket_ = socket;
[email protected]26195ea2012-07-04 13:34:2166 read_complete_ = callback;
67
[email protected]fb5af232013-04-22 22:40:0368 base::MessageLoopForIO::current()->RegisterIOHandler(socket, this);
[email protected]a0e3f0f2012-06-07 12:45:5169
[email protected]fb5af232013-04-22 22:40:0370 context_ = new base::MessageLoopForIO::IOContext();
[email protected]a0e3f0f2012-06-07 12:45:5171 context_->handler = this;
72 memset(&context_->overlapped, 0, sizeof(context_->overlapped));
73
74 return true;
75}
76
[email protected]f1b96af2013-08-23 15:56:3377} // namespace base.