mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	Network: Added Packet class for serialization
This commit is contained in:
		
							parent
							
								
									589dc083a5
								
							
						
					
					
						commit
						7d9b7394dd
					
				
					 3 changed files with 423 additions and 0 deletions
				
			
		|  | @ -1,11 +1,13 @@ | ||||||
| set(SRCS | set(SRCS | ||||||
|             network.cpp |             network.cpp | ||||||
|  |             packet.cpp | ||||||
|             room.cpp |             room.cpp | ||||||
|             room_member.cpp |             room_member.cpp | ||||||
|             ) |             ) | ||||||
| 
 | 
 | ||||||
| set(HEADERS | set(HEADERS | ||||||
|             network.h |             network.h | ||||||
|  |             packet.h | ||||||
|             room.h |             room.h | ||||||
|             room_member.h |             room_member.h | ||||||
|             ) |             ) | ||||||
|  |  | ||||||
							
								
								
									
										229
									
								
								src/network/packet.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										229
									
								
								src/network/packet.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,229 @@ | ||||||
|  | // Copyright 2017 Citra Emulator Project
 | ||||||
|  | // Licensed under GPLv2 or any later version
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
|  | 
 | ||||||
|  | #ifdef _WIN32 | ||||||
|  | #include <winsock2.h> | ||||||
|  | #else | ||||||
|  | #include <arpa/inet.h> | ||||||
|  | #endif | ||||||
|  | #include <cstring> | ||||||
|  | #include <string> | ||||||
|  | #include "network/packet.h" | ||||||
|  | 
 | ||||||
|  | namespace Network { | ||||||
|  | 
 | ||||||
|  | Packet::Packet() : read_pos(0), is_valid(true) {} | ||||||
|  | 
 | ||||||
|  | Packet::~Packet() {} | ||||||
|  | 
 | ||||||
|  | void Packet::Append(const void* in_data, std::size_t size_in_bytes) { | ||||||
|  |     if (in_data && (size_in_bytes > 0)) { | ||||||
|  |         std::size_t start = data.size(); | ||||||
|  |         data.resize(start + size_in_bytes); | ||||||
|  |         std::memcpy(&data[start], in_data, size_in_bytes); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Packet::Read(void* out_data, std::size_t size_in_bytes) { | ||||||
|  |     if (out_data && CheckSize(size_in_bytes)) { | ||||||
|  |         std::memcpy(out_data, &data[read_pos], size_in_bytes); | ||||||
|  |         read_pos += size_in_bytes; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Packet::Clear() { | ||||||
|  |     data.clear(); | ||||||
|  |     read_pos = 0; | ||||||
|  |     is_valid = true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const void* Packet::GetData() const { | ||||||
|  |     return !data.empty() ? &data[0] : NULL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Packet::IgnoreBytes(u32 length) { | ||||||
|  |     read_pos += length; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | std::size_t Packet::GetDataSize() const { | ||||||
|  |     return data.size(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool Packet::EndOfPacket() const { | ||||||
|  |     return read_pos >= data.size(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Packet::operator BoolType() const { | ||||||
|  |     return is_valid ? &Packet::CheckSize : NULL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Packet& Packet::operator>>(bool& out_data) { | ||||||
|  |     u8 value; | ||||||
|  |     if (*this >> value) { | ||||||
|  |         out_data = (value != 0); | ||||||
|  |     } | ||||||
|  |     return *this; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Packet& Packet::operator>>(s8& out_data) { | ||||||
|  |     Read(&out_data, sizeof(out_data)); | ||||||
|  |     return *this; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Packet& Packet::operator>>(u8& out_data) { | ||||||
|  |     Read(&out_data, sizeof(out_data)); | ||||||
|  |     return *this; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Packet& Packet::operator>>(s16& out_data) { | ||||||
|  |     s16 value; | ||||||
|  |     Read(&value, sizeof(value)); | ||||||
|  |     out_data = ntohs(value); | ||||||
|  |     return *this; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Packet& Packet::operator>>(u16& out_data) { | ||||||
|  |     u16 value; | ||||||
|  |     Read(&value, sizeof(value)); | ||||||
|  |     out_data = ntohs(value); | ||||||
|  |     return *this; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Packet& Packet::operator>>(s32& out_data) { | ||||||
|  |     s32 value; | ||||||
|  |     Read(&value, sizeof(value)); | ||||||
|  |     out_data = ntohl(value); | ||||||
|  |     return *this; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Packet& Packet::operator>>(u32& out_data) { | ||||||
|  |     u32 value; | ||||||
|  |     Read(&value, sizeof(value)); | ||||||
|  |     out_data = ntohl(value); | ||||||
|  |     return *this; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Packet& Packet::operator>>(float& out_data) { | ||||||
|  |     Read(&out_data, sizeof(out_data)); | ||||||
|  |     return *this; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Packet& Packet::operator>>(double& out_data) { | ||||||
|  |     Read(&out_data, sizeof(out_data)); | ||||||
|  |     return *this; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Packet& Packet::operator>>(char* out_data) { | ||||||
|  |     // First extract string length
 | ||||||
|  |     u32 length = 0; | ||||||
|  |     *this >> length; | ||||||
|  | 
 | ||||||
|  |     if ((length > 0) && CheckSize(length)) { | ||||||
|  |         // Then extract characters
 | ||||||
|  |         std::memcpy(out_data, &data[read_pos], length); | ||||||
|  |         out_data[length] = '\0'; | ||||||
|  | 
 | ||||||
|  |         // Update reading position
 | ||||||
|  |         read_pos += length; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return *this; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Packet& Packet::operator>>(std::string& out_data) { | ||||||
|  |     // First extract string length
 | ||||||
|  |     u32 length = 0; | ||||||
|  |     *this >> length; | ||||||
|  | 
 | ||||||
|  |     out_data.clear(); | ||||||
|  |     if ((length > 0) && CheckSize(length)) { | ||||||
|  |         // Then extract characters
 | ||||||
|  |         out_data.assign(&data[read_pos], length); | ||||||
|  | 
 | ||||||
|  |         // Update reading position
 | ||||||
|  |         read_pos += length; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return *this; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Packet& Packet::operator<<(bool in_data) { | ||||||
|  |     *this << static_cast<u8>(in_data); | ||||||
|  |     return *this; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Packet& Packet::operator<<(s8 in_data) { | ||||||
|  |     Append(&in_data, sizeof(in_data)); | ||||||
|  |     return *this; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Packet& Packet::operator<<(u8 in_data) { | ||||||
|  |     Append(&in_data, sizeof(in_data)); | ||||||
|  |     return *this; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Packet& Packet::operator<<(s16 in_data) { | ||||||
|  |     s16 toWrite = htons(in_data); | ||||||
|  |     Append(&toWrite, sizeof(toWrite)); | ||||||
|  |     return *this; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Packet& Packet::operator<<(u16 in_data) { | ||||||
|  |     u16 toWrite = htons(in_data); | ||||||
|  |     Append(&toWrite, sizeof(toWrite)); | ||||||
|  |     return *this; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Packet& Packet::operator<<(s32 in_data) { | ||||||
|  |     s32 toWrite = htonl(in_data); | ||||||
|  |     Append(&toWrite, sizeof(toWrite)); | ||||||
|  |     return *this; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Packet& Packet::operator<<(u32 in_data) { | ||||||
|  |     u32 toWrite = htonl(in_data); | ||||||
|  |     Append(&toWrite, sizeof(toWrite)); | ||||||
|  |     return *this; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Packet& Packet::operator<<(float in_data) { | ||||||
|  |     Append(&in_data, sizeof(in_data)); | ||||||
|  |     return *this; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Packet& Packet::operator<<(double in_data) { | ||||||
|  |     Append(&in_data, sizeof(in_data)); | ||||||
|  |     return *this; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Packet& Packet::operator<<(const char* in_data) { | ||||||
|  |     // First insert string length
 | ||||||
|  |     u32 length = std::strlen(in_data); | ||||||
|  |     *this << length; | ||||||
|  | 
 | ||||||
|  |     // Then insert characters
 | ||||||
|  |     Append(in_data, length * sizeof(char)); | ||||||
|  | 
 | ||||||
|  |     return *this; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Packet& Packet::operator<<(const std::string& in_data) { | ||||||
|  |     // First insert string length
 | ||||||
|  |     u32 length = static_cast<u32>(in_data.size()); | ||||||
|  |     *this << length; | ||||||
|  | 
 | ||||||
|  |     // Then insert characters
 | ||||||
|  |     if (length > 0) | ||||||
|  |         Append(in_data.c_str(), length * sizeof(std::string::value_type)); | ||||||
|  | 
 | ||||||
|  |     return *this; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool Packet::CheckSize(std::size_t size) { | ||||||
|  |     is_valid = is_valid && (read_pos + size <= data.size()); | ||||||
|  | 
 | ||||||
|  |     return is_valid; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } // namespace Network
 | ||||||
							
								
								
									
										192
									
								
								src/network/packet.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										192
									
								
								src/network/packet.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,192 @@ | ||||||
|  | // Copyright 2017 Citra Emulator Project
 | ||||||
|  | // Licensed under GPLv2 or any later version
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <array> | ||||||
|  | #include <vector> | ||||||
|  | #include "common/common_types.h" | ||||||
|  | 
 | ||||||
|  | namespace Network { | ||||||
|  | 
 | ||||||
|  | /// A class for serialize data for network transfer. It also handles endianess
 | ||||||
|  | class Packet { | ||||||
|  |     /// A bool-like type that cannot be converted to integer or pointer types
 | ||||||
|  |     typedef bool (Packet::*BoolType)(std::size_t); | ||||||
|  | 
 | ||||||
|  | public: | ||||||
|  |     Packet(); | ||||||
|  |     ~Packet(); | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      * 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; | ||||||
|  |     /**
 | ||||||
|  |      * Test the validity of the packet, for reading | ||||||
|  |      * This operator allows to test the packet as a boolean | ||||||
|  |      * variable, to check if a reading operation was successful. | ||||||
|  |      * | ||||||
|  |      * A packet will be in an invalid state if it has no more | ||||||
|  |      * data to read. | ||||||
|  |      * | ||||||
|  |      * This behaviour is the same as standard C++ streams. | ||||||
|  |      * | ||||||
|  |      * Usage example: | ||||||
|  |      * @code | ||||||
|  |      * float x; | ||||||
|  |      * packet >> x; | ||||||
|  |      * if (packet) | ||||||
|  |      * { | ||||||
|  |      *    // ok, x was extracted successfully
 | ||||||
|  |      * } | ||||||
|  |      * | ||||||
|  |      * // -- or --
 | ||||||
|  |      * | ||||||
|  |      * float x; | ||||||
|  |      * if (packet >> x) | ||||||
|  |      * { | ||||||
|  |      *    // ok, x was extracted successfully
 | ||||||
|  |      * } | ||||||
|  |      * @endcode | ||||||
|  |      * | ||||||
|  |      * Don't focus on the return type, it's equivalent to bool but | ||||||
|  |      * it disallows unwanted implicit conversions to integer or | ||||||
|  |      * pointer types. | ||||||
|  |      * | ||||||
|  |      * @return True if last data extraction from packet was successful | ||||||
|  |      */ | ||||||
|  |     operator BoolType() const; | ||||||
|  | 
 | ||||||
|  |     /// Overloads of operator >> to read data from the packet
 | ||||||
|  |     Packet& operator>>(bool& out_data); | ||||||
|  |     Packet& operator>>(s8& out_data); | ||||||
|  |     Packet& operator>>(u8& out_data); | ||||||
|  |     Packet& operator>>(s16& out_data); | ||||||
|  |     Packet& operator>>(u16& out_data); | ||||||
|  |     Packet& operator>>(s32& out_data); | ||||||
|  |     Packet& operator>>(u32& out_data); | ||||||
|  |     Packet& operator>>(float& out_data); | ||||||
|  |     Packet& operator>>(double& out_data); | ||||||
|  |     Packet& operator>>(char* out_data); | ||||||
|  |     Packet& operator>>(std::string& out_data); | ||||||
|  |     template <typename T> | ||||||
|  |     Packet& operator>>(std::vector<T>& out_data); | ||||||
|  |     template <typename T, std::size_t S> | ||||||
|  |     Packet& operator>>(std::array<T, S>& out_data); | ||||||
|  | 
 | ||||||
|  |     /// Overloads of operator << to write data into the packet
 | ||||||
|  |     Packet& operator<<(bool in_data); | ||||||
|  |     Packet& operator<<(s8 in_data); | ||||||
|  |     Packet& operator<<(u8 in_data); | ||||||
|  |     Packet& operator<<(s16 in_data); | ||||||
|  |     Packet& operator<<(u16 in_data); | ||||||
|  |     Packet& operator<<(s32 in_data); | ||||||
|  |     Packet& operator<<(u32 in_data); | ||||||
|  |     Packet& operator<<(float in_data); | ||||||
|  |     Packet& operator<<(double in_data); | ||||||
|  |     Packet& operator<<(const char* in_data); | ||||||
|  |     Packet& operator<<(const std::string& in_data); | ||||||
|  |     template <typename T> | ||||||
|  |     Packet& operator<<(const std::vector<T>& in_data); | ||||||
|  |     template <typename T, std::size_t S> | ||||||
|  |     Packet& operator<<(const std::array<T, S>& data); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     /// Disallow comparisons between packets
 | ||||||
|  |     bool operator==(const Packet& right) const; | ||||||
|  |     bool operator!=(const Packet& right) const; | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      * 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;   ///< Current reading position in the packet
 | ||||||
|  |     bool is_valid;          ///< Reading state of the packet
 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | template <typename T> | ||||||
|  | Packet& Packet::operator>>(std::vector<T>& out_data) { | ||||||
|  |     for (u32 i = 0; i < out_data.size(); ++i) { | ||||||
|  |         T character = 0; | ||||||
|  |         *this >> character; | ||||||
|  |         out_data[i] = character; | ||||||
|  |     } | ||||||
|  |     return *this; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | template <typename T, std::size_t S> | ||||||
|  | Packet& Packet::operator>>(std::array<T, S>& out_data) { | ||||||
|  |     for (u32 i = 0; i < out_data.size(); ++i) { | ||||||
|  |         T character = 0; | ||||||
|  |         *this >> character; | ||||||
|  |         out_data[i] = character; | ||||||
|  |     } | ||||||
|  |     return *this; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | template <typename T> | ||||||
|  | Packet& Packet::operator<<(const std::vector<T>& in_data) { | ||||||
|  |     for (u32 i = 0; i < in_data.size(); ++i) { | ||||||
|  |         *this << in_data[i]; | ||||||
|  |     } | ||||||
|  |     return *this; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | template <typename T, std::size_t S> | ||||||
|  | Packet& Packet::operator<<(const std::array<T, S>& in_data) { | ||||||
|  |     for (u32 i = 0; i < in_data.size(); ++i) { | ||||||
|  |         *this << in_data[i]; | ||||||
|  |     } | ||||||
|  |     return *this; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } // namespace Network
 | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue