blob: e36f38452d7bb63703e83cee88c0ed37966de05c [file] [log] [blame]
// Copyright (c) 2012 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.
#include "net/third_party/quiche/src/quic/core/crypto/null_decrypter.h"
#include "net/third_party/quiche/src/quic/core/crypto/null_encrypter.h"
#include "net/third_party/quiche/src/quic/core/quic_connection.h"
#include "net/third_party/quiche/src/quic/core/quic_default_packet_writer.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_stream_frame_data_producer.h"
#include "net/third_party/quiche/src/quic/core/quic_trace_visitor.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
#include "net/third_party/quiche/src/quic/test_tools/simple_session_notifier.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/link.h"
#include "net/third_party/quiche/src/quic/test_tools/simulator/queue.h"
namespace quic {
namespace simulator {
// Size of the TX queue used by the kernel/NIC. 1000 is the Linux
// kernel default.
const QuicByteCount kTxQueueSize = 1000;
// Generate a random local network host-port tuple based on the name of the
// endpoint.
QuicSocketAddress GetAddressFromName(QuicString name);
// A QUIC connection endpoint. Wraps around QuicConnection. In order to
// initiate a transfer, the caller has to call AddBytesToTransfer(). The data
// transferred is always the same and is always transferred on a single stream.
// The endpoint receives all packets addressed to it, and verifies that the data
// received is what it's supposed to be.
class QuicEndpoint : public Endpoint,
public UnconstrainedPortInterface,
public Queue::ListenerInterface,
public QuicConnectionVisitorInterface,
public SessionNotifierInterface {
QuicEndpoint(Simulator* simulator,
QuicString name,
QuicString peer_name,
Perspective perspective,
QuicConnectionId connection_id);
~QuicEndpoint() override;
inline QuicConnection* connection() { return &connection_; }
QuicByteCount bytes_to_transfer() const;
QuicByteCount bytes_transferred() const;
QuicByteCount bytes_received() const;
inline size_t write_blocked_count() { return write_blocked_count_; }
inline bool wrong_data_received() const { return wrong_data_received_; }
// Send |bytes| bytes. Initiates the transfer if one is not already in
// progress.
void AddBytesToTransfer(QuicByteCount bytes);
// Drop the next packet upon receipt.
void DropNextIncomingPacket();
// UnconstrainedPortInterface method. Called whenever the endpoint receives a
// packet.
void AcceptPacket(std::unique_ptr<Packet> packet) override;
// Enables logging of the connection trace at the end of the unit test.
void RecordTrace();
// Begin Endpoint implementation.
UnconstrainedPortInterface* GetRxPort() override;
void SetTxPort(ConstrainedPortInterface* port) override;
// End Endpoint implementation.
// Actor method.
void Act() override {}
// Queue::ListenerInterface method.
void OnPacketDequeued() override;
// Begin QuicConnectionVisitorInterface implementation.
void OnStreamFrame(const QuicStreamFrame& frame) override;
void OnCryptoFrame(const QuicCryptoFrame& frame) override;
void OnCanWrite() override;
bool WillingAndAbleToWrite() const override;
bool HasPendingHandshake() const override;
bool HasOpenDynamicStreams() const override;
void OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) override {}
void OnBlockedFrame(const QuicBlockedFrame& frame) override {}
void OnRstStream(const QuicRstStreamFrame& frame) override {}
void OnGoAway(const QuicGoAwayFrame& frame) override {}
void OnMessageReceived(QuicStringPiece message) override {}
void OnConnectionClosed(QuicErrorCode error,
const QuicString& error_details,
ConnectionCloseSource source) override {}
void OnWriteBlocked() override {}
void OnSuccessfulVersionNegotiation(
const ParsedQuicVersion& version) override {}
void OnConnectivityProbeReceived(
const QuicSocketAddress& self_address,
const QuicSocketAddress& peer_address) override {}
void OnCongestionWindowChange(QuicTime now) override {}
void OnConnectionMigration(AddressChangeType type) override {}
void OnPathDegrading() override {}
void OnAckNeedsRetransmittableFrame() override {}
void SendPing() override {}
bool AllowSelfAddressChange() const override;
void OnForwardProgressConfirmed() override {}
bool OnMaxStreamIdFrame(const QuicMaxStreamIdFrame& frame) override {
return true;
bool OnStreamIdBlockedFrame(const QuicStreamIdBlockedFrame& frame) override {
return true;
bool OnStopSendingFrame(const QuicStopSendingFrame& frame) override {
return true;
// End QuicConnectionVisitorInterface implementation.
// Begin SessionNotifierInterface methods:
bool OnFrameAcked(const QuicFrame& frame,
QuicTime::Delta ack_delay_time) override;
void OnStreamFrameRetransmitted(const QuicStreamFrame& frame) override {}
void OnFrameLost(const QuicFrame& frame) override;
void RetransmitFrames(const QuicFrames& frames,
TransmissionType type) override;
bool IsFrameOutstanding(const QuicFrame& frame) const override;
bool HasUnackedCryptoData() const override;
// End SessionNotifierInterface implementation.
// A Writer object that writes into the |nic_tx_queue_|.
class Writer : public QuicPacketWriter {
explicit Writer(QuicEndpoint* endpoint);
~Writer() override;
WriteResult WritePacket(const char* buffer,
size_t buf_len,
const QuicIpAddress& self_address,
const QuicSocketAddress& peer_address,
PerPacketOptions* options) override;
bool IsWriteBlocked() const override;
void SetWritable() override;
QuicByteCount GetMaxPacketSize(
const QuicSocketAddress& peer_address) const override;
bool SupportsReleaseTime() const override;
bool IsBatchMode() const override;
char* GetNextWriteLocation(const QuicIpAddress& self_address,
const QuicSocketAddress& peer_address) override;
WriteResult Flush() override;
QuicEndpoint* endpoint_;
bool is_blocked_;
// The producer outputs the repetition of the same byte. That sequence is
// verified by the receiver.
class DataProducer : public QuicStreamFrameDataProducer {
WriteStreamDataResult WriteStreamData(QuicStreamId id,
QuicStreamOffset offset,
QuicByteCount data_length,
QuicDataWriter* writer) override;
bool WriteCryptoData(EncryptionLevel level,
QuicStreamOffset offset,
QuicByteCount data_length,
QuicDataWriter* writer) override;
// Write stream data until |bytes_to_transfer_| is zero or the connection is
// write-blocked.
void WriteStreamData();
QuicString peer_name_;
Writer writer_;
DataProducer producer_;
// The queue for the outgoing packets. In reality, this might be either on
// the network card, or in the kernel, but for concreteness we assume it's on
// the network card.
Queue nic_tx_queue_;
QuicConnection connection_;
QuicByteCount bytes_to_transfer_;
QuicByteCount bytes_transferred_;
// Counts the number of times the writer became write-blocked.
size_t write_blocked_count_;
// Set to true if the endpoint receives stream data different from what it
// expects.
bool wrong_data_received_;
// If true, drop the next packet when receiving it.
bool drop_next_packet_;
// Record of received offsets in the data stream.
QuicIntervalSet<QuicStreamOffset> offsets_received_;
std::unique_ptr<test::SimpleSessionNotifier> notifier_;
std::unique_ptr<QuicTraceVisitor> trace_visitor_;
// Multiplexes multiple connections at the same host on the network.
class QuicEndpointMultiplexer : public Endpoint,
public UnconstrainedPortInterface {
QuicEndpointMultiplexer(QuicString name,
std::initializer_list<QuicEndpoint*> endpoints);
~QuicEndpointMultiplexer() override;
// Receives a packet and passes it to the specified endpoint if that endpoint
// is one of the endpoints being multiplexed, otherwise ignores the packet.
void AcceptPacket(std::unique_ptr<Packet> packet) override;
UnconstrainedPortInterface* GetRxPort() override;
// Sets the egress port for all the endpoints being multiplexed.
void SetTxPort(ConstrainedPortInterface* port) override;
void Act() override {}
QuicUnorderedMap<QuicString, QuicEndpoint*> mapping_;
} // namespace simulator
} // namespace quic