fix(modbus): classify per-op timeout + framing violations connection-fatal (05/STAB-3)
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
namespace ZB.MOM.WW.OtOpcUa.Driver.Modbus;
|
||||
|
||||
/// <summary>
|
||||
/// Raised when a Modbus TCP transaction leaves the single-flight socket in an unknown /
|
||||
/// desynchronized state — a per-op response timeout, or a framing violation (transaction-id
|
||||
/// mismatch or truncated MBAP length). Unlike a Modbus <em>exception PDU</em> (a well-formed
|
||||
/// protocol-level error where the socket is still coherent and the request must simply
|
||||
/// propagate), a desync means bytes may still be in flight or half-read, so the socket is
|
||||
/// unusable and MUST be torn down before this is thrown.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Derives from <see cref="IOException"/> deliberately: the transport's existing
|
||||
/// reconnect-and-retry classifier (<c>IsSocketLevelFailure</c>) already treats
|
||||
/// <see cref="IOException"/> as socket-fatal, so with auto-reconnect enabled the transport
|
||||
/// transparently reconnects and resends once; with auto-reconnect disabled the (already torn
|
||||
/// down) socket is never reused and this surfaces to the driver's status mapping as a
|
||||
/// communication error.
|
||||
/// </remarks>
|
||||
public sealed class ModbusTransportDesyncException : IOException
|
||||
{
|
||||
/// <summary>The reason the socket was classified desynchronized.</summary>
|
||||
public enum DesyncReason
|
||||
{
|
||||
/// <summary>The per-op deadline (linked <c>CancelAfter</c>) fired — the response never arrived in time.</summary>
|
||||
Timeout,
|
||||
|
||||
/// <summary>The response MBAP transaction id did not match the request's.</summary>
|
||||
TxIdMismatch,
|
||||
|
||||
/// <summary>The response MBAP length field was below the mandatory minimum (truncated frame).</summary>
|
||||
TruncatedFrame,
|
||||
}
|
||||
|
||||
/// <summary>Gets the reason the socket was classified desynchronized.</summary>
|
||||
public DesyncReason Reason { get; }
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="ModbusTransportDesyncException"/> class.</summary>
|
||||
/// <param name="reason">The desync reason.</param>
|
||||
/// <param name="message">A human-readable description.</param>
|
||||
/// <param name="inner">The originating exception, if any.</param>
|
||||
public ModbusTransportDesyncException(DesyncReason reason, string message, Exception? inner = null)
|
||||
: base(message, inner)
|
||||
{
|
||||
Reason = reason;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user