summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar B3n302017-07-08 15:50:59 +0200
committerGravatar B3n302017-07-16 21:28:55 +0200
commit7d9b7394dde4e5e20b72bc0453c6026f43ed8495 (patch)
tree9c12b3b33fe8f429a16ab600379e7dc853f85695 /src
parentNetwork: Threads for Room and RoomMember (diff)
downloadyuzu-7d9b7394dde4e5e20b72bc0453c6026f43ed8495.tar.gz
yuzu-7d9b7394dde4e5e20b72bc0453c6026f43ed8495.tar.xz
yuzu-7d9b7394dde4e5e20b72bc0453c6026f43ed8495.zip
Network: Added Packet class for serialization
Diffstat (limited to 'src')
-rw-r--r--src/network/CMakeLists.txt2
-rw-r--r--src/network/packet.cpp229
-rw-r--r--src/network/packet.h192
3 files changed, 423 insertions, 0 deletions
diff --git a/src/network/CMakeLists.txt b/src/network/CMakeLists.txt
index aeabe430e..ac9d028da 100644
--- a/src/network/CMakeLists.txt
+++ b/src/network/CMakeLists.txt
@@ -1,11 +1,13 @@
1set(SRCS 1set(SRCS
2 network.cpp 2 network.cpp
3 packet.cpp
3 room.cpp 4 room.cpp
4 room_member.cpp 5 room_member.cpp
5 ) 6 )
6 7
7set(HEADERS 8set(HEADERS
8 network.h 9 network.h
10 packet.h
9 room.h 11 room.h
10 room_member.h 12 room_member.h
11 ) 13 )
diff --git a/src/network/packet.cpp b/src/network/packet.cpp
new file mode 100644
index 000000000..b3a61d824
--- /dev/null
+++ b/src/network/packet.cpp
@@ -0,0 +1,229 @@
1// Copyright 2017 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#ifdef _WIN32
6#include <winsock2.h>
7#else
8#include <arpa/inet.h>
9#endif
10#include <cstring>
11#include <string>
12#include "network/packet.h"
13
14namespace Network {
15
16Packet::Packet() : read_pos(0), is_valid(true) {}
17
18Packet::~Packet() {}
19
20void Packet::Append(const void* in_data, std::size_t size_in_bytes) {
21 if (in_data && (size_in_bytes > 0)) {
22 std::size_t start = data.size();
23 data.resize(start + size_in_bytes);
24 std::memcpy(&data[start], in_data, size_in_bytes);
25 }
26}
27
28void Packet::Read(void* out_data, std::size_t size_in_bytes) {
29 if (out_data && CheckSize(size_in_bytes)) {
30 std::memcpy(out_data, &data[read_pos], size_in_bytes);
31 read_pos += size_in_bytes;
32 }
33}
34
35void Packet::Clear() {
36 data.clear();
37 read_pos = 0;
38 is_valid = true;
39}
40
41const void* Packet::GetData() const {
42 return !data.empty() ? &data[0] : NULL;
43}
44
45void Packet::IgnoreBytes(u32 length) {
46 read_pos += length;
47}
48
49std::size_t Packet::GetDataSize() const {
50 return data.size();
51}
52
53bool Packet::EndOfPacket() const {
54 return read_pos >= data.size();
55}
56
57Packet::operator BoolType() const {
58 return is_valid ? &Packet::CheckSize : NULL;
59}
60
61Packet& Packet::operator>>(bool& out_data) {
62 u8 value;
63 if (*this >> value) {
64 out_data = (value != 0);
65 }
66 return *this;
67}
68
69Packet& Packet::operator>>(s8& out_data) {
70 Read(&out_data, sizeof(out_data));
71 return *this;
72}
73
74Packet& Packet::operator>>(u8& out_data) {
75 Read(&out_data, sizeof(out_data));
76 return *this;
77}
78
79Packet& Packet::operator>>(s16& out_data) {
80 s16 value;
81 Read(&value, sizeof(value));
82 out_data = ntohs(value);
83 return *this;
84}
85
86Packet& Packet::operator>>(u16& out_data) {
87 u16 value;
88 Read(&value, sizeof(value));
89 out_data = ntohs(value);
90 return *this;
91}
92
93Packet& Packet::operator>>(s32& out_data) {
94 s32 value;
95 Read(&value, sizeof(value));
96 out_data = ntohl(value);
97 return *this;
98}
99
100Packet& Packet::operator>>(u32& out_data) {
101 u32 value;
102 Read(&value, sizeof(value));
103 out_data = ntohl(value);
104 return *this;
105}
106
107Packet& Packet::operator>>(float& out_data) {
108 Read(&out_data, sizeof(out_data));
109 return *this;
110}
111
112Packet& Packet::operator>>(double& out_data) {
113 Read(&out_data, sizeof(out_data));
114 return *this;
115}
116
117Packet& Packet::operator>>(char* out_data) {
118 // First extract string length
119 u32 length = 0;
120 *this >> length;
121
122 if ((length > 0) && CheckSize(length)) {
123 // Then extract characters
124 std::memcpy(out_data, &data[read_pos], length);
125 out_data[length] = '\0';
126
127 // Update reading position
128 read_pos += length;
129 }
130
131 return *this;
132}
133
134Packet& Packet::operator>>(std::string& out_data) {
135 // First extract string length
136 u32 length = 0;
137 *this >> length;
138
139 out_data.clear();
140 if ((length > 0) && CheckSize(length)) {
141 // Then extract characters
142 out_data.assign(&data[read_pos], length);
143
144 // Update reading position
145 read_pos += length;
146 }
147
148 return *this;
149}
150
151Packet& Packet::operator<<(bool in_data) {
152 *this << static_cast<u8>(in_data);
153 return *this;
154}
155
156Packet& Packet::operator<<(s8 in_data) {
157 Append(&in_data, sizeof(in_data));
158 return *this;
159}
160
161Packet& Packet::operator<<(u8 in_data) {
162 Append(&in_data, sizeof(in_data));
163 return *this;
164}
165
166Packet& Packet::operator<<(s16 in_data) {
167 s16 toWrite = htons(in_data);
168 Append(&toWrite, sizeof(toWrite));
169 return *this;
170}
171
172Packet& Packet::operator<<(u16 in_data) {
173 u16 toWrite = htons(in_data);
174 Append(&toWrite, sizeof(toWrite));
175 return *this;
176}
177
178Packet& Packet::operator<<(s32 in_data) {
179 s32 toWrite = htonl(in_data);
180 Append(&toWrite, sizeof(toWrite));
181 return *this;
182}
183
184Packet& Packet::operator<<(u32 in_data) {
185 u32 toWrite = htonl(in_data);
186 Append(&toWrite, sizeof(toWrite));
187 return *this;
188}
189
190Packet& Packet::operator<<(float in_data) {
191 Append(&in_data, sizeof(in_data));
192 return *this;
193}
194
195Packet& Packet::operator<<(double in_data) {
196 Append(&in_data, sizeof(in_data));
197 return *this;
198}
199
200Packet& Packet::operator<<(const char* in_data) {
201 // First insert string length
202 u32 length = std::strlen(in_data);
203 *this << length;
204
205 // Then insert characters
206 Append(in_data, length * sizeof(char));
207
208 return *this;
209}
210
211Packet& Packet::operator<<(const std::string& in_data) {
212 // First insert string length
213 u32 length = static_cast<u32>(in_data.size());
214 *this << length;
215
216 // Then insert characters
217 if (length > 0)
218 Append(in_data.c_str(), length * sizeof(std::string::value_type));
219
220 return *this;
221}
222
223bool Packet::CheckSize(std::size_t size) {
224 is_valid = is_valid && (read_pos + size <= data.size());
225
226 return is_valid;
227}
228
229} // namespace Network
diff --git a/src/network/packet.h b/src/network/packet.h
new file mode 100644
index 000000000..6d84cfbac
--- /dev/null
+++ b/src/network/packet.h
@@ -0,0 +1,192 @@
1// Copyright 2017 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <array>
8#include <vector>
9#include "common/common_types.h"
10
11namespace Network {
12
13/// A class for serialize data for network transfer. It also handles endianess
14class Packet {
15 /// A bool-like type that cannot be converted to integer or pointer types
16 typedef bool (Packet::*BoolType)(std::size_t);
17
18public:
19 Packet();
20 ~Packet();
21
22 /**
23 * Append data to the end of the packet
24 * @param data Pointer to the sequence of bytes to append
25 * @param size_in_bytes Number of bytes to append
26 */
27 void Append(const void* data, std::size_t size_in_bytes);
28
29 /**
30 * Reads data from the current read position of the packet
31 * @param out_data Pointer where the data should get written to
32 * @param size_in_bytes Number of bytes to read
33 */
34 void Read(void* out_data, std::size_t size_in_bytes);
35
36 /**
37 * Clear the packet
38 * After calling Clear, the packet is empty.
39 */
40 void Clear();
41
42 /**
43 * Ignores bytes while reading
44 * @param length THe number of bytes to ignore
45 */
46 void IgnoreBytes(u32 length);
47
48 /**
49 * Get a pointer to the data contained in the packet
50 * @return Pointer to the data
51 */
52 const void* GetData() const;
53
54 /**
55 * This function returns the number of bytes pointed to by
56 * what getData returns.
57 * @return Data size, in bytes
58 */
59 std::size_t GetDataSize() const;
60
61 /**
62 * This function is useful to know if there is some data
63 * left to be read, without actually reading it.
64 * @return True if all data was read, false otherwise
65 */
66 bool EndOfPacket() const;
67 /**
68 * Test the validity of the packet, for reading
69 * This operator allows to test the packet as a boolean
70 * variable, to check if a reading operation was successful.
71 *
72 * A packet will be in an invalid state if it has no more
73 * data to read.
74 *
75 * This behaviour is the same as standard C++ streams.
76 *
77 * Usage example:
78 * @code
79 * float x;
80 * packet >> x;
81 * if (packet)
82 * {
83 * // ok, x was extracted successfully
84 * }
85 *
86 * // -- or --
87 *
88 * float x;
89 * if (packet >> x)
90 * {
91 * // ok, x was extracted successfully
92 * }
93 * @endcode
94 *
95 * Don't focus on the return type, it's equivalent to bool but
96 * it disallows unwanted implicit conversions to integer or
97 * pointer types.
98 *
99 * @return True if last data extraction from packet was successful
100 */
101 operator BoolType() const;
102
103 /// Overloads of operator >> to read data from the packet
104 Packet& operator>>(bool& out_data);
105 Packet& operator>>(s8& out_data);
106 Packet& operator>>(u8& out_data);
107 Packet& operator>>(s16& out_data);
108 Packet& operator>>(u16& out_data);
109 Packet& operator>>(s32& out_data);
110 Packet& operator>>(u32& out_data);
111 Packet& operator>>(float& out_data);
112 Packet& operator>>(double& out_data);
113 Packet& operator>>(char* out_data);
114 Packet& operator>>(std::string& out_data);
115 template <typename T>
116 Packet& operator>>(std::vector<T>& out_data);
117 template <typename T, std::size_t S>
118 Packet& operator>>(std::array<T, S>& out_data);
119
120 /// Overloads of operator << to write data into the packet
121 Packet& operator<<(bool in_data);
122 Packet& operator<<(s8 in_data);
123 Packet& operator<<(u8 in_data);
124 Packet& operator<<(s16 in_data);
125 Packet& operator<<(u16 in_data);
126 Packet& operator<<(s32 in_data);
127 Packet& operator<<(u32 in_data);
128 Packet& operator<<(float in_data);
129 Packet& operator<<(double in_data);
130 Packet& operator<<(const char* in_data);
131 Packet& operator<<(const std::string& in_data);
132 template <typename T>
133 Packet& operator<<(const std::vector<T>& in_data);
134 template <typename T, std::size_t S>
135 Packet& operator<<(const std::array<T, S>& data);
136
137private:
138 /// Disallow comparisons between packets
139 bool operator==(const Packet& right) const;
140 bool operator!=(const Packet& right) const;
141
142 /**
143 * Check if the packet can extract a given number of bytes
144 * This function updates accordingly the state of the packet.
145 * @param size Size to check
146 * @return True if size bytes can be read from the packet
147 */
148 bool CheckSize(std::size_t size);
149
150 // Member data
151 std::vector<char> data; ///< Data stored in the packet
152 std::size_t read_pos; ///< Current reading position in the packet
153 bool is_valid; ///< Reading state of the packet
154};
155
156template <typename T>
157Packet& Packet::operator>>(std::vector<T>& out_data) {
158 for (u32 i = 0; i < out_data.size(); ++i) {
159 T character = 0;
160 *this >> character;
161 out_data[i] = character;
162 }
163 return *this;
164}
165
166template <typename T, std::size_t S>
167Packet& Packet::operator>>(std::array<T, S>& out_data) {
168 for (u32 i = 0; i < out_data.size(); ++i) {
169 T character = 0;
170 *this >> character;
171 out_data[i] = character;
172 }
173 return *this;
174}
175
176template <typename T>
177Packet& Packet::operator<<(const std::vector<T>& in_data) {
178 for (u32 i = 0; i < in_data.size(); ++i) {
179 *this << in_data[i];
180 }
181 return *this;
182}
183
184template <typename T, std::size_t S>
185Packet& Packet::operator<<(const std::array<T, S>& in_data) {
186 for (u32 i = 0; i < in_data.size(); ++i) {
187 *this << in_data[i];
188 }
189 return *this;
190}
191
192} // namespace Network