Home | History | Annotate | Download | only in quic
      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/callback_helpers.h"
      8 #include "base/location.h"
      9 #include "base/logging.h"
     10 #include "base/metrics/sparse_histogram.h"
     11 #include "net/base/io_buffer.h"
     12 #include "net/base/net_errors.h"
     13 #include "net/udp/udp_server_socket.h"
     14 
     15 namespace net {
     16 
     17 QuicServerPacketWriter::QuicServerPacketWriter(
     18     UDPServerSocket* socket,
     19     QuicBlockedWriterInterface* blocked_writer)
     20     : socket_(socket),
     21       blocked_writer_(blocked_writer),
     22       write_blocked_(false),
     23       weak_factory_(this) {
     24 }
     25 
     26 QuicServerPacketWriter::~QuicServerPacketWriter() {
     27 }
     28 
     29 WriteResult QuicServerPacketWriter::WritePacketWithCallback(
     30     const char* buffer,
     31     size_t buf_len,
     32     const IPAddressNumber& self_address,
     33     const IPEndPoint& peer_address,
     34     WriteCallback callback) {
     35   DCHECK(callback_.is_null());
     36   callback_ = callback;
     37   WriteResult result = WritePacket(buffer, buf_len, self_address, peer_address);
     38   if (result.status != WRITE_STATUS_BLOCKED) {
     39     callback_.Reset();
     40   }
     41   return result;
     42 }
     43 
     44 void QuicServerPacketWriter::OnWriteComplete(int rv) {
     45   DCHECK_NE(rv, ERR_IO_PENDING);
     46   write_blocked_ = false;
     47   WriteResult result(rv < 0 ? WRITE_STATUS_ERROR : WRITE_STATUS_OK, rv);
     48   base::ResetAndReturn(&callback_).Run(result);
     49   blocked_writer_->OnCanWrite();
     50 }
     51 
     52 bool QuicServerPacketWriter::IsWriteBlockedDataBuffered() const {
     53   // UDPServerSocket::SendTo buffers the data until the Write is permitted.
     54   return true;
     55 }
     56 
     57 bool QuicServerPacketWriter::IsWriteBlocked() const {
     58   return write_blocked_;
     59 }
     60 
     61 void QuicServerPacketWriter::SetWritable() {
     62   write_blocked_ = false;
     63 }
     64 
     65 WriteResult QuicServerPacketWriter::WritePacket(
     66     const char* buffer,
     67     size_t buf_len,
     68     const IPAddressNumber& self_address,
     69     const IPEndPoint& peer_address) {
     70   scoped_refptr<StringIOBuffer> buf(
     71       new StringIOBuffer(std::string(buffer, buf_len)));
     72   DCHECK(!IsWriteBlocked());
     73   DCHECK(!callback_.is_null());
     74   int rv;
     75   if (buf_len <= static_cast<size_t>(std::numeric_limits<int>::max())) {
     76     rv = socket_->SendTo(buf.get(),
     77                          static_cast<int>(buf_len),
     78                          peer_address,
     79                          base::Bind(&QuicServerPacketWriter::OnWriteComplete,
     80                                     weak_factory_.GetWeakPtr()));
     81   } else {
     82     rv = ERR_MSG_TOO_BIG;
     83   }
     84   WriteStatus status = WRITE_STATUS_OK;
     85   if (rv < 0) {
     86     if (rv != ERR_IO_PENDING) {
     87       UMA_HISTOGRAM_SPARSE_SLOWLY("Net.QuicSession.WriteError", -rv);
     88       status = WRITE_STATUS_ERROR;
     89     } else {
     90       status = WRITE_STATUS_BLOCKED;
     91       write_blocked_ = true;
     92     }
     93   }
     94   return WriteResult(status, rv);
     95 }
     96 
     97 }  // namespace net
     98