Files
EonaCat.Connections/README.md
T
2026-06-24 06:47:13 +02:00

1079 lines
36 KiB
Markdown

# 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<ConnectionEventArgs> OnConnected;
public event EventHandler<ConnectionEventArgs> OnConnectedWithNickname;
public event EventHandler<ConnectionEventArgs> OnDisconnected;
// Data events
public event EventHandler<DataReceivedEventArgs> OnDataReceived;
// Error events
public event EventHandler<ErrorEventArgs> OnSslError;
public event EventHandler<ErrorEventArgs> OnEncryptionError;
public event EventHandler<ErrorEventArgs> OnGeneralError;
public event EventHandler<ErrorEventArgs> OnSocketError;
// Heartbeat events
public event EventHandler<PingEventArgs> OnClientPingResponse;
public event EventHandler<PingEventArgs> OnPongMissed;
// Idle/Timeout events
public event EventHandler<IdleEventArgs> OnIdleTimeout;
// Logging
public event EventHandler<string> 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<string, Connection> GetClients();
public List<Connection> GetClient(string clientId);
public async Task DisconnectClientAsync(string clientId, DisconnectReason reason, Exception? exception);
// Messaging - Send to Specific Client
public async Task<bool> SendToClientAsync(string clientId, byte[] data);
public async Task<bool> SendToClientAsync(string clientId, string message);
// Messaging - Client-to-Client
public async Task<bool> SendFromClientToClientAsync(string fromClientId, string toClientId, byte[] data);
public async Task<bool> SendFromClientToClientAsync(string fromClientId, string toClientId, string message);
// Broadcast Messaging
public async Task<bool> BroadcastAsync(byte[] data);
public async Task<bool> BroadcastAsync(string message);
// Request-Response Patterns
public async Task<DataReceivedEventArgs> SendToClientAndWaitForResponseAsync(
string clientId, byte[] data, TimeSpan? timeout = null);
public async Task<DataReceivedEventArgs> SendToClientAndWaitForResponseAsync(
string clientId, string message, TimeSpan? timeout = null);
public async Task<DataReceivedEventArgs> SendFromClientToClientAndWaitForResponseAsync(
string fromClientId, string toClientId, byte[] data, TimeSpan? timeout = null);
public async Task<DataReceivedEventArgs> SendFromClientToClientAndWaitForResponseAsync(
string fromClientId, string toClientId, string message, TimeSpan? timeout = null);
public async Task<List<DataReceivedEventArgs>> BroadcastAndWaitForResponsesAsync(
byte[] data, TimeSpan? timeout = null);
public async Task<List<DataReceivedEventArgs>> 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<ConnectionEventArgs> OnConnected;
public event EventHandler<ConnectionEventArgs> OnNicknameSend;
public event EventHandler<ConnectionEventArgs> OnDisconnected;
// Data events
public event EventHandler<DataReceivedEventArgs> OnDataReceived;
// Error events
public event EventHandler<ErrorEventArgs> OnSslError;
public event EventHandler<ErrorEventArgs> OnEncryptionError;
public event EventHandler<ErrorEventArgs> OnGeneralError;
public event EventHandler<ErrorEventArgs> OnSocketError;
// Heartbeat events
public event EventHandler<PingEventArgs> OnPingResponse;
public event EventHandler<PingEventArgs> OnPongResponse;
// Idle/Timeout events
public event EventHandler<IdleClientEventArgs> OnIdleTimeout;
// Logging
public event EventHandler<string> 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<bool> ConnectAsync();
public async Task DisconnectAsync();
public async Task DisconnectDueTimeoutAsync();
// Messaging
public async Task<bool> SendAsync(byte[] data);
public async Task<bool> SendAsync(string message);
// Nickname
public async Task<bool> SendNicknameAsync(string nickname);
// Request-Response
public async Task<DataReceivedEventArgs> SendAndWaitForResponseAsync(
byte[] data, TimeSpan? timeout = null);
public async Task<DataReceivedEventArgs> SendAndWaitForResponseAsync(
string message, TimeSpan? timeout = null);
public async Task<DataReceivedEventArgs> 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<string> { "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)