packet.cpp 5.4 KB

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