Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Some .NET 9 maintenance and JSON encoder improvements #2922

Merged
merged 17 commits into from
Jan 20, 2025
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Fuzzing/Encoders/Fuzz.Tests/Opc.Ua.Encoders.Fuzz.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="NUnit" Version="4.2.2" />
<PackageReference Include="NUnit.Console" Version="3.18.3" />
<PackageReference Include="NUnit" Version="4.3.2" />
<PackageReference Include="NUnit.Console" Version="3.19.0" />
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
Expand Down
4 changes: 0 additions & 4 deletions Libraries/Opc.Ua.Client/Opc.Ua.Client.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,6 @@
<PackageId>$(PackageId).Debug</PackageId>
</PropertyGroup>

<ItemGroup Condition="'$(TargetFramework)' != 'net6.0' AND '$(TargetFramework)' != 'net7.0' AND '$(TargetFramework)' != 'net8.0'">
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="6.0.1" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\Stack\Opc.Ua.Core\Opc.Ua.Core.csproj" />
<ProjectReference Include="..\Opc.Ua.Configuration\Opc.Ua.Configuration.csproj" />
Expand Down
12 changes: 8 additions & 4 deletions Libraries/Opc.Ua.Client/Session/Session.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6084,6 +6084,7 @@ private void ProcessPublishResponse(
// ignore messages with a subscription that has been deleted.
if (subscription != null)
{
#if DEBUG
// Validate publish time and reject old values.
if (notificationMessage.PublishTime.AddMilliseconds(subscription.CurrentPublishingInterval * subscription.CurrentLifetimeCount) < DateTime.UtcNow)
{
Expand All @@ -6095,12 +6096,15 @@ private void ProcessPublishResponse(
{
Utils.LogTrace("PublishTime {0} in publish response is newer than actual time for SubscriptionId {1}.", notificationMessage.PublishTime.ToLocalTime(), subscription.Id);
}
#endif
// save the information that more notifications are expected
notificationMessage.MoreNotifications = moreNotifications;

// save the string table that came with the notification.
notificationMessage.StringTable = responseHeader.StringTable;

// update subscription cache.
subscription.SaveMessageInCache(
availableSequenceNumbers,
notificationMessage,
responseHeader.StringTable);
subscription.SaveMessageInCache(availableSequenceNumbers, notificationMessage);

// raise the notification.
NotificationEventHandler publishEventHandler = m_Publish;
Expand Down
16 changes: 7 additions & 9 deletions Libraries/Opc.Ua.Client/Subscription/Subscription.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1385,8 +1385,7 @@ public List<ServiceResult> SetMonitoringMode(
/// </summary>
public void SaveMessageInCache(
IList<uint> availableSequenceNumbers,
NotificationMessage message,
IList<string> stringTable)
NotificationMessage message)
{
PublishStateChangedEventHandler callback = null;

Expand All @@ -1411,12 +1410,10 @@ public void SaveMessageInCache(

DateTime now = DateTime.UtcNow;
Interlocked.Exchange(ref m_lastNotificationTime, now.Ticks);

int tickCount = HiResClock.TickCount;
m_lastNotificationTickCount = tickCount;

// save the string table that came with notification.
message.StringTable = new List<string>(stringTable);

// create queue for the first time.
if (m_incomingMessages == null)
{
Expand All @@ -1443,10 +1440,11 @@ public void SaveMessageInCache(

if (next != null && next.Value.SequenceNumber > entry.SequenceNumber + 1)
{
IncomingMessage placeholder = new IncomingMessage();
placeholder.SequenceNumber = entry.SequenceNumber + 1;
placeholder.Timestamp = now;
placeholder.TickCount = tickCount;
var placeholder = new IncomingMessage {
SequenceNumber = entry.SequenceNumber + 1,
Timestamp = now,
TickCount = tickCount
};
node = m_incomingMessages.AddAfter(node, placeholder);
continue;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<AssemblyName>Opc.Ua.Security.Certificates</AssemblyName>
<TargetFrameworks>$(LibCoreTargetFrameworks)</TargetFrameworks>
Expand Down Expand Up @@ -41,7 +40,11 @@
<DefineConstants>$(DefineConstants);SIGNASSEMBLY</DefineConstants>
</PropertyGroup>

<ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' != 'net6.0'">
<PackageReference Include="System.Formats.Asn1" Version="9.0.0" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net6.0'">
<PackageReference Include="System.Formats.Asn1" Version="8.0.1" />
</ItemGroup>

Expand All @@ -53,6 +56,10 @@
<PackageReference Include="BouncyCastle.Cryptography" Version="2.5.0" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' != 'net9.0' AND '$(TargetFramework)' != 'net6.0'">
<PackageReference Include="Microsoft.Bcl.Cryptography" Version="9.0.0" />
</ItemGroup>

<Target Name="GetPackagingOutputs" />

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
* http://opcfoundation.org/License/MIT/1.00/
* ======================================================================*/

#if !NET9_0_OR_GREATER
#if NET6_0

using System;
using System.Security.Cryptography.X509Certificates;
Expand Down
13 changes: 9 additions & 4 deletions Stack/Opc.Ua.Core/Opc.Ua.Core.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<DefineConstants>$(DefineConstants);NET_STANDARD;NET_STANDARD_ASYNC</DefineConstants>
Expand Down Expand Up @@ -45,7 +45,7 @@
use latest versions only on .NET 5/6/7/8, otherwise 3.1.x -->
<When Condition="'$(TargetFramework)' == 'netstandard2.0' OR '$(TargetFramework)' == 'netstandard2.1'">
<ItemGroup>
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="6.0.1" />
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="6.0.2" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.1.32" />
</ItemGroup>
</When>
Expand All @@ -54,15 +54,20 @@
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.4" />
</ItemGroup>
</When>
<When Condition="'$(TargetFramework)' == 'net8.0'">
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.2" />
</ItemGroup>
</When>
<When Condition="'$(TargetFramework)' == 'net462' OR '$(TargetFramework)' == 'net472' OR '$(TargetFramework)' == 'net48'">
<ItemGroup>
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="6.0.1" />
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="6.0.2" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.4" />
</ItemGroup>
</When>
<Otherwise>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.1" />
</ItemGroup>
</Otherwise>
</Choose>
Expand Down
17 changes: 13 additions & 4 deletions Stack/Opc.Ua.Core/Stack/Types/NotificationMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,29 @@
namespace Opc.Ua
{
/// <summary>
/// A message return in a Publish response.
/// A message returned in a Publish response.
/// </summary>
public partial class NotificationMessage
{
#region Public Interface
/// <summary>
/// The string table that was received with the message.
/// </summary>
public List<string> StringTable
public StringCollection StringTable
{
get { return m_stringTable; }
set { m_stringTable = value; }
}

/// <summary>
/// Gets a value indicating whether there are more NotificationMessages for this publish interval.
/// </summary>
public bool MoreNotifications
{
get { return m_moreNotifications; }

Check warning on line 40 in Stack/Opc.Ua.Core/Stack/Types/NotificationMessage.cs

View check run for this annotation

Codecov / codecov/patch

Stack/Opc.Ua.Core/Stack/Types/NotificationMessage.cs#L40

Added line #L40 was not covered by tests
set { m_moreNotifications = value; }
}

/// <summary>
/// Gets a value indicating whether this NotificationMessage is empty.
/// </summary>
Expand Down Expand Up @@ -120,7 +129,6 @@
continue;
}


if (!(extension.Body is EventNotificationList notification))
{
continue;
Expand Down Expand Up @@ -159,7 +167,8 @@
#endregion

#region Private Fields
private List<string> m_stringTable;
private bool m_moreNotifications;
private StringCollection m_stringTable;
#endregion
}
}
81 changes: 42 additions & 39 deletions Stack/Opc.Ua.Core/Types/BuiltIn/NodeId.cs
Original file line number Diff line number Diff line change
Expand Up @@ -312,15 +312,15 @@

if (index < 0)
{
throw new ServiceResultException(StatusCodes.BadNodeIdInvalid, $"Invalid NodeId ({originalText}).");
throw ServiceResultException.Create(StatusCodes.BadNodeIdInvalid, "Invalid NodeId ({0}).", originalText);

Check warning on line 315 in Stack/Opc.Ua.Core/Types/BuiltIn/NodeId.cs

View check run for this annotation

Codecov / codecov/patch

Stack/Opc.Ua.Core/Types/BuiltIn/NodeId.cs#L315

Added line #L315 was not covered by tests
}

var namespaceUri = Utils.UnescapeUri(text.Substring(4, index - 4));
namespaceIndex = (options?.UpdateTables == true) ? context.NamespaceUris.GetIndexOrAppend(namespaceUri) : context.NamespaceUris.GetIndex(namespaceUri);

if (namespaceIndex < 0)
{
throw new ServiceResultException(StatusCodes.BadNodeIdInvalid, $"No mapping to NamespaceIndex for NamespaceUri ({namespaceUri}).");
throw ServiceResultException.Create(StatusCodes.BadNodeIdInvalid, "No mapping to NamespaceIndex for NamespaceUri ({0}).", namespaceUri);

Check warning on line 323 in Stack/Opc.Ua.Core/Types/BuiltIn/NodeId.cs

View check run for this annotation

Codecov / codecov/patch

Stack/Opc.Ua.Core/Types/BuiltIn/NodeId.cs#L323

Added line #L323 was not covered by tests
}

text = text.Substring(index + 1);
Expand All @@ -332,7 +332,7 @@

if (index < 0)
{
throw new ServiceResultException(StatusCodes.BadNodeIdInvalid, $"Invalid ExpandedNodeId ({originalText}).");
throw ServiceResultException.Create(StatusCodes.BadNodeIdInvalid, "Invalid ExpandedNodeId ({0}).", originalText);

Check warning on line 335 in Stack/Opc.Ua.Core/Types/BuiltIn/NodeId.cs

View check run for this annotation

Codecov / codecov/patch

Stack/Opc.Ua.Core/Types/BuiltIn/NodeId.cs#L335

Added line #L335 was not covered by tests
}

if (UInt16.TryParse(text.Substring(3, index - 3), out ushort ns))
Expand All @@ -348,58 +348,61 @@
text = text.Substring(index + 1);
}

var idType = text.Substring(0, 1);
text = text.Substring(2);

switch (idType)
if (text.Length >= 2)
{
case "i":
{
if (UInt32.TryParse(text, out uint number))
{
return new NodeId(number, (ushort)namespaceIndex);
}
char idType = text[0];
text = text.Substring(2);

break;
}

case "s":
switch (idType)
{
if (!String.IsNullOrWhiteSpace(text))
case 'i':
{
return new NodeId(text, (ushort)namespaceIndex);
}
if (UInt32.TryParse(text, out uint number))
{
return new NodeId(number, (ushort)namespaceIndex);
}

break;
}
break;
}

case "b":
{
try
case 's':
{
var bytes = Convert.FromBase64String(text);
return new NodeId(bytes, (ushort)namespaceIndex);
if (!String.IsNullOrWhiteSpace(text))
{
return new NodeId(text, (ushort)namespaceIndex);
}

break;
}
catch (Exception)

case 'b':
{
// error handled after the switch statement.
}
try
{
var bytes = Convert.FromBase64String(text);
return new NodeId(bytes, (ushort)namespaceIndex);
}
catch (Exception)

Check warning on line 385 in Stack/Opc.Ua.Core/Types/BuiltIn/NodeId.cs

View check run for this annotation

Codecov / codecov/patch

Stack/Opc.Ua.Core/Types/BuiltIn/NodeId.cs#L385

Added line #L385 was not covered by tests
{
// error handled after the switch statement.
}

Check warning on line 388 in Stack/Opc.Ua.Core/Types/BuiltIn/NodeId.cs

View check run for this annotation

Codecov / codecov/patch

Stack/Opc.Ua.Core/Types/BuiltIn/NodeId.cs#L388

Added line #L388 was not covered by tests

break;
}
break;
}

case "g":
{
if (Guid.TryParse(text, out var guid))
case 'g':
{
return new NodeId(guid, (ushort)namespaceIndex);
}
if (Guid.TryParse(text, out var guid))
{
return new NodeId(guid, (ushort)namespaceIndex);
}

break;
break;
}
}
}

throw new ServiceResultException(StatusCodes.BadNodeIdInvalid, $"Invalid NodeId Identifier ({originalText}).");
throw ServiceResultException.Create(StatusCodes.BadNodeIdInvalid, "Invalid NodeId Identifier ({0}).", originalText);

Check warning on line 405 in Stack/Opc.Ua.Core/Types/BuiltIn/NodeId.cs

View check run for this annotation

Codecov / codecov/patch

Stack/Opc.Ua.Core/Types/BuiltIn/NodeId.cs#L405

Added line #L405 was not covered by tests
}

/// <summary>
Expand Down
6 changes: 6 additions & 0 deletions Stack/Opc.Ua.Core/Types/BuiltIn/NotificationData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,11 @@ public partial class NotificationData
/// A value of MinTime indicates that the time is not known.
/// </remarks>
public DateTime PublishTime { get; set; }

/// <summary>
/// Helper variable for a client to pass the information that more
/// notifications are expected for this publish interval.
/// </summary>
public bool MoreNotifications { get; set; }
}
}
Loading
Loading