feat: Upgrades networking to use io_uring. (#2315)
> [!IMPORTANT] > **Breaking Changes** > - DecodePacket and EncodePacket delegates replaced with IClientEncryption interface > - NetState.Connection (Socket) replaced with internal RingSocket management > - NetState.RecvPipe and NetState.SendPipe removed (buffers managed internally) ## Summary Upgrades the networking stack from PollGroup-based I/O to io_uring, significantly improving I/O performance on Linux. This also adds native client encryption support for encrypted UO clients. ## Major Changes io_uring Networking Architecture - Replaced PollGroup with IORingGroup for async socket I/O operations - Removed Pipe.cs (mirrored ring buffer) and TcpServer.cs in favor of RingSocketManager - Added NetState.Network.cs - centralized network infrastructure handling accept, recv, send, and disconnect completions - Added SocketHelper.cs - platform-specific socket utilities for raw socket handle operations (getpeername, getsockname) - Buffer management now handled by RingSocketManager with configurable slab allocation ### Client Encryption Support - Added full encryption stack in Network/Encryption/: - EncryptionConfig.cs - configurable encryption modes (None, Unencrypted, Encrypted, Both) - EncryptionManager.cs - encryption detection and initialization for login/game packets - LoginEncryption.cs - handles login packet encryption with version-derived keys - GameEncryption.cs - handles game server encryption using Twofish - TwofishEngine.cs - optimized Twofish block cipher implementation - LoginKeys.cs - encryption key table for client versions - IClientEncryption.cs - interface for client encryption implementations ### NetState Improvements - Replaced Socket Connection with RingSocket _socket for managed socket lifecycle - Changed from GCHandle polling to event-based completion processing - Disconnect handling now properly waits for pending sends to flush - Simplified connecting socket management using lazy queue removal ### Configuration - New settings: network.encryptionMode and network.encryptionDebug - Encryption mode flags: Unencrypted, Encrypted, or Both ### Dependencies - Replaced PollGroup NuGet package with IORingGroup - Linux requires liburing-dev / liburing-devel package ### Test plan - Verify server starts and accepts connections on Linux with io_uring - Verify server starts and accepts connections on Windows (fallback to IOCP) - Test unencrypted client connections (ClassicUO with encryption disabled) - Test encrypted client connections if available - Verify graceful disconnect flushes pending data - Confirm CI builds pass on all target platforms
This commit is contained in:
parent
91a553b0bc
commit
3c0d6cb9d6
70 changed files with 2227 additions and 1468 deletions
|
|
@ -23,7 +23,7 @@ public class PlayerPacketTests
|
|||
using var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendStatLockInfo(m);
|
||||
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
var result = ns.SendBuffer.GetReadSpan();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
|
|
@ -38,7 +38,7 @@ public class PlayerPacketTests
|
|||
using var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendChangeUpdateRange((byte)range);
|
||||
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
var result = ns.SendBuffer.GetReadSpan();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
|
|
@ -50,7 +50,7 @@ public class PlayerPacketTests
|
|||
using var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendDeathStatus();
|
||||
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
var result = ns.SendBuffer.GetReadSpan();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
|
|
@ -64,7 +64,7 @@ public class PlayerPacketTests
|
|||
using var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendDisplayProfile((Serial)serial, header, body, footer);
|
||||
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
var result = ns.SendBuffer.GetReadSpan();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
|
|
@ -78,7 +78,7 @@ public class PlayerPacketTests
|
|||
using var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendLiftReject(reason);
|
||||
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
var result = ns.SendBuffer.GetReadSpan();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
|
|
@ -90,7 +90,7 @@ public class PlayerPacketTests
|
|||
using var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendLogoutAck();
|
||||
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
var result = ns.SendBuffer.GetReadSpan();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
|
|
@ -105,7 +105,7 @@ public class PlayerPacketTests
|
|||
using var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendWeather((byte)type, (byte)density, (byte)temp);
|
||||
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
var result = ns.SendBuffer.GetReadSpan();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
|
|
@ -120,7 +120,7 @@ public class PlayerPacketTests
|
|||
using var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendServerChange(p, map);
|
||||
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
var result = ns.SendBuffer.GetReadSpan();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
|
|
@ -135,7 +135,7 @@ public class PlayerPacketTests
|
|||
using var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendSequence(num);
|
||||
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
var result = ns.SendBuffer.GetReadSpan();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
|
|
@ -151,7 +151,7 @@ public class PlayerPacketTests
|
|||
using var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendLaunchBrowser(uri);
|
||||
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
var result = ns.SendBuffer.GetReadSpan();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
|
|
@ -175,7 +175,7 @@ public class PlayerPacketTests
|
|||
itemId, hue, amount
|
||||
);
|
||||
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
var result = ns.SendBuffer.GetReadSpan();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
|
|
@ -189,7 +189,7 @@ public class PlayerPacketTests
|
|||
using var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendSeasonChange((byte)season, playSound);
|
||||
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
var result = ns.SendBuffer.GetReadSpan();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
|
|
@ -204,7 +204,7 @@ public class PlayerPacketTests
|
|||
using var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendDisplayPaperdoll((Serial)m, title, warmode, canLift);
|
||||
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
var result = ns.SendBuffer.GetReadSpan();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
|
|
@ -219,7 +219,7 @@ public class PlayerPacketTests
|
|||
using var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendPlayMusic(music);
|
||||
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
var result = ns.SendBuffer.GetReadSpan();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
|
|
@ -233,7 +233,7 @@ public class PlayerPacketTests
|
|||
using var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendScrollMessage(type, tip ,text);
|
||||
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
var result = ns.SendBuffer.GetReadSpan();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
|
|
@ -247,7 +247,7 @@ public class PlayerPacketTests
|
|||
using var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendCurrentTime(date);
|
||||
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
var result = ns.SendBuffer.GetReadSpan();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
|
|
@ -261,7 +261,7 @@ public class PlayerPacketTests
|
|||
using var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendPathfindMessage(p);
|
||||
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
var result = ns.SendBuffer.GetReadSpan();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
|
|
@ -276,7 +276,7 @@ public class PlayerPacketTests
|
|||
using var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendPingAck(ping);
|
||||
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
var result = ns.SendBuffer.GetReadSpan();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
|
|
@ -291,7 +291,7 @@ public class PlayerPacketTests
|
|||
using var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendDisplayHuePicker(huePicker.Serial, huePicker.ItemID);
|
||||
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
var result = ns.SendBuffer.GetReadSpan();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue