polserver/pol-core/pol/network/packets.cpp
turleypol 76d9c5e9d6
not yet active: handle update range of client. (#440)
* not yet active: handle update range of client.

* allow down to 5 as client view range

* try to secure testclient against racecondition
2021-10-28 23:08:38 +02:00

529 lines
17 KiB
C++

/** @file
*
* @par History
*
* @note New packet add:
* - PacketsSingleton::PacketsSingleton() add queue for it
* - PacketInterface* GetPacket(u8 id, u16 sub) add pkt create
*/
#include "packets.h"
#include "../../clib/rawtypes.h"
#include "../../clib/spinlock.h"
#include "packethelper.h"
#include "packetinterface.h"
#include "pktboth.h"
#include "pktbothid.h"
namespace Pol
{
namespace Network
{
using namespace PktHelper;
using namespace PacketWriterDefs;
/** @class PacketsSingleton
* Central class that holds every pkt object
*
* This way client doesnt need to create pkts, just requests a object and
* after sending readds it
*/
PacketsSingleton::PacketsSingleton()
{
using namespace Core;
// insert packet queues at first creation
packets.insert( PacketQueuePair( ENCRYPTEDPKTBUFFER, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_0B_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_11_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_17_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_1A_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_1B_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_1C_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_1D_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_20_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_21_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTBI_22_APPROVED_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_24_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_25_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_27_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_29_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTBI_2C_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_2D_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_2E_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_2F_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTBI_3A_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTBI_3B_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_3C_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_4F_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_53_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_54_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_55_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTBI_56_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_65_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTBI_66_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTBI_6C_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_6D_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_6E_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTBI_6F_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_70_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTBI_72_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_74_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_76_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_77_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_78_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_7C_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_82_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_88_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_89_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_8C_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_90_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTBI_93_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTBI_95_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTBI_98_OUT_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTBI_99_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTBI_9A_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_9E_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_A1_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_A2_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_A3_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_A5_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_A6_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_A8_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_A9_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_AA_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_AB_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_AE_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_AF_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_B0_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_B7_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTBI_B8_OUT_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_B9_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_BA_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_BC_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTBI_BF_ID, new PacketQueueSubs() ) );
packets.insert( PacketQueuePair( PKTOUT_C1_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTBI_C2_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_C7_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTBI_C8_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_CC_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTBI_D6_OUT_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_DC_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_DD_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_DF_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_E2_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_E3_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTBI_F0_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_F3_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_F5_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_F6_ID, new PacketQueueSingle() ) );
packets.insert( PacketQueuePair( PKTOUT_F7_ID, new PacketQueueSingle() ) );
}
PacketsSingleton::~PacketsSingleton()
{
for ( auto& pkts : packets )
{
delete pkts.second;
}
packets.clear();
}
PacketInterface* PacketsSingleton::getPacket( u8 id, u16 sub )
{
PacketQueueMap::iterator itr = packets.find( id );
if ( itr != packets.end() )
return itr->second->GetNext( id, sub );
throw std::runtime_error( "Request of undefined Packet: " + Clib::hexint( id ) + "-" +
Clib::hexint( sub ) );
}
void PacketsSingleton::ReAddPacket( PacketInterface* pkt )
{
PacketQueueMap::iterator itr = packets.find( pkt->getID() );
if ( itr != packets.end() )
itr->second->Add( pkt );
else
delete pkt;
}
size_t PacketsSingleton::estimateSize() const
{
size_t size = sizeof( PacketsSingleton );
for ( const auto& pkts : packets )
{
size += sizeof( pkts.first ) + ( sizeof( void* ) * 3 + 1 ) / 2;
size += pkts.second->estimateSize();
}
return size;
}
PacketQueueSingle::PacketQueueSingle() : _packets(), _lock() {}
PacketInterface* PacketQueueSingle::GetNext( u8 id, u16 /*sub*/ )
{
// critical start
Clib::SpinLockGuard lock( _lock );
PacketInterface* pkt;
if ( !_packets.empty() )
{
pkt = _packets.front(); // get next one
_packets.pop(); // and remove it from queue
pkt->ReSetBuffer();
}
else
pkt = GetPacket( id );
return pkt;
// critical end
}
PacketQueueSingle::~PacketQueueSingle()
{
Clib::SpinLockGuard lock( _lock );
while ( !_packets.empty() )
{
PacketInterface* pkt = _packets.front();
_packets.pop();
delete pkt;
}
}
void PacketQueueSingle::Add( PacketInterface* pkt )
{
Clib::SpinLockGuard lock( _lock );
if ( _packets.size() > MAX_PACKETS_INSTANCES ) // enough?
delete pkt;
else
{
_packets.push( pkt ); // readd it
}
}
size_t PacketQueueSingle::estimateSize() const
{
Clib::SpinLockGuard lock( _lock );
size_t size = sizeof( PacketQueueSingle );
if ( !_packets.empty() )
size += _packets.front()->estimateSize() * _packets.size();
return size;
}
PacketQueueSubs::PacketQueueSubs() : _packets(), _lock() {}
PacketQueueSubs::~PacketQueueSubs()
{
Clib::SpinLockGuard lock( _lock );
for ( auto& pkts : _packets )
{
while ( !pkts.second.empty() )
{
PacketInterface* pkt = pkts.second.front();
pkts.second.pop();
delete pkt;
}
}
_packets.clear();
}
PacketInterface* PacketQueueSubs::GetNext( u8 id, u16 sub )
{
// critical start
Clib::SpinLockGuard lock( _lock );
PacketInterface* pkt;
if ( !_packets.empty() )
{
PacketInterfaceQueueMap::iterator itr = _packets.find( sub );
if ( itr != _packets.end() )
{
if ( !itr->second.empty() )
{
pkt = itr->second.front(); // get next one
itr->second.pop(); // and remove it from queue
pkt->ReSetBuffer();
return pkt;
}
}
}
pkt = GetPacket( id, sub );
return pkt;
// critical end
}
void PacketQueueSubs::Add( PacketInterface* pkt )
{
u16 sub = pkt->getSubID();
// critical start
Clib::SpinLockGuard lock( _lock );
PacketInterfaceQueueMap::iterator itr = _packets.find( sub );
if ( itr != _packets.end() )
{
if ( itr->second.size() > MAX_PACKETS_INSTANCES ) // enough?
delete pkt;
else
itr->second.push( pkt ); // readd it
}
else // new sub
{
PacketInterfaceQueue qu;
qu.push( pkt );
_packets.insert( PacketInterfaceQueuePair( sub, qu ) );
}
// critical end
}
size_t PacketQueueSubs::Count() const
{
Clib::SpinLockGuard lock( _lock );
size_t count = 0;
for ( const auto& pkts : _packets )
{
count += pkts.second.size();
}
return count;
}
size_t PacketQueueSubs::estimateSize() const
{
Clib::SpinLockGuard lock( _lock );
size_t size = sizeof( PacketQueueSubs );
for ( const auto& pkts : _packets )
{
size += sizeof( pkts.first ) + ( sizeof( void* ) * 3 + 1 ) / 2;
if ( pkts.second.size() )
size += pkts.second.front()->estimateSize() * pkts.second.size();
}
return size;
}
namespace PktHelper
{
// creates new packets
PacketInterface* GetPacket( u8 id, u16 sub )
{
using namespace Core;
switch ( id )
{
case ENCRYPTEDPKTBUFFER:
return new EncryptedPktBuffer();
case PKTOUT_0B_ID:
return new PktOut_0B();
case PKTOUT_11_ID:
return new PktOut_11();
case PKTOUT_17_ID:
return new PktOut_17();
case PKTOUT_1A_ID:
return new PktOut_1A();
case PKTOUT_1B_ID:
return new PktOut_1B();
case PKTOUT_1C_ID:
return new PktOut_1C();
case PKTOUT_1D_ID:
return new PktOut_1D();
case PKTOUT_20_ID:
return new PktOut_20();
case PKTOUT_21_ID:
return new PktOut_21();
case PKTBI_22_APPROVED_ID:
return new PktOut_22();
case PKTOUT_24_ID:
return new PktOut_24();
case PKTOUT_25_ID:
return new PktOut_25();
case PKTOUT_27_ID:
return new PktOut_27();
case PKTOUT_29_ID:
return new PktOut_29();
case PKTBI_2C_ID:
return new PktOut_2C();
case PKTOUT_2D_ID:
return new PktOut_2D();
case PKTOUT_2E_ID:
return new PktOut_2E();
case PKTOUT_2F_ID:
return new PktOut_2F();
case PKTBI_3A_ID:
return new PktOut_3A();
case PKTBI_3B_ID:
return new PktOut_3B();
case PKTOUT_3C_ID:
return new PktOut_3C();
case PKTOUT_4F_ID:
return new PktOut_4F();
case PKTOUT_53_ID:
return new PktOut_53();
case PKTOUT_54_ID:
return new PktOut_54();
case PKTOUT_55_ID:
return new PktOut_55();
case PKTBI_56_ID:
return new PktOut_56();
case PKTOUT_65_ID:
return new PktOut_65();
case PKTBI_66_ID:
return new PktOut_66();
case PKTBI_6C_ID:
return new PktOut_6C();
case PKTOUT_6D_ID:
return new PktOut_6D();
case PKTOUT_6E_ID:
return new PktOut_6E();
case PKTBI_6F_ID:
return new PktOut_6F();
case PKTOUT_70_ID:
return new PktOut_70();
case PKTBI_72_ID:
return new PktOut_72();
case PKTOUT_74_ID:
return new PktOut_74();
case PKTOUT_76_ID:
return new PktOut_76();
case PKTOUT_77_ID:
return new PktOut_77();
case PKTOUT_78_ID:
return new PktOut_78();
case PKTOUT_7C_ID:
return new PktOut_7C();
case PKTOUT_82_ID:
return new PktOut_82();
case PKTOUT_88_ID:
return new PktOut_88();
case PKTOUT_89_ID:
return new PktOut_89();
case PKTOUT_8C_ID:
return new PktOut_8C();
case PKTOUT_90_ID:
return new PktOut_90();
case PKTBI_93_ID:
return new PktOut_93();
case PKTBI_95_ID:
return new PktOut_95();
case PKTBI_98_OUT_ID:
return new PktOut_98();
case PKTBI_99_ID:
return new PktOut_99();
case PKTBI_9A_ID:
return new PktOut_9A();
case PKTOUT_9E_ID:
return new PktOut_9E();
case PKTOUT_A1_ID:
return new PktOut_A1();
case PKTOUT_A2_ID:
return new PktOut_A2();
case PKTOUT_A3_ID:
return new PktOut_A3();
case PKTOUT_A5_ID:
return new PktOut_A5();
case PKTOUT_A6_ID:
return new PktOut_A6();
case PKTOUT_A8_ID:
return new PktOut_A8();
case PKTOUT_A9_ID:
return new PktOut_A9();
case PKTOUT_AA_ID:
return new PktOut_AA();
case PKTOUT_AB_ID:
return new PktOut_AB();
case PKTOUT_AE_ID:
return new PktOut_AE();
case PKTOUT_AF_ID:
return new PktOut_AF();
case PKTOUT_B0_ID:
return new PktOut_B0();
case PKTOUT_B7_ID:
return new PktOut_B7();
case PKTBI_B8_OUT_ID:
return new PktOut_B8();
case PKTOUT_B9_ID:
return new PktOut_B9();
case PKTOUT_BA_ID:
return new PktOut_BA();
case PKTOUT_BC_ID:
return new PktOut_BC();
case PKTBI_BF_ID:
{
switch ( sub )
{
case Core::PKTBI_BF::TYPE_CLOSE_GUMP:
return new PktOut_BF_Sub4();
case Core::PKTBI_BF::TYPE_PARTY_SYSTEM:
return new PktOut_BF_Sub6();
case Core::PKTBI_BF::TYPE_CURSOR_HUE:
return new PktOut_BF_Sub8();
case Core::PKTBI_BF::TYPE_OBJECT_CACHE:
return new PktOut_BF_Sub10();
case Core::PKTBI_BF::TYPE_DISPLAY_POPUP_MENU:
return new PktOut_BF_Sub14();
case Core::PKTBI_BF::TYPE_CLOSE_WINDOW:
return new PktOut_BF_Sub16();
case Core::PKTBI_BF::TYPE_ENABLE_MAP_DIFFS:
return new PktOut_BF_Sub18();
case Core::PKTBI_BF::TYPE_EXTENDED_STATS_OUT:
return new PktOut_BF_Sub19();
case Core::PKTBI_BF::TYPE_NEW_SPELLBOOK:
return new PktOut_BF_Sub1B();
case Core::PKTBI_BF::TYPE_CUSTOM_HOUSE_SHORT:
return new PktOut_BF_Sub1D();
case Core::PKTBI_BF::TYPE_ACTIVATE_CUSTOM_HOUSE_TOOL:
return new PktOut_BF_Sub20();
case Core::PKTBI_BF::TYPE_DAMAGE:
return new PktOut_BF_Sub22();
case Core::PKTBI_BF::TYPE_CHARACTER_RACE_CHANGER:
return new PktOut_BF_Sub2A();
default:
throw std::runtime_error( "Request of undefined Packet: " + Clib::hexint( id ) + "-" +
Clib::hexint( sub ) );
}
}
case PKTOUT_C1_ID:
return new PktOut_C1();
case PKTBI_C2_ID:
return new PktOut_C2();
case PKTOUT_C7_ID:
return new PktOut_C7();
case PKTBI_C8_ID:
return new PktOut_C8();
case PKTOUT_CC_ID:
return new PktOut_CC();
case PKTBI_D6_OUT_ID:
return new PktOut_D6();
case PKTOUT_DC_ID:
return new PktOut_DC();
case PKTOUT_DD_ID:
return new PktOut_DD();
case PKTOUT_DF_ID:
return new PktOut_DF();
case PKTOUT_E2_ID:
return new PktOut_E2();
case PKTOUT_E3_ID:
return new PktOut_E3();
case PKTOUT_F3_ID:
return new PktOut_F3();
case PKTOUT_F5_ID:
return new PktOut_F5();
case PKTOUT_F6_ID:
return new PktOut_F6();
case PKTOUT_F7_ID:
return new PktOut_F7();
case PKTBI_F0_ID:
switch ( sub )
{
case Core::PKTBI_F0::QUERY_PARTY:
return new PktOut_F0_Sub01();
case Core::PKTBI_F0::QUERY_GUILD:
return new PktOut_F0_Sub02();
default:
throw std::runtime_error( "Request of undefined Packet: " + Clib::hexint( id ) + "-" +
Clib::hexint( sub ) );
}
default:
throw std::runtime_error( "Request of undefined Packet: " + Clib::hexint( id ) + "-" +
Clib::hexint( sub ) );
}
}
} // namespace PktHelper
} // namespace Network
} // namespace Pol