Skip to content

Commit

Permalink
Set TCP defaults for max message size to align with min buffer size (#…
Browse files Browse the repository at this point in the history
…2616)

* Avoid user configuration errors by setting unaligned max message size values, fix defaults.
* Set the MaxMessageSize defaults to multiple of MinBufferSize to avoid rounding errors in other UA implementations.
  • Loading branch information
mregen authored May 13, 2024
1 parent 663ed10 commit 52d4492
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 13 deletions.
17 changes: 15 additions & 2 deletions Stack/Opc.Ua.Core/Stack/Tcp/TcpMessageType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -242,15 +242,16 @@ public static class TcpMessageLimits
/// <summary>
/// The default maximum chunk count for Request and Response messages.
/// </summary>
public const int DefaultMaxChunkCount = 32;
public const int DefaultMaxChunkCount = DefaultMaxMessageSize / MinBufferSize;

/// <summary>
/// The default maximum message size.
/// </summary>
/// <remarks>
/// The default is 2MB. Ensure to set this to a value aligned to <see cref="MinBufferSize"/>.
/// This default is for the Tcp transport. <see cref="DefaultEncodingLimits.MaxMessageSize"/> for the generic default.
/// </remarks>
public const int DefaultMaxMessageSize = DefaultMaxChunkCount * DefaultMaxBufferSize;
public const int DefaultMaxMessageSize = MinBufferSize * 256;

/// <summary>
/// The default maximum message size for the discovery channel.
Expand Down Expand Up @@ -301,5 +302,17 @@ public static class TcpMessageLimits
/// The certificates that have the key size larger than KeySizeExtraPadding need an extra padding byte in the transport message
/// </summary>
public const int KeySizeExtraPadding = 2048;

/// <summary>
/// Aligns the max message size to the nearest min buffer size.
/// </summary>
/// <remarks>
/// Align user configured maximum message size to avoid rounding errors in other UA implementations.
/// </remarks>
public static int AlignRoundMaxMessageSize(int value)
{
int alignmentMask = MinBufferSize - 1;
return (value + alignmentMask) & ~alignmentMask;
}
}
}
4 changes: 2 additions & 2 deletions Stack/Opc.Ua.Core/Stack/Tcp/TcpTransportListener.cs
Original file line number Diff line number Diff line change
Expand Up @@ -138,12 +138,12 @@ public void Open(
{
m_inactivityDetectPeriod = configuration.ChannelLifetime / 2;
m_quotas.MaxBufferSize = configuration.MaxBufferSize;
m_quotas.MaxMessageSize = configuration.MaxMessageSize;
m_quotas.MaxMessageSize = TcpMessageLimits.AlignRoundMaxMessageSize(configuration.MaxMessageSize);
m_quotas.ChannelLifetime = configuration.ChannelLifetime;
m_quotas.SecurityTokenLifetime = configuration.SecurityTokenLifetime;
messageContext.MaxArrayLength = configuration.MaxArrayLength;
messageContext.MaxByteStringLength = configuration.MaxByteStringLength;
messageContext.MaxMessageSize = configuration.MaxMessageSize;
messageContext.MaxMessageSize = TcpMessageLimits.AlignRoundMaxMessageSize(configuration.MaxMessageSize);
messageContext.MaxStringLength = configuration.MaxStringLength;
messageContext.MaxEncodingNestingLevels = configuration.MaxEncodingNestingLevels;
messageContext.MaxDecoderRecoveries = configuration.MaxDecoderRecoveries;
Expand Down
4 changes: 2 additions & 2 deletions Stack/Opc.Ua.Core/Stack/Tcp/UaSCBinaryTransportChannel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -423,13 +423,13 @@ private void SaveSettings(Uri url, TransportChannelSettings settings)
EndpointConfiguration configuration = m_settings.Configuration;
m_quotas = new ChannelQuotas {
MaxBufferSize = configuration.MaxBufferSize,
MaxMessageSize = configuration.MaxMessageSize,
MaxMessageSize = TcpMessageLimits.AlignRoundMaxMessageSize(configuration.MaxMessageSize),
ChannelLifetime = configuration.ChannelLifetime,
SecurityTokenLifetime = configuration.SecurityTokenLifetime,
MessageContext = new ServiceMessageContext() {
MaxArrayLength = configuration.MaxArrayLength,
MaxByteStringLength = configuration.MaxByteStringLength,
MaxMessageSize = configuration.MaxMessageSize,
MaxMessageSize = TcpMessageLimits.AlignRoundMaxMessageSize(configuration.MaxMessageSize),
MaxStringLength = configuration.MaxStringLength,
MaxEncodingNestingLevels = configuration.MaxEncodingNestingLevels,
MaxDecoderRecoveries = configuration.MaxDecoderRecoveries,
Expand Down
18 changes: 11 additions & 7 deletions Stack/Opc.Ua.Core/Types/Utils/DefaultEncodingLimits.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/

using System;
using Opc.Ua.Bindings;

namespace Opc.Ua
{
Expand All @@ -21,32 +22,35 @@ namespace Opc.Ua
public static class DefaultEncodingLimits
{
/// <summary>
/// The maximum length for any string, byte string or xml element.
/// The default maximum length for any string, byte string or xml element.
/// </summary>
public static readonly int MaxStringLength = UInt16.MaxValue;

/// <summary>
/// The maximum length for any array.
/// The default maximum length for any array.
/// </summary>
public static readonly int MaxArrayLength = UInt16.MaxValue;

/// <summary>
/// The maximum length for any ByteString.
/// The default maximum length for any ByteString.
/// </summary>
public static readonly int MaxByteStringLength = UInt16.MaxValue * 16;

/// <summary>
/// The maximum length for any Message.
/// The default maximum length for any Message.
/// </summary>
public static readonly int MaxMessageSize = UInt16.MaxValue * 32;
/// <remarks>
/// Default is 2MB. Set to multiple of MinBufferSize to avoid rounding errors in other UA implementations.
/// </remarks>
public static readonly int MaxMessageSize = TcpMessageLimits.MinBufferSize * 256;

/// <summary>
/// The maximum nesting level accepted while encoding or decoding objects.
/// The default maximum nesting level accepted while encoding or decoding objects.
/// </summary>
public static readonly int MaxEncodingNestingLevels = 200;

/// <summary>
/// The number of times the decoder can recover from an error
/// The default number of times the decoder can recover from an error
/// caused by an encoded ExtensionObject before throwing a decoder error.
/// </summary>
public static readonly int MaxDecoderRecoveries = 0;
Expand Down

0 comments on commit 52d4492

Please # to comment.