summaryrefslogtreecommitdiffstats
path: root/src/network/packet.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/packet.cpp')
-rw-r--r--src/network/packet.cpp263
1 files changed, 263 insertions, 0 deletions
diff --git a/src/network/packet.cpp b/src/network/packet.cpp
new file mode 100644
index 000000000..8fc5feabd
--- /dev/null
+++ b/src/network/packet.cpp
@@ -0,0 +1,263 @@
+// 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 {
+
+#ifndef htonll
+u64 htonll(u64 x) {
+ return ((1 == htonl(1)) ? (x) : ((uint64_t)htonl((x)&0xFFFFFFFF) << 32) | htonl((x) >> 32));
+}
+#endif
+
+#ifndef ntohll
+u64 ntohll(u64 x) {
+ return ((1 == ntohl(1)) ? (x) : ((uint64_t)ntohl((x)&0xFFFFFFFF) << 32) | ntohl((x) >> 32));
+}
+#endif
+
+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] : nullptr;
+}
+
+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 bool() const {
+ return is_valid;
+}
+
+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>>(s64& out_data) {
+ s64 value;
+ Read(&value, sizeof(value));
+ out_data = ntohll(value);
+ return *this;
+}
+
+Packet& Packet::operator>>(u64& out_data) {
+ u64 value;
+ Read(&value, sizeof(value));
+ out_data = ntohll(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<<(s64 in_data) {
+ s64 toWrite = htonll(in_data);
+ Append(&toWrite, sizeof(toWrite));
+ return *this;
+}
+
+Packet& Packet::operator<<(u64 in_data) {
+ u64 toWrite = htonll(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 = static_cast<u32>(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