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)
 a response that doesn't need to be confirmed to be received 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...
 

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 = 0
 
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
 
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 104 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 32 of file Connection.cpp.

32  :
33  RawAddress(hostname), HostName(hostname)
34 {
35  // We need to split the port number from the address //
36  StringIterator itr(hostname);
37 
38  auto result = itr.GetUntilNextCharacterOrAll<std::string>(':');
39 
40  HostName = *result;
41 
42  // We should be fine not skipping a letter //
43  result = itr.GetNextNumber<std::string>(DECIMALSEPARATORTYPE_NONE);
44 
45  if(!result){
46 
48 
49  int tmpport = 0;
50 
51  if(!vars->GetValueAndConvertTo<int>("DefaultServerPort", tmpport)){
52 
53  tmpport = 80;
54  }
55 
56  TargetPortNumber = (unsigned short)tmpport;
57 
58  LOG_WARNING("Connection: no port defined, using default, "
59  "hostname: " + hostname + ":" + Convert::ToString(TargetPortNumber));
60  return;
61  }
62 
63  TargetPortNumber = Convert::StringTo<int>(*result.get());
64 }
#define GAMECONFIGURATION_GET_VARIABLEACCESS(x)
std::string HostName
Definition: Connection.h:342
#define LOG_WARNING(x)
Definition: Define.h:82
uint16_t TargetPortNumber
The remote port.
Definition: Connection.h:334
std::string RawAddress
Definition: Connection.h:338
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 66 of file Connection.cpp.

67  :
68  TargetPortNumber(port), TargetHost(targetaddress), AddressGot(true)
69 {
71 }
sf::IpAddress TargetHost
Resolved address of the remote.
Definition: Connection.h:345
uint16_t TargetPortNumber
The remote port.
Definition: Connection.h:334
std::string RawAddress
Definition: Connection.h:338
DLLEXPORT std::string GenerateFormatedAddressString() const
Returns a nicely formated address string for this connection.
Definition: Connection.cpp:930

◆ ~Connection()

DLLEXPORT Connection::~Connection ( )

Definition at line 73 of file Connection.cpp.

73  {
74 
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 1157 of file Connection.cpp.

1157  {
1158 
1159  for (auto iter = SentAckPackets.begin(); iter != SentAckPackets.end(); ++iter){
1160 
1161  if((*iter)->InsidePacket == packetid){
1162 
1163  SentAckPackets.erase(iter);
1164  return;
1165  }
1166  }
1167 }
std::vector< std::shared_ptr< SentAcks > > SentAckPackets
Definition: Connection.h:327

◆ _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 820 of file Connection.cpp.

822 {
823  if(ReceivedRemotePackets.empty()){
824 
825  return nullptr;
826 
827  } else {
828 
829  // First we need to determine which received packet to use as first value //
830  FrontAcks = !FrontAcks;
831 
832  uint32_t firstselected = 0;
833  uint32_t last = 0;
834  uint8_t count = DEFAULT_ACKCOUNT;
835 
836  if(FrontAcks){
837 
838  for(auto iter = ReceivedRemotePackets.begin(); iter != ReceivedRemotePackets.end();
839  ++iter)
840  {
841  if(iter->second == RECEIVED_STATE::StateReceived){
842 
843  firstselected = iter->first;
844  break;
845  }
846  }
847 
848  } else {
849 
850  int backoffset = 0;
851 
852  for(auto iter = ReceivedRemotePackets.rbegin();
853  iter != ReceivedRemotePackets.rend(); ++iter)
854  {
855  if(iter->second == RECEIVED_STATE::StateReceived){
856 
857  if(backoffset >= DEFAULT_ACKCOUNT){
858 
859  break;
860  }
861 
862  ++backoffset;
863  firstselected = iter->first;
864  }
865 
866  ++backoffset;
867  }
868  }
869 
870  if(firstselected != 0 && count != 0){
871 
872  // Create the ack field //
873  auto tmpacks = std::make_shared<SentAcks>(localpacketid,
874  std::make_shared<NetworkAckField>(firstselected, count,
876 
877  // Still skip if there is nothing in it //
878  if(tmpacks->AcksInThePacket->Acks.size() < 1){
879  // It was still empty
880  LOG_WARNING("Generated NetworkAckField was empty even though "
881  "count wasn't zero");
882  return nullptr;
883  }
884 
885  if(autoaddtosent)
886  SentAckPackets.push_back(tmpacks);
887 
888  return tmpacks->AcksInThePacket;
889 
890  } else {
891 
892  // None were found //
893  return nullptr;
894  }
895  }
896 }
#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:327
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:284

◆ _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 899 of file Connection.cpp.

901 {
902  // Return if it doesn't have a proper matching expected response id //
903  const auto lookingforid = response->GetResponseID();
904 
905  if(lookingforid == 0)
906  return nullptr;
907 
908  for(auto& packet : PendingRequests){
909 
910  if(packet->MessageNumber == lookingforid){
911 
912  // Found matching object //
913  return packet;
914  }
915  }
916 
917  // Nothing found //
918  return nullptr;
919 }
std::vector< std::shared_ptr< SentRequest > > PendingRequests
Sent requests that are waiting for a response.
Definition: Connection.h:319

◆ _HandleInternalRequest()

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

Definition at line 652 of file Connection.cpp.

654 {
655  switch (request->GetType()){
657  {
658  SendPacketToConnection(std::make_shared<ResponseConnect>(
659  request->GetIDForResponse()),
661 
662  // Client should also make sure that a request is sent //
665  State == CONNECTION_STATE::Initial))
666  {
667  // TODO: test that this is sent
668  SendPacketToConnection(std::make_shared<RequestConnect>(),
670  }
671 
672  return true;
673  }
675  {
676  // CONNECTION_STATE::Initial is allowed here because the client might send a security
677  // request before sending us a response to our connect request
679 
680  return true;
681  }
682 
683  // Security has been set up for this connection //
684  SendPacketToConnection(std::make_shared<ResponseSecurity>(
685  request->GetIDForResponse(), CONNECTION_ENCRYPTION::None),
687 
688  return true;
689  }
691  {
692  // Client is not allowed to respond to this //
694 
695  LOG_ERROR("Connection: Client received NETWORK_REQUEST_TYPE::Authenticate");
696  return true;
697  }
698 
699  // Connection is now authenticated //
701 
702  LOG_INFO("Connection: Authenticate request accepted from: " +
704 
705  int32_t ConnectedPlayerID = 0;
706  uint64_t token = 0;
707 
708  SendPacketToConnection(std::make_shared<ResponseAuthenticate>(
709  request->GetIDForResponse(), ConnectedPlayerID, token),
711 
712  return true;
713  }
714  default:
715  break;
716  }
717 
718  // Eat up all the packets if not properly opened yet
719  if(State != CONNECTION_STATE::Authenticated){
720 
721  LOG_WARNING("Connection: not yet properly open, ignoring packet from: " +
723  return true;
724  }
725 
726  // Did nothing, normal handling continues //
727  return false;
728 }
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:278
#define LOG_WARNING(x)
Definition: Define.h:82
DLLEXPORT std::string GenerateFormatedAddressString() const
Returns a nicely formated address string for this connection.
Definition: Connection.cpp:930
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:281
Begins the handshake with version number check.

◆ _HandleInternalResponse()

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

Definition at line 730 of file Connection.cpp.

732 {
733  switch (response->GetType()){
735  {
736  // Forced disconnect //
738 
739  // Release will be called by NetworkHandler which sends a close connection packet
740  return true;
741  }
743  {
744  // The first packet of this type that is in response to our initial request
745  // moves this connection to Connected on our side
747 
749 
750  // Client will do security setup here //
751  // TODO: figure out how master server connections should work
753 
754  SendPacketToConnection(std::make_shared<RequestSecurity>(
757  }
758  }
759  return true;
760  }
762  {
764 
765  return true;
766  }
767 
768  // Verify security type is what we wanted //
769  auto* securityresponse = static_cast<ResponseSecurity*>(response.get());
770 
771  if(securityresponse->SecureType != CONNECTION_ENCRYPTION::None){
772 
773  LOG_ERROR("Connection: mismatch security, disconnecting");
775  return true;
776  }
777 
779 
780  // TODO: send an empty authentication request if this is a master server connection
782 
783  SendPacketToConnection(std::make_shared<RequestAuthenticate>("player"),
785  }
786 
787  return true;
788  }
790  {
791  // Connection is now good to go //
792 
793  auto* authresponse = static_cast<ResponseAuthenticate*>(response.get());
794 
795  //authresponse->UserID;
796 
798 
799  LOG_INFO("Connection: Authenticate succeeded from: " +
801 
802  return true;
803  }
804  default:
805  break;
806  }
807 
808  // Eat up all the packets if not properly opened yet
810 
811  LOG_WARNING("Connection: not yet properly open, ignoring packet from: " +
813  return true;
814  }
815 
816  // Did nothing, normal handling continues //
817  return false;
818 }
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:278
DLLEXPORT void SendCloseConnectionPacket()
Sends a packet that tells the other side to disconnect.
Definition: Connection.cpp:213
#define LOG_WARNING(x)
Definition: Define.h:82
DLLEXPORT std::string GenerateFormatedAddressString() const
Returns a nicely formated address string for this connection.
Definition: Connection.cpp:930
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:281
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 591 of file Connection.cpp.

593 {
594  // Generate a request object and make the interface handle it //
595  std::shared_ptr<NetworkRequest> request;
596  try {
597 
598  request = NetworkRequest::LoadFromPacket(packet, packetnumber);
599 
600  if(!request)
601  throw InvalidArgument("request is null");
602 
603  }
604  catch (const InvalidArgument& e){
605 
606  LOG_ERROR("Connection: received an invalid request packet, exception: ");
607  e.PrintToLog();
608  return;
609  }
610 
611  if(alreadyreceived){
612 
613  return;
614  }
615 
616  if(_HandleInternalRequest(request))
617  return;
618 
620 
621  // Restrict mode checking //
622 
623  // We can possibly drop the connection or perform other extra tasks //
625  // Check type //
626  if(!Engine::Get()->GetRemoteConsole()->CanOpenNewConnection(
627  Owner->GetConnection(this), request))
628  {
629  _OnRestrictFail(static_cast<uint16_t>(request->GetType()));
630  return;
631  }
632 
633  // Successfully opened, connection should now be safe as a
634  // general purpose connection
636  return;
637  }
638  }
639 
640  try{
641 
642  Owner->GetInterface()->HandleRequestPacket(request, *this);
643 
644  } catch(const InvalidArgument &e){
645  // We couldn't handle this packet //
646  Logger::Get()->Error("Connection: couldn't handle request packet! :");
647  e.PrintToLog();
648  }
649 }
#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:302
NetworkInterface * GetInterface()
Returns interface object. Type depends on AppType.
DLLEXPORT bool _HandleInternalRequest(const std::shared_ptr< NetworkRequest > &request)
Definition: Connection.cpp:652
virtual DLLEXPORT void HandleRequestPacket(std::shared_ptr< NetworkRequest > request, Connection &connection)=0
Called by ConnectionInfo to handle incoming packets.
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:281
static DLLEXPORT Engine * Get()
Definition: Engine.cpp:82
DLLEXPORT void Error(const std::string &data) override
Definition: Logger.cpp:177

◆ _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 514 of file Connection.cpp.

516 {
517  // Generate a response and pass to the interface //
518  std::shared_ptr<NetworkResponse> response;
519  try {
520 
521  response = NetworkResponse::LoadFromPacket(packet);
522 
523  if(!response)
524  throw InvalidArgument("response is null");
525 
526  }
527  catch (const InvalidArgument& e){
528 
529  LOG_ERROR("Connection: received an invalid response packet, exception: ");
530  e.PrintToLog();
531  return;
532  }
533 
534  if(alreadyreceived){
535 
536  return;
537  }
538 
539  // The response might have a corresponding request //
540  auto possiblerequest = _GetPossibleRequestForResponse(response);
541 
542  // Add the response to the request //
543  if(possiblerequest)
544  possiblerequest->GotResponse = response;
545 
546  if(_HandleInternalResponse(response))
547  return;
548 
550 
551  // Restrict mode checking //
552 
553  // Not allowed //
554  _OnRestrictFail(static_cast<uint16_t>(response->GetType()));
555  return;
556  }
557 
558  // See if interface wants to drop it //
559  if(!Owner->GetInterface()->PreHandleResponse(response, possiblerequest.get(), *this))
560  {
561 
562  LOG_WARNING("Connection: dropping packet due to interface not accepting response");
563  return;
564  }
565 
566  if(!possiblerequest){
567 
568  // Just discard if it is an empty response //
569  if(response->GetType() == NETWORK_RESPONSE_TYPE::None)
570  return;
571 
572  // Handle the response only packet //
573  Owner->GetInterface()->HandleResponseOnlyPacket(response, *this);
574 
575  } else {
576 
577  // Remove the request //
578  for(auto iter = PendingRequests.begin(); iter != PendingRequests.end(); ++iter){
579 
580  if((*iter).get() == possiblerequest.get()){
581 
582  // Notify that the request is done /
583  possiblerequest->OnFinalized(true);
584  PendingRequests.erase(iter);
585  break;
586  }
587  }
588  }
589 }
virtual DLLEXPORT bool PreHandleResponse(std::shared_ptr< NetworkResponse > response, SentNetworkThing *originalrequest, Connection &connection)
Called by ConnectionInfo to verify that a response is good.
std::vector< std::shared_ptr< SentRequest > > PendingRequests
Sent requests that are waiting for a response.
Definition: Connection.h:319
#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.
Definition: Connection.cpp:899
CONNECTION_RESTRICTION RestrictType
Definition: Connection.h:302
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)
Empty response, used for keeping alive/nothing.
virtual DLLEXPORT void HandleResponseOnlyPacket(std::shared_ptr< NetworkResponse > message, Connection &connection)=0
Called by ConnectionInfo when it receives a response without a matching request object.
DLLEXPORT void _OnRestrictFail(uint16_t type)
Closes the connection and reports an error.
NetworkHandler * Owner
Packets are handled by this object.
Definition: Connection.h:281
DLLEXPORT bool _HandleInternalResponse(const std::shared_ptr< NetworkResponse > &response)
Definition: Connection.cpp:730

◆ _HandleTimeouts()

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

Definition at line 292 of file Connection.cpp.

294 {
295  for(auto iter = sentthing.begin(); iter != sentthing.end(); ){
296 
297  // Second timeout //
298  if((timems - (*iter)->RequestStartTime > PACKET_LOST_AFTER_MILLISECONDS) ||
299  (LastConfirmedSent > (*iter)->PacketNumber + PACKET_LOST_AFTER_RECEIVED_NEWER))
300  {
301  // The current attempt is lost //
302  if((*iter)->Resend == RECEIVE_GUARANTEE::ResendOnce){
303 
304  if(++(*iter)->AttemptNumber <= 2){
305 
306  // Resend //
307  _Resend(**iter);
308  ++iter;
309  continue;
310  }
311 
312  } else if((*iter)->Resend == RECEIVE_GUARANTEE::Critical){
313 
314  // If a critical one fails the connection must be closed //
315  if(++(*iter)->AttemptNumber > CRITICAL_PACKET_MAX_TRIES){
316 
317  LOG_INFO("Connection: Lost critical packet too many times, "
318  "closing connection to: " + GenerateFormatedAddressString());
319 
320  (*iter)->OnFinalized(false);
321  Owner->CloseConnection(*this);
322  return;
323  }
324 
325  // Resend //
326  _Resend(**iter);
327  ++iter;
328  continue;
329  }
330 
331  // Shouldn't be sent anymore //
332 
333  // Failed //
334  (*iter)->OnFinalized(false);
335  _FailPacketAcks((*iter)->PacketNumber);
336  iter = sentthing.erase(iter);
337 
338  } else {
339 
340  ++iter;
341  }
342  }
343 }
#define LOG_INFO(x)
Definition: Define.h:81
uint32_t LastConfirmedSent
Holds the id of last local sent packet that we have received an ack for.
Definition: Connection.h:297
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
Packet will get a single resend.
DLLEXPORT std::string GenerateFormatedAddressString() const
Returns a nicely formated address string for this connection.
Definition: Connection.cpp:930
void _Resend(SentRequest &toresend)
Sends a message again. Preserves message number but changes packet id.
Definition: Connection.cpp:220
NetworkHandler * Owner
Packets are handled by this object.
Definition: Connection.h:281
virtual DLLEXPORT void CloseConnection(Connection &connection)
Marks a connection as closing.
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 1135 of file Connection.cpp.

1135  {
1136 
1137  // It is moved through in reverse to quickly return matches,
1138  // but receiving the same packet twice isn't that common
1139  for(auto id : LastReceivedMessageNumbers){
1140 
1141  if(id == packetid){
1142 
1143  // Found a match, this is an already received packet //
1144  return true;
1145  }
1146  }
1147 
1148  // Not found, add for future searches //
1149  LastReceivedMessageNumbers.push_back(packetid);
1150 
1151  // It wasn't there //
1152  return false;
1153 }
boost::circular_buffer< uint32_t > LastReceivedMessageNumbers
Definition: Connection.h:331

◆ _OnRestrictFail()

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

Closes the connection and reports an error.

Definition at line 1169 of file Connection.cpp.

1169  {
1170 
1171  LOG_ERROR("Connection: received a non-valid packet "
1172  "in restrict mode(" + Convert::ToString(static_cast<int>(RestrictType)) + ") type: " +
1173  Convert::ToString(static_cast<int>(type)) + " from: " +
1175 
1176  Owner->CloseConnection(*this);
1177 }
#define LOG_ERROR(x)
Definition: Define.h:83
CONNECTION_RESTRICTION RestrictType
Definition: Connection.h:302
DLLEXPORT std::string GenerateFormatedAddressString() const
Returns a nicely formated address string for this connection.
Definition: Connection.cpp:930
static std::string ToString(const T &val)
Definition: Convert.h:72
NetworkHandler * Owner
Packets are handled by this object.
Definition: Connection.h:281
virtual DLLEXPORT void CloseConnection(Connection &connection)
Marks a connection as closing.

◆ _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 220 of file Connection.cpp.

220  {
221 
222  // Find acks to send //
223  const auto fullpacketid = ++LastUsedLocalID;
224  auto acks = _GetAcksToSend(fullpacketid);
225 
226  // Resend it
228  fullpacketid, acks.get(), StoredWireData);
229 
230  _SendPacketToSocket(StoredWireData);
231 
232  toresend.ResetStartTime();
233 
234  // Increase attempt number
235  ++toresend.AttemptNumber;
236 }
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.
Definition: Connection.cpp:820
uint32_t LastUsedLocalID
Definition: Connection.h:291
DLLEXPORT void ResetStartTime()
Resets the start time.
DLLEXPORT void _SendPacketToSocket(sf::Packet &actualpackettosend)
Sends actualpackettosend to our Owner&#39;s socket.
std::shared_ptr< NetworkRequest > SentRequestData
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 238 of file Connection.cpp.

238  {
239 
240  // Find acks to send //
241  const auto fullpacketid = ++LastUsedLocalID;
242  auto acks = _GetAcksToSend(fullpacketid);
243 
244  // Resend it
246  fullpacketid, acks.get(), StoredWireData);
247 
248  _SendPacketToSocket(StoredWireData);
249 
250  toresend.ResetStartTime();
251 
252  // Increase attempt number
253  ++toresend.AttemptNumber;
254 }
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.
Definition: Connection.cpp:820
uint32_t LastUsedLocalID
Definition: Connection.h:291
DLLEXPORT void ResetStartTime()
Resets the start time.
DLLEXPORT void _SendPacketToSocket(sf::Packet &actualpackettosend)
Sends actualpackettosend to our Owner&#39;s socket.
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:72

◆ _SendPacketToSocket()

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

Sends actualpackettosend to our Owner's socket.

Definition at line 1115 of file Connection.cpp.

1117 {
1118  LEVIATHAN_ASSERT(Owner, "Connection no owner");
1119 
1120  // We have now sent a packet //
1122 
1123 #ifdef OUTPUT_PACKET_BITS
1124 
1125  LOG_WRITE("Packet bits: \n" +
1126  Convert::HexDump(reinterpret_cast<const uint8_t*>(actualpackettosend.getData()),
1127  actualpackettosend.getDataSize()));
1128 
1129 #endif // OUTPUT_PACKET_BITS
1130 
1131  auto guard(Owner->LockSocketForUse());
1132  Owner->_Socket.send(actualpackettosend, TargetHost, TargetPortNumber);
1133 }
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:315
sf::IpAddress TargetHost
Resolved address of the remote.
Definition: Connection.h:345
uint16_t TargetPortNumber
The remote port.
Definition: Connection.h:334
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:281

◆ 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 934 of file Connection.cpp.

937 {
938  // Avoid dividing by zero here //
939  if(packets == 0){
940 
941  ++packets;
942  LOG_WARNING("Connection: avoided dividing by zero by increasing ping packet count by "
943  "one");
944  }
945 
946  // The finishing check task needs to store this. Using a smart
947  // pointer avoids copying this around
948  std::shared_ptr<std::vector<std::shared_ptr<SentNetworkThing>>> sentechos =
949  std::make_shared<std::vector<std::shared_ptr<SentNetworkThing>>>();
950 
951  sentechos->reserve(packets);
952 
953  if(packets >= 100){
954 
955  Logger::Get()->Warning("Connection: trying to send loads of ping packets, sending "+
956  Convert::ToString(packets)+" packets");
957  }
958 
959  // Send the packet count of echo requests //
960  for(int i = 0; i < packets; i++){
961 
962  // Create a suitable echo request This needs to be
963  // regenerated for each loop as each need to have unique id
964  // for responses to be registered properly
965  auto cursent = SendPacketToConnection(std::make_shared<RequestNone>(
967  cursent->SetAsTimed();
968 
969  sentechos->push_back(cursent);
970  }
971 
972  ThreadingManager::Get()->QueueTask(new ConditionalTask(std::bind<void>([](
973  std::shared_ptr<std::vector<std::shared_ptr<SentNetworkThing>>> requests,
974  std::function<void(int, int)> onsucceeded,
975  std::function<void(PING_FAIL_REASON, int)> onfailed,
976  int allowedfails) -> void
977  {
978  int fails = 0;
979 
980  std::vector<int64_t> packagetimes;
981  packagetimes.reserve(requests->size());
982 
983  // Collect the times //
984  auto end = requests->end();
985  for(auto iter = requests->begin(); iter != end; ++iter){
986 
987  if((*iter)->IsDone != SentNetworkThing::DONE_STATUS::DONE ||
988  (*iter)->ConfirmReceiveTime.load(std::memory_order_acquire) < 2)
989  {
990  // This one has failed //
991 
992  fails++;
993  continue;
994  }
995 
996  // Store the time //
997  packagetimes.push_back((*iter)->ConfirmReceiveTime.load(
998  std::memory_order_acquire));
999  }
1000 
1001 
1002  // Check has too many failed //
1003  if(fails > allowedfails){
1004 
1005  Logger::Get()->Warning("Connection: pinging failed due to too many lost "
1006  "packets, lost: "+Convert::ToString(fails));
1007 
1008  onfailed(PING_FAIL_REASON::LossTooHigh, fails);
1009  return;
1010  }
1011 
1012  // Use some nice distribution math to get the ping //
1013  int finalping = 0;
1014 
1015  // The values shouldn't be able to be more than 1000 each so ints will
1016  // be able to hold all the values
1017  int64_t sum = 0;
1018  float averagesquared = 0.f;
1019 
1020  auto end2 = packagetimes.end();
1021  for(auto iter = packagetimes.begin(); iter != end2; ++iter){
1022 
1023  sum += *iter;
1024  averagesquared += (powf(static_cast<float>(*iter), 2));
1025  }
1026 
1027  float average = sum/static_cast<float>(packagetimes.size());
1028 
1029  averagesquared /= static_cast<float>(packagetimes.size());
1030 
1031  float standarddeviation = sqrtf(averagesquared-powf(average, 2));
1032 
1033  // End mathematics
1034 
1035  // Just one more calculation to get ping that represents average bad case in some way,
1036  // might require tweaking...
1037 
1038  finalping = static_cast<int>(average+(standarddeviation*0.7f));
1039 
1040  onsucceeded(finalping, fails);
1041 
1042  Logger::Get()->Info("Connection: pinging completed, ping: "+
1043  Convert::ToString(finalping));
1044 
1045  }, sentechos, onsucceeded, onfailed, allowedfails), std::bind<bool>([](
1046  std::shared_ptr<std::vector<std::shared_ptr<SentNetworkThing>>> requests)
1047  -> bool
1048  {
1049  // Check if even one is still waiting //
1050  auto end = requests->end();
1051  for(auto iter = requests->begin(); iter != end; ++iter){
1052  if(!(*iter)->IsFinalized())
1053  return false;
1054  }
1055 
1056  // None are still waiting, good to go //
1057  return true;
1058 
1059  }, sentechos)));
1060 
1061 }
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:52
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 930 of file Connection.cpp.

930  {
931  return TargetHost.toString() + ":" + Convert::ToString(TargetPortNumber);
932 }
sf::IpAddress TargetHost
Resolved address of the remote.
Definition: Connection.h:345
uint16_t TargetPortNumber
The remote port.
Definition: Connection.h:334
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 1099 of file Connection.cpp.

1099  {
1100 
1101  std::vector<uint32_t> ids;
1102 
1103  for(const auto& acks : SentAckPackets){
1104 
1105  acks->AcksInThePacket->InvokeForEachAck([&](uint32_t id){
1106 
1107  ids.push_back(id);
1108  });
1109  }
1110 
1111  return ids;
1112 }
std::vector< std::shared_ptr< SentAcks > > SentAckPackets
Definition: Connection.h:327
unsigned int uint32_t
Definition: core.h:40

◆ GetRawAddress()

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

Definition at line 198 of file Connection.h.

198  {
199  return RawAddress;
200  }
std::string RawAddress
Definition: Connection.h:338

◆ 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 204 of file Connection.h.

204  {
205  return ReceivedRemotePackets;
206  }
NetworkAckField::PacketReceiveStatus ReceivedRemotePackets
Used to send acks for received remote packets.
Definition: Connection.h:284

◆ GetState()

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

Definition at line 125 of file Connection.h.

125  {
126  return State;
127  }
CONNECTION_STATE State
Marks a remote id as received.
Definition: Connection.h:278

◆ HandlePacket()

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

Handles a packet.

Definition at line 440 of file Connection.cpp.

440  {
441 
442 #ifdef OUTPUT_PACKET_BITS
443 
444  LOG_WRITE("Received bits: \n" +
445  Convert::HexDump(reinterpret_cast<const uint8_t*>(packet.getData()),
446  packet.getDataSize()));
447 
448 #endif // OUTPUT_PACKET_BITS
449 
450  // Handle incoming packet //
453  {
456  },
457  [&](uint32_t ack) -> void
458  {
459  HandleRemoteAck(ack);
460  },
461  [&](uint32_t packetnumber) -> WireData::DECODE_CALLBACK_RESULT
462  {
463  // Report the packet as received //
465 
466  // Update receive time
468 
469  // And the state
471 
473  }
474 
476  },
477  [&](uint8_t messagetype, uint32_t messagenumber, sf::Packet &packet)
479  {
480  // We can discard this here if this is message is already received //
481  bool alreadyReceived = false;
482 
483  if(_IsAlreadyReceived(messagenumber)){
484 
485  alreadyReceived = true;
486  }
487 
488  switch(messagetype){
490  {
491  _HandleResponsePacket(packet,
492  alreadyReceived);
493 
494  break;
495  }
496  case NORMAL_REQUEST_TYPE:
497  {
498  _HandleRequestPacket(packet, messagenumber, alreadyReceived);
499  break;
500  }
501  default:
502  {
503  LOG_ERROR("Connection: received packet has unknown message type (" +
504  Convert::ToString(messagetype) + "(some may have been processed already)");
506  }
507  }
508 
510  }
511  );
512 }
int64_t LastReceivedPacketTime
Definition: Connection.h:316
DLLEXPORT void _HandleResponsePacket(sf::Packet &packet, bool alreadyreceived)
Definition: Connection.cpp:514
#define LOG_ERROR(x)
Definition: Define.h:83
CONNECTION_STATE State
Marks a remote id as received.
Definition: Connection.h:278
constexpr uint8_t NORMAL_RESPONSE_TYPE
Definition: CommonNetwork.h:16
DLLEXPORT void _HandleRequestPacket(sf::Packet &packet, uint32_t messagenumber, bool alreadyreceived)
Definition: Connection.cpp:591
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.
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:144
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:256
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:284
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:34

◆ 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 256 of file Connection.cpp.

258 {
259  if(localidconfirmedassent > LastConfirmedSent)
260  LastConfirmedSent = localidconfirmedassent;
261 
262  for(auto iter = ResponsesNeedingConfirmation.begin();
263  iter != ResponsesNeedingConfirmation.end(); ++iter)
264  {
265  if(localidconfirmedassent == (*iter)->PacketNumber){
266 
267  (*iter)->OnFinalized(true);
268 
269  ResponsesNeedingConfirmation.erase(iter);
270  break;
271  }
272  }
273 
274  // Check which ack packets have been received //
275  for (auto iter = SentAckPackets.begin(); iter != SentAckPackets.end(); ++iter){
276 
277  if(localidconfirmedassent == (*iter)->InsidePacket){
278 
279  // Mark as properly sent //
280  (*iter)->Received = true;
281 
283  RemoveSucceededAcks(*(*iter)->AcksInThePacket);
284 
285  SentAckPackets.erase(iter);
286  break;
287  }
288  }
289 }
std::vector< std::shared_ptr< SentResponse > > ResponsesNeedingConfirmation
Sent responses that need to be confirmed (or resent if they are lost)
Definition: Connection.h:322
uint32_t LastConfirmedSent
Holds the id of last local sent packet that we have received an ack for.
Definition: Connection.h:297
std::vector< std::shared_ptr< SentAcks > > SentAckPackets
Definition: Connection.h:327
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.

77  {
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: " + HostName);
92  return false;
93  }
94 
95  Logger::Get()->Info("Connection: opening connection to " +
97 
98  // Reset various timers //
100 
101  // Send hello message //
102  if(!SendPacketToConnection(std::make_shared<RequestConnect>(),
104  {
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:316
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:315
sf::IpAddress TargetHost
Resolved address of the remote.
Definition: Connection.h:345
std::string HostName
Definition: Connection.h:342
static DLLEXPORT int64_t GetTimeMs64()
DLLEXPORT std::string GenerateFormatedAddressString() const
Returns a nicely formated address string for this connection.
Definition: Connection.cpp:930
static DLLEXPORT Logger * Get()
Definition: Logger.cpp:106
NetworkHandler * Owner
Packets are handled by this object.
Definition: Connection.h:281

◆ IsTargetHostLocalhost()

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

Definition at line 925 of file Connection.cpp.

925  {
926  // Check does the address match localhost //
927  return TargetHost == sf::IpAddress::LocalHost;
928 }
sf::IpAddress TargetHost
Resolved address of the remote.
Definition: Connection.h:345

◆ 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 134 of file Connection.h.

134  {
135 
136  return sentport == TargetPortNumber && sender == TargetHost;
137  }
sf::IpAddress TargetHost
Resolved address of the remote.
Definition: Connection.h:345
uint16_t TargetPortNumber
The remote port.
Definition: Connection.h:334

◆ IsValidForSend()

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

Returns true if this socket is valid for sending.

Definition at line 120 of file Connection.h.

120  {
121 
123  }
CONNECTION_STATE State
Marks a remote id as received.
Definition: Connection.h:278

◆ Release()

DLLEXPORT void Connection::Release ( )

Definition at line 111 of file Connection.cpp.

111  {
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 
128  ResponsesNeedingConfirmation.clear();
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:322
std::vector< std::shared_ptr< SentRequest > > PendingRequests
Sent requests that are waiting for a response.
Definition: Connection.h:319
DLLEXPORT void Info(const std::string &data) override
Definition: Logger.cpp:164
CONNECTION_STATE State
Marks a remote id as received.
Definition: Connection.h:278
sf::IpAddress TargetHost
Resolved address of the remote.
Definition: Connection.h:345
DLLEXPORT void SendCloseConnectionPacket()
Sends a packet that tells the other side to disconnect.
Definition: Connection.cpp:213
DLLEXPORT std::string GenerateFormatedAddressString() const
Returns a nicely formated address string for this connection.
Definition: Connection.cpp:930
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 1082 of file Connection.cpp.

1082  {
1083 
1084  // We need to loop through all our acks and erase them from the map (if set) //
1085  for (uint32_t i = 0; i < static_cast<uint32_t>(acks.Acks.size()); i++){
1086 
1087  for(uint8_t bit = 0; bit < 8; ++bit){
1088 
1089  const auto id = (i * 8) + bit + acks.FirstPacketID;
1090 
1091  if(acks.Acks[i] & (1 << bit)){
1092 
1093  ReceivedRemotePackets.erase(id);
1094  }
1095  }
1096  }
1097 }
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:284

◆ 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 213 of file Connection.cpp.

213  {
214 
216 
218 }
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:278
Empty keep alive response.

◆ SendKeepAlivePacket()

DLLEXPORT void Connection::SendKeepAlivePacket ( )

Sends a keep alive packet if enough time has passed.

Definition at line 208 of file Connection.cpp.

208  {
209 
211 }
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  // Find acks to send //
146  const auto fullpacketid = ++LastUsedLocalID;
147  auto acks = _GetAcksToSend(fullpacketid);
148 
149  // Generate a packet from the request //
150  auto sentthing = WireData::FormatRequestBytes(request, guarantee,
151  ++LastUsedMessageNumber, fullpacketid, acks.get(), StoredWireData);
152 
153  _SendPacketToSocket(StoredWireData);
154 
155  // Add to the sent packets //
156  PendingRequests.push_back(sentthing);
157  return sentthing;
158 }
std::vector< std::shared_ptr< SentRequest > > PendingRequests
Sent requests that are waiting for a response.
Definition: Connection.h:319
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.
Definition: Connection.cpp:820
uint32_t LastUsedLocalID
Definition: Connection.h:291
bool IsValidForSend() const
Returns true if this socket is valid for sending.
Definition: Connection.h:120
DLLEXPORT void _SendPacketToSocket(sf::Packet &actualpackettosend)
Sends actualpackettosend to our Owner&#39;s socket.
uint32_t LastUsedMessageNumber
Holds the number of last sent message (NetworkResponse or NetworkRequest object)
Definition: Connection.h:294
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)

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

Definition at line 160 of file Connection.cpp.

161 {
162  if(!IsValidForSend())
163  return false;
164 
165  // Find acks to send //
166  const auto fullpacketid = ++LastUsedLocalID;
167  auto acks = _GetAcksToSend(fullpacketid);
168 
169  // Generate a packet from the request //
171  fullpacketid, acks.get(), StoredWireData);
172 
173  _SendPacketToSocket(StoredWireData);
174 
175  return true;
176 }
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.
Definition: Connection.cpp:820
uint32_t LastUsedLocalID
Definition: Connection.h:291
bool IsValidForSend() const
Returns true if this socket is valid for sending.
Definition: Connection.h:120
DLLEXPORT void _SendPacketToSocket(sf::Packet &actualpackettosend)
Sends actualpackettosend to our Owner&#39;s socket.
uint32_t LastUsedMessageNumber
Holds the number of last sent message (NetworkResponse or NetworkRequest object)
Definition: Connection.h:294
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:72

◆ 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 178 of file Connection.cpp.

180 {
181  if(!IsValidForSend() || !response)
182  return nullptr;
183 
184  if(guarantee == RECEIVE_GUARANTEE::None){
185 
186  LOG_WARNING("Connection: SendPacketToConnection: wrong send response called "
187  "with none guarantee");
188 
189  SendPacketToConnection(*response);
190  return nullptr;
191  }
192 
193  // Find acks to send //
194  const auto fullpacketid = ++LastUsedLocalID;
195  auto acks = _GetAcksToSend(fullpacketid);
196 
197  // Generate a packet from the request //
198  auto sentthing = WireData::FormatResponseBytes(response, guarantee,
199  ++LastUsedMessageNumber, fullpacketid, acks.get(), StoredWireData);
200 
201  _SendPacketToSocket(StoredWireData);
202 
203  // Add to the sent packets //
204  ResponsesNeedingConfirmation.push_back(sentthing);
205  return sentthing;
206 }
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:322
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.
Definition: Connection.cpp:820
uint32_t LastUsedLocalID
Definition: Connection.h:291
#define LOG_WARNING(x)
Definition: Define.h:82
bool IsValidForSend() const
Returns true if this socket is valid for sending.
Definition: Connection.h:120
DLLEXPORT void _SendPacketToSocket(sf::Packet &actualpackettosend)
Sends actualpackettosend to our Owner&#39;s socket.
uint32_t LastUsedMessageNumber
Holds the number of last sent message (NetworkResponse or NetworkRequest object)
Definition: Connection.h:294
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:72

◆ 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 1063 of file Connection.cpp.

1065 {
1066  // We need to loop through all our acks and set them in the map //
1067  for (uint32_t i = 0; i < static_cast<uint32_t>(acks.Acks.size()); i++){
1068 
1069  for(uint8_t bit = 0; bit < 8; ++bit){
1070 
1071  const auto id = (i * 8) + bit + acks.FirstPacketID;
1072 
1073  if(acks.Acks[i] & (1 << bit)){
1074 
1075  HandleRemoteAck(id);
1076  }
1077  }
1078  }
1079 }
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:256
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 921 of file Connection.cpp.

921  {
922  RestrictType = type;
923 }
CONNECTION_RESTRICTION RestrictType
Definition: Connection.h:302

◆ UpdateListening()

DLLEXPORT void Connection::UpdateListening ( )

Ticks this connection, times out sent packets.

Definition at line 345 of file Connection.cpp.

345  {
346 
347  // Timeout stuff (if possible) //
348  int64_t timems = Time::GetTimeMs64();
349 
350  // Check for connection close //
351  if(timems > LastReceivedPacketTime + KEEPALIVE_TIME*1.5f){
352  // We could timeout the connection //
353  Logger::Get()->Info("Connection: timing out connection to " +
355 
356  // Mark us as closing //
357  Owner->CloseConnection(*this);
358  return;
359  }
360 
362 
364 
365 
366  // Send keep alive packet if it has been a while //
367  if(timems > LastSentPacketTime+KEEPALIVE_TIME){
368 
369  // Send a keep alive packet //
370  // Which must reach the other side or the connection is considered lost
371  auto response = std::make_shared<ResponseNone>(NETWORK_RESPONSE_TYPE::Keepalive);
372 
374  return;
375  }
376 
377  bool acksCouldBeSent = false;
378 
379  // Determines which packet type to send
380  int ackCount = 0;
381 
382  // Check if we have acks that haven't been sent //
383  for(auto iter = ReceivedRemotePackets.begin(); iter != ReceivedRemotePackets.end();
384  ++iter)
385  {
386  if(iter->second == RECEIVED_STATE::StateReceived){
387 
388  // Waiting to be sent //
389  acksCouldBeSent = true;
390  ++ackCount;
391 
392  if(ackCount > ACK_ONLY_DEFAULT_MAX)
393  break;
394  }
395  }
396 
397  if(acksCouldBeSent && timems > LastSentPacketTime + ACKKEEPALIVE){
398 
399  if(ackCount < ACK_ONLY_DEFAULT_MAX){
400 
401  // Send acks only //
402  std::vector<uint32_t> ackNumbers;
403  ackNumbers.reserve(ACK_ONLY_DEFAULT_MAX);
404 
405  for(auto iter = ReceivedRemotePackets.begin(); iter != ReceivedRemotePackets.end();
406  )
407  {
408  if(iter->second == RECEIVED_STATE::StateReceived){
409 
410  ackNumbers.push_back(iter->first);
411 
412  // These are deleted because there is no other way to mark them as sent
413  // In case this is lost and the received doesn't get the acks they should
414  // resend all the things and combined with the previous message ids
415  iter = ReceivedRemotePackets.erase(iter);
416 
417  } else {
418 
419  ++iter;
420  }
421  }
422 
423  WireData::FormatAckOnlyPacket(ackNumbers, StoredWireData);
424 
425  _SendPacketToSocket(StoredWireData);
426 
427  if(DOUBLE_SEND_FOR_ACK_ONLY){
428 
429  _SendPacketToSocket(StoredWireData);
430  }
431 
432  } else {
433 
434  // Send some acks //
436  }
437  }
438 }
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:316
std::vector< std::shared_ptr< SentResponse > > ResponsesNeedingConfirmation
Sent responses that need to be confirmed (or resent if they are lost)
Definition: Connection.h:322
std::vector< std::shared_ptr< SentRequest > > PendingRequests
Sent requests that are waiting for a response.
Definition: Connection.h:319
DLLEXPORT void Info(const std::string &data) override
Definition: Logger.cpp:164
void _HandleTimeouts(int64_t timems, std::vector< std::shared_ptr< TSentType >> sentthing)
Definition: Connection.cpp:292
int64_t LastSentPacketTime
These are used to time out the connection.
Definition: Connection.h:315
DLLEXPORT void _SendPacketToSocket(sf::Packet &actualpackettosend)
Sends actualpackettosend to our Owner&#39;s socket.
static DLLEXPORT int64_t GetTimeMs64()
DLLEXPORT std::string GenerateFormatedAddressString() const
Returns a nicely formated address string for this connection.
Definition: Connection.cpp:930
static DLLEXPORT Logger * Get()
Definition: Logger.cpp:106
Packet is received but no acks have been sent.
NetworkHandler * Owner
Packets are handled by this object.
Definition: Connection.h:281
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:126
NetworkAckField::PacketReceiveStatus ReceivedRemotePackets
Used to send acks for received remote packets.
Definition: Connection.h:284
virtual DLLEXPORT void CloseConnection(Connection &connection)
Marks a connection as closing.
DLLEXPORT void SendKeepAlivePacket()
Sends a keep alive packet if enough time has passed.
Definition: Connection.cpp:208

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 349 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 312 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 308 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 342 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 297 of file Connection.h.

◆ LastReceivedMessageNumbers

boost::circular_buffer<uint32_t> Leviathan::Connection::LastReceivedMessageNumbers
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 331 of file Connection.h.

◆ LastReceivedPacketTime

int64_t Leviathan::Connection::LastReceivedPacketTime = 0
protected

Definition at line 316 of file Connection.h.

◆ LastSentPacketTime

int64_t Leviathan::Connection::LastSentPacketTime = 0
protected

These are used to time out the connection.

Definition at line 315 of file Connection.h.

◆ LastUsedLocalID

uint32_t Leviathan::Connection::LastUsedLocalID = 0
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 291 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 294 of file Connection.h.

◆ Owner

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

Packets are handled by this object.

Definition at line 281 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 319 of file Connection.h.

◆ RawAddress

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

Non-translated address string. Maybe empty

Definition at line 338 of file Connection.h.

◆ ReceivedRemotePackets

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

Used to send acks for received remote packets.

Definition at line 284 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 322 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 302 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 327 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 278 of file Connection.h.

◆ TargetHost

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

Resolved address of the remote.

Definition at line 345 of file Connection.h.

◆ TargetPortNumber

uint16_t Leviathan::Connection::TargetPortNumber
protected

The remote port.

Definition at line 334 of file Connection.h.


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