review(Driver.Historian.Wonderware.Client): async frame-header write + wire-parity test
Re-review at 7286d320. -011: FrameWriter folded the sync WriteByte (could block on SslStream
past the call timeout) into one async 5-byte header write. -012: DefaultTcpConnectFactory
readonly. -013: wire-parity test for PerEventStatus [Key(4)]. No wire change.
This commit is contained in:
+1
-1
@@ -35,7 +35,7 @@ internal sealed class FrameChannel : IAsyncDisposable
|
||||
/// in TLS (server-auth; pinned-thumbprint or CA-chain validation). The Hello handshake +
|
||||
/// shared secret still authenticate the caller on top of this.
|
||||
/// </summary>
|
||||
public static Func<WonderwareHistorianClientOptions, CancellationToken, Task<Stream>> DefaultTcpConnectFactory =
|
||||
public static readonly Func<WonderwareHistorianClientOptions, CancellationToken, Task<Stream>> DefaultTcpConnectFactory =
|
||||
async (opts, ct) =>
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(opts.Host))
|
||||
|
||||
+12
-8
@@ -33,18 +33,22 @@ public sealed class FrameWriter : IDisposable
|
||||
throw new InvalidOperationException(
|
||||
$"Sidecar IPC frame body {body.Length} exceeds {Framing.MaxFrameBodyBytes} byte cap.");
|
||||
|
||||
var lengthPrefix = new byte[Framing.LengthPrefixSize];
|
||||
// Big-endian.
|
||||
lengthPrefix[0] = (byte)((body.Length >> 24) & 0xFF);
|
||||
lengthPrefix[1] = (byte)((body.Length >> 16) & 0xFF);
|
||||
lengthPrefix[2] = (byte)((body.Length >> 8) & 0xFF);
|
||||
lengthPrefix[3] = (byte)( body.Length & 0xFF);
|
||||
// 5-byte header: [4-byte big-endian body length][1-byte message kind].
|
||||
// The kind byte is folded into the header array so every write inside the gate
|
||||
// is async+cancellable — a synchronous Stream.WriteByte() blocks the calling
|
||||
// thread-pool thread and cannot be interrupted by the call-timeout token when
|
||||
// the peer's receive window is full (same class of bug as finding 005 on reads).
|
||||
var header = new byte[Framing.LengthPrefixSize + Framing.KindByteSize];
|
||||
header[0] = (byte)((body.Length >> 24) & 0xFF);
|
||||
header[1] = (byte)((body.Length >> 16) & 0xFF);
|
||||
header[2] = (byte)((body.Length >> 8) & 0xFF);
|
||||
header[3] = (byte)( body.Length & 0xFF);
|
||||
header[4] = (byte)kind;
|
||||
|
||||
await _gate.WaitAsync(ct).ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
await _stream.WriteAsync(lengthPrefix, ct).ConfigureAwait(false);
|
||||
_stream.WriteByte((byte)kind);
|
||||
await _stream.WriteAsync(header, ct).ConfigureAwait(false);
|
||||
await _stream.WriteAsync(body, ct).ConfigureAwait(false);
|
||||
await _stream.FlushAsync(ct).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user