blob: ce581564461af14585df6843972a1a6bbcbdc681 [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 <bitset>
#include <map>
#include <unordered_map>
#include "ack_frame.h"
#include "callback.h"
#include "reliability_and_ordering.h"
#include "status.h"
namespace overnet {
namespace receive_mode {
class ReceiveMode {
public:
virtual ~ReceiveMode() {}
// A new message is available. Ready will be called when a decision on message
// acceptance has been made. This function will return true if it's likely
// beneficial to send an ack frame now.
virtual bool Begin(uint64_t seq, StatusCallback ready) = 0;
// Once a sequence has begun (Begin() called, ready callback made
// *successfully*), Completed must be called exactly once.
// This function will return true if it's likely beneficial to send an ack
// frame now.
virtual bool Completed(uint64_t seq, const Status& status) = 0;
// Create an Ack frame
virtual AckFrame GenerateAck() const = 0;
// Base of the current receive window
virtual uint64_t WindowBase() const = 0;
};
class ReliableOrdered final : public ReceiveMode {
public:
ReliableOrdered() = default;
ReliableOrdered(const ReliableOrdered&) = delete;
ReliableOrdered& operator=(const ReliableOrdered&) = delete;
bool Begin(uint64_t seq, StatusCallback ready) override;
bool Completed(uint64_t seq, const Status& status) override;
AckFrame GenerateAck() const override;
uint64_t WindowBase() const override { return cur_; }
private:
uint64_t cur_ = 1;
uint64_t max_seen_ = 0;
bool cur_in_progress_ = false;
std::unordered_map<uint64_t, StatusCallback> later_;
};
class ReliableUnordered final : public ReceiveMode {
public:
ReliableUnordered() = default;
ReliableUnordered(const ReliableUnordered&) = delete;
ReliableUnordered& operator=(const ReliableUnordered&) = delete;
static constexpr size_t kLookaheadWindow = 128;
bool Begin(uint64_t seq, StatusCallback ready) override;
bool Completed(uint64_t seq, const Status& status) override;
AckFrame GenerateAck() const override;
uint64_t WindowBase() const override { return tip_; }
private:
uint64_t tip_ = 1;
uint64_t max_seen_ = 0;
std::bitset<kLookaheadWindow> in_progress_;
std::bitset<kLookaheadWindow> done_;
};
class UnreliableOrdered final : public ReceiveMode {
public:
UnreliableOrdered() = default;
UnreliableOrdered(const UnreliableOrdered&) = delete;
UnreliableOrdered& operator=(const UnreliableOrdered&) = delete;
bool Begin(uint64_t seq, StatusCallback ready) override;
bool Completed(uint64_t seq, const Status& status) override;
AckFrame GenerateAck() const override;
uint64_t WindowBase() const override { return cur_; }
private:
uint64_t cur_ = 1;
uint64_t max_seen_ = 0;
bool cur_in_progress_ = false;
std::map<uint64_t, StatusCallback> later_;
};
class UnreliableUnordered final : public ReceiveMode {
public:
UnreliableUnordered() = default;
UnreliableUnordered(const UnreliableUnordered&) = delete;
UnreliableUnordered& operator=(const UnreliableUnordered&) = delete;
static constexpr size_t kLookaheadWindow = 256;
bool Begin(uint64_t seq, StatusCallback ready) override;
bool Completed(uint64_t seq, const Status& status) override;
AckFrame GenerateAck() const override;
uint64_t WindowBase() const override { return tip_; }
private:
uint64_t tip_ = 1;
uint64_t max_seen_ = 1;
std::bitset<kLookaheadWindow> in_progress_;
};
class TailReliable final : public ReceiveMode {
public:
TailReliable() = default;
TailReliable(const TailReliable&) = delete;
TailReliable& operator=(const TailReliable&) = delete;
bool Begin(uint64_t seq, StatusCallback ready) override;
bool Completed(uint64_t seq, const Status& status) override;
AckFrame GenerateAck() const override;
uint64_t WindowBase() const override { return cur_; }
private:
uint64_t cur_ = 1;
uint64_t max_seen_ = 0;
bool cur_in_progress_ = false;
std::map<uint64_t, StatusCallback> later_;
};
class Error final : public ReceiveMode {
public:
Error() = default;
Error(const Error&) = delete;
Error& operator=(const Error&) = delete;
bool Begin(uint64_t seq, StatusCallback ready) override;
bool Completed(uint64_t seq, const Status& status) override;
AckFrame GenerateAck() const override;
uint64_t WindowBase() const override { return 1; }
};
class ParameterizedReceiveMode final : public ReceiveMode {
public:
explicit ParameterizedReceiveMode(
ReliabilityAndOrdering reliability_and_ordering)
: storage_(), receive_mode_(storage_.Init(reliability_and_ordering)) {}
~ParameterizedReceiveMode() { receive_mode_->~ReceiveMode(); }
bool Begin(uint64_t seq, StatusCallback ready) override {
return receive_mode_->Begin(seq, std::move(ready));
}
bool Completed(uint64_t seq, const Status& status) override {
return receive_mode_->Completed(seq, status);
}
AckFrame GenerateAck() const override { return receive_mode_->GenerateAck(); }
uint64_t WindowBase() const override { return receive_mode_->WindowBase(); }
ReceiveMode* get() const { return receive_mode_; }
private:
union Storage {
Storage() {}
ReceiveMode* Init(ReliabilityAndOrdering reliability_and_ordering);
~Storage() {}
ReliableOrdered reliable_ordered;
ReliableUnordered reliable_unordered;
UnreliableOrdered unreliable_ordered;
UnreliableUnordered unreliable_unordered;
TailReliable tail_reliable;
Error error;
};
Storage storage_;
ReceiveMode* receive_mode_;
};
} // namespace receive_mode
} // namespace overnet