2018-03-29 17:01:57 -04:00
2019-07-07 20:56:15 +00:00
# include <StdAfx.h>
2018-03-29 17:01:57 -04:00
# include "Client.h"
//Network access.
# include "crc.h"
# include "BinaryWriter.h"
# include "BinaryReader.h"
# include "Network.h"
# include "FragStack.h"
# include "PacketController.h"
# include "World.h"
# include "ClientEvents.h"
# include "Player.h"
# include "ChatMsgs.h"
# include "Config.h"
CPacketController : : CPacketController ( CClient * client )
{
m_pClient = client ;
m_pPeer = client - > GetHostAddress ( ) ;
}
CPacketController : : ~ CPacketController ( )
{
_outgoingMessageQueue . Lock ( ) ;
for ( auto entry : _outgoingMessageQueue )
{
delete [ ] entry . data ;
}
_outgoingMessageQueue . clear ( ) ;
_outgoingMessageQueue . Unlock ( ) ;
for ( auto entry : m_in . fragstack )
{
delete entry ;
}
m_in . fragstack . clear ( ) ;
m_out . _fragQueue . Lock ( ) ;
for ( auto entry : m_out . _fragQueue )
{
delete [ ] ( ( BYTE * ) entry ) ;
}
m_out . _fragQueue . clear ( ) ;
m_out . _fragQueue . Unlock ( ) ;
for ( auto & entry : m_in . blobstack )
{
DELETEBLOB ( entry . second ) ;
}
m_in . blobstack . clear ( ) ;
m_out . _blobCache . Lock ( ) ;
for ( auto & entry : m_out . _blobCache )
{
DELETEBLOB ( entry . second ) ;
}
m_out . _blobCache . clear ( ) ;
m_out . _blobCache . Unlock ( ) ;
}
2019-07-07 20:56:15 +00:00
uint32_t CPacketController : : GetNextEvent ( )
2018-03-29 17:01:57 -04:00
{
2019-07-07 20:56:15 +00:00
// return InterlockedIncrement(&m_out.event_counter);
return + + m_out . event_counter ;
2018-03-29 17:01:57 -04:00
}
void CPacketController : : ResetEvent ( )
{
m_out . event_counter = 0 ;
}
2019-07-07 20:56:15 +00:00
uint32_t CPacketController : : GetNextSequence ( )
2018-03-29 17:01:57 -04:00
{
2019-07-07 20:56:15 +00:00
// return InterlockedIncrement(&m_out.sequence);
return + + m_out . sequence ;
2018-03-29 17:01:57 -04:00
}
2019-07-07 20:56:15 +00:00
BOOL CPacketController : : SendNetMessageInternal ( void * data , uint32_t length , WORD group , bool ephemeral )
2018-03-29 17:01:57 -04:00
{
2019-07-07 20:56:15 +00:00
uint32_t dwRPC = 0x80000000 ;
2018-03-29 17:01:57 -04:00
// Every fragment has a unique sequence.
2019-07-07 20:56:15 +00:00
// uint32_t dwFragSequence = InterlockedIncrement(&m_out.fragment_counter);
uint32_t dwFragSequence = + + m_out . fragment_counter ;
2018-03-29 17:01:57 -04:00
//Calculate the number of fragments necessary for the message.
WORD wFragCount = ( WORD ) ( length / MAX_FRAGMENT_LEN ) ;
if ( length % MAX_FRAGMENT_LEN ) wFragCount + + ;
WORD wFragIndex = 0 ;
WORD wFragLength = 0 ;
while ( wFragIndex < wFragCount )
{
if ( wFragCount ! = ( wFragIndex + 1 ) )
wFragLength = MAX_FRAGMENT_LEN ;
else
{
wFragLength = ( WORD ) ( length % MAX_FRAGMENT_LEN ) ;
if ( ! wFragLength )
wFragLength = MAX_FRAGMENT_LEN ;
}
FragHeader_s header ;
{
2019-05-12 09:21:34 -07:00
if ( ephemeral )
2019-07-07 20:56:15 +00:00
header . id = ( uint64_t ) dwFragSequence | ( ( ( uint64_t ) dwRPC ) < < 32 ) ;
2019-05-12 09:21:34 -07:00
else
2019-07-07 20:56:15 +00:00
header . id = ( uint64_t ) dwFragSequence ;
2018-03-29 17:01:57 -04:00
header . wCount = wFragCount ;
header . wSize = sizeof ( FragHeader_s ) + wFragLength ;
header . wIndex = wFragIndex ;
header . wGroup = group ;
}
QueueFragmentInternal ( & header , & ( ( BYTE * ) data ) [ wFragIndex * MAX_FRAGMENT_LEN ] ) ;
wFragIndex + + ;
}
return TRUE ;
}
void CPacketController : : QueueFragmentInternal ( FragHeader_s * header , BYTE * data )
{
FragPacket_s * fragment = ( FragPacket_s * ) new BYTE [ header - > wSize ] ;
memcpy ( & fragment - > header , header , sizeof ( FragHeader_s ) ) ;
memcpy ( & fragment - > data , data , header - > wSize - sizeof ( FragHeader_s ) ) ;
m_out . _fragQueue . Lock ( ) ;
m_out . _fragQueue . push_back ( fragment ) ;
m_out . _fragQueue . Unlock ( ) ;
}
void CPacketController : : Cleanup ( )
{
//Delete and remove whatever has been processed or successful sent.
//The fragments that are complete have already been processed.
for ( std : : list < FragmentStack * > : : iterator it = m_in . fragstack . begin ( ) ; it ! = m_in . fragstack . end ( ) ; )
{
FragmentStack * poo = * it ;
if ( poo - > IsComplete ( ) )
{
delete poo ;
it = m_in . fragstack . erase ( it ) ;
}
else
it + + ;
}
2019-07-07 20:56:15 +00:00
for ( std : : map < uint32_t , BlobPacket_s * > : : iterator it = m_in . blobstack . begin ( ) ; it ! = m_in . blobstack . end ( ) ; )
2018-03-29 17:01:57 -04:00
{
if ( it - > first > m_in . activesequence )
break ;
DELETEBLOB ( it - > second ) ;
it = m_in . blobstack . erase ( it ) ;
}
if ( m_out . sequence > = 1000 ) // keep no more than 1000 cached
{
if ( ( m_out . sequence - 1000 ) > m_in . flushsequence )
m_in . flushsequence = m_out . sequence - 1000 ;
}
m_out . _blobCache . Lock ( ) ;
2019-07-07 20:56:15 +00:00
for ( std : : map < uint32_t , BlobPacket_s * > : : iterator it = m_out . _blobCache . begin ( ) ; it ! = m_out . _blobCache . end ( ) ; )
2018-03-29 17:01:57 -04:00
{
if ( it - > first > m_in . flushsequence )
break ;
DELETEBLOB ( it - > second ) ;
it = m_out . _blobCache . erase ( it ) ;
}
m_out . _blobCache . Unlock ( ) ;
}
void CPacketController : : ThinkInbound ( )
{
//Check if we have sequences available for processing.
2019-07-07 20:56:15 +00:00
uint32_t dwDesired = m_in . activesequence + 1 ;
2018-03-29 17:01:57 -04:00
iterate :
if ( dwDesired < = m_in . sequence )
{
BlobMap : : iterator it = m_in . blobstack . find ( dwDesired ) ;
if ( it ! = m_in . blobstack . end ( ) )
{
ProcessBlob ( it - > second ) ;
m_in . lastactivity = g_pGlobals - > Time ( ) ;
DELETEBLOB ( it - > second ) ;
m_in . blobstack . erase ( it ) ;
m_in . activesequence = dwDesired + + ;
goto iterate ;
}
}
if ( ( dwDesired + 2 < = m_in . sequence ) & & ( ( m_in . lastrequest + 1 ) < g_pGlobals - > Time ( ) ) )
{
//request lost sequences
2019-07-07 20:56:15 +00:00
std : : vector < uint32_t > lostSequences ;
2018-03-29 17:01:57 -04:00
lostSequences . push_back ( dwDesired ) ;
2019-07-07 20:56:15 +00:00
uint32_t lowBound = dwDesired + 1 ;
uint32_t highBound = m_in . sequence ;
for ( uint32_t check = lowBound ; check < highBound ; check + + )
2018-03-29 17:01:57 -04:00
{
if ( m_in . blobstack . find ( check ) = = m_in . blobstack . end ( ) )
{
lostSequences . push_back ( check ) ;
}
}
2019-07-07 20:56:15 +00:00
uint32_t dwCount = ( uint32_t ) lostSequences . size ( ) ;
CREATEBLOB ( p , sizeof ( uint32_t ) + dwCount * sizeof ( uint32_t ) ) ;
2018-03-29 17:01:57 -04:00
2019-07-07 20:56:15 +00:00
* ( ( uint32_t * ) p - > data ) = ( uint32_t ) lostSequences . size ( ) ;
uint32_t * requestPos = ( ( uint32_t * ) p - > data ) + 1 ;
2018-03-29 17:01:57 -04:00
2019-07-07 20:56:15 +00:00
std : : vector < uint32_t > : : iterator requestIt = lostSequences . begin ( ) ;
2018-03-29 17:01:57 -04:00
for ( ; requestIt ! = lostSequences . end ( ) ; requestIt + + ) {
* requestPos = * requestIt ;
requestPos + + ;
}
g_pNetwork - > SendConnectlessBlob ( m_pPeer , p , BT_REQUESTLOST , NULL , GetElapsedTime ( ) ) ;
DELETEBLOB ( p ) ;
m_in . lastrequest = g_pGlobals - > Time ( ) ;
# ifdef _DEBUG
LOG_PRIVATE ( Network , Verbose , " Requesting %d lost packets for %s.. \n " , lostSequences . size ( ) , m_pClient - > GetDescription ( ) ) ;
# endif
m_in . numresendrequests + = dwCount ;
}
}
void CPacketController : : ThinkOutbound ( )
{
double fTime = g_pGlobals - > Time ( ) ;
if ( m_out . nextflush < fTime )
{
FlushPeerCache ( ) ;
}
if ( m_out . nexttimeupdate < fTime )
{
UpdatePeerTime ( ) ;
}
FlushQueuedNetMessages ( ) ;
FlushFragments ( ) ;
}
void CPacketController : : Think ( )
{
if ( ! IsAlive ( ) )
return ;
// Handle the input first.
ThinkInbound ( ) ;
// Cleanup before we clutter the cache with new stuff.
Cleanup ( ) ;
// Handle the output last.
2019-02-07 00:17:17 -06:00
//ThinkOutbound();
2018-03-29 17:01:57 -04:00
if ( ( g_pGlobals - > Time ( ) - m_in . lastactivity ) > = 30.0f )
{
Kill ( __FILE__ , __LINE__ ) ;
}
}
void CPacketController : : PerformLoginSync ( )
{
/* PUT THIS BACK IN?
m_out . lastloginsync = g_pGlobals - > Time ( ) ;
CREATEBLOB ( LoginSync , 0xE6 ) ;
memset ( & LoginSync - > data [ 8 ] , 0 , 0xDE ) ;
* ( ( double * ) LoginSync - > data ) = g_pGlobals - > Time ( ) ;
g_pNetwork - > SendConnectlessBlob ( m_pPeer , LoginSync , BT_CONNECTIONACK , NULL , GetElapsedTime ( ) ) ;
DELETEBLOB ( LoginSync ) ;
*/
}
void CPacketController : : FlushPeerCache ( )
{
m_out . nextflush = g_pGlobals - > Time ( ) + 3.0f ;
//
2019-07-07 20:56:15 +00:00
CREATEBLOB ( p , sizeof ( uint32_t ) ) ;
2018-03-29 17:01:57 -04:00
2019-07-07 20:56:15 +00:00
* ( ( uint32_t * ) p - > data ) = m_in . activesequence ;
2018-03-29 17:01:57 -04:00
g_pNetwork - > SendConnectlessBlob ( m_pPeer , p , BT_ACKSEQUENCE , m_out . sequence , GetElapsedTime ( ) ) ;
DELETEBLOB ( p ) ;
}
void CPacketController : : UpdatePeerTime ( )
{
m_out . nexttimeupdate = g_pGlobals - > Time ( ) + 3.0 ;
CREATEBLOB ( tupdate , sizeof ( double ) ) ;
* ( ( double * ) tupdate - > data ) = g_pGlobals - > Time ( ) ;
BlobHeader_s * header = & tupdate - > header ;
header - > dwSequence = GetNextSequence ( ) ;
header - > dwFlags = BT_TIMEUPDATE | BT_USES_CRC ;
header - > dwCRC = 0 ;
header - > wRecID = g_pNetwork - > GetServerID ( ) ;
header - > wTime = GetElapsedTime ( ) ;
header - > wTable = 0x01 ;
2019-07-07 20:56:15 +00:00
uint32_t dwXOR = GetNextXORVal ( m_out . crypto ) ;
2018-03-29 17:01:57 -04:00
header - > dwCRC = BlobCRC ( tupdate , dwXOR ) ;
//Off you go.
g_pNetwork - > QueuePacket ( m_pPeer , tupdate , BLOBLEN ( tupdate ) ) ;
// g_pNetwork->SendConnectlessBlob(m_pPeer, tupdate, BT_TIMEUPDATE, m_out.sequence, GetElapsedTime());
//Cache for later use.
2019-07-07 20:56:15 +00:00
m_out . _blobCache . insert ( std : : pair < uint32_t , BlobPacket_s * > ( header - > dwSequence , tupdate ) ) ;
2018-03-29 17:01:57 -04:00
m_out . _sentBytes + = header - > wSize + sizeof ( BlobHeader_s ) ;
}
WORD CPacketController : : GetElapsedTime ( )
{
return ( WORD ) ( ( g_pGlobals - > Time ( ) - m_in . logintime ) * 2 ) ;
}
//This is a generic handler for malicious clients.
2019-07-07 20:56:15 +00:00
void CPacketController : : EvilClient ( const char * szSource , uint32_t dwLine , BOOL bKill )
2018-03-29 17:01:57 -04:00
{
# ifdef _DEBUG
if ( szSource )
2018-04-27 21:03:39 -07:00
SERVER_INFO < < " Evil client @ " < < dwLine < < " of " < < szSource < < " ! " ;
2018-03-29 17:01:57 -04:00
# endif
if ( bKill & & IsAlive ( ) )
{
Kill ( szSource , dwLine ) ;
}
}
void CPacketController : : ProcessBlob ( BlobPacket_s * blob )
{
BlobHeader_s * header = & blob - > header ;
2019-07-07 20:56:15 +00:00
uint32_t dwSequence = header - > dwSequence ;
uint32_t dwFlags = header - > dwFlags ;
uint32_t dwCRC = header - > dwCRC ;
uint32_t dwSize = header - > wSize ;
2018-03-29 17:01:57 -04:00
BYTE * pbData = blob - > data ;
if ( dwFlags & BT_REQUESTLOST ) //0x00000002
{
if ( dwSize > = 4 )
{
//LOG(Temp, Normal, "Client requesting lost packets.\n");
2019-07-07 20:56:15 +00:00
uint32_t dwLostPackets = * ( ( uint32_t * ) pbData ) ;
2018-03-29 17:01:57 -04:00
2019-07-07 20:56:15 +00:00
pbData + = sizeof ( uint32_t ) ;
dwSize - = sizeof ( uint32_t ) ;
2018-03-29 17:01:57 -04:00
2019-07-07 20:56:15 +00:00
if ( dwSize > = ( dwLostPackets * sizeof ( uint32_t ) ) )
2018-03-29 17:01:57 -04:00
{
2019-07-07 20:56:15 +00:00
uint32_t dwDenySize = 0 ;
uint32_t dwDenyBlobs [ 0x50 ] ;
2018-03-29 17:01:57 -04:00
2019-07-07 20:56:15 +00:00
uint32_t lowest_sequence = 0 ;
2018-03-29 17:01:57 -04:00
for ( unsigned int i = 0 ; i < dwLostPackets ; i + + )
{
2019-07-07 20:56:15 +00:00
uint32_t dwRequested = ( ( uint32_t * ) pbData ) [ i ] ;
2018-03-29 17:01:57 -04:00
if ( dwRequested < 2 | | dwRequested > m_out . sequence )
{
// Sequence out of range.
FlagEvilClient ( ) ;
continue ;
}
if ( ! lowest_sequence | | dwRequested < lowest_sequence )
{
lowest_sequence = dwRequested ;
}
//Find the requested sequence in the cache.
m_out . _blobCache . Lock ( ) ;
BlobMap : : iterator it = m_out . _blobCache . find ( dwRequested ) ;
if ( it ! = m_out . _blobCache . end ( ) )
{
ResendBlob ( it - > second ) ;
m_out . _blobCache . Unlock ( ) ;
m_out . numretransmit + + ;
}
else
{
m_out . _blobCache . Unlock ( ) ;
if ( dwDenySize < 0x50 )
{
dwDenyBlobs [ dwDenySize ] = dwRequested ;
dwDenySize + + ;
}
else
{
// Too many
FlagEvilClient ( ) ;
}
}
}
if ( dwDenySize > 0 )
{
2019-07-07 20:56:15 +00:00
uint32_t dwLength = dwDenySize * sizeof ( uint32_t ) ;
CREATEBLOB ( p , sizeof ( uint32_t ) + dwLength ) ;
2018-03-29 17:01:57 -04:00
2019-07-07 20:56:15 +00:00
memcpy ( p - > data , & dwDenySize , sizeof ( uint32_t ) ) ;
memcpy ( p - > data + sizeof ( uint32_t ) , dwDenyBlobs , dwLength ) ;
2018-03-29 17:01:57 -04:00
g_pNetwork - > SendConnectlessBlob ( m_pPeer , p , BT_DENY , NULL , GetElapsedTime ( ) ) ;
DELETEBLOB ( p ) ;
m_out . numdenied + = dwDenySize ;
}
if ( lowest_sequence )
{
m_in . flushsequence = lowest_sequence ;
}
2019-07-07 20:56:15 +00:00
pbData + = sizeof ( uint32_t ) * dwLostPackets ;
dwSize - = sizeof ( uint32_t ) * dwLostPackets ;
2018-03-29 17:01:57 -04:00
}
else
{
FlagEvilClient ( ) ;
return ;
}
}
else
{
FlagEvilClient ( ) ;
return ;
}
}
if ( dwFlags & BT_DENY ) //0x00000008
{
if ( dwSize > = 4 )
{
2019-07-07 20:56:15 +00:00
uint32_t dwDeniedCount = * ( ( uint32_t * ) pbData ) ;
2018-03-29 17:01:57 -04:00
2019-07-07 20:56:15 +00:00
pbData + = sizeof ( uint32_t ) ;
dwSize - = sizeof ( uint32_t ) ;
2018-03-29 17:01:57 -04:00
2019-07-07 20:56:15 +00:00
if ( dwSize = = ( dwDeniedCount * sizeof ( uint32_t ) ) )
2018-03-29 17:01:57 -04:00
{
unsigned int i = 0 ;
while ( i < dwSize )
{
2019-07-07 20:56:15 +00:00
uint32_t dwDenied = ( ( uint32_t * ) pbData ) [ i ] ;
2018-03-29 17:01:57 -04:00
if ( dwDenied < = m_in . sequence )
{
if ( dwDenied = = ( m_in . activesequence + 1 ) )
{
m_in . activesequence + + ;
i = 0 ;
}
}
//else
// FlagEvilClient(__FILE__, __LINE__);
i + + ;
}
}
else
FlagEvilClient ( ) ;
}
else
FlagEvilClient ( ) ;
return ;
}
if ( dwFlags & BT_ACKSEQUENCE )
{
if ( dwSize < 4 )
{
FlagEvilClient ( ) ;
return ;
}
2019-07-07 20:56:15 +00:00
m_in . flushsequence = * ( ( uint32_t * ) pbData ) ;
2018-03-29 17:01:57 -04:00
dwSize - = 4 ;
pbData + = 4 ;
}
/*
if ( dwFlags & BT_LOGIN )
{
if ( m_out . loginsyncs < 0 )
m_out . loginsyncs = 0 ;
return ;
}
*/
/*
if ( dwFlags & BT_CONNECTIONACK ) //0x00000040
{
if ( m_out . loginsyncs > = 0 )
{
m_out . loginsyncs + + ;
if ( m_out . loginsyncs < 2 )
{
m_in . lastactivity = g_pGlobals - > Time ( ) ;
// PerformLoginSync();
}
}
return ;
}
*/
if ( dwFlags & BT_TIMEUPDATE ) //0x00100000
{
# ifdef _DEBUG
//if (dwFlags & BT_FRAGMENTS)
// LOG(Temp, Normal, "Fragments? %s %u\n", __FILE__, __LINE__);
# endif
if ( dwSize < 8 )
{
FlagEvilClient ( ) ;
return ;
}
else
{
//Time critical.
/*
const double gear_tolerance = 1.0f ; // Cheater!! =)
if ( ( g_pGlobals - > Time ( ) + gear_tolerance ) < * ( ( double * ) pbData ) )
{
const char * account = m_pClient - > GetAccount ( ) ;
SOCKADDR_IN * ip = m_pClient - > GetHostAddress ( ) ;
LOG ( Temp , Normal , " Detected client(%s @ %s) using gear. Killing! \n " , ( account ? account : " ??? " ) , ( ip ? inet_ntoa ( ip - > sin_addr ) : " ??? " ) ) ;
g_pNetwork - > KickClient ( m_pClient - > GetIndex ( ) ) ;
}
return ;
*/
}
dwSize - = 8 ;
pbData + = 8 ;
}
if ( dwFlags & BT_ECHOREQUEST )
{
if ( dwSize < 4 )
{
FlagEvilClient ( ) ;
return ;
}
float echoValue = * ( ( float * ) pbData ) ;
/*
2019-07-07 20:56:15 +00:00
CREATEBLOB ( tupdate , sizeof ( uint32_t ) ) ;
* ( ( uint32_t * ) tupdate - > data ) = echoValue ;
2018-03-29 17:01:57 -04:00
BlobHeader_s * header = & tupdate - > header ;
header - > dwSequence = m_out . sequence ;
header - > dwFlags = BT_ECHORESPONSE | BT_USES_CRC ;
header - > dwCRC = 0 ;
header - > wRecID = g_pNetwork - > GetServerID ( ) ;
header - > wTime = GetElapsedTime ( ) ;
header - > wTable = 0x01 ;
2019-07-07 20:56:15 +00:00
uint32_t dwXOR = GetSendXORVal ( m_out . servercrc ) ;
2018-03-29 17:01:57 -04:00
header - > dwCRC = BlobCRC ( tupdate , dwXOR ) ;
//Off you go.
g_pNetwork - > QueuePacket ( m_pPeer , tupdate , BLOBLEN ( tupdate ) ) ;
//Cache for later use.
header - > dwCRC = dwXOR ;
m_out . blobcache . push_back ( tupdate ) ;
*/
CREATEBLOB ( tupdate , sizeof ( float ) * 2 ) ;
( ( float * ) tupdate - > data ) [ 0 ] = echoValue ;
( ( float * ) tupdate - > data ) [ 1 ] = echoValue ;
g_pNetwork - > SendConnectlessBlob ( m_pPeer , tupdate , BT_ECHORESPONSE , m_out . sequence , GetElapsedTime ( ) ) ;
DELETEBLOB ( tupdate ) ;
2019-07-07 20:56:15 +00:00
pbData + = sizeof ( uint32_t ) ;
dwSize - = sizeof ( uint32_t ) ;
2018-03-29 17:01:57 -04:00
}
if ( dwFlags & BT_ECHORESPONSE )
{
if ( dwSize < 8 )
{
FlagEvilClient ( ) ;
return ;
}
else
{
pbData + = sizeof ( float ) ;
pbData + = sizeof ( float ) ;
}
dwSize - = 8 ;
}
if ( dwFlags & BT_FLOW )
{
if ( dwSize < 6 )
{
FlagEvilClient ( ) ;
return ;
}
else
{
2019-07-07 20:56:15 +00:00
uint32_t dwBytes = * ( ( uint32_t * ) pbData ) ;
pbData + = sizeof ( uint32_t ) ;
2018-03-29 17:01:57 -04:00
WORD wElapsed = * ( ( WORD * ) pbData ) ;
pbData + = sizeof ( WORD ) ;
//LOG(Temp, Normal, "Flow: %u bytes over %u seconds\n", dwBytes, wElapsed );
}
dwSize - = 6 ;
}
if ( dwFlags & BT_FRAGMENTS )
{
while ( dwSize > = sizeof ( FragHeader_s ) )
{
FragPacket_s * frag = ( FragPacket_s * ) pbData ;
if ( dwSize < frag - > header . wSize )
break ;
pbData + = frag - > header . wSize ;
dwSize - = frag - > header . wSize ;
BYTE * data = frag - > data ;
2019-07-07 20:56:15 +00:00
uint32_t length = frag - > header . wSize - sizeof ( FragHeader_s ) ;
2018-03-29 17:01:57 -04:00
if ( frag - > header . wCount = = 1 )
{
ProcessMessage ( data , length , frag - > header . wGroup ) ;
}
else
{
FragmentList : : iterator it ;
2019-07-07 20:56:15 +00:00
uint64_t fragID = frag - > header . id ;
2018-03-29 17:01:57 -04:00
bool bCompleted = false ;
for ( it = m_in . fragstack . begin ( ) ; it ! = m_in . fragstack . end ( ) ; it + + )
{
FragmentStack * s = * it ;
if ( s - > _id = = fragID )
{
s - > AddFragment ( frag ) ;
if ( s - > IsComplete ( ) )
{
ProcessMessage ( s - > GetData ( ) , s - > GetLength ( ) , frag - > header . wGroup ) ;
delete s ;
m_in . fragstack . erase ( it ) ;
bCompleted = true ;
}
break ;
}
}
if ( ! bCompleted )
{
if ( it = = m_in . fragstack . end ( ) )
{
// No existing group matches, create one
FragmentStack * s = new FragmentStack ( frag ) ;
m_in . fragstack . push_back ( s ) ;
}
}
}
}
}
}
2019-07-07 20:56:15 +00:00
void CPacketController : : ProcessMessage ( BYTE * data , uint32_t length , WORD group )
2018-03-29 17:01:57 -04:00
{
if ( m_pClient - > IsAlive ( ) )
m_pClient - > ProcessMessage ( data , length , group ) ;
}
void CPacketController : : IncomingBlob ( BlobPacket_s * blob , double recvTime )
{
//No CRC checks as of yet.
BlobHeader_s * header = & blob - > header ;
2019-07-07 20:56:15 +00:00
uint32_t dwSequence = header - > dwSequence ;
uint32_t dwFlags = header - > dwFlags ;
uint32_t dwCRC = header - > dwCRC ;
uint32_t dwSize = header - > wSize ;
2018-03-29 17:01:57 -04:00
BYTE * pbData = blob - > data ;
m_in . receivedbytes + = header - > wSize + sizeof ( BlobHeader_s ) ;
if ( dwSequence > m_in . sequence )
m_in . sequence = dwSequence ;
# if 1
if ( g_pConfig - > SpeedHackKicking ( ) )
{
if ( ! m_in . _clientIntervalBase )
{
m_in . _clientIntervalBase = header - > wTime ;
m_in . _clientIntervalBaseStart = recvTime ;
}
else
{
short intervalDiff = ( short ) ( header - > wTime - m_in . _clientIntervalBase ) ;
2018-08-22 04:34:58 -05:00
if ( intervalDiff > 120 | | intervalDiff < 0 )
2018-03-29 17:01:57 -04:00
{
m_in . _clientIntervalBase = header - > wTime ;
m_in . _clientIntervalBaseStart = recvTime ;
}
2018-08-22 04:34:58 -05:00
else if ( intervalDiff > 30 )
2018-03-29 17:01:57 -04:00
{
2019-07-07 20:56:15 +00:00
uint32_t expectedIntervals = ( recvTime - m_in . _clientIntervalBaseStart ) * 2.0 ;
uint32_t actualIntervals = intervalDiff ;
2018-03-29 17:01:57 -04:00
2018-07-31 23:56:39 -05:00
double rate = ( double ) actualIntervals / ( double ) expectedIntervals ;
if ( rate > g_pConfig - > SpeedHackKickThreshold ( ) )
2018-03-29 17:01:57 -04:00
{
2018-07-31 23:56:39 -05:00
SERVER_ERROR < < " Possible speed hack on user: " < < m_pClient - > GetDescription ( ) < < " ([rate: " < < rate < < " ]) Disconnecting. " ;
2018-03-29 17:01:57 -04:00
Kill ( __FILE__ , __LINE__ ) ;
/*
if ( m_pClient & & m_pClient - > GetEvents ( ) & & m_pClient - > GetEvents ( ) - > GetPlayer ( ) )
{
if ( g_pWorld )
g_pWorld - > BroadcastGlobal ( ServerText ( csprintf ( " %s has been detected using a possible speed hack and has been kicked. " , m_pClient - > GetEvents ( ) - > GetPlayer ( ) - > GetName ( ) . c_str ( ) ) , 1 ) , PRIVATE_MSG ) ;
}
*/
}
}
}
}
# endif
if ( dwFlags & BT_DISCONNECT )
{
Kill ( __FILE__ , __LINE__ ) ;
return ;
}
if ( dwFlags & BT_REQUESTLOST )
{
ProcessBlob ( blob ) ;
return ;
}
if ( ! dwSequence )
{
ProcessBlob ( blob ) ;
return ;
}
if ( dwSequence < = m_in . activesequence ) return ;
// Cache this blob, for later use.
if ( m_in . blobstack . find ( dwSequence ) ! = m_in . blobstack . end ( ) )
{
// LOG(Temp, Normal, "Already had blob sequence!\n");
}
else
{
DUPEBLOB ( p , blob ) ;
2019-07-07 20:56:15 +00:00
m_in . blobstack . insert ( std : : pair < uint32_t , BlobPacket_s * > ( dwSequence , p ) ) ;
2018-03-29 17:01:57 -04:00
}
}
void CPacketController : : ResendBlob ( BlobPacket_s * blob )
{
BlobHeader_s * header = & blob - > header ;
header - > dwFlags | = BT_RESENT ;
2019-07-07 20:56:15 +00:00
uint32_t dwXOR = header - > dwCRC ;
2018-03-29 17:01:57 -04:00
header - > dwCRC = BlobCRC ( blob , dwXOR ) ;
//Off you go.
g_pNetwork - > QueuePacket ( m_pPeer , blob , BLOBLEN ( blob ) ) ;
//Keep in cache.
header - > dwCRC = dwXOR ;
m_out . _sentBytes + = header - > wSize + sizeof ( BlobHeader_s ) ;
}
void CPacketController : : SendFragmentBlob ( BlobPacket_s * blob )
{
BlobHeader_s * header = & blob - > header ;
header - > dwSequence = GetNextSequence ( ) ;
header - > dwFlags = BT_FRAGMENTS | BT_USES_CRC ;
header - > dwCRC = 0 ;
header - > wRecID = g_pNetwork - > GetServerID ( ) ;
header - > wTime = GetElapsedTime ( ) ;
header - > wTable = 0x01 ;
2019-07-07 20:56:15 +00:00
uint32_t dwXOR = GetNextXORVal ( m_out . crypto ) ;
2018-03-29 17:01:57 -04:00
header - > dwCRC = BlobCRC ( blob , dwXOR ) ;
//Off you go.
g_pNetwork - > QueuePacket ( m_pPeer , blob , BLOBLEN ( blob ) ) ;
//Cache for later use.
header - > dwCRC = dwXOR ;
m_out . _blobCache . Lock ( ) ;
2019-07-07 20:56:15 +00:00
m_out . _blobCache . insert ( std : : pair < uint32_t , BlobPacket_s * > ( header - > dwSequence , blob ) ) ;
2018-03-29 17:01:57 -04:00
m_out . _blobCache . Unlock ( ) ;
m_out . _sentBytes + = header - > wSize + sizeof ( BlobHeader_s ) ;
}
2019-04-13 18:18:28 +00:00
void CPacketController : : SendCriticalError ( uint32_t table , uint32_t stringId )
{
//Bad login.
CREATEBLOB ( critErr , sizeof ( uint32_t ) * 2 ) ;
( ( uint32_t * ) critErr - > data ) [ 0 ] = stringId ;
( ( uint32_t * ) critErr - > data ) [ 1 ] = ST_SERVER_ERRORS ;
g_pNetwork - > SendConnectlessBlob ( m_pPeer , critErr , BT_NETERROR , 0 , 0 , true ) ;
DELETEBLOB ( critErr ) ;
Kill ( __FILE__ , __LINE__ ) ;
}
2018-03-29 17:01:57 -04:00
// Sends all the queued fragments
void CPacketController : : FlushFragments ( )
{
m_out . _fragQueue . Lock ( ) ;
auto entry = m_out . _fragQueue . begin ( ) ;
if ( entry = = m_out . _fragQueue . end ( ) )
{
m_out . _fragQueue . Unlock ( ) ;
return ;
}
2018-10-02 17:33:30 -05:00
//m_out._fragQueue.size();
2018-03-29 17:01:57 -04:00
BlobPacket_s * blob = ( BlobPacket_s * ) new BYTE [ MAX_BLOB_LEN ] ;
blob - > header . wSize = 0 ;
do
{
// copy it locally
FragPacket_s * edible = * entry ;
// remove
m_out . _fragQueue . erase ( entry ) ;
m_out . _fragQueue . Unlock ( ) ;
if ( ( blob - > header . wSize + edible - > header . wSize ) < ( MAX_BLOB_LEN - sizeof ( BlobHeader_s ) ) )
{
BYTE * dataPos = & blob - > data [ blob - > header . wSize ] ;
WORD wSize = edible - > header . wSize ;
memcpy ( dataPos , edible , wSize ) ;
blob - > header . wSize + = wSize ;
}
else
{
// this one is full, let's send it and make a new one.
SendFragmentBlob ( blob ) ;
blob = ( BlobPacket_s * ) new BYTE [ MAX_BLOB_LEN ] ;
WORD wSize = blob - > header . wSize = edible - > header . wSize ;
memcpy ( blob - > data , edible , wSize ) ;
}
delete [ ] ( ( BYTE * ) edible ) ;
m_out . _fragQueue . Lock ( ) ;
entry = m_out . _fragQueue . begin ( ) ;
} while ( entry ! = m_out . _fragQueue . end ( ) ) ;
m_out . _fragQueue . Unlock ( ) ;
SendFragmentBlob ( blob ) ;
}
2019-07-07 20:56:15 +00:00
void CPacketController : : QueueNetMessage ( void * data , uint32_t length , WORD group , uint32_t weenie_id , bool ephemeral )
2018-03-29 17:01:57 -04:00
{
if ( ! IsAlive ( ) )
{
return ;
}
BYTE * messageData ;
2019-07-07 20:56:15 +00:00
uint32_t messageLength ;
2018-03-29 17:01:57 -04:00
if ( weenie_id )
{
messageLength = sizeof ( EventHeader ) + length ;
messageData = new BYTE [ messageLength ] ;
EventHeader * gameEvent = ( EventHeader * ) messageData ;
gameEvent - > dwF7B0 = 0xF7B0 ;
gameEvent - > dwPlayer = weenie_id ;
gameEvent - > dwSequence = GetNextEvent ( ) ;
memcpy ( ( BYTE * ) messageData + sizeof ( EventHeader ) , data , length ) ;
}
else
{
messageLength = length ;
messageData = new BYTE [ messageLength ] ;
memcpy ( messageData , data , length ) ;
}
COutgoingNetMessage message ;
message . data = messageData ;
message . length = messageLength ;
message . group_id = group ;
2019-05-12 09:21:34 -07:00
message . ephemeral = ephemeral ;
2018-03-29 17:01:57 -04:00
_outgoingMessageQueue . Lock ( ) ;
_outgoingMessageQueue . push_back ( message ) ;
_outgoingMessageQueue . Unlock ( ) ;
}
void CPacketController : : FlushQueuedNetMessages ( )
{
_outgoingMessageQueue . Lock ( ) ;
auto entry = _outgoingMessageQueue . begin ( ) ;
while ( entry ! = _outgoingMessageQueue . end ( ) )
{
// copy it locally
COutgoingNetMessage queued = * entry ;
// remove
_outgoingMessageQueue . erase ( entry ) ;
// unlock while we send it
_outgoingMessageQueue . Unlock ( ) ;
2019-05-12 09:21:34 -07:00
SendNetMessageInternal ( queued . data , queued . length , queued . group_id , queued . ephemeral ) ;
2018-03-29 17:01:57 -04:00
delete [ ] queued . data ;
_outgoingMessageQueue . Lock ( ) ;
entry = _outgoingMessageQueue . begin ( ) ;
}
_outgoingMessageQueue . Unlock ( ) ;
}