2018-02-09 20:55:11 -08:00
using System ;
using System.IO ;
2018-08-26 06:45:47 -05:00
2019-12-30 19:10:12 -06:00
using log4net ;
using ACE.Common.Cryptography ;
2018-02-08 17:05:02 -06:00
namespace ACE.Server.Network
2017-02-17 15:05:03 -05:00
{
public class ClientPacket : Packet
{
2018-08-26 06:45:47 -05:00
private static readonly ILog packetLog = LogManager . GetLogger ( System . Reflection . Assembly . GetEntryAssembly ( ) , "Packets" ) ;
2018-12-10 20:44:30 -06:00
public static int MaxPacketSize { get ; } = 1024 ;
2019-12-30 19:10:12 -06:00
public BinaryReader DataReader { get ; private set ; }
public PacketHeaderOptional HeaderOptional { get ; } = new PacketHeaderOptional ( ) ;
2018-02-09 20:55:11 -08:00
2020-07-11 08:35:28 -05:00
/// <summary>
/// If you pass in a shared buffer, be sure to ReleaseBuffer() after you've processed the packet, and before you use the buffer again for the next job.
/// </summary>
public bool Unpack ( byte [ ] buffer , int bufferSize )
2018-02-09 20:55:11 -08:00
{
try
2017-02-17 15:05:03 -05:00
{
2020-07-11 08:35:28 -05:00
if ( bufferSize < PacketHeader . HeaderSize )
2019-12-30 19:10:12 -06:00
return false ;
2020-07-11 08:35:28 -05:00
Header . Unpack ( buffer ) ;
2019-12-30 19:10:12 -06:00
2020-07-11 08:35:28 -05:00
if ( Header . Size > bufferSize - PacketHeader . HeaderSize )
2019-12-30 19:10:12 -06:00
return false ;
2020-07-11 08:35:28 -05:00
Data = new MemoryStream ( buffer , PacketHeader . HeaderSize , Header . Size , false , true ) ;
2019-12-30 19:10:12 -06:00
DataReader = new BinaryReader ( Data ) ;
HeaderOptional . Unpack ( DataReader , Header ) ;
if ( ! HeaderOptional . IsValid )
return false ;
if ( ! ReadFragments ( ) )
return false ;
return true ;
2018-02-09 20:55:11 -08:00
}
2019-03-10 17:40:23 -04:00
catch ( Exception ex )
2018-02-09 20:55:11 -08:00
{
2019-03-10 17:40:23 -04:00
packetLog . Error ( "Invalid packet data" , ex ) ;
2019-12-30 19:10:12 -06:00
return false ;
2017-02-17 15:05:03 -05:00
}
}
2019-12-30 19:10:12 -06:00
private bool ReadFragments ( )
2017-02-17 15:05:03 -05:00
{
if ( Header . HasFlag ( PacketHeaderFlags . BlobFragments ) )
2017-03-15 19:31:47 -05:00
{
2019-12-30 19:10:12 -06:00
while ( DataReader . BaseStream . Position ! = DataReader . BaseStream . Length )
2018-11-30 23:58:00 -05:00
{
try
{
2019-12-30 19:10:12 -06:00
var fragment = new ClientPacketFragment ( ) ;
2020-04-11 12:54:25 -04:00
if ( ! fragment . Unpack ( DataReader ) ) return false ;
2019-12-30 19:10:12 -06:00
Fragments . Add ( fragment ) ;
2018-11-30 23:58:00 -05:00
}
catch ( Exception )
{
// corrupt packet
2019-12-30 19:10:12 -06:00
return false ;
2018-11-30 23:58:00 -05:00
}
}
2017-03-15 19:31:47 -05:00
}
2019-12-30 19:10:12 -06:00
return true ;
2017-02-17 15:05:03 -05:00
}
2017-04-01 21:01:50 -04:00
2020-07-11 08:35:28 -05:00
public void ReleaseBuffer ( )
{
Data = null ;
DataReader = null ;
}
2019-03-10 17:40:23 -04:00
private uint? _fragmentChecksum ;
private uint fragmentChecksum
{
get
{
if ( _fragmentChecksum = = null )
{
uint fragmentChecksum = 0 u ;
2019-12-30 19:10:12 -06:00
2019-03-10 17:40:23 -04:00
foreach ( ClientPacketFragment fragment in Fragments )
fragmentChecksum + = fragment . CalculateHash32 ( ) ;
2019-12-30 19:10:12 -06:00
2019-03-10 17:40:23 -04:00
_fragmentChecksum = fragmentChecksum ;
}
2019-12-30 19:10:12 -06:00
2019-03-10 17:40:23 -04:00
return _fragmentChecksum . Value ;
}
}
2019-12-30 19:10:12 -06:00
2019-03-10 17:40:23 -04:00
private uint? _headerChecksum ;
private uint headerChecksum
{
get
{
if ( _headerChecksum = = null )
_headerChecksum = Header . CalculateHash32 ( ) ;
2019-12-30 19:10:12 -06:00
2019-03-10 17:40:23 -04:00
return _headerChecksum . Value ;
}
}
2019-12-30 19:10:12 -06:00
2019-03-10 17:40:23 -04:00
private uint? _headerOptionalChecksum ;
private uint headerOptionalChecksum
{
get
{
if ( _headerOptionalChecksum = = null )
_headerOptionalChecksum = HeaderOptional . CalculateHash32 ( ) ;
2019-12-30 19:10:12 -06:00
2019-03-10 17:40:23 -04:00
return _headerOptionalChecksum . Value ;
}
}
2019-12-30 19:10:12 -06:00
2019-03-10 17:40:23 -04:00
private uint? _payloadChecksum ;
private uint payloadChecksum
2017-04-01 21:01:50 -04:00
{
2019-03-10 17:40:23 -04:00
get
{
if ( _payloadChecksum = = null )
_payloadChecksum = headerOptionalChecksum + fragmentChecksum ;
2019-12-30 19:10:12 -06:00
2019-03-10 17:40:23 -04:00
return _payloadChecksum . Value ;
}
}
2019-12-21 08:29:05 -05:00
public bool VerifyCRC ( CryptoSystem fq )
2019-03-10 17:40:23 -04:00
{
if ( Header . HasFlag ( PacketHeaderFlags . EncryptedChecksum ) )
{
2020-04-11 12:54:25 -04:00
var key = ( ( Header . Checksum - headerChecksum ) ^ payloadChecksum ) ;
if ( fq . Search ( key ) )
{
fq . ConsumeKey ( key ) ;
2019-03-10 17:40:23 -04:00
return true ;
2020-04-11 12:54:25 -04:00
}
2019-03-10 17:40:23 -04:00
}
else
{
2020-04-11 12:54:25 -04:00
if ( headerChecksum + payloadChecksum = = Header . Checksum )
2019-03-10 17:40:23 -04:00
{
2026-08-03 11:48:37 +00:00
if ( packetLog . IsDebugEnabled )
packetLog . DebugFormat ( "{0}" , this ) ;
2019-12-16 12:06:22 -05:00
return true ;
2019-03-10 17:40:23 -04:00
}
2019-12-30 19:10:12 -06:00
2026-08-03 11:48:37 +00:00
if ( packetLog . IsDebugEnabled )
packetLog . DebugFormat ( "{0}, Checksum Failed" , this ) ;
2019-03-10 17:40:23 -04:00
}
2019-12-30 19:10:12 -06:00
2019-03-10 17:40:23 -04:00
NetworkStatistics . C2S_CRCErrors_Aggregate_Increment ( ) ;
2019-12-30 19:10:12 -06:00
2019-03-10 17:40:23 -04:00
return false ;
}
public override string ToString ( )
{
return $"<<< {Header} {HeaderOptional}" . TrimEnd ( ) ;
2017-04-01 21:01:50 -04:00
}
2017-02-17 15:05:03 -05:00
}
}