From 638b33b830c837deb9fdc17445c13ba46bd92c1a Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Sun, 19 Jul 2026 18:53:08 +0100 Subject: [PATCH] Expose TCP schema host health --- .../CultNetTcpSchemaTransport.cs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/GameCult.Networking/CultNetTcpSchemaTransport.cs b/src/GameCult.Networking/CultNetTcpSchemaTransport.cs index 168ce924..15935b87 100644 --- a/src/GameCult.Networking/CultNetTcpSchemaTransport.cs +++ b/src/GameCult.Networking/CultNetTcpSchemaTransport.cs @@ -110,6 +110,8 @@ namespace GameCult.Networking private readonly ConcurrentDictionary _handlers = new(); private readonly ConcurrentDictionary _peers = new(); private readonly CancellationTokenSource _shutdown = new(); + private readonly TaskCompletionSource _backgroundFailure = new( + TaskCreationOptions.RunContinuationsAsynchronously); private bool _disposed; public TcpFramedCultNetSchemaServer(TcpListener listener) @@ -120,7 +122,14 @@ namespace GameCult.Networking } public event Action? PeerDisconnected; + /// Raised when one peer connection fails without stopping the listener. + public event Action? PeerFailed; + /// Gets the bound TCP endpoint. public IPEndPoint LocalEndPoint => (IPEndPoint)_listener.LocalEndpoint; + /// Gets the number of active TCP peers. + public int PeerCount => _peers.Count; + /// Completes if the background accept loop fails. + public Task BackgroundFailure => _backgroundFailure.Task; public void OnCultNet(Func callback) where TMessage : ICultNetSchemaMessage @@ -162,6 +171,10 @@ namespace GameCult.Networking catch (Exception) when (_disposed || cancellationToken.IsCancellationRequested) { } + catch (Exception error) + { + _backgroundFailure.TrySetResult(error); + } } private async Task ServePeerAsync(TcpPeer peer, CancellationToken cancellationToken) @@ -182,6 +195,10 @@ namespace GameCult.Networking catch (Exception) when (_disposed || cancellationToken.IsCancellationRequested || !peer.Connected) { } + catch (Exception error) + { + PeerFailed?.Invoke(peer.RemoteEndPoint, error); + } finally { if (_peers.TryRemove(peer, out _)) PeerDisconnected?.Invoke(peer);