feat: Adds a memory mirrored ring buffer for networking. (#1533)
## Breaking Changes
Incoming packet registration signature has changed to:
```cs
delegate* void OnReceiveCallback(NetState state, SpanReader reader, int packetLength);
IncomingPackets.Register(int packetID, int length, bool ingame, OnReceiveCallback onReceive);
```
For example, an incoming packet handler signature would now look like this:
```cs
public static void SomeIncomingPacket(NetState state, SpanReader reader, int packetLength)
{
// Parse the data
}
```
## Summary
Updates the network Pipe class to use a mirrored memory technique. This technique involves mapping the same physical memory to two contiguous virtual memory spaces so the byte buffer appears duplicated. This allows writing to a double-sized array to wrap around without the need for the `CircularBuffer` classes.
In practice this allows us to use `Span<byte>` as if the buffer was a regular array.
### Bug Fixes
- [X] Fixes bad fixed length string parsing
This commit is contained in:
parent
629a5008c3
commit
10a69bf754
83 changed files with 958 additions and 2432 deletions
|
|
@ -13,6 +13,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using System.Buffers;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.Toolkit.HighPerformance;
|
||||
using Server.Diagnostics;
|
||||
|
|
@ -54,18 +55,18 @@ public static class IncomingPlayerPackets
|
|||
IncomingPackets.RegisterEncoded(0x32, true, &QuestGumpRequest);
|
||||
}
|
||||
|
||||
public static void DeathStatusResponse(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void DeathStatusResponse(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
// Ignored
|
||||
}
|
||||
|
||||
public static void RequestScrollWindow(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void RequestScrollWindow(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
int lastTip = reader.ReadInt16();
|
||||
int type = reader.ReadByte();
|
||||
}
|
||||
|
||||
public static void AttackReq(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void AttackReq(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
@ -82,7 +83,7 @@ public static class IncomingPlayerPackets
|
|||
}
|
||||
}
|
||||
|
||||
public static void HuePickerResponse(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void HuePickerResponse(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var serial = reader.ReadUInt32();
|
||||
_ = reader.ReadInt16(); // Item ID
|
||||
|
|
@ -99,7 +100,7 @@ public static class IncomingPlayerPackets
|
|||
}
|
||||
}
|
||||
|
||||
public static void SystemInfo(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void SystemInfo(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
int v1 = reader.ReadByte();
|
||||
int v2 = reader.ReadUInt16();
|
||||
|
|
@ -115,7 +116,7 @@ public static class IncomingPlayerPackets
|
|||
var v8 = reader.ReadInt32();
|
||||
}
|
||||
|
||||
public static void TextCommand(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void TextCommand(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
@ -210,7 +211,7 @@ public static class IncomingPlayerPackets
|
|||
}
|
||||
}
|
||||
|
||||
public static void AsciiPromptResponse(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void AsciiPromptResponse(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
@ -246,7 +247,7 @@ public static class IncomingPlayerPackets
|
|||
}
|
||||
}
|
||||
|
||||
public static void UnicodePromptResponse(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void UnicodePromptResponse(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
@ -283,7 +284,7 @@ public static class IncomingPlayerPackets
|
|||
}
|
||||
}
|
||||
|
||||
public static void MenuResponse(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void MenuResponse(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var serial = reader.ReadUInt32();
|
||||
int menuID = reader.ReadInt16(); // unused in our implementation
|
||||
|
|
@ -313,33 +314,33 @@ public static class IncomingPlayerPackets
|
|||
}
|
||||
}
|
||||
|
||||
public static void Disconnect(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void Disconnect(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var minusOne = reader.ReadInt32();
|
||||
}
|
||||
|
||||
public static void ConfigurationFile(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void ConfigurationFile(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
}
|
||||
|
||||
public static void LogoutReq(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void LogoutReq(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
state.SendLogoutAck();
|
||||
}
|
||||
|
||||
public static void ChangeSkillLock(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void ChangeSkillLock(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var s = state.Mobile.Skills[reader.ReadInt16()];
|
||||
|
||||
s?.SetLockNoRelay((SkillLock)reader.ReadByte());
|
||||
}
|
||||
|
||||
public static void HelpRequest(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void HelpRequest(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
EventSink.InvokeHelpRequest(state.Mobile);
|
||||
}
|
||||
|
||||
public static void DisplayGumpResponse(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void DisplayGumpResponse(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var serial = (Serial)reader.ReadUInt32();
|
||||
var typeID = reader.ReadInt32();
|
||||
|
|
@ -481,13 +482,13 @@ public static class IncomingPlayerPackets
|
|||
}
|
||||
}
|
||||
|
||||
public static void SetWarMode(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void SetWarMode(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
state.Mobile?.DelayChangeWarmode(reader.ReadBoolean());
|
||||
}
|
||||
|
||||
// TODO: Throttle/make this more safe
|
||||
public static void Resynchronize(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void Resynchronize(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
@ -504,17 +505,17 @@ public static class IncomingPlayerPackets
|
|||
state.Sequence = 0;
|
||||
}
|
||||
|
||||
public static void PingReq(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void PingReq(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
state.SendPingAck(reader.ReadByte());
|
||||
}
|
||||
|
||||
public static void SetUpdateRange(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void SetUpdateRange(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
state.SendChangeUpdateRange(18);
|
||||
}
|
||||
|
||||
public static void MobileQuery(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void MobileQuery(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
if (from == null)
|
||||
|
|
@ -545,13 +546,13 @@ public static class IncomingPlayerPackets
|
|||
}
|
||||
default:
|
||||
{
|
||||
reader.Trace(state);
|
||||
state.Trace(reader.Buffer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void CrashReport(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void CrashReport(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var clientMaj = reader.ReadByte();
|
||||
var clientMin = reader.ReadByte();
|
||||
|
|
@ -595,7 +596,7 @@ public static class IncomingPlayerPackets
|
|||
EventSink.InvokeQuestGumpRequest(state.Mobile);
|
||||
}
|
||||
|
||||
public static unsafe void EncodedCommand(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static unsafe void EncodedCommand(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var e = World.FindEntity((Serial)reader.ReadUInt32());
|
||||
int packetId = reader.ReadUInt16();
|
||||
|
|
@ -612,7 +613,7 @@ public static class IncomingPlayerPackets
|
|||
|
||||
if (ph == null)
|
||||
{
|
||||
reader.Trace(state);
|
||||
state.Trace(reader.Buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue