# EonaCat.Connections A high-performance, production-ready .netStandard 2.0, .NET Framework 4.8+ / .NET 8 compatible library for building scalable TCP/UDP servers and clients with optional TLS encryption and application-layer AES encryption. ## Features ### Core Capabilities - **High Performance**: Event-driven, asynchronous architecture with minimal allocations - **Massive Scalability**: Handles tens of thousands of concurrent connections using SocketAsyncEventArgs (SAEA) - **Dual Protocol Support**: TCP and UDP with independent or mixed configurations - **TLS/SSL Encryption**: Secure TCP connections using SslStream with certificate support - **Application-Layer Encryption**: AES-CBC + PBKDF2_SHA256 encryption for both TCP and UDP payloads - **Low Latency**: Optimized for millisecond-level response times ### Advanced Features - **Auto-Reconnection**: Automatic client reconnection with configurable retry logic and exponential backoff - **Heartbeat/Ping-Pong**: Keep-alive mechanism to detect dead connections - **Idle Detection**: Automatic detection and handling of idle connections with configurable timeout - **Message Framing**: Support for delimiter-based, length-prefixed, or raw message modes - **Request-Response Patterns**: Send message and wait for response with timeout support - **Broadcast Messaging**: Send to all connected clients simultaneously - **Client-to-Client Messaging**: Direct peer communication through the server - **Nicknames**: Optional client identification system - **Health API**: Lightweight REST API for monitoring server health and statistics - **Status Reporting**: Auto-generated HTML status pages showing connected clients and throughput - **Network Monitoring**: Built-in network health monitoring and outage detection - **SSL Diagnostics**: Detailed SSL handshake diagnostics and performance metrics - **Connection Management**: Full lifecycle management with detailed disconnect reasons ## Design Goals - High performance and low latency - Scalable to tens of thousands of concurrent connections - Scalable socket I/O via SocketAsyncEventArgs (SAEA) for raw TCP and UDP - TLS (SSL) over TCP using SslStream (built-in) - Optional encryption (AES-CBC + PBKDF2_SHA256) for TCP/UDP payloads - Minimal allocations, event-driven callbacks - For highest throughput, run x64, enable LargePage, set appropriate Socket options and OS registry tuning ## Configuration The `Configuration` class provides extensive customization options: ### Connection Settings - **Protocol**: `TCP` or `UDP` (default: TCP) - **Host**: Server address for clients (default: 127.0.0.1) - **Port**: Network port (default: 8080) - **MaxConnections**: Maximum concurrent connections (default: 100000) - **ConnectionTimeout**: Timeout for connection attempts (default: 30s) ### TLS/SSL Settings - **Certificate**: X509Certificate2 for server (enables TLS when set) - **AdditionalCertificates**: Additional certificates for chain validation - **IsSelfSignedEnabled**: Allow self-signed certificates (testing only) - **CheckCertificateRevocation**: Validate certificate revocation status - **MutuallyAuthenticate**: Require mutual TLS authentication - **UseSsl**: Read-only property (true if Certificate is set) - **EnableSslDiagnostics**: Enable detailed SSL handshake diagnostics - **AllowTlsRenegotiation**: Allow TLS renegotiation ### SSL Retry & Handshake Configuration - **SSLMaxRetries**: Maximum SSL handshake retry attempts (0 = unlimited, default: 0) - **SSLTimeoutInSeconds**: SSL handshake timeout (default: 35) - **SSLRetryDelayInSeconds**: Delay between SSL retries (default: 5) - **UseExponentialBackoffForSslRetries**: Enable exponential backoff (default: false) - **SSLRetryDelayMaxSeconds**: Maximum retry delay when exponential backoff enabled (default: 60) ### Encryption Settings - **UseAesEncryption**: Enable AES-CBC encryption (default: false) - **AesPassword**: Password for AES key derivation - **UseBigEndian**: Use big-endian byte order (default: false) ### Keep-Alive & Heartbeat - **EnableKeepAlive**: Enable TCP keep-alive probes (default: true) - **KeepAliveTimeSeconds**: Time before first keep-alive probe (default: 60) - **KeepAliveIntervalSeconds**: Interval between probes (default: 10) - **KeepAliveRetryCount**: Unacked probes before disconnect (default: 10) - **EnableHeartbeat**: Enable ping-pong heartbeat (default: false) - **HeartbeatIntervalSeconds**: Heartbeat interval (default: 5) - **EnablePingPongLogs**: Log ping-pong messages (default: false) - **DisconnectOnMissedPong**: Disconnect on missed pong response (default: false) ### Message Framing - **MessageFraming**: `None`, `Delimiter`, or `LengthPrefixed` (default: None) - **Delimiter**: Message separator bytes (default: %) - **LengthPrefixedLength**: Prefix byte count for length-prefixed mode (default: 4) - **MAX_MESSAGE_SIZE**: Maximum message size (default: 100 MB) ### Idle Detection & Timeout - **IdleTimeoutSeconds**: Idle connection timeout, 0 = disabled (default: 30) ### Socket Configuration - **BufferSize**: Socket buffer size (default: ExtraLarge ~65K) - **EnableNagle**: Enable Nagle's algorithm (default: false) - **EnableRST**: Send RST flag on close (default: false) ### Auto-Reconnection (Client) - **EnableAutoReconnect**: Auto-reconnect on disconnect (default: true) - **ReconnectDelayInSeconds**: Delay before reconnection attempt (default: 5) - **MaxReconnectAttempts**: Max reconnect attempts, 0 = unlimited (default: 0) ### Logging & Diagnostics - **EnableConnectionDebugLogs**: Log connection lifecycle events (default: false) ### HTML Status & Health API - **EnableAutoHtmlReports**: Generate periodic HTML error reports (default: false) - **HtmlReportOutputDirectory**: Report output directory (default: ./reports) - **HtmlReportIntervalSeconds**: Report generation interval (default: 60) - **EnableServerStatusPage**: Generate HTML status page with client list (default: false) - **ServerStatusPageIntervalSeconds**: Status page update interval (default: 5) - **EnableHealthApi**: Start lightweight REST health API (default: false) - **HealthApiPort**: Health API port, 0 = random (default: 0) - **HealthApiBindAddress**: Health API bind address (default: 127.0.0.1) ### Certificate Management - **TrustedThumbprints**: List of trusted certificate thumbprints for validation - **CheckAgainstInternalTrustedCertificates**: Validate against Windows certificate store (default: true) ## NetworkServer API ### Events ```csharp // Connection events public event EventHandler OnConnected; public event EventHandler OnConnectedWithNickname; public event EventHandler OnDisconnected; // Data events public event EventHandler OnDataReceived; // Error events public event EventHandler OnSslError; public event EventHandler OnEncryptionError; public event EventHandler OnGeneralError; public event EventHandler OnSocketError; // Heartbeat events public event EventHandler OnClientPingResponse; public event EventHandler OnPongMissed; // Idle/Timeout events public event EventHandler OnIdleTimeout; // Logging public event EventHandler OnLog; ``` ### Properties ```csharp // Server Status public bool IsStarted { get; } public int Port { get; } public int ActiveConnections { get; } public int MaxConnections { get; } public ProtocolType Protocol { get; } // Security Status public bool IsSecure { get; } // TLS or AES enabled public bool IsEncrypted { get; } // AES enabled // Statistics public long DroppedPackets { get; } public long DroppedConnections { get; } public long TotalConnections { get; } public long BytesSent { get; } public long BytesReceived { get; } public long MessagesSent { get; } public long MessagesReceived { get; } public double MessagesPerSecond { get; } public TimeSpan Uptime { get; } public DateTime StartTime { get; } public DateTime LastDataSent { get; } public DateTime LastDataReceived { get; } // Status Pages public ServerStatusPage ServerStatus { get; } public SocketStatusPage StatusPage { get; } public HealthApiServer HealthApi { get; } // Debug public bool DEBUG_DATA_SEND { get; set; } public bool DEBUG_DATA_RECEIVED { get; set; } ``` ### Core Methods ```csharp // Lifecycle public Task StartAsync(); public void Stop(); public async Task StopAsync(); public Task StartTcpServerAsync(); public async Task StartUdpServerAsync(CancellationToken token); public async Task StopTcpServerAsync(); // Client Management public Dictionary GetClients(); public List GetClient(string clientId); public async Task DisconnectClientAsync(string clientId, DisconnectReason reason, Exception? exception); // Messaging - Send to Specific Client public async Task SendToClientAsync(string clientId, byte[] data); public async Task SendToClientAsync(string clientId, string message); // Messaging - Client-to-Client public async Task SendFromClientToClientAsync(string fromClientId, string toClientId, byte[] data); public async Task SendFromClientToClientAsync(string fromClientId, string toClientId, string message); // Broadcast Messaging public async Task BroadcastAsync(byte[] data); public async Task BroadcastAsync(string message); // Request-Response Patterns public async Task SendToClientAndWaitForResponseAsync( string clientId, byte[] data, TimeSpan? timeout = null); public async Task SendToClientAndWaitForResponseAsync( string clientId, string message, TimeSpan? timeout = null); public async Task SendFromClientToClientAndWaitForResponseAsync( string fromClientId, string toClientId, byte[] data, TimeSpan? timeout = null); public async Task SendFromClientToClientAndWaitForResponseAsync( string fromClientId, string toClientId, string message, TimeSpan? timeout = null); public async Task> BroadcastAndWaitForResponsesAsync( byte[] data, TimeSpan? timeout = null); public async Task> BroadcastAndWaitForResponsesAsync( string message, TimeSpan? timeout = null); // Configuration public void SetSeparator(string separator); public void SetSeparator(byte[] separator); // Statistics public Stats GetStats(); // Cleanup public void Dispose(); ``` ## NetworkClient API ### Events ```csharp // Connection events public event EventHandler OnConnected; public event EventHandler OnNicknameSend; public event EventHandler OnDisconnected; // Data events public event EventHandler OnDataReceived; // Error events public event EventHandler OnSslError; public event EventHandler OnEncryptionError; public event EventHandler OnGeneralError; public event EventHandler OnSocketError; // Heartbeat events public event EventHandler OnPingResponse; public event EventHandler OnPongResponse; // Idle/Timeout events public event EventHandler OnIdleTimeout; // Logging public event EventHandler OnLog; ``` ### Properties ```csharp // Connection Status public bool IsConnected { get; set; } public int Port { get; } // Connection Time Metrics public DateTime ConnectionTime { get; } public TimeSpan Uptime { get; } public DateTime LastActive { get; } public int IdleTimeInSeconds(); public int IdleTimeInMinutes(); public int IdleTimeInHours(); public int IdleTimeInDays(); public int ConnectedTimeInSeconds(); public int ConnectedTimeInMinutes(); public int ConnectedTimeInHours(); public int ConnectedTimeInDays(); // Security Status public bool IsSecure { get; } // TLS or AES enabled public bool IsEncrypted { get; } // AES enabled public bool IsTcp { get; } // Statistics public long BytesSent { get; } public long BytesReceived { get; } public long MessagesSent { get; } public long MessagesReceived { get; } // Heartbeat public bool DisconnectOnMissedPong { get; set; } public bool EnableKeepAlive { get; set; } // Auto-Reconnect public bool IsAutoConnectStarted { get; } public bool IsIdleTimeoutTriggered { get; } // Debug public bool DEBUG_DATA_SEND { get; set; } public bool DEBUG_DATA_RECEIVED { get; set; } ``` ### Core Methods ```csharp // Connection Lifecycle public async Task ConnectAsync(); public async Task DisconnectAsync(); public async Task DisconnectDueTimeoutAsync(); // Messaging public async Task SendAsync(byte[] data); public async Task SendAsync(string message); // Nickname public async Task SendNicknameAsync(string nickname); // Request-Response public async Task SendAndWaitForResponseAsync( byte[] data, TimeSpan? timeout = null); public async Task SendAndWaitForResponseAsync( string message, TimeSpan? timeout = null); public async Task SendNicknameAndWaitForResponseAsync( string nickname, TimeSpan? timeout = null); // Cleanup public void Dispose(); ``` ## Message Framing Modes Three message framing modes are supported: ### 1. None (Default) Raw bytes sent as-is, no frame boundaries marked: ```csharp config.MessageFraming = FramingMode.None; ``` ### 2. Delimiter Messages separated by a delimiter byte sequence (default: %): ```csharp config.MessageFraming = FramingMode.Delimiter; config.Delimiter = Encoding.UTF8.GetBytes("%"); ``` ### 3. Length-Prefixed Messages prefixed with their length as bytes: ```csharp config.MessageFraming = FramingMode.LengthPrefixed; config.LengthPrefixedLength = 4; // 4-byte prefix ``` ## SSL/TLS Certificate Setup ### Generate self-signed certificate for TLS (TCP): Run the following in PowerShell as Administrator: ```powershell $cert = New-SelfSignedCertificate ` -DnsName "localhost" ` -CertStoreLocation "Cert:\LocalMachine\My" ` -KeyExportPolicy Exportable ` -NotAfter (Get-Date).AddYears(5) ` -FriendlyName "EonaCat Connections Test Certificate" $password = ConvertTo-SecureString -String "p@ss" -Force -AsPlainText Export-PfxCertificate ` -Cert "Cert:\LocalMachine\My\$($cert.Thumbprint)" ` -FilePath "C:\temp\server.pfx" ` -Password $password ``` This creates a self-signed certificate with password `p@ss` in `C:\temp\server.pfx`. ## Advanced Features ### Auto-Reconnection The client automatically reconnects on disconnect: ```csharp config.EnableAutoReconnect = true; // Enable auto-reconnect config.ReconnectDelayInSeconds = 5; // Delay before retry config.MaxReconnectAttempts = 0; // 0 = unlimited attempts ``` ### Heartbeat (Ping-Pong) Keep connections alive and detect dead connections: ```csharp config.EnableHeartbeat = true; config.HeartbeatIntervalSeconds = 5; config.DisconnectOnMissedPong = true; // Disconnect if pong not received ``` ### Idle Detection Automatically disconnect idle connections: ```csharp config.IdleTimeoutSeconds = 30; // 0 = disabled ``` ### Request-Response Patterns Send a message and wait for a response with timeout: ```csharp // Server sends message and waits for client response var response = await server.SendToClientAndWaitForResponseAsync( clientId, "question", TimeSpan.FromSeconds(5)); if (response != null) { Console.WriteLine($"Got response: {response.StringData}"); } // Client sends message and waits for server response var response = await client.SendAndWaitForResponseAsync( "answer", TimeSpan.FromSeconds(5)); ``` ### Health API Enable a lightweight REST API for server monitoring: ```csharp config.EnableHealthApi = true; config.HealthApiPort = 0; // Random port config.HealthApiBindAddress = IPAddress.Any; // For Docker/containers // After server starts, access the API: // http://localhost:{HealthApi.Port}/health // http://localhost:{HealthApi.Port}/stats ``` ### Status Pages Auto-generate HTML status reports: ```csharp config.EnableServerStatusPage = true; config.ServerStatusPageIntervalSeconds = 5; config.EnableAutoHtmlReports = true; config.HtmlReportOutputDirectory = "./reports"; config.HtmlReportIntervalSeconds = 60; ``` ### SSL Diagnostics Enable detailed SSL handshake diagnostics: ```csharp config.EnableSslDiagnostics = true; // Access via: server.StatusPage.SslMetrics ``` ### Network Monitoring Monitor network health and detect outages: ```csharp var monitor = new NetworkMonitor(); monitor.OnNetworkOutageDetected += (s, e) => { Console.WriteLine($"Network outage detected: {e.Duration}"); }; ``` ## Server Example ```csharp using EonaCat.Connections; using EonaCat.Connections.Models; using System.Security.Cryptography.X509Certificates; namespace EonaCat.Connections.Server.Example { public class Program { private static NetworkServer _server; public static void Main(string[] args) { CreateServerAsync().GetAwaiter().GetResult(); while (true) { Console.Write("Enter message to broadcast (or 'exit' to quit): "); var message = Console.ReadLine(); if (!string.IsNullOrEmpty(message) && message.Equals("exit", StringComparison.OrdinalIgnoreCase)) { _server.StopAsync().GetAwaiter().GetResult(); _server.Dispose(); Console.WriteLine("Server stopped."); break; } if (!string.IsNullOrEmpty(message)) { _server.BroadcastAsync(message).GetAwaiter().GetResult(); } } } private static async Task CreateServerAsync() { var config = new Configuration { Protocol = ProtocolType.TCP, Port = 1111, Certificate = new X509Certificate2("server.pfx", "p@ss"), // Enables TLS UseAesEncryption = true, AesPassword = "EonaCat.Connections.Password", MaxConnections = 100000, EnableHeartbeat = true, HeartbeatIntervalSeconds = 5, IdleTimeoutSeconds = 30, EnableHealthApi = true, HealthApiPort = 8888, }; _server = new NetworkServer(config); // Connection events _server.OnConnected += (sender, e) => Console.WriteLine($"[CONNECTED] Client {e.ClientId} from {e.RemoteEndPoint}"); _server.OnConnectedWithNickname += (sender, e) => Console.WriteLine($"[NICKNAME] Client {e.ClientId} identified as: {e.Nickname}"); // Data reception _server.OnDataReceived += async (sender, e) => { var clientName = e.HasNickname ? e.Nickname : e.ClientId; Console.WriteLine($"[DATA] From {clientName}: {(e.IsBinary ? $"{e.Data.Length} bytes" : e.StringData)}"); // Echo response if (e.IsBinary) { await _server.SendToClientAsync(e.ClientId, e.Data); } else { await _server.SendToClientAsync(e.ClientId, $"Echo: {e.StringData}"); } }; // Disconnection _server.OnDisconnected += (sender, e) => { var clientName = e.HasNickname ? e.Nickname : e.ClientId; Console.WriteLine($"[DISCONNECTED] {clientName} ({e.DisconnectReason})"); }; // Error handling _server.OnGeneralError += (sender, e) => Console.WriteLine($"[ERROR] {e.Message}"); _server.OnSslError += (sender, e) => Console.WriteLine($"[SSL ERROR] {e.Message}"); // Idle connections _server.OnIdleTimeout += (sender, e) => Console.WriteLine($"[IDLE] Client disconnected due to timeout: {e.ClientId}"); // Heartbeat _server.OnPongMissed += (sender, e) => Console.WriteLine($"[HEARTBEAT] Pong missed from {e.ClientId}"); Console.WriteLine("Server starting..."); await _server.StartAsync(); Console.WriteLine($"Server listening on port {_server.Port}"); Console.WriteLine($"Health API available on: http://localhost:8888/health"); } } } ``` ## Client Example ```csharp using EonaCat.Connections; using EonaCat.Connections.Models; using System.Security.Cryptography.X509Certificates; namespace EonaCat.Connections.Client.Example { public class Program { private static NetworkClient _client; public static async Task Main(string[] args) { await CreateClientAsync(); while (true) { if (!_client.IsConnected) { Console.WriteLine("Waiting for connection..."); await Task.Delay(1000); continue; } Console.Write("Enter message to send (or 'exit' to quit): "); var message = Console.ReadLine(); if (!string.IsNullOrEmpty(message) && message.Equals("exit", StringComparison.OrdinalIgnoreCase)) { await _client.DisconnectAsync(); _client.Dispose(); break; } if (!string.IsNullOrEmpty(message)) { await _client.SendAsync(message); // Optional: wait for response var response = await _client.SendAndWaitForResponseAsync( message, TimeSpan.FromSeconds(5)); if (response != null) { Console.WriteLine($"Server response: {response.StringData}"); } } } } private static async Task CreateClientAsync() { var config = new Configuration { Protocol = ProtocolType.TCP, Host = "127.0.0.1", Port = 1111, Certificate = new X509Certificate2("client.pfx", "p@ss"), // For TLS (optional) UseAesEncryption = true, AesPassword = "EonaCat.Connections.Password", EnableAutoReconnect = true, ReconnectDelayInSeconds = 5, MaxReconnectAttempts = 0, // Unlimited retries EnableHeartbeat = true, HeartbeatIntervalSeconds = 5, IdleTimeoutSeconds = 30, }; _client = new NetworkClient(config); // Error handling _client.OnGeneralError += (sender, e) => Console.WriteLine($"[ERROR] {e.Message}"); _client.OnSslError += (sender, e) => Console.WriteLine($"[SSL ERROR] {e.Message}"); // Connection events _client.OnConnected += async (sender, e) => { Console.WriteLine($"[CONNECTED] Connected to server at {e.RemoteEndPoint}"); // Set client nickname await _client.SendNicknameAsync("TestUser"); // Send initial message await _client.SendAsync("Hello from client!"); }; // Data reception _client.OnDataReceived += (sender, e) => Console.WriteLine($"[SERVER] {(e.IsBinary ? $"{e.Data.Length} bytes" : e.StringData)}"); // Disconnection _client.OnDisconnected += (sender, e) => Console.WriteLine($"[DISCONNECTED] Disconnected from server ({e.DisconnectReason})"); // Idle/Timeout _client.OnIdleTimeout += (sender, e) => Console.WriteLine($"[IDLE] Connection idle for {e.IdleTime} seconds"); // Heartbeat _client.OnPingResponse += (sender, e) => Console.WriteLine($"[PING] Response time: {e.ResponseTime}ms"); Console.WriteLine("Client connecting..."); await _client.ConnectAsync(); } } } ``` ## Advanced Usage Examples ### Request-Response Pattern ```csharp // Server: Wait for client to send data, then respond _server.OnDataReceived += async (sender, e) => { if (e.StringData == "QUERY") { await _server.SendToClientAsync(e.ClientId, "RESPONSE_DATA"); } }; // Client: Send request and wait for response var response = await _client.SendAndWaitForResponseAsync( "QUERY", TimeSpan.FromSeconds(10)); Console.WriteLine($"Got: {response.StringData}"); // Server: Broadcast and wait for all responses var responses = await _server.BroadcastAndWaitForResponsesAsync( "QUESTION", TimeSpan.FromSeconds(15)); Console.WriteLine($"Received {responses.Count} responses"); ``` ### Client-to-Client Communication ```csharp // Client A sends to Client B through server await _server.SendFromClientToClientAsync( "clientA_id", "clientB_id", "Direct message"); // Or with response var response = await _server.SendFromClientToClientAndWaitForResponseAsync( "clientA_id", "clientB_id", "Question for B"); ``` ### Message Framing ```csharp // Delimiter-based framing config.MessageFraming = FramingMode.Delimiter; config.Delimiter = Encoding.UTF8.GetBytes("\n"); // Length-prefixed framing config.MessageFraming = FramingMode.LengthPrefixed; config.LengthPrefixedLength = 4; // 4-byte length prefix // Custom separator server.SetSeparator("||"); ``` ### Accessing Statistics ```csharp // Server statistics Console.WriteLine($"Active connections: {_server.ActiveConnections}"); Console.WriteLine($"Total connected: {_server.TotalConnections}"); Console.WriteLine($"Messages/sec: {_server.MessagesPerSecond}"); Console.WriteLine($"Data sent: {_server.BytesSent} bytes"); Console.WriteLine($"Data received: {_server.BytesReceived} bytes"); Console.WriteLine($"Uptime: {_server.Uptime}"); var stats = _server.GetStats(); Console.WriteLine($"Dropped packets: {stats.DroppedPackets}"); Console.WriteLine($"Dropped connections: {stats.DroppedConnections}"); // Client statistics Console.WriteLine($"Connection time: {_client.ConnectedTimeInHours()} hours"); Console.WriteLine($"Idle time: {_client.IdleTimeInSeconds()} seconds"); Console.WriteLine($"Bytes sent: {_client.BytesSent}"); Console.WriteLine($"Messages sent: {_client.MessagesSent}"); ``` ### SSL/TLS with Certificate Validation ```csharp // Server with certificate var config = new Configuration { Certificate = new X509Certificate2("server.pfx", "password"), MutuallyAuthenticate = true, CheckCertificateRevocation = true, }; // Client with certificate validation var clientConfig = new Configuration { Host = "server.example.com", Port = 443, Certificate = new X509Certificate2("client.pfx", "password"), MutuallyAuthenticate = true, TrustedThumbprints = new List { "CERT_THUMBPRINT" }, CheckCertificateRevocation = true, }; ``` ### Encryption and Security ```csharp // AES Encryption config.UseAesEncryption = true; config.AesPassword = "SecurePassword123"; // Both TLS and AES together config.Certificate = new X509Certificate2("server.pfx", "pass"); config.UseAesEncryption = true; config.AesPassword = "AdditionalPassword"; // Disable Nagle for low-latency config.EnableNagle = false; ``` ## Event Arguments Reference ### ConnectionEventArgs - `string ClientId` - Unique client identifier - `EndPoint RemoteEndPoint` - Client's remote address/port - `string Nickname` - Client's nickname (if set) - `bool HasNickname` - Whether client has a nickname ### DataReceivedEventArgs - `string ClientId` - Sender client ID - `byte[] Data` - Raw binary data - `string StringData` - Data decoded as UTF-8 string - `bool IsBinary` - True if binary data, false if text - `bool HasNickname` - Whether sender has a nickname - `string Nickname` - Sender's nickname (if set) ### ErrorEventArgs - `string Message` - Error description - `string ClientId` - Associated client (if applicable) - `Exception Exception` - Inner exception details ### PingEventArgs - `string ClientId` - Client that responded to ping - `long ResponseTime` - Response time in milliseconds ### IdleEventArgs / IdleClientEventArgs - `string ClientId` - Idle client ID - `double IdleTime` - Idle duration in seconds - `DisconnectReason Reason` - Reason for disconnection ## Disconnect Reasons The `DisconnectReason` enum provides detailed disconnect information: ```csharp public enum DisconnectReason { Unknown, // Unknown reason RemoteClosed, // Remote peer closed connection LocalClosed, // Local side closed connection Timeout, // Connection timeout Error, // General error SSLError, // SSL/TLS handshake error ServerShutdown, // Server shutting down Reconnect, // Reconnecting (client) ClientRequested, // Client requested disconnect Forced, // Forcefully disconnected NoPongReceived, // Heartbeat pong not received ProtocolError, // Protocol violation } ``` ## Key Security Enhancements ### 1. New Security Validation Layer (SecurityValidator.cs) **Location:** `EonaCat.Connections/Helpers/SecurityValidator.cs` **Features:** - **Length Prefix Validation** - Prevents buffer overflow and memory exhaustion by validating message lengths against configured maximum - **Message Stream Size Validation** - Detects decompression bombs and message accumulation attacks - **UDP Packet Validation** - Ensures UDP packets don't exceed buffer boundaries - **Rate Limiting** - Implements token-bucket style rate limiting per source address to prevent DoS attacks - **HTTP Header Validation** - Detects header injection attacks by checking for newline and null byte characters - **Delimiter Validation** - Prevents delimiter injection attacks - **Compression Ratio Validation** - Detects decompression bomb attacks - **Error Message Sanitization** - Prevents information leakage in error responses - **Rate Limit Cache Cleanup** - Prevents memory leaks from rate limit tracking ### 2. Configuration Security Settings ```csharp public long MaxMessageStreamSize { get; set; } = 500 * 1024 * 1024; // 500 MB public int MaxMessagesPerSecond { get; set; } = 0; // 0 = unlimited public bool EnableLengthPrefixValidation { get; set; } = true; public int MaxUdpPacketsPerSecond { get; set; } = 0; // 0 = unlimited public int MaxHealthApiRequestSize { get; set; } = 10 * 1024 * 1024; // 10 MB public bool EnableErrorMessageSanitization { get; set; } = true; public bool EnableRateLimitCacheCleanup { get; set; } = true; public int RateLimitCacheCleanupIntervalSeconds { get; set; } = 300; public bool EnableHttpHeaderValidation { get; set; } = true; ``` **Benefits:** - Configurable security thresholds for different deployment scenarios - Ability to fine-tune security vs. performance trade-offs - Granular control over which protections are enabled ### 3. NetworkServer Hardening 1. **Message Extraction Validation** - Updated `TryExtractLengthPrefixedMessage()` to use SecurityValidator for length prefix validation - Added checks to prevent message stream from exceeding configured maximum size - Enhanced error messages to indicate validation failures 2. **Message Stream Protection** - `HandleClientCommunicationAsync()` now validates message stream size before writing received data - Prevents accumulation of large amounts of buffered data that could exhaust memory - Disconnects clients that exceed limits with proper error logging 3. **UDP Rate Limiting** - `HandleUdpDataAsync()` implements packet size validation - UDP packet rate limiting prevents flood attacks - Per-source tracking of packet rates 4. **Background Cleanup Task** - Added `CleanupRateLimitCacheAsync()` to periodically clean up rate limit entries - Prevents memory leaks from unbounded cache growth - Configurable cleanup interval 5. **Startup Integration** - Rate limit cache cleanup task integrated into server startup - Runs as background task with configurable interval ### 4. NetworkClient Hardening 1. **Length-Prefixed Message Validation** - Updated `ReceiveLengthPrefixedMessagesAsync()` to validate length prefixes using SecurityValidator - Added dedicated exception handling for malformed length messages - Improved error messages for validation failures 2. **Delimiter-Based Message Protection** - Enhanced `ReceiveDelimiterAsync()` with max message stream size enforcement - Added checks for accumulated message buffer size - Prevents memory exhaustion from large buffered data ### 5. HealthApiServer REST API Hardening 1. **Request Size Limits** - New `MaxRequestSize` property to enforce maximum HTTP request/response size - Defaults to 10 MB, configurable before server starts - Request line limited to 8192 bytes - Total headers limited to 65536 bytes 2. **HTTP Header Security** - Enhanced `ReadRequestLineAsync()` to validate for invalid control characters - Rejects null bytes (0x00) in request lines - `DrainHeadersAsync()` validates header size and detects null bytes - Prevents header-based injection attacks 3. **Response Security Hardening** - `WriteResponseAsync()` validates response body size against limit - Content-Type validation prevents injection of control characters - Additional security headers added: - `X-Frame-Options: DENY` - Clickjacking protection - `X-XSS-Protection: 1; mode=block` - XSS protection - `Strict-Transport-Security` - Forces HTTPS - `Pragma: no-cache` - Additional cache control - Improved error handling for oversized responses ## Attack Vectors Mitigated ### 1. Buffer Overflow Attacks - **Mitigation:** Length prefix validation, buffer size checks, message size limits - **Implementation:** SecurityValidator validates all length values before buffer allocation ### 2. Memory Exhaustion / Decompression Bombs - **Mitigation:** MaxMessageStreamSize configuration, per-message size limits - **Implementation:** Accumulated stream size checked before each write operation ### 3. Slow Loris / Slowhttptest Attacks - **Mitigation:** Request timeouts, header size limits - **Implementation:** Network timeouts and maximum header sizes enforced ### 4. UDP Flood / Amplification Attacks - **Mitigation:** UDP rate limiting, packet size validation - **Implementation:** Per-source rate limiting with configurable thresholds ### 5. HTTP Header Injection - **Mitigation:** HTTP header validation, null byte detection - **Implementation:** SecurityValidator checks for newlines and null bytes in headers ### 6. Malformed Packet Attacks - **Mitigation:** Strict validation of message framing and length prefixes - **Implementation:** Enhanced error handling with specific exceptions for malformed data ### 7. Information Leakage - **Mitigation:** Error message sanitization - **Implementation:** Sensitive error details hidden from clients, detailed logs for server admins ### 8. Rate Limiting / DoS - **Mitigation:** Per-client/source rate limiting capability - **Implementation:** SecurityValidator.CheckRateLimit with configurable thresholds ## Configuration Best Practices ### Production Deployment ```csharp var config = new Configuration { // Message constraints MAX_MESSAGE_SIZE = 100 * 1024 * 1024, // 100 MB MaxMessageStreamSize = 500 * 1024 * 1024, // 500 MB // Rate limiting MaxMessagesPerSecond = 1000, // Per client MaxUdpPacketsPerSecond = 5000, // Per source MaxHealthApiRequestSize = 10 * 1024 * 1024, // 10 MB // Security features EnableLengthPrefixValidation = true, EnableErrorMessageSanitization = true, EnableRateLimitCacheCleanup = true, EnableHttpHeaderValidation = true }; ``` ### High-Security Deployment ```csharp var config = new Configuration { MAX_MESSAGE_SIZE = 10 * 1024 * 1024, // 10 MB MaxMessageStreamSize = 50 * 1024 * 1024, // 50 MB MaxMessagesPerSecond = 100, // Strict rate limit MaxUdpPacketsPerSecond = 500, // Strict UDP limit MaxHealthApiRequestSize = 1 * 1024 * 1024, // 1 MB // All security features enabled by default }; ``` ## Performance Considerations ### Optimization Tips 1. **Disable Nagle's Algorithm**: Set `EnableNagle = false` for lower latency 2. **Buffer Size**: Use appropriate `BufferSize` (default is ExtraLarge ~65KB) 3. **Keep-Alive**: Enable `EnableKeepAlive` to detect dead connections early 4. **Message Framing**: Use `LengthPrefixed` for better parsing performance 5. **Connection Pool**: Design clients to maintain persistent connections 6. **Batching**: Group small messages when possible 7. **Thread Affinity**: Run on dedicated cores for high throughput ### Monitoring - Use `HealthApi` for external monitoring - Enable `EnableServerStatusPage` for HTML reports - Monitor `MessagesPerSecond` for throughput - Track `IdleTimeout` events for connection health - Use `NetworkMonitor` for advanced diagnostics ## Thread Safety - `NetworkServer` and `NetworkClient` are thread-safe for all public methods - Events are called on socket completion threads - Use `ConfigureAwait(false)` in async handlers - Access shared state with appropriate synchronization ## Supported Platforms - ** .NET Standard 2.0** - Full support - **.NET Framework 4.8+** - Full support - **.NET 8.0** - Full support - **Platforms**: Windows, Linux, macOS (with .NET Core)