1f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// found in the LICENSE file. 4f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 5f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "net/quic/quic_server_packet_writer.h" 6f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 7116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/callback_helpers.h" 8f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/location.h" 9f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/logging.h" 10f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/metrics/sparse_histogram.h" 11f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "net/base/io_buffer.h" 12f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "net/base/net_errors.h" 13116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "net/udp/udp_server_socket.h" 14f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 15f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace net { 16f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 17116680a4aac90f2aa7413d9095a592090648e557Ben MurdochQuicServerPacketWriter::QuicServerPacketWriter( 18116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch UDPServerSocket* socket, 19116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch QuicBlockedWriterInterface* blocked_writer) 201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : socket_(socket), 21116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch blocked_writer_(blocked_writer), 221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci write_blocked_(false), 231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci weak_factory_(this) { 24f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 25f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 26f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)QuicServerPacketWriter::~QuicServerPacketWriter() { 27f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 28f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 29116680a4aac90f2aa7413d9095a592090648e557Ben MurdochWriteResult QuicServerPacketWriter::WritePacketWithCallback( 30116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const char* buffer, 31116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch size_t buf_len, 32116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const IPAddressNumber& self_address, 33116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const IPEndPoint& peer_address, 34116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch WriteCallback callback) { 35116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(callback_.is_null()); 36116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch callback_ = callback; 37116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch WriteResult result = WritePacket(buffer, buf_len, self_address, peer_address); 38116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (result.status != WRITE_STATUS_BLOCKED) { 39116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch callback_.Reset(); 40f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 41116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return result; 42116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 44116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid QuicServerPacketWriter::OnWriteComplete(int rv) { 45116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK_NE(rv, ERR_IO_PENDING); 46116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch write_blocked_ = false; 47116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch WriteResult result(rv < 0 ? WRITE_STATUS_ERROR : WRITE_STATUS_OK, rv); 48116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::ResetAndReturn(&callback_).Run(result); 49116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch blocked_writer_->OnCanWrite(); 50f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 51f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 52f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool QuicServerPacketWriter::IsWriteBlockedDataBuffered() const { 53f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // UDPServerSocket::SendTo buffers the data until the Write is permitted. 54f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 55f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 56f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool QuicServerPacketWriter::IsWriteBlocked() const { 58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return write_blocked_; 59f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 60f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 61f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void QuicServerPacketWriter::SetWritable() { 62f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) write_blocked_ = false; 63f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 65116680a4aac90f2aa7413d9095a592090648e557Ben MurdochWriteResult QuicServerPacketWriter::WritePacket( 66116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const char* buffer, 67116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch size_t buf_len, 68116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const IPAddressNumber& self_address, 69116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const IPEndPoint& peer_address) { 70116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_refptr<StringIOBuffer> buf( 71116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch new StringIOBuffer(std::string(buffer, buf_len))); 72116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(!IsWriteBlocked()); 73116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(!callback_.is_null()); 74116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int rv; 75116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (buf_len <= static_cast<size_t>(std::numeric_limits<int>::max())) { 76116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch rv = socket_->SendTo(buf.get(), 77116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch static_cast<int>(buf_len), 78116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch peer_address, 79116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Bind(&QuicServerPacketWriter::OnWriteComplete, 80116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch weak_factory_.GetWeakPtr())); 81116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else { 82116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch rv = ERR_MSG_TOO_BIG; 83116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 84116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch WriteStatus status = WRITE_STATUS_OK; 85116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (rv < 0) { 86116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (rv != ERR_IO_PENDING) { 87116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch UMA_HISTOGRAM_SPARSE_SLOWLY("Net.QuicSession.WriteError", -rv); 88116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch status = WRITE_STATUS_ERROR; 89116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else { 90116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch status = WRITE_STATUS_BLOCKED; 91116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch write_blocked_ = true; 92116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 93116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 94116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return WriteResult(status, rv); 95f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 96f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 97f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} // namespace net 98