Leviathan  0.8.0.0
Leviathan game engine
Leviathan::WireData Class Referencefinal

#include <WireData.h>

Public Types

enum  DECODE_CALLBACK_RESULT { DECODE_CALLBACK_RESULT::Continue, DECODE_CALLBACK_RESULT::Error }
 Return value for controlling how DecodeIncomingData continues after the callback. More...
 

Static Public Member Functions

static DLLEXPORT std::shared_ptr< SentRequestFormatRequestBytes (const std::shared_ptr< NetworkRequest > &request, RECEIVE_GUARANTEE guarantee, uint32_t messagenumber, uint32_t localpacketid, const NetworkAckField *acks, sf::Packet &bytesreceiver)
 Constructs a single request message containing normal packet. More...
 
static DLLEXPORT void FormatRequestBytes (const NetworkRequest &request, uint32_t messagenumber, uint32_t localpacketid, const NetworkAckField *acks, sf::Packet &bytesreceiver)
 Constructs a request without creating a SentRequest. More...
 
static DLLEXPORT std::shared_ptr< SentResponseFormatResponseBytes (const std::shared_ptr< NetworkResponse > &response, RECEIVE_GUARANTEE guarantee, uint32_t messagenumber, uint32_t localpacketid, const NetworkAckField *acks, sf::Packet &bytesreceiver)
 Constructs a single response message. More...
 
static DLLEXPORT std::shared_ptr< SentResponseFormatResponseBytesTracked (const NetworkResponse &response, uint32_t messagenumber, uint32_t localpacketid, const NetworkAckField *acks, sf::Packet &bytesreceiver)
 Constructs a single response message that can't be resent. More...
 
static DLLEXPORT void FormatResponseBytes (const NetworkResponse &response, uint32_t messagenumber, uint32_t localpacketid, const NetworkAckField *acks, sf::Packet &bytesreceiver)
 Constructs a single response message. More...
 
static DLLEXPORT void FormatAckOnlyPacket (const std::vector< uint32_t > &packetstoack, sf::Packet &bytesreceiver)
 Constructs an ack only packet with the specified acks. More...
 
static DLLEXPORT void DecodeIncomingData (sf::Packet &packet, const std::function< DECODE_CALLBACK_RESULT(NetworkAckField &)> &ackcallback, const std::function< void(uint32_t)> &singleack, const std::function< DECODE_CALLBACK_RESULT(uint32_t)> &packetnumberreceived, const std::function< DECODE_CALLBACK_RESULT(uint8_t, uint32_t, sf::Packet &)> &messagereceived)
 Decodes a packet to the right objects and invokes the callbacks. More...
 

Static Protected Member Functions

static DLLEXPORT void PrepareHeaderForPacket (uint32_t localpacketid, uint32_t *firstmessagenumber, size_t messagenumbercount, const NetworkAckField *acks, sf::Packet &tofill)
 
static DLLEXPORT void FillHeaderAckData (const NetworkAckField *acks, sf::Packet &tofill)
 

Detailed Description

Class for serializing and deserializing the final bytes that are sent over the network

Used by Connection and tests to format NetworkResponse and NetworkRequest objects

Definition at line 30 of file WireData.h.

Member Enumeration Documentation

◆ DECODE_CALLBACK_RESULT

Return value for controlling how DecodeIncomingData continues after the callback.

Enumerator
Continue 
Error 

Definition at line 33 of file WireData.h.

33  {
34 
35  Continue,
36  Error
37  };
Only set when the derived class forgot to set it.

Member Function Documentation

◆ DecodeIncomingData()

DLLEXPORT void WireData::DecodeIncomingData ( sf::Packet &  packet,
const std::function< DECODE_CALLBACK_RESULT(NetworkAckField &)> &  ackcallback,
const std::function< void(uint32_t)> &  singleack,
const std::function< DECODE_CALLBACK_RESULT(uint32_t)> &  packetnumberreceived,
const std::function< DECODE_CALLBACK_RESULT(uint8_t, uint32_t, sf::Packet &)> &  messagereceived 
)
static

Decodes a packet to the right objects and invokes the callbacks.

This does the opposito of the various Format methods in this class.

Note
In case of errors they will be logged and this will silently return without invoking the callbacks
Parameters
ackcallbackCalled when a NetworkAckField is decoded from the packet
singleackCalled when a a single whole ack number is loaded
packetnumberreceivedCalled when a packet id is decoded
handlemessageThis is the most important callback as it is called once for every message decoded from the packet. This may not be null
messagereceivedCalled once for every message. The actual message data is still in the packet and needs to be decoded. The callback parameters are: message type and message number

Definition at line 163 of file WireData.cpp.

169 {
170  // Header //
171  uint16_t leviathanMagic = 0;
172  packet >> leviathanMagic;
173 
174  if(!packet) {
175 
176  Logger::Get()->Error("Received packet has invalid (header) format");
177  return;
178  }
179 
180  switch(leviathanMagic) {
182  uint32_t packetNumber = 0;
183  packet >> packetNumber;
184 
185  if(!packet) {
186 
187  Logger::Get()->Error("Received packet has invalid (packet number) format");
188  return;
189  }
190 
191  NetworkAckField otherreceivedpackages(packet);
192 
193  if(!packet) {
194 
195  Logger::Get()->Error("Received packet has invalid format");
196  }
197 
198  // Messages //
199  uint8_t messageCount = 0;
200 
201  if(!(packet >> messageCount)) {
202 
203  Logger::Get()->Error("Received packet has invalid format, missing Message Count");
204  }
205 
206  // Marks things as successfully sent //
207  if(ackcallback) {
208 
209  auto callbackResult = ackcallback(otherreceivedpackages);
210 
211  if(callbackResult != DECODE_CALLBACK_RESULT::Continue) {
212 
213  LOG_ERROR("Packet decode callback signaled error");
214  return;
215  }
216  }
217 
218  // Report the packet as received //
219  if(packetnumberreceived) {
220 
221  auto callbackResult = packetnumberreceived(packetNumber);
222 
223  if(callbackResult != DECODE_CALLBACK_RESULT::Continue) {
224 
225  LOG_ERROR("Packet decode callback signaled error");
226  return;
227  }
228  }
229 
230  for(int i = 0; i < messageCount; ++i) {
231 
232  uint8_t messageType = 0;
233  packet >> messageType;
234 
235  uint32_t messageNumber = 0;
236  packet >> messageNumber;
237 
238  if(!packet) {
239 
240  LOG_ERROR("Connection: received packet has an invalid message "
241  "(some may have been processed already)");
242  return;
243  }
244 
245  auto callbackResult = messagereceived(messageType, messageNumber, packet);
246 
247  if(callbackResult != DECODE_CALLBACK_RESULT::Continue) {
248 
249  LOG_ERROR("Packet decode callback signaled error");
250  return;
251  }
252  }
253 
254  return;
255  }
256  case LEVIATHAN_ACK_PACKET: {
257  uint8_t ackCount = 0;
258 
259  if(!(packet >> ackCount)) {
260 
261  LOG_ERROR("Received packet has invalid (ack number) format");
262  return;
263  }
264 
265  for(uint8_t i = 0; i < ackCount; ++i) {
266 
267  uint32_t ack = 0;
268 
269  if(!(packet >> ack)) {
270 
271  LOG_ERROR("Received packet ended while acks were being unpacked, "
272  "some were applied");
273  return;
274  }
275 
276  if(singleack)
277  singleack(ack);
278  }
279 
280  return;
281  }
282  default: {
283  LOG_ERROR("Received packet has an unknown type: " + Convert::ToString(leviathanMagic));
284  return;
285  }
286  }
287 }
#define LOG_ERROR(x)
Definition: Define.h:83
constexpr uint16_t LEVIATHAN_ACK_PACKET
Definition: CommonNetwork.h:14
constexpr uint16_t LEVIATHAN_NORMAL_PACKET
Definition: CommonNetwork.h:12
unsigned char uint8_t
Definition: core.h:38
unsigned short uint16_t
Definition: core.h:39
static std::string ToString(const T &val)
Definition: Convert.h:72
static DLLEXPORT Logger * Get()
Definition: Logger.cpp:106
unsigned int uint32_t
Definition: core.h:40
DLLEXPORT void Error(const std::string &data) override
Definition: Logger.cpp:177

◆ FillHeaderAckData()

DLLEXPORT void WireData::FillHeaderAckData ( const NetworkAckField acks,
sf::Packet &  tofill 
)
staticprotected

Format ack part of header

used by PrepareHeaderForPacket. Split out for testing purposes

Definition at line 315 of file WireData.cpp.

316 {
317  if(!acks) {
318 
319  // Set first to be zero which assumes that no data follows
320  tofill << uint32_t(0);
321 
322  } else {
323 
324  // Put into the packet //
325  acks->AddDataToPacket(tofill);
326  }
327 }
DLLEXPORT void AddDataToPacket(sf::Packet &packet) const
unsigned int uint32_t
Definition: core.h:40

◆ FormatAckOnlyPacket()

DLLEXPORT void WireData::FormatAckOnlyPacket ( const std::vector< uint32_t > &  packetstoack,
sf::Packet &  bytesreceiver 
)
static

Constructs an ack only packet with the specified acks.

Definition at line 145 of file WireData.cpp.

147 {
148  bytesreceiver << LEVIATHAN_ACK_PACKET;
149 
150  LEVIATHAN_ASSERT(packetstoack.size() < std::numeric_limits<uint8_t>::max(),
151  "CreateAckOnlyPacket too many packetstoack provided, can't fit in uint8");
152 
153  const uint8_t count = static_cast<uint8_t>(packetstoack.size());
154 
155  bytesreceiver << count;
156 
157  for(uint8_t i = 0; i < count; ++i) {
158 
159  bytesreceiver << packetstoack[i];
160  }
161 }
constexpr uint16_t LEVIATHAN_ACK_PACKET
Definition: CommonNetwork.h:14
unsigned char uint8_t
Definition: core.h:38

◆ FormatRequestBytes() [1/2]

DLLEXPORT std::shared_ptr< SentRequest > WireData::FormatRequestBytes ( const std::shared_ptr< NetworkRequest > &  request,
RECEIVE_GUARANTEE  guarantee,
uint32_t  messagenumber,
uint32_t  localpacketid,
const NetworkAckField acks,
sf::Packet &  bytesreceiver 
)
static

Constructs a single request message containing normal packet.

Parameters
bytesreceiverThe packet to fill in with the final data. This will be cleared before data is added so you can reuse the same packet
acksThe acks to include in the packet header or null for no acks
requestThe request to format
guaranteeThis is just passed on to the result object
messagenumberThe unique message id for request
localpacketidThe unique id for the final network packet

Definition at line 18 of file WireData.cpp.

22 {
23  LEVIATHAN_ASSERT(request, "trying to generate packet data for empty request");
24 
25  bytesreceiver.clear();
26 
27  std::array<uint32_t, 1> messages;
28  // Requests don't use this marking mechanism
29  messages[0] = messagenumber;
30 
31  // We need a complete header with acks and stuff //
32  PrepareHeaderForPacket(localpacketid, &messages[0], 1, acks, bytesreceiver);
33 
34  // Request type //
35  bytesreceiver << NORMAL_REQUEST_TYPE;
36 
37  // Message number //
38  bytesreceiver << messagenumber;
39 
40  // Pack the message data in //
41  request->AddDataToPacket(bytesreceiver);
42 
43  return std::make_shared<SentRequest>(localpacketid, messagenumber, guarantee, request);
44 }
static DLLEXPORT void PrepareHeaderForPacket(uint32_t localpacketid, uint32_t *firstmessagenumber, size_t messagenumbercount, const NetworkAckField *acks, sf::Packet &tofill)
Definition: WireData.cpp:290
constexpr uint8_t NORMAL_REQUEST_TYPE
Definition: CommonNetwork.h:18

◆ FormatRequestBytes() [2/2]

DLLEXPORT void WireData::FormatRequestBytes ( const NetworkRequest request,
uint32_t  messagenumber,
uint32_t  localpacketid,
const NetworkAckField acks,
sf::Packet &  bytesreceiver 
)
static

Constructs a request without creating a SentRequest.

This is used for resends

Definition at line 46 of file WireData.cpp.

49 {
50  bytesreceiver.clear();
51 
52  std::array<uint32_t, 1> messages;
53  // Requests don't use this marking mechanism
54  messages[0] = messagenumber;
55 
56  // We need a complete header with acks and stuff //
57  PrepareHeaderForPacket(localpacketid, &messages[0], 1, acks, bytesreceiver);
58 
59  // Request type //
60  bytesreceiver << NORMAL_REQUEST_TYPE;
61 
62  // Message number //
63  bytesreceiver << messagenumber;
64 
65  // Pack the message data in //
66  request.AddDataToPacket(bytesreceiver);
67 }
void AddDataToPacket(sf::Packet &packet) const
static DLLEXPORT void PrepareHeaderForPacket(uint32_t localpacketid, uint32_t *firstmessagenumber, size_t messagenumbercount, const NetworkAckField *acks, sf::Packet &tofill)
Definition: WireData.cpp:290
constexpr uint8_t NORMAL_REQUEST_TYPE
Definition: CommonNetwork.h:18

◆ FormatResponseBytes() [1/2]

DLLEXPORT std::shared_ptr< SentResponse > WireData::FormatResponseBytes ( const std::shared_ptr< NetworkResponse > &  response,
RECEIVE_GUARANTEE  guarantee,
uint32_t  messagenumber,
uint32_t  localpacketid,
const NetworkAckField acks,
sf::Packet &  bytesreceiver 
)
static

Constructs a single response message.

See also
FormatRequestBytes

Definition at line 69 of file WireData.cpp.

73 {
74  LEVIATHAN_ASSERT(response, "trying to generate packet data for empty response");
75 
76  bytesreceiver.clear();
77 
78  std::array<uint32_t, 1> messages;
79  // Requests don't use this marking mechanism
80  messages[0] = messagenumber;
81 
82  // We need a complete header with acks and stuff //
83  PrepareHeaderForPacket(localpacketid, &messages[0], 1, acks, bytesreceiver);
84 
85  // Request type //
86  bytesreceiver << NORMAL_RESPONSE_TYPE;
87 
88  // Message number //
89  bytesreceiver << messagenumber;
90 
91  // Pack the message data in //
92  response->AddDataToPacket(bytesreceiver);
93 
94  return std::make_shared<SentResponse>(localpacketid, messagenumber, guarantee, response);
95 }
constexpr uint8_t NORMAL_RESPONSE_TYPE
Definition: CommonNetwork.h:16
static DLLEXPORT void PrepareHeaderForPacket(uint32_t localpacketid, uint32_t *firstmessagenumber, size_t messagenumbercount, const NetworkAckField *acks, sf::Packet &tofill)
Definition: WireData.cpp:290

◆ FormatResponseBytes() [2/2]

DLLEXPORT void WireData::FormatResponseBytes ( const NetworkResponse response,
uint32_t  messagenumber,
uint32_t  localpacketid,
const NetworkAckField acks,
sf::Packet &  bytesreceiver 
)
static

Constructs a single response message.

Note
This version is meant for unreliable responses as this doesn't return a SentResponse. This is also used for resends
See also
FormatRequestBytes

Definition at line 97 of file WireData.cpp.

100 {
101  bytesreceiver.clear();
102 
103  std::array<uint32_t, 1> messages;
104  // Requests don't use this marking mechanism
105  messages[0] = messagenumber;
106 
107  // We need a complete header with acks and stuff //
108  PrepareHeaderForPacket(localpacketid, &messages[0], 1, acks, bytesreceiver);
109 
110  // Request type //
111  bytesreceiver << NORMAL_RESPONSE_TYPE;
112 
113  // Message number //
114  bytesreceiver << messagenumber;
115 
116  // Pack the message data in //
117  response.AddDataToPacket(bytesreceiver);
118 }
void AddDataToPacket(sf::Packet &packet) const
constexpr uint8_t NORMAL_RESPONSE_TYPE
Definition: CommonNetwork.h:16
static DLLEXPORT void PrepareHeaderForPacket(uint32_t localpacketid, uint32_t *firstmessagenumber, size_t messagenumbercount, const NetworkAckField *acks, sf::Packet &tofill)
Definition: WireData.cpp:290

◆ FormatResponseBytesTracked()

DLLEXPORT std::shared_ptr< SentResponse > WireData::FormatResponseBytesTracked ( const NetworkResponse response,
uint32_t  messagenumber,
uint32_t  localpacketid,
const NetworkAckField acks,
sf::Packet &  bytesreceiver 
)
static

Constructs a single response message that can't be resent.

See also
FormatRequestBytes
Todo:
This has a lot of duplicated code with FormatResponseBytes

Definition at line 120 of file WireData.cpp.

123 {
124  bytesreceiver.clear();
125 
126  std::array<uint32_t, 1> messages;
127  // Requests don't use this marking mechanism
128  messages[0] = messagenumber;
129 
130  // We need a complete header with acks and stuff //
131  PrepareHeaderForPacket(localpacketid, &messages[0], 1, acks, bytesreceiver);
132 
133  // Request type //
134  bytesreceiver << NORMAL_RESPONSE_TYPE;
135 
136  // Message number //
137  bytesreceiver << messagenumber;
138 
139  // Pack the message data in //
140  response.AddDataToPacket(bytesreceiver);
141 
142  return std::make_shared<SentResponse>(localpacketid, messagenumber, response);
143 }
void AddDataToPacket(sf::Packet &packet) const
constexpr uint8_t NORMAL_RESPONSE_TYPE
Definition: CommonNetwork.h:16
static DLLEXPORT void PrepareHeaderForPacket(uint32_t localpacketid, uint32_t *firstmessagenumber, size_t messagenumbercount, const NetworkAckField *acks, sf::Packet &tofill)
Definition: WireData.cpp:290

◆ PrepareHeaderForPacket()

DLLEXPORT void WireData::PrepareHeaderForPacket ( uint32_t  localpacketid,
uint32_t *  firstmessagenumber,
size_t  messagenumbercount,
const NetworkAckField acks,
sf::Packet &  tofill 
)
staticprotected

Not meant to be called directly

used to format packet header fields

Parameters
firstmessagenumberPointer to first message number
messagenumbercountNumber of message numbers in firstmessagenumber

Definition at line 290 of file WireData.cpp.

293 {
294  LEVIATHAN_ASSERT(localpacketid > 0, "Trying to fill packet with packetid == 0");
295 
296  // See the doxygen page networkformat for the header format //
297 
298  // Type //
299  tofill << LEVIATHAN_NORMAL_PACKET;
300 
301  // PKT ID //
302  tofill << localpacketid;
303 
304  // Acks
305  FillHeaderAckData(acks, tofill);
306 
307 
308  // Message count
309  LEVIATHAN_ASSERT(messagenumbercount <= std::numeric_limits<uint8_t>::max(),
310  "too many messages in _PreparePacketHeader");
311 
312  tofill << static_cast<uint8_t>(messagenumbercount);
313 }
static DLLEXPORT void FillHeaderAckData(const NetworkAckField *acks, sf::Packet &tofill)
Definition: WireData.cpp:315
constexpr uint16_t LEVIATHAN_NORMAL_PACKET
Definition: CommonNetwork.h:12

The documentation for this class was generated from the following files: