UDP Listener
Trên trang này
Namespace: Nalix.Network.Listeners.Udp
Assembly: Nalix.Network
Nalix.Network.Listeners.Udp cung cấp hai triển khai listener UDP:
UdpListenerBase(public abstract partial class UdpListenerBase : IListener): Listener UDP đi kèm đã xác thực, giải quyết mỗi datagram thành mộtConnectionđã xác thực qua TCP đang có trongIConnectionHub, dựa trên tiền tốSessionToken8 byte và thẻ MACXxHash324 byte ở cuối.UdpPassthroughListener(public sealed class UdpPassthroughListener : UdpListenerBase): Listener UDP thô không kết nối, bỏ qua kiểm tra token/MAC và chuyển datagram thô tớiIProtocolbằng các instancePassthroughConnectionnhẹ được theo dõi trongTimingWheel.
Nguồn mã
src/Nalix.Network/Listeners/UdpListener/UdpListener.Core.cssrc/Nalix.Network/Listeners/UdpListener/UdpListener.PublicMethods.cssrc/Nalix.Network/Listeners/UdpListener/UdpListener.Receive.cssrc/Nalix.Network/Listeners/UdpListener/UdpListener.SocketConfig.cssrc/Nalix.Network/Listeners/UdpListener/UdpListener.Metrics.cssrc/Nalix.Network/Listeners/UdpListener/UdpPassthroughListener.cssrc/Nalix.Network/Connections/PassthroughConnection.cssrc/Nalix.Network/RateLimiting/Datagram.Guard.cssrc/Nalix.Network/Options/DatagramGuardOptions.cs
1. Bố cục datagram đã xác thực (UdpListenerBase)
Mọi datagram UDP đến đã xác thực đều có một envelope xác thực 12 byte (8-byte SessionToken prefix + 4-byte XxHash32 MAC suffix) bọc gói Nalix:
+-----------------------------------+-----------------------------------+-----------------------------------+
| SessionToken (8B, LE UInt64) | Packet Payload (>= 6B Header) | UdpMacTag (4B, LE UInt32) |
| = ConnectionId (ISnowflake) | [OpCode(2)..SequenceId(2)..Body] | XxHash32(Secret, seed: Hash(0..N))|
+-----------------------------------+-----------------------------------+-----------------------------------+
Bytes 0..7 Bytes 8..(Length - 5) Bytes (Length - 4)..(Length - 1)
Pipeline kiểm tra nhiều cổng (UdpListener.Receive.cs)
flowchart TD
Recv["ReceiveFromAsync (PooledUdpReceiveEventArgs)"] --> Rate{"DatagramGuard.TryAccept(ip)?"}
Rate -->|No| Drop["Drop Datagram"]
Rate -->|Yes| Size{"BytesTransferred <= MaxUdpDatagramSize (1440)?"}
Size -->|No| Drop
Size -->|Yes| MinLen{"Length >= 8B Token + 6B Header + 4B MAC (18B)?"}
MinLen -->|No| Drop
MinLen -->|Yes| Resolve["Hub.GetConnection(buffer[..8])"]
Resolve -->|Unknown / Disposed / Secret.IsZero| Drop
Resolve -->|Resolved| Mac["Verify 4B Trailing XxHash32 MAC Tag + Strip Tag"]
Mac -->|Mismatch| Drop
Mac -->|Valid| Pin{"Endpoint Pinning Match (SEC-30)?"}
Pin -->|Mismatch| Drop
Pin -->|Matched| Replay{"connection.UdpReplayWindow.TryCheck(header.SequenceId)?"}
Replay -->|Replayed / Stale| Drop
Replay -->|Valid| Hook{"IsAuthenticated(connection, remoteEndPoint, payload)?"}
Hook -->|False| Drop
Hook -->|True| Deliver["SocketUdpTransport.EnsureUDP + AsyncCallback.Invoke(CallbackLane.Process)"]- Cổng kiểm tra tốc độ và kích thước theo IP: Kiểm tra
_rateLimiter.TryAccept(ip)(DatagramGuard) và loại các datagram lớn hơnNetworkSocketOptions.MaxUdpDatagramSize(1440byte). - Phân giải phiên: Đọc
SessionToken8 byte (buffer[..8]) và phân giảiConnectionđang hoạt động từIConnectionHub. Loại nếu kết nối không tồn tại hoặcconnection.Secret.IsZero(handshake chưa hoàn tất). - Xác thực MAC
XxHash32có khóa (UdpMacTagSize = 4):- Đặt
dataLen = lease.Length - 4. - Tính
uint payloadHash = XxHash32.Compute(lease.Span[..dataLen]). - Tính
uint computedTag = XxHash32.Compute(connection.Secret.AsSpan(), seed: payloadHash). - So sánh
computedTagvới thẻ little-endian 4 byte ở cuối (lease.Span.Slice(dataLen, 4)) và loại thẻ 4 byte đó (lease.CommitLength(dataLen)).
- Đặt
- Ghim endpoint (
SEC-30): Xác minh IP nguồn UDP (và cổng, khi được ghim) khớp vớiconnection.NetworkEndpoint. - Cửa sổ replay trượt (
SEC-27): Kiểm traheader.SequenceId16-bit (ushort) vớiconnection.UdpReplayWindow(DatagramGuardOptions.UdpReplayWindowSize = 512bit). - Hook tùy chỉnh và xử lý khung: Gọi
IsAuthenticated(connection, remoteEndPoint, payload), gắnSocketUdpTransport.EnsureUDP, bỏ tiền tốSessionToken8 byte, và chuyển gói quaAsyncCallback(FramePipeline.ProcessInbound$\rightarrow$IProtocol.ProcessMessage).
2. Chế độ passthrough thô (UdpPassthroughListener)
Được đăng ký qua builder.MapUdp<TProtocol>(port, passthrough: true) khi bạn triển khai các protocol UDP tùy chỉnh của bên thứ ba (như RakNet hoặc UDP nhị phân tùy chỉnh):
- Bỏ qua
SessionToken8 byte, thẻ MACXxHash324 byte,UdpReplayWindowvàFramePipeline. - Theo dõi mỗi
IPEndPointtừ xa dưới dạng mộtPassthroughConnection(public sealed class PassthroughConnection : IConnection, IConnectionTrafficMetrics, TimingWheel.ITimeoutTrackedConnection), đượcIConnectionGuardkiểm soát chấp nhận, giới hạn ởMaxPendingPackets = 64gói đang chờ đồng thời cho mỗi endpoint, và đăng ký vàoTimingWheelđể tự động loại bỏ khi nhàn rỗi. PassthroughConnectionlộUDP(IConnection.ITransport) được gắn với socket listener dùng chung để gửi phản hồi, còn truy cậpPassthroughConnection.TCPsẽ némNotSupportedException.
API công khai và protected (UdpListenerBase)
namespace Nalix.Network.Listeners.Udp;
public abstract partial class UdpListenerBase : IListener
{
protected UdpListenerBase(ushort port, IProtocol protocol, IConnectionHub hub);
protected UdpListenerBase(IProtocol protocol, IConnectionHub hub);
public bool IsListening { get; }
public UMetrics Metrics { get; }
protected IProtocol Protocol { get; }
protected Socket? ListenerSocket { get; }
public void Activate(CancellationToken cancellationToken = default);
public void Deactivate(CancellationToken cancellationToken = default);
public virtual bool TryResolveConnection(
IConnectionHub hub,
ReadOnlySpan<byte> sessionToken,
out Connection? connection);
public abstract bool IsAuthenticated(
IConnection connection,
EndPoint remoteEndPoint,
ReadOnlySpan<byte> payload);
protected virtual void ProcessDatagram(BufferLease lease, EndPoint? remoteEndPoint);
public string GenerateReport();
public void WriteReportData(Utf8JsonWriter writer);
public void Dispose();
protected virtual void Dispose(bool disposing);
}