C3/Src/Core/BaseQuery.h

103 lines
4.1 KiB
C++

#pragma once
namespace FSecure::C3::Core
{
// Forward declarations.
struct DeviceBridge;
// Typedefs and constants.
using ProceduresUnderlyingType = std::int8_t; ///< Underlying type for Procedure number field.
using SequenceNumberFieldUnderlyingType = std::uint32_t; /// Underlying type for Query/Response sequence numbers (including type bits = 2 bits).
/// Abstract class for all Queries.
struct BaseQuery
{
/// Enumeration for types of responses that can be requested for Queries.
enum class ResponseType : std::uint8_t
{
StatusBits, ///< Bit field: 00 - success, 01 - error, 10 - partial success, 11 - ACK.
StatusCode, ///< First - a bit field: 00 - success, 01 - error, 10 - success + extensions, 11 - partial success. Then StatusCode if the first bit-field was equal to 01 or 11.
ACK, ///< No status code nor bits. Just send back the ACK packet as soon as possible.
StatusCodePlusExtensions, ///< Same as StatusCode, but with extensions after bit-field, if the first bit field was 2 (e.g. iid of a newly added Interface) or after the StatusCode equal to 01 or 11. If status code doesn't require extensions (e.g. "No GDC") then extensions are omitted.
None = 255, ///< Do not respond.
};
/// Creates Query that is empty and should be filled then sent.
/// @param sender informs on the origin of message.
BaseQuery(std::weak_ptr<DeviceBridge> sender);
/// Creates Query that is empty and should be filled then sent.
/// @param responseType informs how recipient should react on message.
BaseQuery(ResponseType responseType = ResponseType::None);
/// Procedure number getter.
/// @return Procedure number.
/// @throws std::logic_error if not overriden.
virtual ProceduresUnderlyingType GetProcedureNumber() const { throw std::logic_error{ OBF("This method need to be overridden.") }; }
/// Deleted copy constructor.
BaseQuery(BaseQuery&) = delete;
/// Deleted copy assignment operator.
BaseQuery& operator=(BaseQuery&) = delete;
/// Default move constructor.
BaseQuery(BaseQuery&&) = default;
/// Default move assignment operator.
BaseQuery& operator=(BaseQuery&&) = default;
/// Response type setter.
/// @param responseType response type to set.
void SetResponseType(ResponseType responseType);
/// Compiles Query packet into a ByteVector.
/// @return Packet buffer.
virtual ByteVector ComposeQueryPacket() const = 0;
/// Sender Channel Getter.
/// @return Sender Channel or nullptr if this Query is yet about to be sent.
std::weak_ptr<DeviceBridge> GetSenderChannel();
/// Returns sequence Number.
auto GetSequenceNumber() const
{
return m_SequenceNumber;
}
protected:
/// Constructs Procedure header.
/// @return buffer containing composed header.
virtual ByteVector CompileProtocolHeader() const = 0;
/// Constructs Query packet header out of internal state and data.
/// @return Buffer containing the headers.
virtual ByteVector CompileQueryHeader() const;
private:
/// If true then this Query is just a copy of what was sent form remote Relay. If false then this is going to be send after filling up.
const bool m_ReceivedOrWillBeSent;
/// Underlying type for Query / Response sequence numbers(including type bits = 2 bits).
using SequenceNumberFieldUnderlyingType = std::uint32_t;
/// Number of bits sequence number occupy in the SequenceNumberType type.
static constexpr unsigned s_SequenceNumberBitLength = sizeof(SequenceNumberFieldUnderlyingType) * 8 - 2;
/// Sequence number
const SequenceNumberFieldUnderlyingType m_SequenceNumber;
/// sequence number generator (unique for every Query).
/// @return a unique number that can be used for a Query sequence number.
static SequenceNumberFieldUnderlyingType GenerateSequenceNumber();
std::uint8_t BuildSequenceNumberField(std::uint8_t statusBits) const;
/// Sender of this Query.Equals nullptr if this Query is yet about to be sent.
std::weak_ptr<DeviceBridge> m_SenderChannel;
/// Type of response requested for this Query.
ResponseType m_ResponseType;
};
}