2022-07-25 10:18:30 -05:00
|
|
|
// SPDX-FileCopyrightText: Copyright 2017 Citra Emulator Project
|
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2022-07-05 19:20:39 -05:00
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <array>
|
|
|
|
#include <vector>
|
|
|
|
#include "common/common_types.h"
|
|
|
|
|
|
|
|
namespace Network {
|
|
|
|
|
2023-03-11 21:10:38 -06:00
|
|
|
/// A class that serializes data for network transfer. It also handles endianness
|
2022-07-05 19:20:39 -05:00
|
|
|
class Packet {
|
|
|
|
public:
|
|
|
|
Packet() = default;
|
|
|
|
~Packet() = default;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Append data to the end of the packet
|
|
|
|
* @param data Pointer to the sequence of bytes to append
|
|
|
|
* @param size_in_bytes Number of bytes to append
|
|
|
|
*/
|
|
|
|
void Append(const void* data, std::size_t size_in_bytes);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reads data from the current read position of the packet
|
|
|
|
* @param out_data Pointer where the data should get written to
|
|
|
|
* @param size_in_bytes Number of bytes to read
|
|
|
|
*/
|
|
|
|
void Read(void* out_data, std::size_t size_in_bytes);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Clear the packet
|
|
|
|
* After calling Clear, the packet is empty.
|
|
|
|
*/
|
|
|
|
void Clear();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Ignores bytes while reading
|
|
|
|
* @param length THe number of bytes to ignore
|
|
|
|
*/
|
|
|
|
void IgnoreBytes(u32 length);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get a pointer to the data contained in the packet
|
|
|
|
* @return Pointer to the data
|
|
|
|
*/
|
|
|
|
const void* GetData() const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This function returns the number of bytes pointed to by
|
|
|
|
* what getData returns.
|
|
|
|
* @return Data size, in bytes
|
|
|
|
*/
|
|
|
|
std::size_t GetDataSize() const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This function is useful to know if there is some data
|
|
|
|
* left to be read, without actually reading it.
|
|
|
|
* @return True if all data was read, false otherwise
|
|
|
|
*/
|
|
|
|
bool EndOfPacket() const;
|
|
|
|
|
|
|
|
explicit operator bool() const;
|
|
|
|
|
2022-07-25 12:16:59 -05:00
|
|
|
/// Overloads of read function to read data from the packet
|
|
|
|
Packet& Read(bool& out_data);
|
|
|
|
Packet& Read(s8& out_data);
|
|
|
|
Packet& Read(u8& out_data);
|
|
|
|
Packet& Read(s16& out_data);
|
|
|
|
Packet& Read(u16& out_data);
|
|
|
|
Packet& Read(s32& out_data);
|
|
|
|
Packet& Read(u32& out_data);
|
|
|
|
Packet& Read(s64& out_data);
|
|
|
|
Packet& Read(u64& out_data);
|
|
|
|
Packet& Read(float& out_data);
|
|
|
|
Packet& Read(double& out_data);
|
|
|
|
Packet& Read(char* out_data);
|
|
|
|
Packet& Read(std::string& out_data);
|
2022-07-05 19:20:39 -05:00
|
|
|
template <typename T>
|
2022-07-25 12:16:59 -05:00
|
|
|
Packet& Read(std::vector<T>& out_data);
|
2022-07-05 19:20:39 -05:00
|
|
|
template <typename T, std::size_t S>
|
2022-07-25 12:16:59 -05:00
|
|
|
Packet& Read(std::array<T, S>& out_data);
|
|
|
|
|
|
|
|
/// Overloads of write function to write data into the packet
|
|
|
|
Packet& Write(bool in_data);
|
|
|
|
Packet& Write(s8 in_data);
|
|
|
|
Packet& Write(u8 in_data);
|
|
|
|
Packet& Write(s16 in_data);
|
|
|
|
Packet& Write(u16 in_data);
|
|
|
|
Packet& Write(s32 in_data);
|
|
|
|
Packet& Write(u32 in_data);
|
|
|
|
Packet& Write(s64 in_data);
|
|
|
|
Packet& Write(u64 in_data);
|
|
|
|
Packet& Write(float in_data);
|
|
|
|
Packet& Write(double in_data);
|
|
|
|
Packet& Write(const char* in_data);
|
|
|
|
Packet& Write(const std::string& in_data);
|
2022-07-05 19:20:39 -05:00
|
|
|
template <typename T>
|
2022-07-25 12:16:59 -05:00
|
|
|
Packet& Write(const std::vector<T>& in_data);
|
2022-07-05 19:20:39 -05:00
|
|
|
template <typename T, std::size_t S>
|
2022-07-25 12:16:59 -05:00
|
|
|
Packet& Write(const std::array<T, S>& data);
|
2022-07-05 19:20:39 -05:00
|
|
|
|
|
|
|
private:
|
|
|
|
/**
|
|
|
|
* Check if the packet can extract a given number of bytes
|
|
|
|
* This function updates accordingly the state of the packet.
|
|
|
|
* @param size Size to check
|
|
|
|
* @return True if size bytes can be read from the packet
|
|
|
|
*/
|
|
|
|
bool CheckSize(std::size_t size);
|
|
|
|
|
|
|
|
// Member data
|
|
|
|
std::vector<char> data; ///< Data stored in the packet
|
|
|
|
std::size_t read_pos = 0; ///< Current reading position in the packet
|
|
|
|
bool is_valid = true; ///< Reading state of the packet
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename T>
|
2022-07-25 12:16:59 -05:00
|
|
|
Packet& Packet::Read(std::vector<T>& out_data) {
|
2022-07-05 19:20:39 -05:00
|
|
|
// First extract the size
|
|
|
|
u32 size = 0;
|
2022-07-25 12:16:59 -05:00
|
|
|
Read(size);
|
2022-07-05 19:20:39 -05:00
|
|
|
out_data.resize(size);
|
|
|
|
|
|
|
|
// Then extract the data
|
|
|
|
for (std::size_t i = 0; i < out_data.size(); ++i) {
|
|
|
|
T character;
|
2022-07-25 12:16:59 -05:00
|
|
|
Read(character);
|
2022-07-05 19:20:39 -05:00
|
|
|
out_data[i] = character;
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T, std::size_t S>
|
2022-07-25 12:16:59 -05:00
|
|
|
Packet& Packet::Read(std::array<T, S>& out_data) {
|
2022-07-05 19:20:39 -05:00
|
|
|
for (std::size_t i = 0; i < out_data.size(); ++i) {
|
|
|
|
T character;
|
2022-07-25 12:16:59 -05:00
|
|
|
Read(character);
|
2022-07-05 19:20:39 -05:00
|
|
|
out_data[i] = character;
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
2022-07-25 12:16:59 -05:00
|
|
|
Packet& Packet::Write(const std::vector<T>& in_data) {
|
2022-07-05 19:20:39 -05:00
|
|
|
// First insert the size
|
2022-07-25 12:16:59 -05:00
|
|
|
Write(static_cast<u32>(in_data.size()));
|
2022-07-05 19:20:39 -05:00
|
|
|
|
|
|
|
// Then insert the data
|
|
|
|
for (std::size_t i = 0; i < in_data.size(); ++i) {
|
2022-07-25 12:16:59 -05:00
|
|
|
Write(in_data[i]);
|
2022-07-05 19:20:39 -05:00
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T, std::size_t S>
|
2022-07-25 12:16:59 -05:00
|
|
|
Packet& Packet::Write(const std::array<T, S>& in_data) {
|
2022-07-05 19:20:39 -05:00
|
|
|
for (std::size_t i = 0; i < in_data.size(); ++i) {
|
2022-07-25 12:16:59 -05:00
|
|
|
Write(in_data[i]);
|
2022-07-05 19:20:39 -05:00
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace Network
|