Leviathan  0.8.0.0
Leviathan game engine
Leviathan::Connection Class Reference

Class that handles a single connection to another instance. More...

#include <Connection.h>

Public Member Functions

DLLEXPORT Connection (const std::string &hostname)
 Creates a new connection to hostname. More...
 
DLLEXPORT Connection (const sf::IpAddress &targetaddress, unsigned short port)
 
DLLEXPORT ~Connection ()
 
DLLEXPORT bool Init (NetworkHandler *owninghandler)
 
DLLEXPORT void Release ()
 
bool IsValidForSend () const
 Returns true if this socket is valid for sending. More...
 
CONNECTION_STATE GetState () const
 
DLLEXPORT void SetRestrictionMode (CONNECTION_RESTRICTION type)
 Adds special restriction on the connection. More...
 
bool IsThisYours (const sf::IpAddress &sender, unsigned short sentport)
 Checks does the sender and port match our corresponding values. More...
 
DLLEXPORT void HandlePacket (sf::Packet &packet)
 Handles a packet. More...
 
DLLEXPORT bool IsTargetHostLocalhost ()
 
DLLEXPORT void UpdateListening ()
 Ticks this connection, times out sent packets. More...
 
DLLEXPORT std::shared_ptr< SentRequestSendPacketToConnection (const std::shared_ptr< NetworkRequest > &request, RECEIVE_GUARANTEE guarantee)
 
DLLEXPORT bool SendPacketToConnection (const NetworkResponse &response)
 Sends a response that doesn't need to be confirmed to be received. More...
 
DLLEXPORT std::shared_ptr< SentResponseSendPacketToConnectionWithTrackingWithoutGuarantee (const NetworkResponse &response)
 Sends a response that won't be resent but it will be tracked. More...
 
DLLEXPORT std::shared_ptr< SentResponseSendPacketToConnection (const std::shared_ptr< NetworkResponse > &response, RECEIVE_GUARANTEE guarantee)
 
DLLEXPORT void SendKeepAlivePacket ()
 Sends a keep alive packet if enough time has passed. More...
 
DLLEXPORT void SendCloseConnectionPacket ()
 Sends a packet that tells the other side to disconnect. More...
 
DLLEXPORT std::string GenerateFormatedAddressString () const
 Returns a nicely formated address string for this connection. More...
 
DLLEXPORT void CalculateNetworkPing (int packets, int allowedfails, std::function< void(int, int)> onsucceeded, std::function< void(PING_FAIL_REASON, int)> onfailed)
 Calculates the ping (round-trip time) on this connection. More...
 
DLLEXPORT void HandleRemoteAck (uint32_t localidconfirmedassent)
 Called when the other side sends us an ack. More...
 
DLLEXPORT std::vector< uint32_t > GetCurrentlySentAcks ()
 Basically a debug method (this is very slow) More...
 
std::string GetRawAddress () const
 
const auto & GetReceivedPackets () const
 Returns a reference to a list of received packets that haven't been acknowledged successfully to the other side. More...
 
const auto & GetPendingRequests () const
 Returns the pending requests. More...
 
const auto & GetResponsesNeedingConfirmation () const
 Returns responses that are tracked and haven't been acknowledged by the other side. More...
 

Protected Member Functions

DLLEXPORT void _HandleRequestPacket (sf::Packet &packet, uint32_t messagenumber, bool alreadyreceived)
 
DLLEXPORT void _HandleResponsePacket (sf::Packet &packet, bool alreadyreceived)
 
DLLEXPORT void SetPacketsReceivedIfNotSet (NetworkAckField &acks)
 Sets acks in a packet as properly sent in this. More...
 
DLLEXPORT void RemoveSucceededAcks (NetworkAckField &acks)
 Removes acks that were successful in the packet from target. More...
 
DLLEXPORT void _SendPacketToSocket (sf::Packet &actualpackettosend)
 Sends actualpackettosend to our Owner's socket. More...
 
DLLEXPORT void _FailPacketAcks (uint32_t packetid)
 Marks acks depending on packet to be lost. More...
 
bool _IsAlreadyReceived (uint32_t messagenumber)
 Returns true if we have already received message with number. More...
 
DLLEXPORT void _OnRestrictFail (uint16_t type)
 Closes the connection and reports an error. More...
 
DLLEXPORT bool _HandleInternalRequest (const std::shared_ptr< NetworkRequest > &request)
 
DLLEXPORT bool _HandleInternalResponse (const std::shared_ptr< NetworkResponse > &response)
 
void _Resend (SentRequest &toresend)
 Sends a message again. Preserves message number but changes packet id. More...
 
void _Resend (SentResponse &toresend)
 
template<class TSentType >
void _HandleTimeouts (int64_t timems, std::vector< std::shared_ptr< TSentType >> sentthing)
 
std::shared_ptr< SentRequest_GetPossibleRequestForResponse (const std::shared_ptr< NetworkResponse > &response)
 Returns a request matching the response's reference ID or NULL. More...
 
DLLEXPORT std::shared_ptr< NetworkAckField_GetAcksToSend (uint32_t localpacketid, bool autoaddtosent=true)
 Returns acks to be sent with a normal packet, or null if no acks to send. More...
 

Protected Attributes

CONNECTION_STATE State = CONNECTION_STATE::NothingReceived
 Marks a remote id as received. More...
 
NetworkHandlerOwner = nullptr
 Packets are handled by this object. More...
 
NetworkAckField::PacketReceiveStatus ReceivedRemotePackets
 Used to send acks for received remote packets. More...
 
uint32_t LastUsedLocalID = PACKET_NUMBERING_OFFSET
 
uint32_t LastUsedMessageNumber = 0
 Holds the number of last sent message (NetworkResponse or NetworkRequest object) More...
 
uint32_t LastConfirmedSent = 0
 Holds the id of last local sent packet that we have received an ack for. More...
 
CONNECTION_RESTRICTION RestrictType = CONNECTION_RESTRICTION::None
 
bool FrontAcks = false
 
uint8_t ExtraAckCount = 0
 
int64_t LastSentPacketTime = 0
 These are used to time out the connection. More...
 
int64_t LastReceivedPacketTime = 0
 
std::vector< std::shared_ptr< SentRequest > > PendingRequests
 Sent requests that are waiting for a response. More...
 
std::vector< std::shared_ptr< SentResponse > > ResponsesNeedingConfirmation
 Sent responses that need to be confirmed (or resent if they are lost) More...
 
std::vector< std::shared_ptr< SentAcks > > SentAckPackets
 
boost::circular_buffer< uint32_t > LastReceivedMessageNumbers {KEEP_IDS_FOR_DISCARD}
 
uint16_t TargetPortNumber
 The remote port. More...
 
std::string RawAddress
 
std::string HostName
 
sf::IpAddress TargetHost
 Resolved address of the remote. More...
 
bool AddressGot = false
 

Detailed Description

Class that handles a single connection to another instance.

This is not thread safe so only one thread at a time may handle this connection. this means that all worker threads must use Engine::Invoke to send packets

Note
this class does not use reference counting

Definition at line 105 of file Connection.h.

Constructor & Destructor Documentation

◆ Connection() [1/2]

DLLEXPORT Connection::Connection ( const std::string &  hostname)

Creates a new connection to hostname.

Todo:
Add a option to game configuration for default port

Definition at line 34 of file Connection.cpp.

34  :
35  RawAddress(hostname), HostName(hostname)
36 {
37  // We need to split the port number from the address //
38  StringIterator itr(hostname);
39 
40  auto result = itr.GetUntilNextCharacterOrAll<std::string>(':');
41 
42  HostName = *result;
43 
44  // We should be fine not skipping a letter //
45  result = itr.GetNextNumber<std::string>(DECIMALSEPARATORTYPE_NONE);
46 
47  if(!result) {
48 
50 
51  int tmpport = 0;
52 
53  if(!vars->GetValueAndConvertTo<int>("DefaultServerPort", tmpport)) {
54 
55  tmpport = 80;
56  }
57 
58  TargetPortNumber = (unsigned short)tmpport;
59 
60  LOG_WARNING("Connection: no port defined, using default, "
61  "hostname: " +
62  hostname + ":" + Convert::ToString(TargetPortNumber));
63  return;
64  }
65 
66  TargetPortNumber = Convert::StringTo<int>(*result.get());
67 }
#define GAMECONFIGURATION_GET_VARIABLEACCESS(x)
std::string HostName
Definition: Connection.h:359
#define LOG_WARNING(x)
Definition: Define.h:82
uint16_t TargetPortNumber
The remote port.
Definition: Connection.h:351
std::string RawAddress
Definition: Connection.h:355
Iterator class for getting parts of a string.
static std::string ToString(const T &val)
Definition: Convert.h:72

◆ Connection() [2/2]

DLLEXPORT Connection::Connection ( const sf::IpAddress &  targetaddress,
unsigned short  port 
)

Definition at line 69 of file Connection.cpp.

69  :
70  TargetPortNumber(port), TargetHost(targetaddress), AddressGot(true)
71 {
73 }
sf::IpAddress TargetHost
Resolved address of the remote.
Definition: Connection.h:362
uint16_t TargetPortNumber
The remote port.
Definition: Connection.h:351
std::string RawAddress
Definition: Connection.h:355
DLLEXPORT std::string GenerateFormatedAddressString() const
Returns a nicely formated address string for this connection.

◆ ~Connection()

DLLEXPORT Connection::~Connection ( )

Definition at line 75 of file Connection.cpp.

75 {}

Member Function Documentation

◆ _FailPacketAcks()

DLLEXPORT void Leviathan::Connection::_FailPacketAcks ( uint32_t  packetid)
protected

Marks acks depending on packet to be lost.

Definition at line 1390 of file Connection.cpp.

1391 {
1392  for(auto iter = SentAckPackets.begin(); iter != SentAckPackets.end(); ++iter) {
1393 
1394  if((*iter)->InsidePacket == packetid) {
1395 
1396  SentAckPackets.erase(iter);
1397  return;
1398  }
1399  }
1400 }
std::vector< std::shared_ptr< SentAcks > > SentAckPackets
Definition: Connection.h:344

◆ _GetAcksToSend()

DLLEXPORT std::shared_ptr< Leviathan::NetworkAckField > Leviathan::Connection::_GetAcksToSend ( uint32_t  localpacketid,
bool  autoaddtosent = true 
)
protected

Returns acks to be sent with a normal packet, or null if no acks to send.

Parameters
autoaddtosentIf true the generated ack field is added to SentAckPackets

Definition at line 1045 of file Connection.cpp.

1047 {
1048  if(ReceivedRemotePackets.empty()) {
1049 
1050  return nullptr;
1051 
1052  } else {
1053 
1054  // First we need to determine which received packet to use as first value //
1055  FrontAcks = !FrontAcks;
1056 
1057  uint32_t firstselected = 0;
1058  uint32_t last = 0;
1059  uint8_t count = DEFAULT_ACKCOUNT;
1060 
1061  if(FrontAcks) {
1062 
1063  for(auto iter = ReceivedRemotePackets.begin(); iter != ReceivedRemotePackets.end();
1064  ++iter) {
1065  if(iter->second == RECEIVED_STATE::StateReceived) {
1066 
1067  firstselected = iter->first;
1068  break;
1069  }
1070  }
1071 
1072  } else {
1073 
1074  int backoffset = 0;
1075 
1076  for(auto iter = ReceivedRemotePackets.rbegin();
1077  iter != ReceivedRemotePackets.rend(); ++iter) {
1078  if(iter->second == RECEIVED_STATE::StateReceived) {
1079 
1080  if(backoffset >= DEFAULT_ACKCOUNT) {
1081 
1082  break;
1083  }
1084 
1085  ++backoffset;
1086  firstselected = iter->first;
1087  }
1088 
1089  ++backoffset;
1090  }
1091  }
1092 
1093  if(firstselected != 0 && count != 0) {
1094 
1095  // Create the ack field //
1096  auto tmpacks = std::make_shared<SentAcks>(
1097  localpacketid, std::make_shared<NetworkAckField>(
1098  firstselected, count, ReceivedRemotePackets));
1099 
1100  // Still skip if there is nothing in it //
1101  if(tmpacks->AcksInThePacket->Acks.size() < 1) {
1102  // It was still empty
1103  LOG_WARNING("Generated NetworkAckField was empty even though "
1104  "count wasn't zero");
1105  return nullptr;
1106  }
1107 
1108  if(autoaddtosent)
1109  SentAckPackets.push_back(tmpacks);
1110 
1111  return tmpacks->AcksInThePacket;
1112 
1113  } else {
1114 
1115  // None were found //
1116  return nullptr;
1117  }
1118  }
1119 }
#define LOG_WARNING(x)
Definition: Define.h:82
unsigned char uint8_t
Definition: core.h:38
std::vector< std::shared_ptr< SentAcks > > SentAckPackets
Definition: Connection.h:344
Packet is received but no acks have been sent.
unsigned int uint32_t
Definition: core.h:40
NetworkAckField::PacketReceiveStatus ReceivedRemotePackets
Used to send acks for received remote packets.
Definition: Connection.h:301

◆ _GetPossibleRequestForResponse()

std::shared_ptr< SentRequest > Connection::_GetPossibleRequestForResponse ( const std::shared_ptr< NetworkResponse > &  response)
protected

Returns a request matching the response's reference ID or NULL.

Definition at line 1122 of file Connection.cpp.

1124 {
1125  // Return if it doesn't have a proper matching expected response id //
1126  const auto lookingforid = response->GetResponseID();
1127 
1128  if(lookingforid == 0)
1129  return nullptr;
1130 
1131  for(auto& packet : PendingRequests) {
1132 
1133  if(packet->MessageNumber == lookingforid) {
1134 
1135  // Found matching object //
1136  return packet;
1137  }
1138  }
1139 
1140  // Nothing found //
1141  return nullptr;
1142 }
std::vector< std::shared_ptr< SentRequest > > PendingRequests
Sent requests that are waiting for a response.
Definition: Connection.h:336

◆ _HandleInternalRequest()

DLLEXPORT bool Leviathan::Connection::_HandleInternalRequest ( const std::shared_ptr< NetworkRequest > &  request)
protected

Definition at line 822 of file Connection.cpp.

824 {
825  switch(request->GetType()) {
827 
828  SendPacketToConnection(std::make_shared<ResponseConnect>(request->GetIDForResponse()),
830 
832 
834 #ifdef SPAM_ME_SOME_PACKETS
836  "received: request connect, moving to state Connected with " +
838 #endif
839  // Client will do security setup here. This is duplicated from the response state
840  // move as the server and client can do a simultaneous open //
841  // TODO: figure out how master server connections should work
843 
845  std::make_shared<RequestSecurity>(CONNECTION_ENCRYPTION::None),
847  }
848  }
849 
850  return true;
851  }
853  // CONNECTION_STATE::Initial is allowed here because the client might send a security
854  // request before sending us a response to our connect request
856 
857  return true;
858  }
859 
860  // Security has been set up for this connection //
861  SendPacketToConnection(std::make_shared<ResponseSecurity>(
862  request->GetIDForResponse(), CONNECTION_ENCRYPTION::None),
864 
866 
867 #ifdef SPAM_ME_SOME_PACKETS
868  LOG_WRITE(SPAM_PREFIX + "received: request security, moving to state Secured with " +
870 #endif
871 
872  return true;
873  }
875  // Client is not allowed to respond to this //
877 
878  LOG_ERROR("Connection: Client received NETWORK_REQUEST_TYPE::Authenticate");
879  return true;
880  }
881 
882  // State must be security
884 
885  return true;
886  }
887 
888  // Connection is now authenticated //
890 
891 #ifdef SPAM_ME_SOME_PACKETS
893  "received: request authenticate, moving to state Authenticated with " +
895 #endif
896 
897  LOG_INFO("Connection: Authenticate request accepted from: " +
899 
900  int32_t ConnectedPlayerID = 0;
901  uint64_t token = 0;
902 
903  SendPacketToConnection(std::make_shared<ResponseAuthenticate>(
904  request->GetIDForResponse(), ConnectedPlayerID, token),
906 
907  return true;
908  }
909  default: break;
910  }
911 
912  // Eat up all the packets if not properly opened yet
914 
915  LOG_WARNING("Connection: not yet properly open, ignoring packet (request type: " +
916  request->GetTypeStr() + ") from: " + GenerateFormatedAddressString());
917  return true;
918  }
919 
920  // Did nothing, normal handling continues //
921  return false;
922 }
Only one side of the connection can send this request, usually the client.
DLLEXPORT std::shared_ptr< SentRequest > SendPacketToConnection(const std::shared_ptr< NetworkRequest > &request, RECEIVE_GUARANTEE guarantee)
Definition: Connection.cpp:139
#define LOG_INFO(x)
Definition: Define.h:81
#define LOG_ERROR(x)
Definition: Define.h:83
CONNECTION_STATE State
Marks a remote id as received.
Definition: Connection.h:295
#define LOG_WARNING(x)
Definition: Define.h:82
#define LOG_WRITE(x)
Definition: Define.h:84
#define SPAM_PREFIX
Makes the program spam a ton of debug info about packets //.
Definition: Connection.cpp:29
Packet will get a single resend.
DLLEXPORT std::string GenerateFormatedAddressString() const
Returns a nicely formated address string for this connection.
Moves to this state once handshake is complete.
NETWORKED_TYPE GetNetworkType() const
Gets the type of network this program uses.
NetworkHandler * Owner
Packets are handled by this object.
Definition: Connection.h:298
Begins the handshake with version number check.

◆ _HandleInternalResponse()

DLLEXPORT bool Leviathan::Connection::_HandleInternalResponse ( const std::shared_ptr< NetworkResponse > &  response)
protected

Definition at line 924 of file Connection.cpp.

926 {
927  switch(response->GetType()) {
929  // Forced disconnect //
931 
932 #ifdef SPAM_ME_SOME_PACKETS
933  LOG_WRITE(SPAM_PREFIX + "received: response close, moving to state Closed from " +
935 #endif
936 
937  // Release will be called by NetworkHandler which sends a close connection packet
938  return true;
939  }
941 
942  if(static_cast<ResponseConnect*>(response.get())->CheckValue != 42) {
943 
944  LOG_ERROR(
945  "Connection: received ResponseConnect with invalid check value, ignoring it");
946  return true;
947  }
948 
949  // The first packet of this type that is in response to our initial request
950  // moves this connection to Connected on our side
952 
954 
955 #ifdef SPAM_ME_SOME_PACKETS
957  "received: response Connect, moving to state Connected with " +
959 #endif
960 
961  // Client will do security setup here //
962  // TODO: figure out how master server connections should work
964 
966  std::make_shared<RequestSecurity>(CONNECTION_ENCRYPTION::None),
968  }
969  }
970 
971  return true;
972  }
975 
976  return true;
977  }
978 
979  // Verify security type is what we wanted //
980  auto* securityresponse = static_cast<ResponseSecurity*>(response.get());
981 
982  if(securityresponse->SecureType != CONNECTION_ENCRYPTION::None) {
983 
984  LOG_ERROR("Connection: mismatch security, disconnecting");
986  return true;
987  }
988 
990 
991 #ifdef SPAM_ME_SOME_PACKETS
992  LOG_WRITE(SPAM_PREFIX + "received: response Security, moving to state Secured with " +
994 #endif
995 
996  // TODO: send an empty authentication request if this is a master server connection
998 
1000  std::make_shared<RequestAuthenticate>("player"), RECEIVE_GUARANTEE::Critical);
1001  }
1002 
1003  return true;
1004  }
1007 
1008  return true;
1009  }
1010 
1011  // Connection is now good to go //
1012 
1013  auto* authresponse = static_cast<ResponseAuthenticate*>(response.get());
1014 
1015  // authresponse->UserID;
1016 
1018 
1019 #ifdef SPAM_ME_SOME_PACKETS
1021  "received: response Authenticate, moving to state Authenticated with " +
1023 #endif
1024 
1025  LOG_INFO(
1026  "Connection: Authenticate succeeded from: " + GenerateFormatedAddressString());
1027 
1028  return true;
1029  }
1030  default: break;
1031  }
1032 
1033  // Eat up all the packets if not properly opened yet
1035 
1036  LOG_WARNING("Connection: not yet properly open, ignoring packet (response type: " +
1037  response->GetTypeStr() + ") from: " + GenerateFormatedAddressString());
1038  return true;
1039  }
1040 
1041  // Did nothing, normal handling continues //
1042  return false;
1043 }
Only one side of the connection can send this request, usually the client.
DLLEXPORT std::shared_ptr< SentRequest > SendPacketToConnection(const std::shared_ptr< NetworkRequest > &request, RECEIVE_GUARANTEE guarantee)
Definition: Connection.cpp:139
#define LOG_INFO(x)
Definition: Define.h:81
#define LOG_ERROR(x)
Definition: Define.h:83
CONNECTION_STATE State
Marks a remote id as received.
Definition: Connection.h:295
DLLEXPORT void SendCloseConnectionPacket()
Sends a packet that tells the other side to disconnect.
Definition: Connection.cpp:260
#define LOG_WARNING(x)
Definition: Define.h:82
#define LOG_WRITE(x)
Definition: Define.h:84
#define SPAM_PREFIX
Makes the program spam a ton of debug info about packets //.
Definition: Connection.cpp:29
DLLEXPORT std::string GenerateFormatedAddressString() const
Returns a nicely formated address string for this connection.
Moves to this state once handshake is complete.
NETWORKED_TYPE GetNetworkType() const
Gets the type of network this program uses.
NetworkHandler * Owner
Packets are handled by this object.
Definition: Connection.h:298
Begins the handshake with version number check.
Sent in response to a NETWORK_REQUEST_TYPE::Connect.

◆ _HandleRequestPacket()

DLLEXPORT void Leviathan::Connection::_HandleRequestPacket ( sf::Packet &  packet,
uint32_t  messagenumber,
bool  alreadyreceived 
)
protected
Parameters
alreadyreceivedIf true only the message is unpacked and discarded

Definition at line 757 of file Connection.cpp.

759 {
760  // Generate a request object and make the interface handle it //
761  std::shared_ptr<NetworkRequest> request;
762  try {
763 
764  request = NetworkRequest::LoadFromPacket(packet, messagenumber);
765 
766  if(!request)
767  throw InvalidArgument("request is null");
768 
769  } catch(const InvalidArgument& e) {
770 
771  LOG_ERROR("Connection: received an invalid request packet, exception: ");
772  e.PrintToLog();
773  return;
774  }
775 
776  if(alreadyreceived) {
777 
778  return;
779  }
780 
781 #ifdef SPAM_ME_SOME_PACKETS
782  LOG_WRITE(SPAM_PREFIX + "Request received: type " + request->GetTypeStr() +
783  " (id for resp: " + std::to_string(request->GetIDForResponse()) + ") from " +
785 #endif
786 
787  if(_HandleInternalRequest(request))
788  return;
789 
791 
792  // Restrict mode checking //
793 
794  // We can possibly drop the connection or perform other extra tasks //
796  // Check type //
798  Owner->GetConnection(this), request)) {
799  _OnRestrictFail(static_cast<uint16_t>(request->GetType()));
800  return;
801  }
802 
803  // Successfully opened, connection should now be safe as a
804  // general purpose connection
806  return;
807  }
808  }
809 
810  try {
811 
812  Owner->GetInterface()->HandleRequestPacket(request, *this);
813 
814  } catch(const InvalidArgument& e) {
815  // We couldn't handle this packet //
816  Logger::Get()->Error("Connection: couldn't handle request packet! :");
817  e.PrintToLog();
818  }
819 }
DLLEXPORT bool CanOpenNewConnection(std::shared_ptr< Connection > connection, std::shared_ptr< NetworkRequest > request)
Returns true if request from connection is allowed to open a remote console session.
#define LOG_ERROR(x)
Definition: Define.h:83
static DLLEXPORT std::shared_ptr< NetworkRequest > LoadFromPacket(sf::Packet &packet, uint32_t messagenumber)
CONNECTION_RESTRICTION RestrictType
Definition: Connection.h:319
NetworkInterface * GetInterface()
Returns interface object. Type depends on AppType.
DLLEXPORT bool _HandleInternalRequest(const std::shared_ptr< NetworkRequest > &request)
Definition: Connection.cpp:822
#define LOG_WRITE(x)
Definition: Define.h:84
#define SPAM_PREFIX
Makes the program spam a ton of debug info about packets //.
Definition: Connection.cpp:29
DLLEXPORT std::string GenerateFormatedAddressString() const
Returns a nicely formated address string for this connection.
RemoteConsole * GetRemoteConsole()
Definition: Engine.h:222
static DLLEXPORT Logger * Get()
Definition: Logger.cpp:106
DLLEXPORT std::shared_ptr< Connection > GetConnection(Connection *directptr) const
Returns a persistent pointer to a connection.
DLLEXPORT void _OnRestrictFail(uint16_t type)
Closes the connection and reports an error.
NetworkHandler * Owner
Packets are handled by this object.
Definition: Connection.h:298
static DLLEXPORT Engine * Get()
Definition: Engine.cpp:84
DLLEXPORT void Error(const std::string &data) override
Definition: Logger.cpp:177
virtual DLLEXPORT void HandleRequestPacket(const std::shared_ptr< NetworkRequest > &request, Connection &connection)=0
Called by ConnectionInfo to handle incoming packets.

◆ _HandleResponsePacket()

DLLEXPORT void Leviathan::Connection::_HandleResponsePacket ( sf::Packet &  packet,
bool  alreadyreceived 
)
protected
Parameters
alreadyreceivedIf true only the message is unpacked and discarded

Definition at line 641 of file Connection.cpp.

643 {
644  // Generate a response and pass to the interface //
645  std::shared_ptr<NetworkResponse> response;
646  try {
647 
648  response = NetworkResponse::LoadFromPacket(packet);
649 
650  if(!response)
651  throw InvalidArgument("response is null");
652 
653  } catch(const InvalidArgument& e) {
654 
655  LOG_ERROR("Connection: received an invalid response packet, exception: ");
656  e.PrintToLog();
657  return;
658  }
659 
660  if(alreadyreceived) {
661 
662  return;
663  }
664 
665  // The response might have a corresponding request //
666  auto possiblerequest = _GetPossibleRequestForResponse(response);
667 
668  // Add the response to the request //
669  if(possiblerequest) {
670  possiblerequest->GotResponse = response;
671 
672  bool found = false;
673 
674  // Finalizing it must always happen
675  for(auto iter = PendingRequests.begin(); iter != PendingRequests.end(); ++iter) {
676 
677  if((*iter).get() == possiblerequest.get()) {
678 
679 #ifdef SPAM_ME_SOME_PACKETS
680  LOG_WRITE(SPAM_PREFIX + "Response received: request type " +
681  possiblerequest->SentRequestData->GetTypeStr() +
682  " (id: " + std::to_string(response->GetResponseID()) + ") from " +
684 #endif
685 
686  // Notify that the request is done /
687  possiblerequest->OnFinalized(true);
688  PendingRequests.erase(iter);
689  found = true;
690  break;
691  }
692  }
693 
694  if(!found) {
695 #ifdef SPAM_ME_SOME_PACKETS
697  "Response received (but wasn't found in pending): request type " +
698  possiblerequest->SentRequestData->GetTypeStr() +
699  " (id: " + std::to_string(response->GetResponseID()) + ") from " +
701 #endif
702  possiblerequest->OnFinalized(true);
703  }
704  } else {
705 
706  if(response->GetResponseID() != 0) {
707  LOG_WARNING("Connection: received response (" + response->GetTypeStr() +
708  ") that is a response to message number: " +
709  std::to_string(response->GetResponseID()) +
710  ", but no request was found with that number");
711  }
712  }
713 
714 #ifdef SPAM_ME_SOME_PACKETS
715  if(!possiblerequest) {
716  LOG_WRITE(SPAM_PREFIX + "Response only received: response type " +
717  response->GetTypeStr() +
718  " (id: " + std::to_string(response->GetResponseID()) + ") from " +
720  }
721 #endif
722 
723  if(_HandleInternalResponse(response))
724  return;
725 
727 
728  // Restrict mode checking //
729 
730  // Not allowed //
731  _OnRestrictFail(static_cast<uint16_t>(response->GetType()));
732  return;
733  }
734 
735  // See if interface wants to drop it //
736  if(!Owner->GetInterface()->PreHandleResponse(response, possiblerequest.get(), *this)) {
737 
738  LOG_WARNING("Connection: dropping packet due to interface not accepting response");
739  return;
740  }
741 
742  if(!possiblerequest) {
743 
744  // Just discard if it is an empty response //
745  if(response->GetType() == NETWORK_RESPONSE_TYPE::None)
746  return;
747 
748  // Handle the response only packet //
749  Owner->GetInterface()->HandleResponseOnlyPacket(response, *this);
750 
751  } else {
752 
753  // It was already finalized so there is nothing to do here
754  }
755 }
std::vector< std::shared_ptr< SentRequest > > PendingRequests
Sent requests that are waiting for a response.
Definition: Connection.h:336
#define LOG_ERROR(x)
Definition: Define.h:83
std::shared_ptr< SentRequest > _GetPossibleRequestForResponse(const std::shared_ptr< NetworkResponse > &response)
Returns a request matching the response&#39;s reference ID or NULL.
virtual DLLEXPORT bool PreHandleResponse(const std::shared_ptr< NetworkResponse > &response, SentNetworkThing *originalrequest, Connection &connection)
Called by ConnectionInfo to verify that a response is good.
CONNECTION_RESTRICTION RestrictType
Definition: Connection.h:319
NetworkInterface * GetInterface()
Returns interface object. Type depends on AppType.
#define LOG_WARNING(x)
Definition: Define.h:82
static DLLEXPORT std::shared_ptr< NetworkResponse > LoadFromPacket(sf::Packet &packet)
virtual DLLEXPORT void HandleResponseOnlyPacket(const std::shared_ptr< NetworkResponse > &message, Connection &connection)=0
Called by ConnectionInfo when it receives a response without a matching request object.
#define LOG_WRITE(x)
Definition: Define.h:84
#define SPAM_PREFIX
Makes the program spam a ton of debug info about packets //.
Definition: Connection.cpp:29
Empty response, used for keeping alive/nothing.
DLLEXPORT std::string GenerateFormatedAddressString() const
Returns a nicely formated address string for this connection.
DLLEXPORT void _OnRestrictFail(uint16_t type)
Closes the connection and reports an error.
NetworkHandler * Owner
Packets are handled by this object.
Definition: Connection.h:298
DLLEXPORT bool _HandleInternalResponse(const std::shared_ptr< NetworkResponse > &response)
Definition: Connection.cpp:924

◆ _HandleTimeouts()

template<class TSentType >
void Leviathan::Connection::_HandleTimeouts ( int64_t  timems,
std::vector< std::shared_ptr< TSentType >>  sentthing 
)
protected

Definition at line 371 of file Connection.cpp.

373 {
374  for(auto iter = sentthing.begin(); iter != sentthing.end();) {
375 
376  // Ignore already finalized things
377  if((*iter)->IsDone != SentNetworkThing::DONE_STATUS::WAITING) {
378 
379  // This is triggered a ton...
380  // TODO: figure that out
381  // LOG_ERROR("Connection: sent things contained a finalized packet, removed it");
382  iter = sentthing.erase(iter);
383  continue;
384  }
385 
386  // Second timeout //
387  if((timems - (*iter)->RequestStartTime > PACKET_LOST_AFTER_MILLISECONDS) ||
388  (LastConfirmedSent > (*iter)->PacketNumber + PACKET_LOST_AFTER_RECEIVED_NEWER)) {
389 
390 #ifdef SPAM_ME_SOME_PACKETS
391  LOG_WRITE(SPAM_PREFIX + "Timeout for " + (*iter)->GetTypeStr() + " (" +
392  typeid(TSentType).name() + " to " + GenerateFormatedAddressString() +
393  " message number: " + std::to_string((*iter)->MessageNumber) +
394  " was sent in packet: " + std::to_string((*iter)->PacketNumber));
395 #endif
396 
397  // The current attempt is lost //
398  if((*iter)->Resend == RECEIVE_GUARANTEE::ResendOnce) {
399 
400  if(++(*iter)->AttemptNumber <= 2) {
401 
402  // Resend //
403  _Resend(**iter);
404  ++iter;
405  continue;
406  }
407  } else if((*iter)->Resend == RECEIVE_GUARANTEE::Critical) {
408 
409  // If a critical one fails the connection must be closed //
410  if(++(*iter)->AttemptNumber > CRITICAL_PACKET_MAX_TRIES) {
411 
412  // LOG_ERROR("Connection: Lost critical packet too many times, "
413  // "closing connection to: " +
414  // GenerateFormatedAddressString());
415 
416  LOG_ERROR("Connection: Lost critical packet too many times, "
417  "not closing to get this to work somewhat: " +
419 
420  LOG_INFO(
421  "Connection: critical message was type: " + (*iter)->GetTypeStr() +
422  " number: " + std::to_string((*iter)->MessageNumber) +
423  " in packet: " + std::to_string((*iter)->PacketNumber));
424 
425  (*iter)->OnFinalized(false);
426  iter = sentthing.erase(iter);
427  // TODO: re-enable when there is time to debug this
428  // SendCloseConnectionPacket();
429  return;
430  }
431 
432  // Resend //
433  _Resend(**iter);
434  ++iter;
435  continue;
436  }
437 
438  // Shouldn't be sent anymore //
439 
440  // Failed //
441  (*iter)->OnFinalized(false);
442 
443 #ifdef SPAM_ME_SOME_PACKETS
444  LOG_WRITE(SPAM_PREFIX + "Packet failed, type: " + (*iter)->GetTypeStr() + " to " +
446  " message number: " + std::to_string((*iter)->MessageNumber) +
447  " was sent in packet: " + std::to_string((*iter)->PacketNumber));
448 #endif
449 
450  _FailPacketAcks((*iter)->PacketNumber);
451  iter = sentthing.erase(iter);
452 
453  } else {
454 
455  ++iter;
456  }
457  }
458 }
#define LOG_INFO(x)
Definition: Define.h:81
#define LOG_ERROR(x)
Definition: Define.h:83
uint32_t LastConfirmedSent
Holds the id of last local sent packet that we have received an ack for.
Definition: Connection.h:314
constexpr auto CRITICAL_PACKET_MAX_TRIES
Definition: Define.h:40
DLLEXPORT void _FailPacketAcks(uint32_t packetid)
Marks acks depending on packet to be lost.
constexpr auto PACKET_LOST_AFTER_RECEIVED_NEWER
Definition: Define.h:38
#define LOG_WRITE(x)
Definition: Define.h:84
#define SPAM_PREFIX
Makes the program spam a ton of debug info about packets //.
Definition: Connection.cpp:29
Packet will get a single resend.
DLLEXPORT std::string GenerateFormatedAddressString() const
Returns a nicely formated address string for this connection.
void _Resend(SentRequest &toresend)
Sends a message again. Preserves message number but changes packet id.
Definition: Connection.cpp:271
constexpr auto PACKET_LOST_AFTER_MILLISECONDS
Definition: Define.h:36

◆ _IsAlreadyReceived()

bool Connection::_IsAlreadyReceived ( uint32_t  messagenumber)
protected

Returns true if we have already received message with number.

Note
Will also store it for future lookups

Definition at line 1356 of file Connection.cpp.

1357 {
1358  // If it is more than KEEP_IDS_FOR_DISCARD older than the first packet in
1359  // LastReceivedMessageNumbers
1360  if(!LastReceivedMessageNumbers.empty()) {
1361 
1362  if(messagenumber + (KEEP_IDS_FOR_DISCARD * 2) < LastReceivedMessageNumbers.front()) {
1363 
1364  LOG_WARNING("Connection: received very old message, ignoring it, message id: " +
1365  std::to_string(messagenumber));
1366  return true;
1367  }
1368  }
1369 
1370  // It is moved through in reverse to quickly return matches,
1371  // but receiving the same packet twice isn't that common
1372  for(auto id : LastReceivedMessageNumbers) {
1373 
1374  if(id == messagenumber) {
1375 
1376  // Found a match, this is an already received packet //
1377  return true;
1378  }
1379  }
1380 
1381  // Not found, add for future searches //
1382  LastReceivedMessageNumbers.push_back(messagenumber);
1383 
1384  // It wasn't there //
1385  return false;
1386 }
#define LOG_WARNING(x)
Definition: Define.h:82
boost::circular_buffer< uint32_t > LastReceivedMessageNumbers
Definition: Connection.h:348

◆ _OnRestrictFail()

DLLEXPORT void Leviathan::Connection::_OnRestrictFail ( uint16_t  type)
protected

Closes the connection and reports an error.

Definition at line 1402 of file Connection.cpp.

1403 {
1404  LOG_ERROR("Connection: received a non-valid packet "
1405  "in restrict mode(" +
1406  Convert::ToString(static_cast<int>(RestrictType)) +
1407  ") type: " + Convert::ToString(static_cast<int>(type)) +
1408  " from: " + GenerateFormatedAddressString());
1409 
1411 }
#define LOG_ERROR(x)
Definition: Define.h:83
CONNECTION_RESTRICTION RestrictType
Definition: Connection.h:319
DLLEXPORT void SendCloseConnectionPacket()
Sends a packet that tells the other side to disconnect.
Definition: Connection.cpp:260
DLLEXPORT std::string GenerateFormatedAddressString() const
Returns a nicely formated address string for this connection.
static std::string ToString(const T &val)
Definition: Convert.h:72

◆ _Resend() [1/2]

void Connection::_Resend ( SentRequest toresend)
protected

Sends a message again. Preserves message number but changes packet id.

Todo:
Create Resend method that pools together many failed messages

Definition at line 271 of file Connection.cpp.

272 {
273 #ifdef SPAM_ME_SOME_PACKETS
274  LOG_WRITE(SPAM_PREFIX + "Resending: request " + toresend.SentRequestData->GetTypeStr() +
275  " (id: " + std::to_string(toresend.SentRequestData->GetIDForResponse()) +
276  ", message number: " + std::to_string(toresend.MessageNumber) +
277  ") in packet: " + std::to_string(LastUsedLocalID + 1) +
278  " attempt number: " + std::to_string(toresend.AttemptNumber) + " to " +
280 #endif
281 
282  // Find acks to send //
283  const auto fullpacketid = ++LastUsedLocalID;
284  auto acks = _GetAcksToSend(fullpacketid);
285 
286  // Resend it
288  fullpacketid, acks.get(), StoredWireData);
289 
290  _SendPacketToSocket(StoredWireData);
291 
292  toresend.ResetStartTime();
293 
294  // Increase attempt number
295  ++toresend.AttemptNumber;
296 }
DLLEXPORT std::shared_ptr< NetworkAckField > _GetAcksToSend(uint32_t localpacketid, bool autoaddtosent=true)
Returns acks to be sent with a normal packet, or null if no acks to send.
uint32_t LastUsedLocalID
Definition: Connection.h:308
DLLEXPORT void ResetStartTime()
Resets the start time.
DLLEXPORT void _SendPacketToSocket(sf::Packet &actualpackettosend)
Sends actualpackettosend to our Owner&#39;s socket.
#define LOG_WRITE(x)
Definition: Define.h:84
std::shared_ptr< NetworkRequest > SentRequestData
#define SPAM_PREFIX
Makes the program spam a ton of debug info about packets //.
Definition: Connection.cpp:29
DLLEXPORT std::string GenerateFormatedAddressString() const
Returns a nicely formated address string for this connection.
static DLLEXPORT std::shared_ptr< SentRequest > FormatRequestBytes(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.
Definition: WireData.cpp:18

◆ _Resend() [2/2]

void Connection::_Resend ( SentResponse toresend)
protected

Definition at line 298 of file Connection.cpp.

299 {
300 #ifdef SPAM_ME_SOME_PACKETS
301  LOG_WRITE(SPAM_PREFIX + "Resending: response " + toresend.SentResponseData->GetTypeStr() +
302  " (to: " + std::to_string(toresend.SentResponseData->GetResponseID()) +
303  ", message number: " + std::to_string(toresend.MessageNumber) +
304  ") in packet: " + std::to_string(LastUsedLocalID + 1) +
305  " attempt number: " + std::to_string(toresend.AttemptNumber) + " to " +
307 #endif
308 
309  // Find acks to send //
310  const auto fullpacketid = ++LastUsedLocalID;
311  auto acks = _GetAcksToSend(fullpacketid);
312 
313  // Resend it
315  fullpacketid, acks.get(), StoredWireData);
316 
317  _SendPacketToSocket(StoredWireData);
318 
319  toresend.ResetStartTime();
320 
321  // Increase attempt number
322  ++toresend.AttemptNumber;
323 }
std::shared_ptr< NetworkResponse > SentResponseData
DLLEXPORT std::shared_ptr< NetworkAckField > _GetAcksToSend(uint32_t localpacketid, bool autoaddtosent=true)
Returns acks to be sent with a normal packet, or null if no acks to send.
uint32_t LastUsedLocalID
Definition: Connection.h:308
DLLEXPORT void ResetStartTime()
Resets the start time.
DLLEXPORT void _SendPacketToSocket(sf::Packet &actualpackettosend)
Sends actualpackettosend to our Owner&#39;s socket.
#define LOG_WRITE(x)
Definition: Define.h:84
#define SPAM_PREFIX
Makes the program spam a ton of debug info about packets //.
Definition: Connection.cpp:29
DLLEXPORT std::string GenerateFormatedAddressString() const
Returns a nicely formated address string for this connection.
static DLLEXPORT std::shared_ptr< SentResponse > FormatResponseBytes(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.
Definition: WireData.cpp:69

◆ _SendPacketToSocket()

DLLEXPORT void Leviathan::Connection::_SendPacketToSocket ( sf::Packet &  actualpackettosend)
protected

Sends actualpackettosend to our Owner's socket.

Definition at line 1337 of file Connection.cpp.

1338 {
1339  LEVIATHAN_ASSERT(Owner, "Connection no owner");
1340 
1341  // We have now sent a packet //
1343 
1344 #ifdef OUTPUT_PACKET_BITS
1345 
1346  LOG_WRITE("Packet bits: \n" +
1347  Convert::HexDump(reinterpret_cast<const uint8_t*>(actualpackettosend.getData()),
1348  actualpackettosend.getDataSize()));
1349 
1350 #endif // OUTPUT_PACKET_BITS
1351 
1352  auto guard(Owner->LockSocketForUse());
1353  Owner->_Socket.send(actualpackettosend, TargetHost, TargetPortNumber);
1354 }
sf::UdpSocket _Socket
Main socket for listening for incoming packets and sending.
int64_t LastSentPacketTime
These are used to time out the connection.
Definition: Connection.h:332
sf::IpAddress TargetHost
Resolved address of the remote.
Definition: Connection.h:362
uint16_t TargetPortNumber
The remote port.
Definition: Connection.h:351
static DLLEXPORT int64_t GetTimeMs64()
#define LOG_WRITE(x)
Definition: Define.h:84
static std::string HexDump(const uint8_t *memory, size_t size, uint32_t groupby=4)
Converts memory at pointer into a hex dump.
Definition: Convert.h:102
NetworkHandler * Owner
Packets are handled by this object.
Definition: Connection.h:298

◆ CalculateNetworkPing()

DLLEXPORT void Connection::CalculateNetworkPing ( int  packets,
int  allowedfails,
std::function< void(int, int)>  onsucceeded,
std::function< void(PING_FAIL_REASON, int)>  onfailed 
)

Calculates the ping (round-trip time) on this connection.

Note
This will send packets asynchronously to the connection and can take up to an second to call the callbacks
Parameters
packetsThe amount of timing packets to send
allowedfailsIs the amount of missed packets allowed before failing
onsucceededCalled after successfully completed. First value is the ping in milliseconds and the second is failed packets
onfailedIs called if the function fails. First value will be the reason and second the failed packet count
Todo:
Check whether the packets should be send in a cluster or not (as they are currently sent in one go)

Definition at line 1160 of file Connection.cpp.

1163 {
1164  // Avoid dividing by zero here //
1165  if(packets == 0) {
1166 
1167  ++packets;
1168  LOG_WARNING("Connection: avoided dividing by zero by increasing ping packet count by "
1169  "one");
1170  }
1171 
1172  // The finishing check task needs to store this. Using a smart
1173  // pointer avoids copying this around
1174  std::shared_ptr<std::vector<std::shared_ptr<SentNetworkThing>>> sentechos =
1175  std::make_shared<std::vector<std::shared_ptr<SentNetworkThing>>>();
1176 
1177  sentechos->reserve(packets);
1178 
1179  if(packets >= 100) {
1180 
1181  Logger::Get()->Warning("Connection: trying to send loads of ping packets, sending " +
1182  Convert::ToString(packets) + " packets");
1183  }
1184 
1185  // Send the packet count of echo requests //
1186  for(int i = 0; i < packets; i++) {
1187 
1188  // Create a suitable echo request This needs to be
1189  // regenerated for each loop as each need to have unique id
1190  // for responses to be registered properly
1191  auto cursent =
1192  SendPacketToConnection(std::make_shared<RequestNone>(NETWORK_REQUEST_TYPE::Echo),
1194  cursent->SetAsTimed();
1195 
1196  sentechos->push_back(cursent);
1197  }
1198 
1200  std::bind<void>(
1201  [](std::shared_ptr<std::vector<std::shared_ptr<SentNetworkThing>>> requests,
1202  std::function<void(int, int)> onsucceeded,
1203  std::function<void(PING_FAIL_REASON, int)> onfailed,
1204  int allowedfails) -> void {
1205  int fails = 0;
1206 
1207  std::vector<int64_t> packagetimes;
1208  packagetimes.reserve(requests->size());
1209 
1210  // Collect the times //
1211  auto end = requests->end();
1212  for(auto iter = requests->begin(); iter != end; ++iter) {
1213 
1214  if((*iter)->IsDone != SentNetworkThing::DONE_STATUS::DONE ||
1215  (*iter)->ConfirmReceiveTime.load(std::memory_order_acquire) < 2) {
1216  // This one has failed //
1217 
1218  fails++;
1219  continue;
1220  }
1221 
1222  // Store the time //
1223  packagetimes.push_back(
1224  (*iter)->ConfirmReceiveTime.load(std::memory_order_acquire));
1225  }
1226 
1227 
1228  // Check has too many failed //
1229  if(fails > allowedfails) {
1230 
1231  Logger::Get()->Warning("Connection: pinging failed due to too many lost "
1232  "packets, lost: " +
1233  Convert::ToString(fails));
1234 
1235  onfailed(PING_FAIL_REASON::LossTooHigh, fails);
1236  return;
1237  }
1238 
1239  // Use some nice distribution math to get the ping //
1240  int finalping = 0;
1241 
1242  // The values shouldn't be able to be more than 1000 each so ints will
1243  // be able to hold all the values
1244  int64_t sum = 0;
1245  float averagesquared = 0.f;
1246 
1247  auto end2 = packagetimes.end();
1248  for(auto iter = packagetimes.begin(); iter != end2; ++iter) {
1249 
1250  sum += *iter;
1251  averagesquared += (powf(static_cast<float>(*iter), 2));
1252  }
1253 
1254  float average = sum / static_cast<float>(packagetimes.size());
1255 
1256  averagesquared /= static_cast<float>(packagetimes.size());
1257 
1258  float standarddeviation = sqrtf(averagesquared - powf(average, 2));
1259 
1260  // End mathematics
1261 
1262  // Just one more calculation to get ping that represents average bad case in
1263  // some way, might require tweaking...
1264 
1265  finalping = static_cast<int>(average + (standarddeviation * 0.7f));
1266 
1267  onsucceeded(finalping, fails);
1268 
1269  Logger::Get()->Info(
1270  "Connection: pinging completed, ping: " + Convert::ToString(finalping));
1271  },
1272  sentechos, onsucceeded, onfailed, allowedfails),
1273  std::bind<bool>(
1274  [](std::shared_ptr<std::vector<std::shared_ptr<SentNetworkThing>>> requests)
1275  -> bool {
1276  // Check if even one is still waiting //
1277  auto end = requests->end();
1278  for(auto iter = requests->begin(); iter != end; ++iter) {
1279  if(!(*iter)->IsFinalized())
1280  return false;
1281  }
1282 
1283  // None are still waiting, good to go //
1284  return true;
1285  },
1286  sentechos)));
1287 }
DLLEXPORT std::shared_ptr< SentRequest > SendPacketToConnection(const std::shared_ptr< NetworkRequest > &request, RECEIVE_GUARANTEE guarantee)
Definition: Connection.cpp:139
DLLEXPORT void Info(const std::string &data) override
Definition: Logger.cpp:164
PING_FAIL_REASON
If true 2 ack only packets are created each time one is sent.
Definition: Connection.h:56
DLLEXPORT void QueueTask(std::shared_ptr< QueuedTask > task)
Adds a task to the queue.
Encapsulates a function that can later be ran in a free thread.
Definition: QueuedTask.h:82
static DLLEXPORT ThreadingManager * Get()
#define LOG_WARNING(x)
Definition: Define.h:82
DLLEXPORT void Warning(const std::string &data) override
Definition: Logger.cpp:190
static std::string ToString(const T &val)
Definition: Convert.h:72
static DLLEXPORT Logger * Get()
Definition: Logger.cpp:106
Sent by servers to ping (time the time a client takes to respond) clients.

◆ GenerateFormatedAddressString()

DLLEXPORT std::string Connection::GenerateFormatedAddressString ( ) const

Returns a nicely formated address string for this connection.

Returns
For example something like "0.0.0.127:2565"
Todo:
this could be cached

Definition at line 1155 of file Connection.cpp.

1156 {
1157  return TargetHost.toString() + ":" + Convert::ToString(TargetPortNumber);
1158 }
sf::IpAddress TargetHost
Resolved address of the remote.
Definition: Connection.h:362
uint16_t TargetPortNumber
The remote port.
Definition: Connection.h:351
static std::string ToString(const T &val)
Definition: Convert.h:72

◆ GetCurrentlySentAcks()

DLLEXPORT std::vector< uint32_t > Connection::GetCurrentlySentAcks ( )

Basically a debug method (this is very slow)

Definition at line 1324 of file Connection.cpp.

1325 {
1326  std::vector<uint32_t> ids;
1327 
1328  for(const auto& acks : SentAckPackets) {
1329 
1330  acks->AcksInThePacket->InvokeForEachAck([&](uint32_t id) { ids.push_back(id); });
1331  }
1332 
1333  return ids;
1334 }
std::vector< std::shared_ptr< SentAcks > > SentAckPackets
Definition: Connection.h:344
unsigned int uint32_t
Definition: core.h:40

◆ GetPendingRequests()

const auto& Leviathan::Connection::GetPendingRequests ( ) const
inline

Returns the pending requests.

Definition at line 217 of file Connection.h.

218  {
219  return PendingRequests;
220  }
std::vector< std::shared_ptr< SentRequest > > PendingRequests
Sent requests that are waiting for a response.
Definition: Connection.h:336

◆ GetRawAddress()

std::string Leviathan::Connection::GetRawAddress ( ) const
inline

Definition at line 204 of file Connection.h.

205  {
206  return RawAddress;
207  }
std::string RawAddress
Definition: Connection.h:355

◆ GetReceivedPackets()

const auto& Leviathan::Connection::GetReceivedPackets ( ) const
inline

Returns a reference to a list of received packets that haven't been acknowledged successfully to the other side.

Definition at line 211 of file Connection.h.

212  {
213  return ReceivedRemotePackets;
214  }
NetworkAckField::PacketReceiveStatus ReceivedRemotePackets
Used to send acks for received remote packets.
Definition: Connection.h:301

◆ GetResponsesNeedingConfirmation()

const auto& Leviathan::Connection::GetResponsesNeedingConfirmation ( ) const
inline

Returns responses that are tracked and haven't been acknowledged by the other side.

Definition at line 224 of file Connection.h.

225  {
227  }
std::vector< std::shared_ptr< SentResponse > > ResponsesNeedingConfirmation
Sent responses that need to be confirmed (or resent if they are lost)
Definition: Connection.h:339

◆ GetState()

CONNECTION_STATE Leviathan::Connection::GetState ( ) const
inline

Definition at line 126 of file Connection.h.

127  {
128  return State;
129  }
CONNECTION_STATE State
Marks a remote id as received.
Definition: Connection.h:295

◆ HandlePacket()

DLLEXPORT void Connection::HandlePacket ( sf::Packet &  packet)

Handles a packet.

Definition at line 563 of file Connection.cpp.

564 {
565 
566 #ifdef OUTPUT_PACKET_BITS
567 
568  LOG_WRITE("Received bits: \n" +
570  reinterpret_cast<const uint8_t*>(packet.getData()), packet.getDataSize()));
571 
572 #endif // OUTPUT_PACKET_BITS
573 
574  // Handle incoming packet //
579  },
580  [&](uint32_t ack) -> void { HandleRemoteAck(ack); },
581  [&](uint32_t packetnumber) -> WireData::DECODE_CALLBACK_RESULT {
582 
583 #ifdef SPAM_ME_SOME_PACKETS
585  "received: packet number: " + std::to_string(packetnumber) + " from " +
587 #endif
588 
589  // Report the packet as received //
591 
592  // Update receive time
594 
595  // And the state
597 
599  }
600 
602  },
603  [&](uint8_t messagetype, uint32_t messagenumber,
604  sf::Packet& packet) -> WireData::DECODE_CALLBACK_RESULT {
605  // We can discard this here if this is message is already received //
606  bool alreadyReceived = false;
607 
608  if(_IsAlreadyReceived(messagenumber)) {
609 
610  alreadyReceived = true;
611  }
612 
613 #ifdef SPAM_ME_SOME_PACKETS
615  "received: message number: " + std::to_string(messagenumber) +
616  ", already received: " + std::to_string(alreadyReceived) + " from " +
618 #endif
619 
620  switch(messagetype) {
621  case NORMAL_RESPONSE_TYPE: {
622  _HandleResponsePacket(packet, alreadyReceived);
623  break;
624  }
625  case NORMAL_REQUEST_TYPE: {
626  _HandleRequestPacket(packet, messagenumber, alreadyReceived);
627  break;
628  }
629  default: {
630  LOG_ERROR("Connection: received packet has unknown message type (" +
631  Convert::ToString(messagetype) +
632  "(some may have been processed already)");
634  }
635  }
636 
638  });
639 }
int64_t LastReceivedPacketTime
Definition: Connection.h:333
DLLEXPORT void _HandleResponsePacket(sf::Packet &packet, bool alreadyreceived)
Definition: Connection.cpp:641
#define LOG_ERROR(x)
Definition: Define.h:83
CONNECTION_STATE State
Marks a remote id as received.
Definition: Connection.h:295
constexpr uint8_t NORMAL_RESPONSE_TYPE
Definition: CommonNetwork.h:16
DLLEXPORT void _HandleRequestPacket(sf::Packet &packet, uint32_t messagenumber, bool alreadyreceived)
Definition: Connection.cpp:757
unsigned char uint8_t
Definition: core.h:38
static DLLEXPORT int64_t GetTimeMs64()
#define LOG_WRITE(x)
Definition: Define.h:84
DLLEXPORT void SetPacketsReceivedIfNotSet(NetworkAckField &acks)
Sets acks in a packet as properly sent in this.
#define SPAM_PREFIX
Makes the program spam a ton of debug info about packets //.
Definition: Connection.cpp:29
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.
Definition: WireData.cpp:163
DLLEXPORT std::string GenerateFormatedAddressString() const
Returns a nicely formated address string for this connection.
static std::string ToString(const T &val)
Definition: Convert.h:72
constexpr uint8_t NORMAL_REQUEST_TYPE
Definition: CommonNetwork.h:18
DLLEXPORT void HandleRemoteAck(uint32_t localidconfirmedassent)
Called when the other side sends us an ack.
Definition: Connection.cpp:325
Packet is received but no acks have been sent.
static std::string HexDump(const uint8_t *memory, size_t size, uint32_t groupby=4)
Converts memory at pointer into a hex dump.
Definition: Convert.h:102
Begins the handshake with version number check.
unsigned int uint32_t
Definition: core.h:40
NetworkAckField::PacketReceiveStatus ReceivedRemotePackets
Used to send acks for received remote packets.
Definition: Connection.h:301
bool _IsAlreadyReceived(uint32_t messagenumber)
Returns true if we have already received message with number.
DECODE_CALLBACK_RESULT
Return value for controlling how DecodeIncomingData continues after the callback. ...
Definition: WireData.h:33

◆ HandleRemoteAck()

DLLEXPORT void Connection::HandleRemoteAck ( uint32_t  localidconfirmedassent)
inline

Called when the other side sends us an ack.

Used to mark our packets as sent

Mark acks as received

Definition at line 325 of file Connection.cpp.

326 {
327 #ifdef SPAM_ME_SOME_PACKETS
329  "Received ack for our packet: " + std::to_string(localidconfirmedassent) +
330  " from " + GenerateFormatedAddressString());
331 #endif
332 
333  if(localidconfirmedassent > LastConfirmedSent)
334  LastConfirmedSent = localidconfirmedassent;
335 
336  for(auto iter = ResponsesNeedingConfirmation.begin();
337  iter != ResponsesNeedingConfirmation.end();) {
338  if(localidconfirmedassent == (*iter)->PacketNumber) {
339 
340 #ifdef SPAM_ME_SOME_PACKETS
341  LOG_WRITE(SPAM_PREFIX + "Received ack for confirmed response: " +
342  std::to_string((*iter)->MessageNumber) + " from " +
344 #endif
345 
346  (*iter)->OnFinalized(true);
347  iter = ResponsesNeedingConfirmation.erase(iter);
348  } else {
349  ++iter;
350  }
351  }
352 
353  // Check which ack packets have been received //
354  for(auto iter = SentAckPackets.begin(); iter != SentAckPackets.end(); ++iter) {
355 
356  if(localidconfirmedassent == (*iter)->InsidePacket) {
357 
358  // Mark as properly sent //
359  (*iter)->Received = true;
360 
362  RemoveSucceededAcks(*(*iter)->AcksInThePacket);
363 
364  SentAckPackets.erase(iter);
365  break;
366  }
367  }
368 }
std::vector< std::shared_ptr< SentResponse > > ResponsesNeedingConfirmation
Sent responses that need to be confirmed (or resent if they are lost)
Definition: Connection.h:339
uint32_t LastConfirmedSent
Holds the id of last local sent packet that we have received an ack for.
Definition: Connection.h:314
std::vector< std::shared_ptr< SentAcks > > SentAckPackets
Definition: Connection.h:344
#define LOG_WRITE(x)
Definition: Define.h:84
#define SPAM_PREFIX
Makes the program spam a ton of debug info about packets //.
Definition: Connection.cpp:29
DLLEXPORT std::string GenerateFormatedAddressString() const
Returns a nicely formated address string for this connection.
DLLEXPORT void RemoveSucceededAcks(NetworkAckField &acks)
Removes acks that were successful in the packet from target.

◆ Init()

DLLEXPORT bool Connection::Init ( NetworkHandler owninghandler)

Creates the address object

Warning
This function will lock the NetworkHandler object and thus it needs to be still valid
Todo:
Make this async resolve the address

Definition at line 77 of file Connection.cpp.

78 {
79  Owner = owninghandler;
80 
81  // TODO: make this asynchronous
82  // This might do something //
83  if(!AddressGot) {
84  TargetHost = sf::IpAddress(HostName);
85  }
86 
87  // We fail if we got an invalid address //
88  if(TargetHost == sf::IpAddress::None) {
89 
90  LOG_ERROR("Connection: Init: couldn't translate host name to a real address, "
91  "host: " +
92  HostName);
93  return false;
94  }
95 
96  Logger::Get()->Info(
97  "Connection: opening connection to " + GenerateFormatedAddressString());
98 
99  // Reset various timers //
101 
102  // Send hello message //
104  std::make_shared<RequestConnect>(), RECEIVE_GUARANTEE::Critical)) {
105  LEVIATHAN_ASSERT(0, "Connection Init cannot send packet");
106  }
107 
108  return true;
109 }
DLLEXPORT std::shared_ptr< SentRequest > SendPacketToConnection(const std::shared_ptr< NetworkRequest > &request, RECEIVE_GUARANTEE guarantee)
Definition: Connection.cpp:139
int64_t LastReceivedPacketTime
Definition: Connection.h:333
DLLEXPORT void Info(const std::string &data) override
Definition: Logger.cpp:164
#define LOG_ERROR(x)
Definition: Define.h:83
int64_t LastSentPacketTime
These are used to time out the connection.
Definition: Connection.h:332
sf::IpAddress TargetHost
Resolved address of the remote.
Definition: Connection.h:362
std::string HostName
Definition: Connection.h:359
static DLLEXPORT int64_t GetTimeMs64()
DLLEXPORT std::string GenerateFormatedAddressString() const
Returns a nicely formated address string for this connection.
static DLLEXPORT Logger * Get()
Definition: Logger.cpp:106
NetworkHandler * Owner
Packets are handled by this object.
Definition: Connection.h:298

◆ IsTargetHostLocalhost()

DLLEXPORT bool Connection::IsTargetHostLocalhost ( )
Returns
True if this is a connection to a port on localhost

Definition at line 1149 of file Connection.cpp.

1150 {
1151  // Check does the address match localhost //
1152  return TargetHost == sf::IpAddress::LocalHost;
1153 }
sf::IpAddress TargetHost
Resolved address of the remote.
Definition: Connection.h:362

◆ IsThisYours()

bool Leviathan::Connection::IsThisYours ( const sf::IpAddress &  sender,
unsigned short  sentport 
)
inline

Checks does the sender and port match our corresponding values.

Returns
True if sender and sentport match the ones in this connection

Definition at line 136 of file Connection.h.

137  {
138  return sentport == TargetPortNumber && sender == TargetHost;
139  }
sf::IpAddress TargetHost
Resolved address of the remote.
Definition: Connection.h:362
uint16_t TargetPortNumber
The remote port.
Definition: Connection.h:351

◆ IsValidForSend()

bool Leviathan::Connection::IsValidForSend ( ) const
inline

Returns true if this socket is valid for sending.

Definition at line 121 of file Connection.h.

122  {
124  }
CONNECTION_STATE State
Marks a remote id as received.
Definition: Connection.h:295

◆ Release()

DLLEXPORT void Connection::Release ( )

Definition at line 111 of file Connection.cpp.

112 {
113  Logger::Get()->Info("Connection: disconnecting from " + GenerateFormatedAddressString());
114 
115  // Send a close packet //
116  // This will mark this as closed
118 
119  // Make sure that all our remaining packets fail //
120  for(auto& packet : PendingRequests)
121  packet->SetWaitStatus(false);
122 
123  PendingRequests.clear();
124 
125  for(auto& packet : ResponsesNeedingConfirmation)
126  packet->SetWaitStatus(false);
127 
129 
130  // All are now properly closed //
131 
132  // Destroy some of our stuff //
133  TargetHost = sf::IpAddress::None;
134 
135  LEVIATHAN_ASSERT(State == CONNECTION_STATE::Closed,
136  "Connection Release didn't set the connection as closed");
137 }
std::vector< std::shared_ptr< SentResponse > > ResponsesNeedingConfirmation
Sent responses that need to be confirmed (or resent if they are lost)
Definition: Connection.h:339
std::vector< std::shared_ptr< SentRequest > > PendingRequests
Sent requests that are waiting for a response.
Definition: Connection.h:336
DLLEXPORT void Info(const std::string &data) override
Definition: Logger.cpp:164
CONNECTION_STATE State
Marks a remote id as received.
Definition: Connection.h:295
sf::IpAddress TargetHost
Resolved address of the remote.
Definition: Connection.h:362
DLLEXPORT void SendCloseConnectionPacket()
Sends a packet that tells the other side to disconnect.
Definition: Connection.cpp:260
DLLEXPORT std::string GenerateFormatedAddressString() const
Returns a nicely formated address string for this connection.
static DLLEXPORT Logger * Get()
Definition: Logger.cpp:106

◆ RemoveSucceededAcks()

DLLEXPORT void Leviathan::Connection::RemoveSucceededAcks ( NetworkAckField acks)
protected

Removes acks that were successful in the packet from target.

Note
Should be called after the packet containing these acks is marked as successful

Definition at line 1307 of file Connection.cpp.

1308 {
1309  // We need to loop through all our acks and erase them from the map (if set) //
1310  for(uint32_t i = 0; i < static_cast<uint32_t>(acks.Acks.size()); i++) {
1311 
1312  for(uint8_t bit = 0; bit < 8; ++bit) {
1313 
1314  const auto id = (i * 8) + bit + acks.FirstPacketID;
1315 
1316  if(acks.Acks[i] & (1 << bit)) {
1317 
1318  ReceivedRemotePackets.erase(id);
1319  }
1320  }
1321  }
1322 }
std::vector< uint8_t > Acks
unsigned char uint8_t
Definition: core.h:38
unsigned int uint32_t
Definition: core.h:40
NetworkAckField::PacketReceiveStatus ReceivedRemotePackets
Used to send acks for received remote packets.
Definition: Connection.h:301

◆ SendCloseConnectionPacket()

DLLEXPORT void Connection::SendCloseConnectionPacket ( )

Sends a packet that tells the other side to disconnect.

Todo:
Add a message parameter for the reason

Definition at line 260 of file Connection.cpp.

261 {
262 #ifdef SPAM_ME_SOME_PACKETS
263  LOG_WRITE(SPAM_PREFIX + "Sending: close packet to " + GenerateFormatedAddressString());
264 #endif
265 
267 
269 }
DLLEXPORT std::shared_ptr< SentRequest > SendPacketToConnection(const std::shared_ptr< NetworkRequest > &request, RECEIVE_GUARANTEE guarantee)
Definition: Connection.cpp:139
CONNECTION_STATE State
Marks a remote id as received.
Definition: Connection.h:295
#define LOG_WRITE(x)
Definition: Define.h:84
#define SPAM_PREFIX
Makes the program spam a ton of debug info about packets //.
Definition: Connection.cpp:29
DLLEXPORT std::string GenerateFormatedAddressString() const
Returns a nicely formated address string for this connection.
Empty keep alive response.

◆ SendKeepAlivePacket()

DLLEXPORT void Connection::SendKeepAlivePacket ( )

Sends a keep alive packet if enough time has passed.

Definition at line 255 of file Connection.cpp.

256 {
258 }
DLLEXPORT std::shared_ptr< SentRequest > SendPacketToConnection(const std::shared_ptr< NetworkRequest > &request, RECEIVE_GUARANTEE guarantee)
Definition: Connection.cpp:139
Empty keep alive response.

◆ SendPacketToConnection() [1/3]

DLLEXPORT std::shared_ptr< SentRequest > Connection::SendPacketToConnection ( const std::shared_ptr< NetworkRequest > &  request,
RECEIVE_GUARANTEE  guarantee 
)

Send a request packet to this connection

Returns
nullptr If this connection is closed

Definition at line 139 of file Connection.cpp.

141 {
142  if(!IsValidForSend() || !request)
143  return nullptr;
144 
145 #ifdef SPAM_ME_SOME_PACKETS
146  LOG_WRITE(SPAM_PREFIX + "Sending: request " + request->GetTypeStr() +
147  " (message number: " + std::to_string(LastUsedMessageNumber + 1) +
148  ") in packet: " + std::to_string(LastUsedLocalID + 1) + " to " +
150 #endif
151 
152  // Find acks to send //
153  const auto fullpacketid = ++LastUsedLocalID;
154  auto acks = _GetAcksToSend(fullpacketid);
155 
156  // Generate a packet from the request //
157  auto sentthing = WireData::FormatRequestBytes(
158  request, guarantee, ++LastUsedMessageNumber, fullpacketid, acks.get(), StoredWireData);
159 
160  _SendPacketToSocket(StoredWireData);
161 
162  // Add to the sent packets //
163  PendingRequests.push_back(sentthing);
164  return sentthing;
165 }
std::vector< std::shared_ptr< SentRequest > > PendingRequests
Sent requests that are waiting for a response.
Definition: Connection.h:336
DLLEXPORT std::shared_ptr< NetworkAckField > _GetAcksToSend(uint32_t localpacketid, bool autoaddtosent=true)
Returns acks to be sent with a normal packet, or null if no acks to send.
uint32_t LastUsedLocalID
Definition: Connection.h:308
bool IsValidForSend() const
Returns true if this socket is valid for sending.
Definition: Connection.h:121
DLLEXPORT void _SendPacketToSocket(sf::Packet &actualpackettosend)
Sends actualpackettosend to our Owner&#39;s socket.
#define LOG_WRITE(x)
Definition: Define.h:84
#define SPAM_PREFIX
Makes the program spam a ton of debug info about packets //.
Definition: Connection.cpp:29
uint32_t LastUsedMessageNumber
Holds the number of last sent message (NetworkResponse or NetworkRequest object)
Definition: Connection.h:311
DLLEXPORT std::string GenerateFormatedAddressString() const
Returns a nicely formated address string for this connection.
static DLLEXPORT std::shared_ptr< SentRequest > FormatRequestBytes(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.
Definition: WireData.cpp:18

◆ SendPacketToConnection() [2/3]

DLLEXPORT bool Connection::SendPacketToConnection ( const NetworkResponse response)

Sends a response that doesn't need to be confirmed to be received.

Definition at line 167 of file Connection.cpp.

168 {
169  if(!IsValidForSend())
170  return false;
171 
172 #ifdef SPAM_ME_SOME_PACKETS
173  LOG_WRITE(SPAM_PREFIX + "Sending: response " + response.GetTypeStr() +
174  " (to: " + std::to_string(response.GetResponseID()) + ") in packet: " +
175  std::to_string(LastUsedLocalID + 1) + " to " + GenerateFormatedAddressString());
176 #endif
177 
178  // Find acks to send //
179  const auto fullpacketid = ++LastUsedLocalID;
180  auto acks = _GetAcksToSend(fullpacketid);
181 
182  // Generate a packet from the request //
184  response, ++LastUsedMessageNumber, fullpacketid, acks.get(), StoredWireData);
185 
186  _SendPacketToSocket(StoredWireData);
187 
188  return true;
189 }
DLLEXPORT std::shared_ptr< NetworkAckField > _GetAcksToSend(uint32_t localpacketid, bool autoaddtosent=true)
Returns acks to be sent with a normal packet, or null if no acks to send.
uint32_t LastUsedLocalID
Definition: Connection.h:308
DLLEXPORT std::string GetTypeStr() const
bool IsValidForSend() const
Returns true if this socket is valid for sending.
Definition: Connection.h:121
DLLEXPORT void _SendPacketToSocket(sf::Packet &actualpackettosend)
Sends actualpackettosend to our Owner&#39;s socket.
#define LOG_WRITE(x)
Definition: Define.h:84
#define SPAM_PREFIX
Makes the program spam a ton of debug info about packets //.
Definition: Connection.cpp:29
uint32_t LastUsedMessageNumber
Holds the number of last sent message (NetworkResponse or NetworkRequest object)
Definition: Connection.h:311
DLLEXPORT std::string GenerateFormatedAddressString() const
Returns a nicely formated address string for this connection.
static DLLEXPORT std::shared_ptr< SentResponse > FormatResponseBytes(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.
Definition: WireData.cpp:69

◆ SendPacketToConnection() [3/3]

DLLEXPORT std::shared_ptr< SentResponse > Connection::SendPacketToConnection ( const std::shared_ptr< NetworkResponse > &  response,
RECEIVE_GUARANTEE  guarantee 
)

Sends a response packet to this connection

Returns
nullptr If this connection is closed

Definition at line 219 of file Connection.cpp.

221 {
222  if(!IsValidForSend() || !response)
223  return nullptr;
224 
225  if(guarantee == RECEIVE_GUARANTEE::None) {
226 
227  LOG_WARNING("Connection: SendPacketToConnection: wrong send response variant called "
228  "with none guarantee");
229 
230  SendPacketToConnection(*response);
231  return nullptr;
232  }
233 
234 #ifdef SPAM_ME_SOME_PACKETS
235  LOG_WRITE(SPAM_PREFIX + "Sending: guaranteed response " + response->GetTypeStr() +
236  " (to: " + std::to_string(response->GetResponseID()) + ") in packet: " +
237  std::to_string(LastUsedLocalID + 1) + " to " + GenerateFormatedAddressString());
238 #endif
239 
240  // Find acks to send //
241  const auto fullpacketid = ++LastUsedLocalID;
242  auto acks = _GetAcksToSend(fullpacketid);
243 
244  // Generate a packet from the request //
245  auto sentthing = WireData::FormatResponseBytes(response, guarantee,
246  ++LastUsedMessageNumber, fullpacketid, acks.get(), StoredWireData);
247 
248  _SendPacketToSocket(StoredWireData);
249 
250  // Add to the sent packets //
251  ResponsesNeedingConfirmation.push_back(sentthing);
252  return sentthing;
253 }
DLLEXPORT std::shared_ptr< SentRequest > SendPacketToConnection(const std::shared_ptr< NetworkRequest > &request, RECEIVE_GUARANTEE guarantee)
Definition: Connection.cpp:139
std::vector< std::shared_ptr< SentResponse > > ResponsesNeedingConfirmation
Sent responses that need to be confirmed (or resent if they are lost)
Definition: Connection.h:339
Packet is sent once and if lost won&#39;t be resent.
DLLEXPORT std::shared_ptr< NetworkAckField > _GetAcksToSend(uint32_t localpacketid, bool autoaddtosent=true)
Returns acks to be sent with a normal packet, or null if no acks to send.
uint32_t LastUsedLocalID
Definition: Connection.h:308
#define LOG_WARNING(x)
Definition: Define.h:82
bool IsValidForSend() const
Returns true if this socket is valid for sending.
Definition: Connection.h:121
DLLEXPORT void _SendPacketToSocket(sf::Packet &actualpackettosend)
Sends actualpackettosend to our Owner&#39;s socket.
#define LOG_WRITE(x)
Definition: Define.h:84
#define SPAM_PREFIX
Makes the program spam a ton of debug info about packets //.
Definition: Connection.cpp:29
uint32_t LastUsedMessageNumber
Holds the number of last sent message (NetworkResponse or NetworkRequest object)
Definition: Connection.h:311
DLLEXPORT std::string GenerateFormatedAddressString() const
Returns a nicely formated address string for this connection.
static DLLEXPORT std::shared_ptr< SentResponse > FormatResponseBytes(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.
Definition: WireData.cpp:69

◆ SendPacketToConnectionWithTrackingWithoutGuarantee()

DLLEXPORT std::shared_ptr< SentResponse > Connection::SendPacketToConnectionWithTrackingWithoutGuarantee ( const NetworkResponse response)

Sends a response that won't be resent but it will be tracked.

Definition at line 192 of file Connection.cpp.

194 {
195  if(!IsValidForSend())
196  return nullptr;
197 
198 #ifdef SPAM_ME_SOME_PACKETS
199  LOG_WRITE(SPAM_PREFIX + "Sending: only tracked response " + response.GetTypeStr() +
200  " (to: " + std::to_string(response.GetResponseID()) + ") in packet: " +
201  std::to_string(LastUsedLocalID + 1) + " to " + GenerateFormatedAddressString());
202 #endif
203 
204  // Find acks to send //
205  const auto fullpacketid = ++LastUsedLocalID;
206  auto acks = _GetAcksToSend(fullpacketid);
207 
208  // Generate a packet from the request //
209  auto sentthing = WireData::FormatResponseBytesTracked(
210  response, ++LastUsedMessageNumber, fullpacketid, acks.get(), StoredWireData);
211 
212  _SendPacketToSocket(StoredWireData);
213 
214  // Add to the sent packets //
215  ResponsesNeedingConfirmation.push_back(sentthing);
216  return sentthing;
217 }
std::vector< std::shared_ptr< SentResponse > > ResponsesNeedingConfirmation
Sent responses that need to be confirmed (or resent if they are lost)
Definition: Connection.h:339
DLLEXPORT std::shared_ptr< NetworkAckField > _GetAcksToSend(uint32_t localpacketid, bool autoaddtosent=true)
Returns acks to be sent with a normal packet, or null if no acks to send.
uint32_t LastUsedLocalID
Definition: Connection.h:308
DLLEXPORT std::string GetTypeStr() const
bool IsValidForSend() const
Returns true if this socket is valid for sending.
Definition: Connection.h:121
DLLEXPORT void _SendPacketToSocket(sf::Packet &actualpackettosend)
Sends actualpackettosend to our Owner&#39;s socket.
#define LOG_WRITE(x)
Definition: Define.h:84
#define SPAM_PREFIX
Makes the program spam a ton of debug info about packets //.
Definition: Connection.cpp:29
uint32_t LastUsedMessageNumber
Holds the number of last sent message (NetworkResponse or NetworkRequest object)
Definition: Connection.h:311
DLLEXPORT std::string GenerateFormatedAddressString() const
Returns a nicely formated address string for this connection.
static DLLEXPORT std::shared_ptr< SentResponse > FormatResponseBytesTracked(const NetworkResponse &response, uint32_t messagenumber, uint32_t localpacketid, const NetworkAckField *acks, sf::Packet &bytesreceiver)
Constructs a single response message that can&#39;t be resent.
Definition: WireData.cpp:120

◆ SetPacketsReceivedIfNotSet()

DLLEXPORT void Leviathan::Connection::SetPacketsReceivedIfNotSet ( NetworkAckField acks)
protected

Sets acks in a packet as properly sent in this.

Acks that were false in the packet are untouched

Definition at line 1289 of file Connection.cpp.

1290 {
1291  // We need to loop through all our acks and set them in the map //
1292  for(uint32_t i = 0; i < static_cast<uint32_t>(acks.Acks.size()); i++) {
1293 
1294  for(uint8_t bit = 0; bit < 8; ++bit) {
1295 
1296  const auto id = (i * 8) + bit + acks.FirstPacketID;
1297 
1298  if(acks.Acks[i] & (1 << bit)) {
1299 
1300  HandleRemoteAck(id);
1301  }
1302  }
1303  }
1304 }
std::vector< uint8_t > Acks
unsigned char uint8_t
Definition: core.h:38
DLLEXPORT void HandleRemoteAck(uint32_t localidconfirmedassent)
Called when the other side sends us an ack.
Definition: Connection.cpp:325
unsigned int uint32_t
Definition: core.h:40

◆ SetRestrictionMode()

DLLEXPORT void Connection::SetRestrictionMode ( CONNECTION_RESTRICTION  type)

Adds special restriction on the connection.

Definition at line 1144 of file Connection.cpp.

1145 {
1146  RestrictType = type;
1147 }
CONNECTION_RESTRICTION RestrictType
Definition: Connection.h:319

◆ UpdateListening()

DLLEXPORT void Connection::UpdateListening ( )

Ticks this connection, times out sent packets.

Definition at line 460 of file Connection.cpp.

461 {
462  // Timeout stuff (if possible) //
463  int64_t timems = Time::GetTimeMs64();
464 
465  // Check for connection close //
466  if(timems > LastReceivedPacketTime + KEEPALIVE_TIME * 1.5f) {
467  // We could timeout the connection //
468  LOG_WARNING("Connection: timing out connection to " + GenerateFormatedAddressString());
469 
470  // Mark us as closing //
472  return;
473  }
474 
476 
478 
479 
480  // Send keep alive packet if it has been a while //
481  if(timems > LastSentPacketTime + KEEPALIVE_TIME) {
482 
483  // Send a keep alive packet //
484  // Which must reach the other side or the connection is considered lost
485  auto response = std::make_shared<ResponseNone>(NETWORK_RESPONSE_TYPE::Keepalive);
486 
488  return;
489  }
490 
491  bool acksCouldBeSent = false;
492 
493  // Determines which packet type to send
494  int ackCount = 0;
495 
496  // Check if we have acks that haven't been sent //
497  for(auto iter = ReceivedRemotePackets.begin(); iter != ReceivedRemotePackets.end();
498  ++iter) {
499  if(iter->second == RECEIVED_STATE::StateReceived) {
500 
501  // Waiting to be sent //
502  acksCouldBeSent = true;
503  ++ackCount;
504 
505  if(ackCount > ACK_ONLY_DEFAULT_MAX)
506  break;
507  }
508  }
509 
510  if(acksCouldBeSent && timems > LastSentPacketTime + ACKKEEPALIVE) {
511 
512  if(ackCount < ACK_ONLY_DEFAULT_MAX) {
513 
514  // Send acks only //
515  std::vector<uint32_t> ackNumbers;
516  ackNumbers.reserve(ACK_ONLY_DEFAULT_MAX);
517 
518  for(auto iter = ReceivedRemotePackets.begin();
519  iter != ReceivedRemotePackets.end();) {
520  if(iter->second == RECEIVED_STATE::StateReceived) {
521 
522  ackNumbers.push_back(iter->first);
523 
524  // These are deleted because there is no other way to mark them as sent
525  // In case this is lost and the received doesn't get the acks they should
526  // resend all the things and combined with the previous message ids
527  // iter = ReceivedRemotePackets.erase(iter);
528  ++iter;
529 
530  } else {
531 
532  ++iter;
533  }
534  }
535 
536  WireData::FormatAckOnlyPacket(ackNumbers, StoredWireData);
537 
538 #ifdef SPAM_ME_SOME_PACKETS
539  std::string acks;
540 
541  for(auto ack : ackNumbers)
542  acks += " " + std::to_string(ack);
543 
544  LOG_WRITE(SPAM_PREFIX + "Sending ack only packet: ack count: " +
545  std::to_string(ackNumbers.size()) + " acks:" + acks);
546 #endif
547 
548  _SendPacketToSocket(StoredWireData);
549 
550  if(DOUBLE_SEND_FOR_ACK_ONLY) {
551 
552  _SendPacketToSocket(StoredWireData);
553  }
554 
555  } else {
556 
557  // Send some acks //
559  }
560  }
561 }
DLLEXPORT std::shared_ptr< SentRequest > SendPacketToConnection(const std::shared_ptr< NetworkRequest > &request, RECEIVE_GUARANTEE guarantee)
Definition: Connection.cpp:139
int64_t LastReceivedPacketTime
Definition: Connection.h:333
std::vector< std::shared_ptr< SentResponse > > ResponsesNeedingConfirmation
Sent responses that need to be confirmed (or resent if they are lost)
Definition: Connection.h:339
std::vector< std::shared_ptr< SentRequest > > PendingRequests
Sent requests that are waiting for a response.
Definition: Connection.h:336
void _HandleTimeouts(int64_t timems, std::vector< std::shared_ptr< TSentType >> sentthing)
Definition: Connection.cpp:371
int64_t LastSentPacketTime
These are used to time out the connection.
Definition: Connection.h:332
DLLEXPORT void SendCloseConnectionPacket()
Sends a packet that tells the other side to disconnect.
Definition: Connection.cpp:260
#define LOG_WARNING(x)
Definition: Define.h:82
DLLEXPORT void _SendPacketToSocket(sf::Packet &actualpackettosend)
Sends actualpackettosend to our Owner&#39;s socket.
static DLLEXPORT int64_t GetTimeMs64()
#define LOG_WRITE(x)
Definition: Define.h:84
#define SPAM_PREFIX
Makes the program spam a ton of debug info about packets //.
Definition: Connection.cpp:29
DLLEXPORT std::string GenerateFormatedAddressString() const
Returns a nicely formated address string for this connection.
Packet is received but no acks have been sent.
static DLLEXPORT void FormatAckOnlyPacket(const std::vector< uint32_t > &packetstoack, sf::Packet &bytesreceiver)
Constructs an ack only packet with the specified acks.
Definition: WireData.cpp:145
NetworkAckField::PacketReceiveStatus ReceivedRemotePackets
Used to send acks for received remote packets.
Definition: Connection.h:301
DLLEXPORT void SendKeepAlivePacket()
Sends a keep alive packet if enough time has passed.
Definition: Connection.cpp:255

Member Data Documentation

◆ AddressGot

bool Leviathan::Connection::AddressGot = false
protected

True when TargetHost has been retrieved from HostName or TargetHost is made valid some other way

Definition at line 366 of file Connection.h.

◆ ExtraAckCount

uint8_t Leviathan::Connection::ExtraAckCount = 0
protected

When acks pile up increase this value to send more acks

Todo:
Implement this

Definition at line 329 of file Connection.h.

◆ FrontAcks

bool Leviathan::Connection::FrontAcks = false
protected

Flipped every time a packet is sent to toggle sending acks from the front or the back In normal operation doesn't matter but in exceptional circumstances allows more acks to be sent by sending 2 group of acks for each round while waiting for confirmation of ack receive

Definition at line 325 of file Connection.h.

◆ HostName

std::string Leviathan::Connection::HostName
protected

If the target remote was specified with an URL this stores it for later reconstruction (something like play.boostslair.com)

Definition at line 359 of file Connection.h.

◆ LastConfirmedSent

uint32_t Leviathan::Connection::LastConfirmedSent = 0
protected

Holds the id of last local sent packet that we have received an ack for.

Definition at line 314 of file Connection.h.

◆ LastReceivedMessageNumbers

boost::circular_buffer<uint32_t> Leviathan::Connection::LastReceivedMessageNumbers {KEEP_IDS_FOR_DISCARD}
protected

Numbers of messages that have been received before, used to skip processing duplicates

Todo:
Implement a lower bound (under which everything is dropped) and make this smaller

Definition at line 348 of file Connection.h.

◆ LastReceivedPacketTime

int64_t Leviathan::Connection::LastReceivedPacketTime = 0
protected

Definition at line 333 of file Connection.h.

◆ LastSentPacketTime

int64_t Leviathan::Connection::LastSentPacketTime = 0
protected

These are used to time out the connection.

Definition at line 332 of file Connection.h.

◆ LastUsedLocalID

uint32_t Leviathan::Connection::LastUsedLocalID = PACKET_NUMBERING_OFFSET
protected

Holds the ID of the last sent packet Incremented every time a packet is sent to keep local packet ids different

Note
The world will break once this wraps around and reaches 0
Todo:
Fix that

Definition at line 308 of file Connection.h.

◆ LastUsedMessageNumber

uint32_t Leviathan::Connection::LastUsedMessageNumber = 0
protected

Holds the number of last sent message (NetworkResponse or NetworkRequest object)

Definition at line 311 of file Connection.h.

◆ Owner

NetworkHandler* Leviathan::Connection::Owner = nullptr
protected

Packets are handled by this object.

Definition at line 298 of file Connection.h.

◆ PendingRequests

std::vector<std::shared_ptr<SentRequest> > Leviathan::Connection::PendingRequests
protected

Sent requests that are waiting for a response.

Definition at line 336 of file Connection.h.

◆ RawAddress

std::string Leviathan::Connection::RawAddress
protected

Non-translated address string. Maybe empty

Definition at line 355 of file Connection.h.

◆ ReceivedRemotePackets

NetworkAckField::PacketReceiveStatus Leviathan::Connection::ReceivedRemotePackets
protected

Used to send acks for received remote packets.

Definition at line 301 of file Connection.h.

◆ ResponsesNeedingConfirmation

std::vector<std::shared_ptr<SentResponse> > Leviathan::Connection::ResponsesNeedingConfirmation
protected

Sent responses that need to be confirmed (or resent if they are lost)

Definition at line 339 of file Connection.h.

◆ RestrictType

CONNECTION_RESTRICTION Leviathan::Connection::RestrictType = CONNECTION_RESTRICTION::None
protected

Connections might have special restrictions on them This is mainly used to accept only remote console feature on clients

Definition at line 319 of file Connection.h.

◆ SentAckPackets

std::vector<std::shared_ptr<SentAcks> > Leviathan::Connection::SentAckPackets
protected

Holds sent ack groups until they are considered lost or received and then is used to mark the packets received by the other side as successfully sent

Definition at line 344 of file Connection.h.

◆ State

CONNECTION_STATE Leviathan::Connection::State = CONNECTION_STATE::NothingReceived
protected

Marks a remote id as received.

This function will also store the packetid for later checks

Returns
True If already received a packet with the id The main state of connection

Definition at line 295 of file Connection.h.

◆ TargetHost

sf::IpAddress Leviathan::Connection::TargetHost
protected

Resolved address of the remote.

Definition at line 362 of file Connection.h.

◆ TargetPortNumber

uint16_t Leviathan::Connection::TargetPortNumber
protected

The remote port.

Definition at line 351 of file Connection.h.


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