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 "net/quic/quic_default_packet_writer.h"
6
7#include "base/location.h"
8#include "base/logging.h"
9#include "base/metrics/sparse_histogram.h"
10#include "net/base/io_buffer.h"
11#include "net/base/net_errors.h"
12
13namespace net {
14
15QuicDefaultPacketWriter::QuicDefaultPacketWriter() : weak_factory_(this) {
16}
17
18QuicDefaultPacketWriter::QuicDefaultPacketWriter(DatagramClientSocket* socket)
19    : socket_(socket),
20      write_blocked_(false),
21      weak_factory_(this) {
22}
23
24QuicDefaultPacketWriter::~QuicDefaultPacketWriter() {}
25
26WriteResult QuicDefaultPacketWriter::WritePacket(
27    const char* buffer, size_t buf_len,
28    const net::IPAddressNumber& self_address,
29    const net::IPEndPoint& peer_address) {
30  scoped_refptr<StringIOBuffer> buf(
31      new StringIOBuffer(std::string(buffer, buf_len)));
32  DCHECK(!IsWriteBlocked());
33  int rv = socket_->Write(buf.get(),
34                          buf_len,
35                          base::Bind(&QuicDefaultPacketWriter::OnWriteComplete,
36                                     weak_factory_.GetWeakPtr()));
37  WriteStatus status = WRITE_STATUS_OK;
38  if (rv < 0) {
39    if (rv != ERR_IO_PENDING) {
40      UMA_HISTOGRAM_SPARSE_SLOWLY("Net.QuicSession.WriteError", -rv);
41      status = WRITE_STATUS_ERROR;
42    } else {
43      status = WRITE_STATUS_BLOCKED;
44      write_blocked_ = true;
45    }
46  }
47
48  return WriteResult(status, rv);
49}
50
51bool QuicDefaultPacketWriter::IsWriteBlockedDataBuffered() const {
52  // Chrome sockets' Write() methods buffer the data until the Write is
53  // permitted.
54  return true;
55}
56
57bool QuicDefaultPacketWriter::IsWriteBlocked() const {
58  return write_blocked_;
59}
60
61void QuicDefaultPacketWriter::SetWritable() {
62  write_blocked_ = false;
63}
64
65void QuicDefaultPacketWriter::OnWriteComplete(int rv) {
66  DCHECK_NE(rv, ERR_IO_PENDING);
67  write_blocked_ = false;
68  if (rv < 0) {
69    connection_->OnWriteError(rv);
70  }
71  connection_->OnCanWrite();
72}
73
74}  // namespace net
75