Class BaseAuthenticatorCore<TConnection>
- Namespace
- FishMMO.Auth.Implementation
- Assembly
- FishMMO-ServerAuth.dll
Abstract engine-independent base for all server authenticators. Provides X25519 ECDH handshake logic, stale-auth TTL sweeps, per-IP and global handshake rate limiting, and connection auth-state tracking — with no dependency on Unity, FishNet, or any game-engine type.
Concrete implementations supply transport-specific callbacks (broadcast, disconnect, IP resolution) by implementing the abstract members, then call OnHandshakeReceived(TConnection, byte[], byte[], string, ushort, ushort, string) from their transport layer.
public abstract class BaseAuthenticatorCore<TConnection>
Type Parameters
TConnectionThe type representing a network connection.
- Inheritance
-
BaseAuthenticatorCore<TConnection>
- Derived
- Inherited Members
Constructors
BaseAuthenticatorCore(IAccountManager<TConnection>)
Initializes the core with the required account manager.
protected BaseAuthenticatorCore(IAccountManager<TConnection> accountManager)
Parameters
accountManagerIAccountManager<TConnection>The account manager instance.
Fields
AuthHardDeadlineSeconds
Hard deadline in seconds for any single authentication attempt. RefreshAuthTtl(TConnection) will not extend a connection's TTL beyond this absolute limit from its original start time, preventing unbounded TTL extension.
protected const float AuthHardDeadlineSeconds = 60
Field Value
AuthStaleTtlSeconds
Authentication TTL in seconds. Connections that do not complete auth within this window are purged.
protected const float AuthStaleTtlSeconds = 15
Field Value
AuthSweepMaxRemovals
Maximum stale auth entries purged per sweep.
protected const int AuthSweepMaxRemovals = 64
Field Value
AuthSweepMaxScan
Maximum stale auth entries scanned per sweep.
protected const int AuthSweepMaxScan = 256
Field Value
HandshakeIpBurstLimit
Maximum Phase-2 handshake completions accepted from one IP inside HandshakeIpWindowSeconds. The old fixed 0.25 s debounce keyed the whole handshake round trip on one interval: any second completion inside the window — a player behind the same NAT as another, or a re-login whose connect+token+challenge cycle finishes faster than the window on a sub-10 ms link — was silently disconnected. A burst of 8 covers the legitimate worst case (a household logging in together, a fast reconnect loop) without meaningfully weakening the sustained per-IP throttle the limiter exists for.
protected const int HandshakeIpBurstLimit = 8
Field Value
HandshakeIpWindowSeconds
Duration of the per-IP Phase-2 handshake measurement window. Combined with HandshakeIpBurstLimit this sustains 4 completed handshakes/second/IP (unchanged from the previous single-deadline debounce) while allowing a burst of near-simultaneous completions from one IP.
protected const float HandshakeIpWindowSeconds = 2
Field Value
HandshakeRateLimitSweepMaxRemovals
Maximum entries removed per handshake rate-limit sweep.
protected const int HandshakeRateLimitSweepMaxRemovals = 2048
Field Value
HandshakeRateLimitSweepMaxScan
Maximum entries scanned per handshake rate-limit sweep.
protected const int HandshakeRateLimitSweepMaxScan = 4096
Field Value
MaxGlobalHandshakesPerSecond
Maximum X25519 handshakes accepted in a single 1-second window.
protected const int MaxGlobalHandshakesPerSecond = 500
Field Value
MaxPendingAuthConnections
Maximum number of concurrent pending authentication connections.
protected const int MaxPendingAuthConnections = 10000
Field Value
Properties
AccountManager
The account manager for this authenticator.
protected IAccountManager<TConnection> AccountManager { get; }
Property Value
- IAccountManager<TConnection>
ExpectedGameVersion
Expected game version string (e.g. "0.1.0"). Set by the server host before
connections are accepted. If null or empty, game version validation is skipped
(development safety). When set, clients with a mismatched ClientHandshake.GameVersion
are rejected with VersionMismatch.
public string ExpectedGameVersion { get; set; }
Property Value
IsWorkerIdle
Returns true when no async worker operations are in-flight. Subclasses with bounded-channel workers should override to check channel emptiness. Default returns true.
public virtual bool IsWorkerIdle { get; }
Property Value
LogPrefix
Log source tag used in all log messages emitted by this core.
protected virtual string LogPrefix { get; }
Property Value
Methods
BroadcastAuthResult(TConnection, ClientAuthenticationResult, bool)
Broadcasts an authentication result to a single connection.
protected abstract void BroadcastAuthResult(TConnection conn, ClientAuthenticationResult result, bool reliable)
Parameters
connTConnectionTarget connection.
resultClientAuthenticationResultAuth result code.
reliableboolTrue for reliable delivery, false for unreliable.
BroadcastCookieChallenge(TConnection, byte[])
Sends a cookie-challenge ServerHandshake response to the client.
Called on the network-receive thread — must be non-blocking.
protected abstract void BroadcastCookieChallenge(TConnection conn, byte[] cookie)
Parameters
connTConnectionThe target connection.
cookiebyte[]The HMAC cookie to send.
BroadcastServerHandshake(TConnection, byte[], ushort)
Sends the final ServerHandshake response (with the server's X25519 public key)
to complete ECDH key agreement.
Called on the network-receive thread — must be non-blocking.
protected abstract void BroadcastServerHandshake(TConnection conn, byte[] serverPublicKey, ushort agreedVersion)
Parameters
connTConnectionThe target connection.
serverPublicKeybyte[]Server's ephemeral X25519 public key.
agreedVersionushortNegotiated protocol version.
ClearTransientAuthState(int)
Clears transient per-connection authenticator TTL tracking state.
protected void ClearTransientAuthState(int clientId)
Parameters
clientIdintConnection client ID.
DisconnectConnection(TConnection, bool)
Disconnects the specified connection.
protected abstract void DisconnectConnection(TConnection conn, bool graceful)
Parameters
connTConnectionThe connection to disconnect.
gracefulboolIf true, attempt a graceful close; otherwise force-close immediately.
EnqueueMainThread(TConnection, Action)
Enqueues an action to be executed on the main/UI thread. Implementations using Unity must marshal all network API calls (Broadcast, Disconnect) via this method. Non-Unity implementations may execute immediately or use their own dispatcher.
protected abstract void EnqueueMainThread(TConnection conn, Action action)
Parameters
connTConnectionThe connection context (for lifetime checking).
actionActionThe action to enqueue.
GetConnectionAddress(TConnection)
Returns the remote IP address (or equivalent string identifier) for the connection. Used for cookie challenge IP binding and rate limiting.
protected abstract string GetConnectionAddress(TConnection conn)
Parameters
connTConnection
Returns
GetConnectionClientId(TConnection)
Returns the numeric client ID for the connection (e.g., FishNet ClientId).
Used as the key for TTL tracking dictionaries.
protected abstract int GetConnectionClientId(TConnection conn)
Parameters
connTConnection
Returns
HandleConnectionStopped(TConnection)
Called by the hosting transport layer when a connection has been disconnected. Purges all authenticator state for the connection without disconnecting (already stopped).
public void HandleConnectionStopped(TConnection conn)
Parameters
connTConnectionThe stopped connection.
InitializeWorkers(CancellationToken)
Generates a fresh cookie HMAC key and starts protocol-specific workers. Must be called before accepting connections.
public void InitializeWorkers(CancellationToken cancellationToken)
Parameters
cancellationTokenCancellationTokenToken for signalling graceful shutdown.
InitializeWorkersCore(CancellationToken)
Subclass-specific worker initialization: create channels and start worker tasks. Called after the base generates the cookie key.
protected abstract void InitializeWorkersCore(CancellationToken cancellationToken)
Parameters
cancellationTokenCancellationTokenToken for signalling worker shutdown.
IsConnectionAuthenticated(TConnection)
Returns whether this connection has already completed authentication. Called on the network-receive thread — must be thread-safe and non-blocking.
protected abstract bool IsConnectionAuthenticated(TConnection conn)
Parameters
connTConnection
Returns
OnAuthSweep()
Override for subclass-specific logic that runs alongside the stale-auth sweep.
protected virtual void OnAuthSweep()
OnHandshakeDeferred(TConnection)
Invoked when a handshake cannot be admitted because the pending authentication
cap (MaxPendingAuthConnections) has been reached. Override to
implement a login queue — return true if the connection was queued and
should NOT be disconnected; return false (default) to drop the handshake.
protected virtual bool OnHandshakeDeferred(TConnection conn)
Parameters
connTConnectionThe connection that is being deferred.
Returns
- bool
trueif the connection was queued;falseto reject.
OnHandshakeReceived(TConnection, byte[], byte[], string, ushort, ushort, string)
Processes an incoming client handshake. Must be called from the transport layer
(e.g., on receipt of a ClientHandshakeBroadcast).
Implements a two-phase stateless cookie challenge followed by X25519 ECDH key agreement.
Runs with no blocking I/O — safe to call on a network-receive thread.
public void OnHandshakeReceived(TConnection conn, byte[] publicKey, byte[] cookie, string connectionToken, ushort minVersion, ushort maxVersion, string gameVersion = "")
Parameters
connTConnectionThe network connection.
publicKeybyte[]Client's X25519 ephemeral public key (32 bytes). Must not be null.
cookiebyte[]Cookie echoed from a prior challenge, or null on first attempt.
connectionTokenstringminVersionushortMinimum protocol version supported by the client.
maxVersionushortMaximum protocol version supported by the client.
gameVersionstring
OnPurgeConnectionState(TConnection)
Override for subclass-specific cleanup during connection purge.
Called before AccountManager.RemoveConnectionAccount but after
ClearTransientAuthState(int) has removed TTL tracking.
protected virtual void OnPurgeConnectionState(TConnection conn)
Parameters
connTConnectionThe connection being purged.
OnTick()
Override for subclass-specific per-tick logic (e.g., additional periodic sweeps).
protected virtual void OnTick()
PurgeConnectionAuthState(TConnection, bool)
Purges all authenticator state for a connection and optionally disconnects it. TTL tracking is cleared before disconnect to prevent races.
protected void PurgeConnectionAuthState(TConnection conn, bool disconnect)
Parameters
connTConnectionConnection to purge.
disconnectboolIf true, disconnect the client after purge.
RefreshAuthTtl(TConnection)
Resets the TTL timestamp for a tracked connection to UtcNow. Call from async workers at meaningful progress points to prevent premature sweeping. Refuses to refresh beyond AuthHardDeadlineSeconds from original start.
protected void RefreshAuthTtl(TConnection conn)
Parameters
connTConnectionConnection whose TTL to refresh.
ResolveRateLimitKey(TConnection)
Resolves a rate-limit key for a connection. Override to return a connection-ID string in proxy/NAT deployments where all clients share the same transport-level IP. Default: returns the normalized remote IP address.
protected virtual string ResolveRateLimitKey(TConnection conn)
Parameters
connTConnectionThe network connection.
Returns
- string
A string key suitable for per-identity rate limiting.
ShutdownWorkers()
Gracefully shuts down all async workers and zeroes sensitive key material. Calls ShutdownWorkersCore() first to allow subclasses to complete channel writers for graceful worker exit.
public void ShutdownWorkers()
ShutdownWorkersCore()
Subclass-specific worker shutdown: complete channel writers, null channel references, and clear subclass-specific state. Called BEFORE the base zeroes the cookie key.
protected abstract void ShutdownWorkersCore()
Tick()
Runs the stale-auth TTL sweep and the handshake rate-limit sweep. Must be called periodically by the hosting environment (e.g., every server tick or Update frame).
public void Tick()
TrackAuthStart(TConnection)
Starts auth TTL tracking for a connection if not already tracked.
Returns false if the pending authentication cap has been reached.
protected bool TrackAuthStart(TConnection conn)
Parameters
connTConnectionConnection entering the authentication flow.
Returns
- bool
trueif tracking was started;falseif the cap was reached.