1// Copyright 2014 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_server_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
15QuicServerPacketWriter::QuicServerPacketWriter() : weak_factory_(this) {
16}
17
18QuicServerPacketWriter::QuicServerPacketWriter(UDPServerSocket* socket)
19    : weak_factory_(this),
20      socket_(socket),
21      write_blocked_(false) {
22}
23
24QuicServerPacketWriter::~QuicServerPacketWriter() {
25}
26
27WriteResult QuicServerPacketWriter::WritePacket(
28    const char* buffer, size_t buf_len,
29    const net::IPAddressNumber& self_address,
30    const net::IPEndPoint& peer_address) {
31  scoped_refptr<StringIOBuffer> buf(
32      new StringIOBuffer(std::string(buffer, buf_len)));
33  DCHECK(!IsWriteBlocked());
34  int rv = socket_->SendTo(buf.get(),
35                           buf_len,
36                           peer_address,
37                           base::Bind(&QuicServerPacketWriter::OnWriteComplete,
38                                      weak_factory_.GetWeakPtr()));
39  WriteStatus status = WRITE_STATUS_OK;
40  if (rv < 0) {
41    if (rv != ERR_IO_PENDING) {
42      UMA_HISTOGRAM_SPARSE_SLOWLY("Net.QuicSession.WriteError", -rv);
43      status = WRITE_STATUS_ERROR;
44    } else {
45      status = WRITE_STATUS_BLOCKED;
46      write_blocked_ = true;
47    }
48  }
49
50  return WriteResult(status, rv);
51}
52
53bool QuicServerPacketWriter::IsWriteBlockedDataBuffered() const {
54  // UDPServerSocket::SendTo buffers the data until the Write is permitted.
55  return true;
56}
57
58bool QuicServerPacketWriter::IsWriteBlocked() const {
59  return write_blocked_;
60}
61
62void QuicServerPacketWriter::SetWritable() {
63  write_blocked_ = false;
64}
65
66void QuicServerPacketWriter::OnWriteComplete(int rv) {
67  DCHECK_NE(rv, ERR_IO_PENDING);
68  write_blocked_ = false;
69  WriteResult result(rv < 0 ? WRITE_STATUS_ERROR : WRITE_STATUS_OK, rv);
70  connection_->OnPacketSent(result);
71  connection_->OnCanWrite();
72}
73
74}  // namespace net
75