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 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 34 of file WireData.h.

34  {
35 
36  Continue,
37  Error
38  };
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 144 of file WireData.cpp.

150 {
151 
152  // Header //
153  uint16_t leviathanMagic = 0;
154  packet >> leviathanMagic;
155 
156  if(!packet){
157 
158  Logger::Get()->Error("Received packet has invalid (header) format");
159  return;
160  }
161 
162  switch(leviathanMagic){
164  {
165  uint32_t packetNumber = 0;
166  packet >> packetNumber;
167 
168  if(!packet){
169 
170  Logger::Get()->Error("Received packet has invalid (packet number) format");
171  return;
172  }
173 
174  NetworkAckField otherreceivedpackages(packet);
175 
176  if(!packet){
177 
178  Logger::Get()->Error("Received packet has invalid format");
179  }
180 
181  // Messages //
182  uint8_t messageCount = 0;
183 
184  if(!(packet >> messageCount)){
185 
186  Logger::Get()->Error("Received packet has invalid format, missing Message Count");
187  }
188 
189  // Marks things as successfully sent //
190  if(ackcallback){
191 
192  auto callbackResult = ackcallback(otherreceivedpackages);
193 
194  if(callbackResult != DECODE_CALLBACK_RESULT::Continue){
195 
196  LOG_ERROR("Packet decode callback signaled error");
197  return;
198  }
199  }
200 
201  // Report the packet as received //
202  if(packetnumberreceived){
203 
204  auto callbackResult = packetnumberreceived(packetNumber);
205 
206  if(callbackResult != DECODE_CALLBACK_RESULT::Continue){
207 
208  LOG_ERROR("Packet decode callback signaled error");
209  return;
210  }
211  }
212 
213  for(int i = 0; i < messageCount; ++i){
214 
215  uint8_t messageType = 0;
216  packet >> messageType;
217 
218  uint32_t messageNumber = 0;
219  packet >> messageNumber;
220 
221  if(!packet){
222 
223  LOG_ERROR("Connection: received packet has an invalid message "
224  "(some may have been processed already)");
225  return;
226  }
227 
228  auto callbackResult = messagereceived(messageType, messageNumber, packet);
229 
230  if(callbackResult != DECODE_CALLBACK_RESULT::Continue){
231 
232  LOG_ERROR("Packet decode callback signaled error");
233  return;
234  }
235  }
236 
237  return;
238  }
240  {
241  uint8_t ackCount = 0;
242 
243  if(!(packet >> ackCount)){
244 
245  LOG_ERROR("Received packet has invalid (ack number) format");
246  return;
247  }
248 
249  for(uint8_t i = 0; i < ackCount; ++i){
250 
251  uint32_t ack = 0;
252 
253  if(!(packet >> ack)){
254 
255  LOG_ERROR("Received packet ended while acks were being unpacked, "
256  "some were applied");
257  return;
258  }
259 
260  if(singleack)
261  singleack(ack);
262  }
263 
264  return;
265  }
266  default:
267  {
268  LOG_ERROR("Received packet has an unknown type: " + Convert::ToString(leviathanMagic));
269  return;
270  }
271  }
272 }
#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 302 of file WireData.cpp.

304 {
305  if(!acks){
306 
307  // Set first to be zero which assumes that no data follows
308  tofill << uint32_t(0);
309 
310  } else {
311 
312  // Put into the packet //
313  acks->AddDataToPacket(tofill);
314  }
315 }
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 126 of file WireData.cpp.

128 {
129  bytesreceiver << LEVIATHAN_ACK_PACKET;
130 
131  LEVIATHAN_ASSERT(packetstoack.size() < std::numeric_limits<uint8_t>::max(),
132  "CreateAckOnlyPacket too many packetstoack provided, can't fit in uint8");
133 
134  const uint8_t count = static_cast<uint8_t>(packetstoack.size());
135 
136  bytesreceiver << count;
137 
138  for(uint8_t i = 0; i < count; ++i){
139 
140  bytesreceiver << packetstoack[i];
141  }
142 }
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,
33  acks, bytesreceiver);
34 
35  // Request type //
36  bytesreceiver << NORMAL_REQUEST_TYPE;
37 
38  // Message number //
39  bytesreceiver << messagenumber;
40 
41  // Pack the message data in //
42  request->AddDataToPacket(bytesreceiver);
43 
44  return std::make_shared<SentRequest>(localpacketid, messagenumber,
45  guarantee, request);
46 }
static DLLEXPORT void PrepareHeaderForPacket(uint32_t localpacketid, uint32_t *firstmessagenumber, size_t messagenumbercount, const NetworkAckField *acks, sf::Packet &tofill)
Definition: WireData.cpp:277
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 48 of file WireData.cpp.

51 {
52  bytesreceiver.clear();
53 
54  std::array<uint32_t, 1> messages;
55  // Requests don't use this marking mechanism
56  messages[0] = messagenumber;
57 
58  // We need a complete header with acks and stuff //
59  PrepareHeaderForPacket(localpacketid, &messages[0], 1,
60  acks, bytesreceiver);
61 
62  // Request type //
63  bytesreceiver << NORMAL_REQUEST_TYPE;
64 
65  // Message number //
66  bytesreceiver << messagenumber;
67 
68  // Pack the message data in //
69  request.AddDataToPacket(bytesreceiver);
70 }
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:277
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 72 of file WireData.cpp.

76 {
77  LEVIATHAN_ASSERT(response, "trying to generate packet data for empty response");
78 
79  bytesreceiver.clear();
80 
81  std::array<uint32_t, 1> messages;
82  // Requests don't use this marking mechanism
83  messages[0] = messagenumber;
84 
85  // We need a complete header with acks and stuff //
86  PrepareHeaderForPacket(localpacketid, &messages[0], 1,
87  acks, bytesreceiver);
88 
89  // Request type //
90  bytesreceiver << NORMAL_RESPONSE_TYPE;
91 
92  // Message number //
93  bytesreceiver << messagenumber;
94 
95  // Pack the message data in //
96  response->AddDataToPacket(bytesreceiver);
97 
98  return std::make_shared<SentResponse>(localpacketid, messagenumber,
99  guarantee, response);
100 }
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:277

◆ 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 102 of file WireData.cpp.

105 {
106  bytesreceiver.clear();
107 
108  std::array<uint32_t, 1> messages;
109  // Requests don't use this marking mechanism
110  messages[0] = messagenumber;
111 
112  // We need a complete header with acks and stuff //
113  PrepareHeaderForPacket(localpacketid, &messages[0], 1,
114  acks, bytesreceiver);
115 
116  // Request type //
117  bytesreceiver << NORMAL_RESPONSE_TYPE;
118 
119  // Message number //
120  bytesreceiver << messagenumber;
121 
122  // Pack the message data in //
123  response.AddDataToPacket(bytesreceiver);
124 }
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:277

◆ 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 277 of file WireData.cpp.

280 {
281  LEVIATHAN_ASSERT(localpacketid > 0, "Trying to fill packet with packetid == 0");
282 
283  // See the doxygen page networkformat for the header format //
284 
285  // Type //
286  tofill << LEVIATHAN_NORMAL_PACKET;
287 
288  // PKT ID //
289  tofill << localpacketid;
290 
291  // Acks
292  FillHeaderAckData(acks, tofill);
293 
294 
295  // Message count
296  LEVIATHAN_ASSERT(messagenumbercount <= std::numeric_limits<uint8_t>::max(),
297  "too many messages in _PreparePacketHeader");
298 
299  tofill << static_cast<uint8_t>(messagenumbercount);
300 }
static DLLEXPORT void FillHeaderAckData(const NetworkAckField *acks, sf::Packet &tofill)
Definition: WireData.cpp:302
constexpr uint16_t LEVIATHAN_NORMAL_PACKET
Definition: CommonNetwork.h:12

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