summaryrefslogtreecommitdiff
path: root/src/network/packet.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/packet.cpp')
-rw-r--r--src/network/packet.cpp262
1 files changed, 262 insertions, 0 deletions
diff --git a/src/network/packet.cpp b/src/network/packet.cpp
new file mode 100644
index 000000000..0e22f1eb4
--- /dev/null
+++ b/src/network/packet.cpp
@@ -0,0 +1,262 @@
1// SPDX-FileCopyrightText: Copyright 2017 Citra Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#ifdef _WIN32
5#include <winsock2.h>
6#else
7#include <arpa/inet.h>
8#endif
9#include <cstring>
10#include <string>
11#include "network/packet.h"
12
13namespace Network {
14
15#ifndef htonll
16static u64 htonll(u64 x) {
17 return ((1 == htonl(1)) ? (x) : ((uint64_t)htonl((x)&0xFFFFFFFF) << 32) | htonl((x) >> 32));
18}
19#endif
20
21#ifndef ntohll
22static u64 ntohll(u64 x) {
23 return ((1 == ntohl(1)) ? (x) : ((uint64_t)ntohl((x)&0xFFFFFFFF) << 32) | ntohl((x) >> 32));
24}
25#endif
26
27void Packet::Append(const void* in_data, std::size_t size_in_bytes) {
28 if (in_data && (size_in_bytes > 0)) {
29 std::size_t start = data.size();
30 data.resize(start + size_in_bytes);
31 std::memcpy(&data[start], in_data, size_in_bytes);
32 }
33}
34
35void Packet::Read(void* out_data, std::size_t size_in_bytes) {
36 if (out_data && CheckSize(size_in_bytes)) {
37 std::memcpy(out_data, &data[read_pos], size_in_bytes);
38 read_pos += size_in_bytes;
39 }
40}
41
42void Packet::Clear() {
43 data.clear();
44 read_pos = 0;
45 is_valid = true;
46}
47
48const void* Packet::GetData() const {
49 return !data.empty() ? &data[0] : nullptr;
50}
51
52void Packet::IgnoreBytes(u32 length) {
53 read_pos += length;
54}
55
56std::size_t Packet::GetDataSize() const {
57 return data.size();
58}
59
60bool Packet::EndOfPacket() const {
61 return read_pos >= data.size();
62}
63
64Packet::operator bool() const {
65 return is_valid;
66}
67
68Packet& Packet::Read(bool& out_data) {
69 u8 value{};
70 if (Read(value)) {
71 out_data = (value != 0);
72 }
73 return *this;
74}
75
76Packet& Packet::Read(s8& out_data) {
77 Read(&out_data, sizeof(out_data));
78 return *this;
79}
80
81Packet& Packet::Read(u8& out_data) {
82 Read(&out_data, sizeof(out_data));
83 return *this;
84}
85
86Packet& Packet::Read(s16& out_data) {
87 s16 value{};
88 Read(&value, sizeof(value));
89 out_data = ntohs(value);
90 return *this;
91}
92
93Packet& Packet::Read(u16& out_data) {
94 u16 value{};
95 Read(&value, sizeof(value));
96 out_data = ntohs(value);
97 return *this;
98}
99
100Packet& Packet::Read(s32& out_data) {
101 s32 value{};
102 Read(&value, sizeof(value));
103 out_data = ntohl(value);
104 return *this;
105}
106
107Packet& Packet::Read(u32& out_data) {
108 u32 value{};
109 Read(&value, sizeof(value));
110 out_data = ntohl(value);
111 return *this;
112}
113
114Packet& Packet::Read(s64& out_data) {
115 s64 value{};
116 Read(&value, sizeof(value));
117 out_data = ntohll(value);
118 return *this;
119}
120
121Packet& Packet::Read(u64& out_data) {
122 u64 value{};
123 Read(&value, sizeof(value));
124 out_data = ntohll(value);
125 return *this;
126}
127
128Packet& Packet::Read(float& out_data) {
129 Read(&out_data, sizeof(out_data));
130 return *this;
131}
132
133Packet& Packet::Read(double& out_data) {
134 Read(&out_data, sizeof(out_data));
135 return *this;
136}
137
138Packet& Packet::Read(char* out_data) {
139 // First extract string length
140 u32 length = 0;
141 Read(length);
142
143 if ((length > 0) && CheckSize(length)) {
144 // Then extract characters
145 std::memcpy(out_data, &data[read_pos], length);
146 out_data[length] = '\0';
147
148 // Update reading position
149 read_pos += length;
150 }
151
152 return *this;
153}
154
155Packet& Packet::Read(std::string& out_data) {
156 // First extract string length
157 u32 length = 0;
158 Read(length);
159
160 out_data.clear();
161 if ((length > 0) && CheckSize(length)) {
162 // Then extract characters
163 out_data.assign(&data[read_pos], length);
164
165 // Update reading position
166 read_pos += length;
167 }
168
169 return *this;
170}
171
172Packet& Packet::Write(bool in_data) {
173 Write(static_cast<u8>(in_data));
174 return *this;
175}
176
177Packet& Packet::Write(s8 in_data) {
178 Append(&in_data, sizeof(in_data));
179 return *this;
180}
181
182Packet& Packet::Write(u8 in_data) {
183 Append(&in_data, sizeof(in_data));
184 return *this;
185}
186
187Packet& Packet::Write(s16 in_data) {
188 s16 toWrite = htons(in_data);
189 Append(&toWrite, sizeof(toWrite));
190 return *this;
191}
192
193Packet& Packet::Write(u16 in_data) {
194 u16 toWrite = htons(in_data);
195 Append(&toWrite, sizeof(toWrite));
196 return *this;
197}
198
199Packet& Packet::Write(s32 in_data) {
200 s32 toWrite = htonl(in_data);
201 Append(&toWrite, sizeof(toWrite));
202 return *this;
203}
204
205Packet& Packet::Write(u32 in_data) {
206 u32 toWrite = htonl(in_data);
207 Append(&toWrite, sizeof(toWrite));
208 return *this;
209}
210
211Packet& Packet::Write(s64 in_data) {
212 s64 toWrite = htonll(in_data);
213 Append(&toWrite, sizeof(toWrite));
214 return *this;
215}
216
217Packet& Packet::Write(u64 in_data) {
218 u64 toWrite = htonll(in_data);
219 Append(&toWrite, sizeof(toWrite));
220 return *this;
221}
222
223Packet& Packet::Write(float in_data) {
224 Append(&in_data, sizeof(in_data));
225 return *this;
226}
227
228Packet& Packet::Write(double in_data) {
229 Append(&in_data, sizeof(in_data));
230 return *this;
231}
232
233Packet& Packet::Write(const char* in_data) {
234 // First insert string length
235 u32 length = static_cast<u32>(std::strlen(in_data));
236 Write(length);
237
238 // Then insert characters
239 Append(in_data, length * sizeof(char));
240
241 return *this;
242}
243
244Packet& Packet::Write(const std::string& in_data) {
245 // First insert string length
246 u32 length = static_cast<u32>(in_data.size());
247 Write(length);
248
249 // Then insert characters
250 if (length > 0)
251 Append(in_data.c_str(), length * sizeof(std::string::value_type));
252
253 return *this;
254}
255
256bool Packet::CheckSize(std::size_t size) {
257 is_valid = is_valid && (read_pos + size <= data.size());
258
259 return is_valid;
260}
261
262} // namespace Network