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 15namespace net { 16 17QuicServerPacketWriter::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 26QuicServerPacketWriter::~QuicServerPacketWriter() { 27} 28 29WriteResult 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 44void 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 52bool QuicServerPacketWriter::IsWriteBlockedDataBuffered() const { 53 // UDPServerSocket::SendTo buffers the data until the Write is permitted. 54 return true; 55} 56 57bool QuicServerPacketWriter::IsWriteBlocked() const { 58 return write_blocked_; 59} 60 61void QuicServerPacketWriter::SetWritable() { 62 write_blocked_ = false; 63} 64 65WriteResult 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