11e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
21e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
31e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// found in the LICENSE file.
41e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
51e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "net/quic/quic_default_packet_writer.h"
61e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
71e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/location.h"
81e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/logging.h"
91e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/metrics/sparse_histogram.h"
101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "net/base/io_buffer.h"
111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "net/base/net_errors.h"
121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)namespace net {
141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)QuicDefaultPacketWriter::QuicDefaultPacketWriter() : weak_factory_(this) {
161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)QuicDefaultPacketWriter::QuicDefaultPacketWriter(DatagramClientSocket* socket)
191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    : socket_(socket),
201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      write_blocked_(false),
211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      weak_factory_(this) {
221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)QuicDefaultPacketWriter::~QuicDefaultPacketWriter() {}
251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)WriteResult QuicDefaultPacketWriter::WritePacket(
271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const char* buffer, size_t buf_len,
281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const net::IPAddressNumber& self_address,
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const net::IPEndPoint& peer_address) {
301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  scoped_refptr<StringIOBuffer> buf(
311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      new StringIOBuffer(std::string(buffer, buf_len)));
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(!IsWriteBlocked());
331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int rv = socket_->Write(buf.get(),
341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                          buf_len,
351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                          base::Bind(&QuicDefaultPacketWriter::OnWriteComplete,
361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                     weak_factory_.GetWeakPtr()));
371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  WriteStatus status = WRITE_STATUS_OK;
381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (rv < 0) {
391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (rv != ERR_IO_PENDING) {
401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      UMA_HISTOGRAM_SPARSE_SLOWLY("Net.QuicSession.WriteError", -rv);
411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      status = WRITE_STATUS_ERROR;
421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    } else {
431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      status = WRITE_STATUS_BLOCKED;
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      write_blocked_ = true;
451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return WriteResult(status, rv);
491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)bool QuicDefaultPacketWriter::IsWriteBlockedDataBuffered() const {
521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Chrome sockets' Write() methods buffer the data until the Write is
531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // permitted.
541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return true;
551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool QuicDefaultPacketWriter::IsWriteBlocked() const {
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return write_blocked_;
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void QuicDefaultPacketWriter::SetWritable() {
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  write_blocked_ = false;
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void QuicDefaultPacketWriter::OnWriteComplete(int rv) {
661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK_NE(rv, ERR_IO_PENDING);
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  write_blocked_ = false;
6803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (rv < 0) {
6903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    connection_->OnWriteError(rv);
7003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  connection_->OnCanWrite();
721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}  // namespace net
75