blob: 4fc89ba7be555bce6efb9334a3410aeb8932c600 [file] [log] [blame]
/** @file
*
* A brief file description
*
* @section license License
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "QUICFrameGenerator.h"
#include "QUICTypes.h"
#include "QUICFrame.h"
#include <list>
class QUICConnection;
class QUICAckFrameManager : public QUICFrameGenerator
{
public:
class QUICAckFrameCreator
{
public:
struct RecvdPacket {
bool ack_only = false;
QUICPacketNumber packet_number = 0;
};
QUICAckFrameCreator(QUICPacketNumberSpace pn_space, QUICAckFrameManager *ack_manager);
~QUICAckFrameCreator();
void push_back(QUICPacketNumber packet_number, size_t size, bool ack_only);
size_t size() const;
void clear();
void sort();
void forget(QUICPacketNumber largest_acknowledged);
bool available() const;
bool is_ack_frame_ready();
void set_max_ack_delay(uint16_t delay);
// Checks maximum_frame_size and return _ack_frame
QUICAckFrame *generate_ack_frame(uint8_t *buf, uint16_t maximum_frame_size);
// refresh state when frame lost
void refresh_state();
QUICPacketNumber largest_ack_number() const;
ink_hrtime largest_ack_received_time() const;
private:
uint64_t _calculate_delay();
QUICAckFrame *_create_ack_frame(uint8_t *buf);
std::list<RecvdPacket> _packet_numbers;
bool _available = false; // packet_number has data to sent
bool _should_send = false; // ack frame should be sent immediately
bool _has_new_data = false; // new data after last sent
uint32_t _ack_eliciting_count = 0; // every two ack-eliciting packet should send ack immediately
uint16_t _max_ack_delay = 25;
QUICPacketNumber _largest_ack_number = 0;
QUICPacketNumber _expect_next = 0;
ink_hrtime _largest_ack_received_time = 0;
ink_hrtime _latest_packet_received_time = 0;
QUICAckFrameManager *_ack_manager = nullptr;
QUICPacketNumberSpace _pn_space = QUICPacketNumberSpace::Initial;
};
static constexpr int MAXIMUM_PACKET_COUNT = 256;
QUICAckFrameManager();
~QUICAckFrameManager();
void set_ack_delay_exponent(uint8_t ack_delay_exponent);
void set_max_ack_delay(uint16_t delay);
void set_force_to_send(bool on = true);
bool force_to_send() const;
/*
* All packet numbers ATS received need to be passed to this method.
* Returns 0 if updated successfully.
*/
int update(QUICEncryptionLevel level, QUICPacketNumber packet_number, size_t size, bool akc_only);
/*
* Returns true only if should send ack.
*/
bool will_generate_frame(QUICEncryptionLevel level, size_t current_packet_size, bool ack_eliciting, uint32_t seq_num) override;
/*
* Calls create directly.
*/
QUICFrame *generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t connection_credit, uint16_t maximum_frame_size,
size_t current_packet_size, uint32_t seq_num) override;
QUICFrameId issue_frame_id();
uint8_t ack_delay_exponent() const;
protected:
virtual bool _is_level_matched(QUICEncryptionLevel level) override;
private:
virtual void _on_frame_acked(QUICFrameInformationUPtr &info) override;
virtual void _on_frame_lost(QUICFrameInformationUPtr &info) override;
/*
* Returns QUICAckFrame only if ACK frame is able to be sent.
* Caller must send the ACK frame to the peer if it was returned.
*/
QUICAckFrame *_create_ack_frame(uint8_t *buf, QUICEncryptionLevel level);
uint64_t _calculate_delay(QUICEncryptionLevel level);
bool _available[4] = {false};
bool _should_send[4] = {false};
// Initial, 0/1-RTT, and Handshake
std::unique_ptr<QUICAckFrameCreator> _ack_creator[3];
uint8_t _ack_delay_exponent = 0;
};