fix(abcip): Task 13 review r1 - bounded listing pager, exclusive large reads, template bound, safe lease release
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using ZB.MOM.WW.OtOpcUa.Driver.Ab.Transport;
|
||||
using ZB.MOM.WW.OtOpcUa.Driver.Ab.Transport.Cip;
|
||||
using ZB.MOM.WW.OtOpcUa.Driver.Ab.Transport.Logix;
|
||||
@@ -17,7 +19,11 @@ internal sealed class NativeAbCipTemplateReader : IAbCipTemplateReader
|
||||
/// <summary>Bytes of the template definition header not counted in the Read Template length.</summary>
|
||||
private const int DefinitionHeaderBytes = 23;
|
||||
|
||||
/// <summary>Upper bound on a template's Read Template length; Logix templates are far smaller.</summary>
|
||||
internal const long MaxTemplateBytes = 64 * 1024;
|
||||
|
||||
private readonly Func<AbCipTagCreateParams, (RequestScheduler Scheduler, ICipChannel Channel, Func<ValueTask> Release)> _acquire;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
/// <summary>Production constructor: leases from <paramref name="pool"/>.</summary>
|
||||
/// <param name="pool">The connection pool (the factory passes <see cref="DeviceSessionPool.Shared"/>).</param>
|
||||
@@ -32,9 +38,14 @@ internal sealed class NativeAbCipTemplateReader : IAbCipTemplateReader
|
||||
|
||||
/// <summary>Test seam: supplies the scheduler, channel and release directly.</summary>
|
||||
/// <param name="acquire">Acquires the connection parts for a device.</param>
|
||||
/// <param name="logger">Receives release failures; null discards them.</param>
|
||||
internal NativeAbCipTemplateReader(
|
||||
Func<AbCipTagCreateParams, (RequestScheduler Scheduler, ICipChannel Channel, Func<ValueTask> Release)> acquire) =>
|
||||
Func<AbCipTagCreateParams, (RequestScheduler Scheduler, ICipChannel Channel, Func<ValueTask> Release)> acquire,
|
||||
ILogger? logger = null)
|
||||
{
|
||||
_acquire = acquire;
|
||||
_logger = logger ?? NullLogger.Instance;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<byte[]> ReadAsync(
|
||||
@@ -53,7 +64,7 @@ internal sealed class NativeAbCipTemplateReader : IAbCipTemplateReader
|
||||
|
||||
// The CIP-documented Read Template length: definition words * 4 - 23.
|
||||
var total = checked((long)attrs.DefinitionWords * 4 - DefinitionHeaderBytes);
|
||||
if (total < 0)
|
||||
if (total < 0 || total > MaxTemplateBytes)
|
||||
throw new AbTransportException(AbStatus.BadReply,
|
||||
$"Template {id} reports an impossible definition size of {attrs.DefinitionWords} words.");
|
||||
|
||||
@@ -63,7 +74,7 @@ internal sealed class NativeAbCipTemplateReader : IAbCipTemplateReader
|
||||
{
|
||||
var chunk = (ushort)Math.Min(total - offset, channel.MaxRequestBytes - RequestOverhead);
|
||||
var reply = await scheduler
|
||||
.SendAsync(TemplateObjectServices.ReadTemplate(id, (uint)offset, chunk), cancellationToken)
|
||||
.SendAsync(TemplateObjectServices.ReadTemplate(id, (uint)offset, chunk), cancellationToken, exclusive: true)
|
||||
.ConfigureAwait(false);
|
||||
if (reply.GeneralStatus is not (0x00 or 0x06))
|
||||
throw new AbTransportException(reply.Status,
|
||||
@@ -80,7 +91,7 @@ internal sealed class NativeAbCipTemplateReader : IAbCipTemplateReader
|
||||
}
|
||||
finally
|
||||
{
|
||||
NativeLease.ReleaseBounded(release);
|
||||
NativeLease.ReleaseBounded(release, _logger);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user