mirror of
https://github.com/ACEmulator/ACE
synced 2026-08-17 12:26:06 -04:00
* adding @netstats admin command * trying to figure out the issue * fixing bug causing AcknowledgeSequence packets to increment the lastReceivedFragmentSequence variable, causing the Sequence to break and never recover for that session fixing bug causing RequestTransmit packets to be ignored fixing bug causing the server to crash when a C2S packet is corrupt or malformed changing the C2S RequestForTransmit packet count to be per request packet instead of per requested sequence adding Developer commands junk, junk_s2c, junk_c2s, trash_s2c, and trash_c2s to simulate bad connections and manually corrupt packets * updating changelog.md * Update changelog.md fixed incorrect variable name referred to in change log * Update changelog.md fix formatting * adding preprocessor definition NETDIAG and directives to ACE.Common and ACE.Server to help development by preserving troubleshooting tools without interference with the optimal solution * Apply suggestions from code review set accessor only needed for NETDIAG functionality minor change log addition * reverting some unnecessary source syntax and formatting changes. removing an unused exception variable * reverting some unnecessary source syntax and formatting changes * minor optimization of a duplicate prevention check
123 lines
5 KiB
C#
123 lines
5 KiB
C#
using System.Collections.Generic;
|
|
using System.IO;
|
|
using ACE.Common.Cryptography;
|
|
|
|
namespace ACE.Server.Network
|
|
{
|
|
public class PacketHeaderOptional
|
|
{
|
|
public uint Size { get; private set; }
|
|
|
|
public uint Sequence { get; private set; }
|
|
public double TimeSynch { get; private set; }
|
|
public float EchoRequestClientTime { get; private set; }
|
|
public List<uint> RetransmitData { get; } = new List<uint>();
|
|
public bool IsValid { get; private set; } = true;
|
|
|
|
private MemoryStream headerBytes = new MemoryStream();
|
|
|
|
public byte[] Bytes => headerBytes.ToArray();
|
|
|
|
public PacketHeaderOptional(BinaryReader payload, PacketHeader header)
|
|
{
|
|
Size = (uint)payload.BaseStream.Position;
|
|
BinaryWriter writer = new BinaryWriter(headerBytes);
|
|
|
|
if (header.HasFlag(PacketHeaderFlags.ServerSwitch)) // 0x100
|
|
writer.Write(payload.ReadBytes(8));
|
|
|
|
if (header.HasFlag(PacketHeaderFlags.RequestRetransmit)) // 0x1000
|
|
{
|
|
if (payload.BaseStream.Length < payload.BaseStream.Position + 4) { IsValid = false; return; }
|
|
uint retransmitCount = payload.ReadUInt32();
|
|
writer.Write(retransmitCount);
|
|
for (uint i = 0u; i < retransmitCount; i++)
|
|
{
|
|
if (payload.BaseStream.Length < payload.BaseStream.Position + 4) { IsValid = false; return; }
|
|
uint sequence = payload.ReadUInt32();
|
|
writer.Write(sequence);
|
|
RetransmitData.Add(sequence);
|
|
}
|
|
}
|
|
|
|
if (header.HasFlag(PacketHeaderFlags.RejectRetransmit)) // 0x2000
|
|
{
|
|
if (payload.BaseStream.Length < payload.BaseStream.Position + 4) { IsValid = false; return; }
|
|
uint count = payload.ReadUInt32();
|
|
writer.Write(count);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
if (payload.BaseStream.Length < payload.BaseStream.Position + 4) { IsValid = false; return; }
|
|
writer.Write(payload.ReadBytes(4));
|
|
}
|
|
}
|
|
|
|
if (header.HasFlag(PacketHeaderFlags.AckSequence)) // 0x4000
|
|
{
|
|
if (payload.BaseStream.Length < payload.BaseStream.Position + 4) { IsValid = false; return; }
|
|
Sequence = payload.ReadUInt32();
|
|
writer.Write(Sequence);
|
|
}
|
|
|
|
if (header.HasFlag(PacketHeaderFlags.LoginRequest)) // 0x10000
|
|
{
|
|
var position = payload.BaseStream.Position;
|
|
var length = payload.BaseStream.Length - position;
|
|
if (length < 1) { IsValid = false; return; }
|
|
byte[] loginBytes = new byte[length];
|
|
payload.BaseStream.Read(loginBytes, (int)position, (int)length);
|
|
writer.Write(loginBytes);
|
|
payload.BaseStream.Position = position;
|
|
}
|
|
|
|
if (header.HasFlag(PacketHeaderFlags.WorldLoginRequest)) // 0x20000
|
|
{
|
|
if (payload.BaseStream.Length < payload.BaseStream.Position + 8) { IsValid = false; return; }
|
|
var position = payload.BaseStream.Position;
|
|
writer.Write(payload.ReadBytes(8));
|
|
payload.BaseStream.Position = position;
|
|
}
|
|
|
|
if (header.HasFlag(PacketHeaderFlags.ConnectResponse)) // 0x80000
|
|
{
|
|
var position = payload.BaseStream.Position;
|
|
if (payload.BaseStream.Length < payload.BaseStream.Position + 8) { IsValid = false; return; }
|
|
writer.Write(payload.ReadBytes(8));
|
|
payload.BaseStream.Position = position;
|
|
}
|
|
|
|
if (header.HasFlag(PacketHeaderFlags.CICMDCommand)) // 0x400000
|
|
{
|
|
if (payload.BaseStream.Length < payload.BaseStream.Position + 8) { IsValid = false; return; }
|
|
writer.Write(payload.ReadBytes(8));
|
|
}
|
|
|
|
if (header.HasFlag(PacketHeaderFlags.TimeSync)) // 0x1000000
|
|
{
|
|
if (payload.BaseStream.Length < payload.BaseStream.Position + 8) { IsValid = false; return; }
|
|
TimeSynch = payload.ReadDouble();
|
|
writer.Write(TimeSynch);
|
|
}
|
|
|
|
if (header.HasFlag(PacketHeaderFlags.EchoRequest)) // 0x2000000
|
|
{
|
|
if (payload.BaseStream.Length < payload.BaseStream.Position + 4) { IsValid = false; return; }
|
|
EchoRequestClientTime = payload.ReadSingle();
|
|
writer.Write(EchoRequestClientTime);
|
|
}
|
|
|
|
if (header.HasFlag(PacketHeaderFlags.Flow)) // 0x8000000
|
|
{
|
|
if (payload.BaseStream.Length < payload.BaseStream.Position + 6) { IsValid = false; return; }
|
|
writer.Write(payload.ReadBytes(6));
|
|
}
|
|
|
|
Size = (uint)payload.BaseStream.Position - Size;
|
|
}
|
|
|
|
public uint CalculateHash32()
|
|
{
|
|
return Hash32.Calculate(Bytes, Bytes.Length);
|
|
}
|
|
}
|
|
}
|