blob: 1ef8d5a43570ff8e73c016408e4c15b65fae7625 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#pragma once
#include <assert.h>
#include <tuple>
#include <vector>
#include "slice.h"
#include "status.h"
namespace overnet {
class AckFrame {
public:
class Writer {
public:
explicit Writer(const AckFrame* ack_frame);
size_t wire_length() const { return wire_length_; }
uint8_t* Write(uint8_t* out) const;
private:
const AckFrame* const ack_frame_;
const uint8_t ack_to_seq_length_;
const uint8_t ack_delay_us_length_;
const uint8_t window_grant_bytes_length_;
std::vector<uint8_t> nack_length_;
size_t wire_length_;
};
AckFrame(uint64_t ack_to_seq, uint64_t ack_delay_us,
uint64_t window_grant_bytes)
: ack_to_seq_(ack_to_seq),
ack_delay_us_(ack_delay_us),
window_grant_bytes_(window_grant_bytes) {
assert(ack_to_seq_ > 0);
}
AckFrame(uint64_t ack_to_seq, uint64_t ack_delay_us,
uint64_t window_grant_bytes,
std::initializer_list<uint64_t> nack_seqs)
: ack_to_seq_(ack_to_seq),
ack_delay_us_(ack_delay_us),
window_grant_bytes_(window_grant_bytes),
nack_seqs_(nack_seqs) {}
explicit AckFrame(uint64_t ack_to_seq) : AckFrame(ack_to_seq, 0, 0) {}
AckFrame(const AckFrame&) = delete;
AckFrame& operator=(const AckFrame&) = delete;
AckFrame(AckFrame&& other)
: ack_to_seq_(other.ack_to_seq_),
ack_delay_us_(other.ack_delay_us_),
window_grant_bytes_(other.window_grant_bytes_),
nack_seqs_(std::move(other.nack_seqs_)) {}
AckFrame& operator=(AckFrame&& other) {
ack_to_seq_ = other.ack_to_seq_;
ack_delay_us_ = other.ack_delay_us_;
window_grant_bytes_ = other.window_grant_bytes_;
nack_seqs_ = std::move(other.nack_seqs_);
return *this;
}
void AddNack(uint64_t seq) {
assert(ack_to_seq_ > 0);
assert(seq > (nack_seqs_.empty() ? ack_to_seq_ - 1 : nack_seqs_.back()));
nack_seqs_.push_back(seq);
}
static StatusOr<AckFrame> Parse(Slice slice);
friend bool operator==(const AckFrame& a, const AckFrame& b) {
return std::tie(a.ack_to_seq_, a.ack_delay_us_, a.window_grant_bytes_,
a.nack_seqs_) == std::tie(b.ack_to_seq_, b.ack_delay_us_,
b.window_grant_bytes_,
b.nack_seqs_);
}
uint64_t ack_to_seq() const { return ack_to_seq_; }
uint64_t ack_delay_us() const { return ack_delay_us_; }
uint64_t window_grant_bytes() const { return window_grant_bytes_; }
const std::vector<uint64_t>& nack_seqs() const { return nack_seqs_; }
private:
// All messages with sequence number prior to ack_to_seq_ are implicitly
// acknowledged.
uint64_t ack_to_seq_;
// How long between receiving ack_to_seq_-1 and generating this data
// structure.
uint64_t ack_delay_us_;
// Size of window grant: acks also grant flow control window
// such a grant is for ack_to_seq_ onwards.
uint64_t window_grant_bytes_;
// All messages contained in nack_seqs_ need to be resent.
// NOTE: it's assumed that nack_seqs_ is in-order and all value are greater
// than or equal to ack_to_seq_.
std::vector<uint64_t> nack_seqs_;
};
std::ostream& operator<<(std::ostream& out, const AckFrame& ack_frame);
} // namespace overnet