blob: 09bc2cc56c3adeaf21df4893b2404ba7d8118ba5 [file] [log] [blame]
// Copyright (c) 2016 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 QUICHE_QUIC_CORE_QUIC_BUFFERED_PACKET_STORE_H_
#define QUICHE_QUIC_CORE_QUIC_BUFFERED_PACKET_STORE_H_
#include <list>
#include <string>
#include "net/third_party/quiche/src/quic/core/quic_alarm.h"
#include "net/third_party/quiche/src/quic/core/quic_alarm_factory.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_time.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_clock.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
namespace quic {
namespace test {
class QuicBufferedPacketStorePeer;
} // namespace test
// This class buffers packets for each connection until either
// 1) They are requested to be delivered via
// DeliverPacket()/DeliverPacketsForNextConnection(), or
// 2) They expire after exceeding their lifetime in the store.
//
// It can only buffer packets on certain number of connections. It has two pools
// of connections: connections with CHLO buffered and those without CHLO. The
// latter has its own upper limit along with the max number of connections this
// store can hold. The former pool can grow till this store is full.
class QUIC_EXPORT_PRIVATE QuicBufferedPacketStore {
public:
enum EnqueuePacketResult {
SUCCESS = 0,
TOO_MANY_PACKETS, // Too many packets stored up for a certain connection.
TOO_MANY_CONNECTIONS // Too many connections stored up in the store.
};
struct QUIC_EXPORT_PRIVATE BufferedPacket {
BufferedPacket(std::unique_ptr<QuicReceivedPacket> packet,
QuicSocketAddress self_address,
QuicSocketAddress peer_address);
BufferedPacket(BufferedPacket&& other);
BufferedPacket& operator=(BufferedPacket&& other);
~BufferedPacket();
std::unique_ptr<QuicReceivedPacket> packet;
QuicSocketAddress self_address;
QuicSocketAddress peer_address;
};
// A queue of BufferedPackets for a connection.
struct QUIC_EXPORT_PRIVATE BufferedPacketList {
BufferedPacketList();
BufferedPacketList(BufferedPacketList&& other);
BufferedPacketList& operator=(BufferedPacketList&& other);
~BufferedPacketList();
std::list<BufferedPacket> buffered_packets;
QuicTime creation_time;
// The alpn from the CHLO, if one was found.
std::string alpn;
// Indicating whether this is an IETF QUIC connection.
bool ietf_quic;
// If buffered_packets contains the CHLO, it is the version of the CHLO.
// Otherwise, it is the version of the first packet in |buffered_packets|.
ParsedQuicVersion version;
};
typedef QuicLinkedHashMap<QuicConnectionId,
BufferedPacketList,
QuicConnectionIdHash>
BufferedPacketMap;
class QUIC_EXPORT_PRIVATE VisitorInterface {
public:
virtual ~VisitorInterface() {}
// Called for each expired connection when alarm fires.
virtual void OnExpiredPackets(QuicConnectionId connection_id,
BufferedPacketList early_arrived_packets) = 0;
};
QuicBufferedPacketStore(VisitorInterface* vistor,
const QuicClock* clock,
QuicAlarmFactory* alarm_factory);
QuicBufferedPacketStore(const QuicBufferedPacketStore&) = delete;
~QuicBufferedPacketStore();
QuicBufferedPacketStore& operator=(const QuicBufferedPacketStore&) = delete;
// Adds a copy of packet into packet queue for given connection.
// TODO(danzh): Consider to split this method to EnqueueChlo() and
// EnqueueDataPacket().
EnqueuePacketResult EnqueuePacket(QuicConnectionId connection_id,
bool ietf_quic,
const QuicReceivedPacket& packet,
QuicSocketAddress self_address,
QuicSocketAddress peer_address,
bool is_chlo,
const std::string& alpn,
const ParsedQuicVersion& version);
// Returns true if there are any packets buffered for |connection_id|.
bool HasBufferedPackets(QuicConnectionId connection_id) const;
// Returns the list of buffered packets for |connection_id| and removes them
// from the store. Returns an empty list if no early arrived packets for this
// connection are present.
BufferedPacketList DeliverPackets(QuicConnectionId connection_id);
// Discards packets buffered for |connection_id|, if any.
void DiscardPackets(QuicConnectionId connection_id);
// Examines how long packets have been buffered in the store for each
// connection. If they stay too long, removes them for new coming packets and
// calls |visitor_|'s OnPotentialConnectionExpire().
// Resets the alarm at the end.
void OnExpirationTimeout();
// Delivers buffered packets for next connection with CHLO to open.
// Return connection id for next connection in |connection_id|
// and all buffered packets including CHLO.
// The returned list should at least has one packet(CHLO) if
// store does have any connection to open. If no connection in the store has
// received CHLO yet, empty list will be returned.
BufferedPacketList DeliverPacketsForNextConnection(
QuicConnectionId* connection_id);
// Is given connection already buffered in the store?
bool HasChloForConnection(QuicConnectionId connection_id);
// Is there any CHLO buffered in the store?
bool HasChlosBuffered() const;
private:
friend class test::QuicBufferedPacketStorePeer;
// Set expiration alarm if it hasn't been set.
void MaybeSetExpirationAlarm();
// Return true if add an extra packet will go beyond allowed max connection
// limit. The limit for non-CHLO packet and CHLO packet is different.
bool ShouldBufferPacket(bool is_chlo);
// A map to store packet queues with creation time for each connection.
BufferedPacketMap undecryptable_packets_;
// The max time the packets of a connection can be buffer in the store.
const QuicTime::Delta connection_life_span_;
VisitorInterface* visitor_; // Unowned.
const QuicClock* clock_; // Unowned.
// This alarm fires every |connection_life_span_| to clean up
// packets staying in the store for too long.
std::unique_ptr<QuicAlarm> expiration_alarm_;
// Keeps track of connection with CHLO buffered up already and the order they
// arrive.
QuicLinkedHashMap<QuicConnectionId, bool, QuicConnectionIdHash>
connections_with_chlo_;
};
} // namespace quic
#endif // QUICHE_QUIC_CORE_QUIC_BUFFERED_PACKET_STORE_H_