| // Copyright 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef NET_QUIC_QUIC_CHROMIUM_PACKET_WRITER_H_ |
| #define NET_QUIC_QUIC_CHROMIUM_PACKET_WRITER_H_ |
| |
| #include "base/macros.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/timer/timer.h" |
| #include "net/base/completion_repeating_callback.h" |
| #include "net/base/io_buffer.h" |
| #include "net/base/net_export.h" |
| #include "net/socket/datagram_client_socket.h" |
| #include "net/third_party/quic/core/quic_connection.h" |
| #include "net/third_party/quic/core/quic_packet_writer.h" |
| #include "net/third_party/quic/core/quic_packets.h" |
| #include "net/third_party/quic/core/quic_types.h" |
| #include "starboard/types.h" |
| |
| namespace net { |
| |
| // Chrome specific packet writer which uses a datagram Socket for writing data. |
| class NET_EXPORT_PRIVATE QuicChromiumPacketWriter |
| : public quic::QuicPacketWriter { |
| public: |
| // Define a specific IO buffer that can be allocated once, but be |
| // assigned new contents and reused, avoiding the alternative of |
| // repeated memory allocations. This packet writer only ever has a |
| // single write in flight, a constraint inherited from the interface |
| // of the underlying datagram Socket. |
| class NET_EXPORT_PRIVATE ReusableIOBuffer : public IOBuffer { |
| public: |
| explicit ReusableIOBuffer(size_t capacity); |
| |
| size_t capacity() const { return capacity_; } |
| size_t size() const { return size_; } |
| |
| // Does memcpy from |buffer| into this->data(). |buf_len <= |
| // capacity()| must be true, |HasOneRef()| must be true. |
| void Set(const char* buffer, size_t buf_len); |
| |
| private: |
| ~ReusableIOBuffer() override; |
| size_t capacity_; |
| size_t size_; |
| }; |
| // Delegate interface which receives notifications on socket write events. |
| class NET_EXPORT_PRIVATE Delegate { |
| public: |
| // Called when a socket write attempt results in a failure, so |
| // that the delegate may recover from it by perhaps rewriting the |
| // packet to a different socket. An implementation must return the |
| // return value from the rewrite attempt if there is one, and |
| // |error_code| otherwise. |
| virtual int HandleWriteError( |
| int error_code, |
| scoped_refptr<ReusableIOBuffer> last_packet) = 0; |
| |
| // Called to propagate the final write error to the delegate. |
| virtual void OnWriteError(int error_code) = 0; |
| |
| // Called when the writer is unblocked due to a write completion. |
| virtual void OnWriteUnblocked() = 0; |
| }; |
| |
| QuicChromiumPacketWriter(); |
| // |socket| and |task_runner| must outlive writer. |
| QuicChromiumPacketWriter(DatagramClientSocket* socket, |
| base::SequencedTaskRunner* task_runner); |
| ~QuicChromiumPacketWriter() override; |
| |
| // |delegate| must outlive writer. |
| void set_delegate(Delegate* delegate) { delegate_ = delegate; } |
| |
| // This method may unblock the packet writer if |force_write_blocked| is |
| // false. |
| void set_force_write_blocked(bool force_write_blocked); |
| |
| // Writes |packet| to the socket and handles write result if the write |
| // completes synchronously. |
| void WritePacketToSocket(scoped_refptr<ReusableIOBuffer> packet); |
| |
| // quic::QuicPacketWriter |
| quic::WriteResult WritePacket(const char* buffer, |
| size_t buf_len, |
| const quic::QuicIpAddress& self_address, |
| const quic::QuicSocketAddress& peer_address, |
| quic::PerPacketOptions* options) override; |
| bool IsWriteBlocked() const override; |
| void SetWritable() override; |
| quic::QuicByteCount GetMaxPacketSize( |
| const quic::QuicSocketAddress& peer_address) const override; |
| bool SupportsReleaseTime() const override; |
| bool IsBatchMode() const override; |
| char* GetNextWriteLocation( |
| const quic::QuicIpAddress& self_address, |
| const quic::QuicSocketAddress& peer_address) override; |
| quic::WriteResult Flush() override; |
| |
| void OnWriteComplete(int rv); |
| |
| private: |
| void SetPacket(const char* buffer, size_t buf_len); |
| bool MaybeRetryAfterWriteError(int rv); |
| void RetryPacketAfterNoBuffers(); |
| quic::WriteResult WritePacketToSocketImpl(); |
| DatagramClientSocket* socket_; // Unowned. |
| Delegate* delegate_; // Unowned. |
| // Reused for every packet write for the lifetime of the writer. Is |
| // moved to the delegate in the case of a write error. |
| scoped_refptr<ReusableIOBuffer> packet_; |
| |
| // Whether a write is currently in progress: true if an asynchronous write is |
| // in flight, or a retry of a previous write is in progress, or session is |
| // handling write error of a previous write. |
| bool write_in_progress_; |
| |
| // If ture, IsWriteBlocked() will return true regardless of |
| // |write_in_progress_|. |
| bool force_write_blocked_; |
| |
| int retry_count_; |
| // Timer set when a packet should be retried after ENOBUFS. |
| base::OneShotTimer retry_timer_; |
| |
| CompletionRepeatingCallback write_callback_; |
| base::WeakPtrFactory<QuicChromiumPacketWriter> weak_factory_; |
| |
| DISALLOW_COPY_AND_ASSIGN(QuicChromiumPacketWriter); |
| }; |
| |
| } // namespace net |
| |
| #endif // NET_QUIC_QUIC_CHROMIUM_PACKET_WRITER_H_ |