Digitalisierte Elektroverteilung zur permanenten Verbraucherüberwachung
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

net_message.h 6.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. /*
  2. MMO Client/Server Framework using ASIO
  3. "Happy Birthday Mrs Javidx9!" - javidx9
  4. Videos:
  5. Part #1: https://youtu.be/2hNdkYInj4g
  6. Part #2: https://youtu.be/UbjxGvrDrbw
  7. License (OLC-3)
  8. ~~~~~~~~~~~~~~~
  9. Copyright 2018 - 2020 OneLoneCoder.com
  10. Redistribution and use in source and binary forms, with or without
  11. modification, are permitted provided that the following conditions
  12. are met:
  13. 1. Redistributions or derivations of source code must retain the above
  14. copyright notice, this list of conditions and the following disclaimer.
  15. 2. Redistributions or derivative works in binary form must reproduce
  16. the above copyright notice. This list of conditions and the following
  17. disclaimer must be reproduced in the documentation and/or other
  18. materials provided with the distribution.
  19. 3. Neither the name of the copyright holder nor the names of its
  20. contributors may be used to endorse or promote products derived
  21. from this software without specific prior written permission.
  22. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  23. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  24. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  25. A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  26. HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  27. SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  28. LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  29. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  30. THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  31. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  32. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  33. Links
  34. ~~~~~
  35. YouTube: https://www.youtube.com/javidx9
  36. Discord: https://discord.gg/WhwHUMV
  37. Twitter: https://www.twitter.com/javidx9
  38. Twitch: https://www.twitch.tv/javidx9
  39. GitHub: https://www.github.com/onelonecoder
  40. Homepage: https://www.onelonecoder.com
  41. Author
  42. ~~~~~~
  43. David Barr, aka javidx9, �OneLoneCoder 2019, 2020
  44. */
  45. #pragma once
  46. #include "net_common.h"
  47. #include <string>
  48. namespace net
  49. {
  50. ///[OLC_HEADERIFYIER] START "MESSAGE"
  51. // Message Header is sent at start of all messages. The template allows us
  52. // to use "enum class" to ensure that the messages are valid at compile time
  53. template <typename T>
  54. struct MessageHeader
  55. {
  56. T id{};
  57. uint32_t size = 0;
  58. };
  59. // Message Body contains a header and a std::vector, containing raw bytes
  60. // of infomation. This way the message can be variable length, but the size
  61. // in the header must be updated.
  62. template <typename T>
  63. struct Message
  64. {
  65. // Header & Body vector
  66. MessageHeader<T> header{};
  67. std::vector<uint8_t> body;
  68. // returns size of entire message packet in bytes
  69. size_t size() const
  70. {
  71. return body.size();
  72. }
  73. // Override for std::cout compatibility - produces friendly description of message
  74. friend std::ostream& operator << (std::ostream& os, const Message<T>& msg)
  75. {
  76. os << "ID:" << int(msg.header.id) << " Size:" << msg.header.size;
  77. return os;
  78. }
  79. // Convenience Operator overloads - These allow us to add and remove stuff from
  80. // the body vector as if it were a stack, so First in, Last Out. These are a
  81. // template in itself, because we dont know what data type the user is pushing or
  82. // popping, so lets allow them all. NOTE: It assumes the data type is fundamentally
  83. // Plain Old Data (POD). TLDR: Serialise & Deserialise into/from a vector
  84. // Pushes any POD-like data into the message buffer
  85. template<typename DataType>
  86. friend Message<T>& operator << (Message<T>& msg, const DataType& data)
  87. {
  88. // Check that the type of the data being pushed is trivially copyable
  89. static_assert(std::is_standard_layout<DataType>::value, "Data is too complex to be pushed into vector");
  90. // Cache current size of vector, as this will be the point we insert the data
  91. size_t i = msg.body.size();
  92. // Resize the vector by the size of the data being pushed
  93. msg.body.resize(i + sizeof(DataType));
  94. // Physically copy the data into the newly allocated vector space
  95. std::memcpy(msg.body.data() + i, &data, sizeof(DataType));
  96. // Recalculate the message size
  97. msg.header.size = msg.size();
  98. // Return the target message so it can be "chained"
  99. return msg;
  100. }
  101. //Specified template to write string
  102. friend Message<T>& operator << (Message<T>& msg, const std::string& data)
  103. {
  104. // Cache current size of vector, as this will be the point we insert the data
  105. size_t i = msg.body.size();
  106. // Resize the vector by the size of the data being pushed
  107. //msg.body.resize(i + sizeof(data));
  108. // Physically copy the data of the string character by character
  109. msg.body.resize(i + data.size());
  110. for (size_t index = 0; index < data.size(); index++) {
  111. msg.body[i+index] = data.at(index);
  112. //std::memcpy(msg.body.data() + i, &c, sizeof(uint8_t));
  113. }
  114. // Recalculate the message size
  115. msg.header.size = (uint32_t)msg.size();
  116. // Return the target message so it can be "chained"
  117. return msg;
  118. }
  119. // Pulls any POD-like data form the message buffer
  120. template<typename DataType>
  121. friend Message<T>& operator >> (Message<T>& msg, DataType& data)
  122. {
  123. // Check that the type of the data being pushed is trivially copyable
  124. static_assert(std::is_standard_layout<DataType>::value, "Data is too complex to be pulled from vector");
  125. // Cache the location towards the end of the vector where the pulled data starts
  126. size_t i = msg.body.size() - sizeof(DataType);
  127. // Physically copy the data from the vector into the user variable
  128. std::memcpy(&data, msg.body.data() + i, sizeof(DataType));
  129. // Shrink the vector to remove read bytes, and reset end position
  130. msg.body.resize(i);
  131. // Recalculate the message size
  132. msg.header.size = msg.size();
  133. // Return the target message so it can be "chained"
  134. return msg;
  135. }
  136. //Specified template to read string
  137. friend Message<T>& operator >> (Message<T>& msg, std::string& data)
  138. {
  139. // Cache the location towards the end of the vector where the pulled data starts
  140. size_t i = 0;
  141. // Physically copy the data from the vector into the user variable
  142. std::memcpy(&data, msg.body.data(), msg.body.size());
  143. // Shrink the vector to remove read bytes, and reset end position
  144. msg.body.resize(i);
  145. // Return the target message so it can be "chained"
  146. return msg;
  147. }
  148. };
  149. // An "owned" message is identical to a regular message, but it is associated with
  150. // a connection. On a server, the owner would be the client that sent the message,
  151. // on a client the owner would be the server.
  152. // Forward declare the connection
  153. template <typename T>
  154. class Connection;
  155. template <typename T>
  156. struct OwnedMessage
  157. {
  158. std::shared_ptr<Connection<T>> remote = nullptr;
  159. Message<T> msg;
  160. // Again, a friendly string maker
  161. friend std::ostream& operator<<(std::ostream& os, const OwnedMessage<T>& msg)
  162. {
  163. os << msg.msg;
  164. return os;
  165. }
  166. };
  167. }