Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe
This commit is contained in:
@@ -39,7 +39,7 @@ public sealed class EncapsulationClient : IAsyncDisposable
|
||||
private static readonly TimeSpan UnregisterBudget = TimeSpan.FromMilliseconds(500);
|
||||
|
||||
private readonly TcpClient _tcp;
|
||||
private readonly NetworkStream _stream;
|
||||
private readonly Stream _stream;
|
||||
|
||||
// Never disposed: an abandoned exchange may release it after DisposeAsync returns, and
|
||||
// SemaphoreSlim.Release on a disposed instance throws. It holds no unmanaged resource unless
|
||||
@@ -56,12 +56,17 @@ public sealed class EncapsulationClient : IAsyncDisposable
|
||||
/// <summary>False once the connection has faulted or been disposed.</summary>
|
||||
public bool IsConnected => !_faulted && Volatile.Read(ref _disposed) == 0 && _tcp.Connected;
|
||||
|
||||
private EncapsulationClient(TcpClient tcp)
|
||||
private EncapsulationClient(TcpClient tcp, Stream? stream = null)
|
||||
{
|
||||
_tcp = tcp;
|
||||
_stream = tcp.GetStream();
|
||||
_stream = stream ?? tcp.GetStream();
|
||||
}
|
||||
|
||||
/// <summary>Test seam: wraps an already-connected <paramref name="tcp"/> but routes all frame I/O through
|
||||
/// <paramref name="stream"/> (e.g. one whose write never completes), skipping RegisterSession. The TCP
|
||||
/// client is still what <see cref="Fault"/> closes and <see cref="IsConnected"/> consults.</summary>
|
||||
internal static EncapsulationClient ForStream(TcpClient tcp, Stream stream) => new(tcp, stream);
|
||||
|
||||
/// <summary>Open the TCP connection and register an encapsulation session. <paramref name="timeout"/>
|
||||
/// bounds the TCP connect and the RegisterSession exchange separately.</summary>
|
||||
public static async Task<EncapsulationClient> ConnectAsync(string host, int port, TimeSpan timeout, CancellationToken ct)
|
||||
|
||||
Reference in New Issue
Block a user