With the following call stack the EndAsync method is called with timeout=Int.MaxValue and a vaild cancellation token.
In this case after a successfull operation the Delay will not finish and stay forever.
So with each KeepAliveIntervall an task leak is left over after the operation has finished.
Opc.Ua.Core.dll!Opc.Ua.Bindings.ChannelAsyncOperation<int>.EndAsync(int timeout, bool throwOnError, System.Threading.CancellationToken ct) Line 263
Opc.Ua.Core.dll!Opc.Ua.Bindings.UaSCUaBinaryClientChannel.SendRequestAsync(Opc.Ua.IServiceRequest request, int timeout, System.Threading.CancellationToken ct) Line 338
Opc.Ua.Core.dll!Opc.Ua.Bindings.UaSCUaBinaryTransportChannel.SendRequestAsync(Opc.Ua.IServiceRequest request, System.Threading.CancellationToken ct) Line 259
Opc.Ua.Core.dll!Opc.Ua.SessionClient.ReadAsync(Opc.Ua.RequestHeader requestHeader, double maxAge, Opc.Ua.TimestampsToReturn timestampsToReturn, Opc.Ua.ReadValueIdCollection nodesToRead, System.Threading.CancellationToken ct) Line 6590
Opc.Ua.Client.dll!Opc.Ua.SessionClientBatched.ReadAsync(Opc.Ua.RequestHeader requestHeader, double maxAge, Opc.Ua.TimestampsToReturn timestampsToReturn, Opc.Ua.ReadValueIdCollection nodesToRead, System.Threading.CancellationToken ct) Line 376
Opc.Ua.Client.dll!Opc.Ua.Client.Session.OnSendKeepAliveAsync(Opc.Ua.ReadValueIdCollection nodesToRead, System.Threading.CancellationToken ct) Line 3076
* Fix memory leak from undisposed sockets and retained event handlers during server restart
When an OPC UA server is stopped and restarted in-process, TcpServerChannel
instances were never garbage collected because UaSCBinaryChannel.Dispose() did
not close the underlying socket. Pending ReceiveAsync operations kept the
channels pinned via SocketAsyncEngine, causing a steady heap growth per cycle.
Changes:
- Close socket in UaSCBinaryChannel.Dispose() to cancel pending async I/O
- Unsubscribe CertificateValidator.CertificateUpdate in StandardServer.Dispose()
- Unsubscribe ConfigurationWatcher.Changed in StandardServer.Dispose()
- Unsubscribe ConnectionStatusChanged from TransportListeners in ServerBase.Dispose()
Verified over 786 restart cycles with stable heap.
* Remove verbose comment
* Remove redundant event unsubscribe before dispose
* Remove duplicate CertificateUpdate unsubscribe (already existed in master)
(cherry picked from commit eae41a55ac)
* test(numeric-range): add failing test
* fix(numeric-range): include sub ranges in equality check
* test(numeric-range): add tests for coverage
(cherry picked from commit 56486efcdb)
* test(type-info): add failing test
* fix(type-info): require IEnumerable implementation before treating generic type as array
* test(type-info): add test for coverage
(cherry picked from commit 25a4882145)
ServerBase.StopAsync() calls Close() on each transport listener then
Clear() on the list. ServerBase.Dispose() later iterates
TransportListeners to call Dispose() on each — but the list is already
empty, so TcpTransportListener.Dispose() never runs.
Add Utils.SilentDispose() after Close() in StopAsync to ensure
TcpTransportListener.Dispose() executes before the list is cleared.
This pull request modernizes the OPC UA .NET codebase and tests, removes .NET Standard 2.0 support from certificate/security code, and updates test code to use C# 12 and .NET 8+ features for clarity and maintainability.
- Certificate and BouncyCastle interop files (e.g., CertificateBuilder.cs, X509Extensions.cs, X509SignatureFactory.cs) are refactored to drop NETSTANDARD2_0 support and use modern .NET APIs and conditional compilation.
- Test code across the codebase is updated to use default, strongly-typed Parse methods, collection expressions, and improved async/await patterns.
- Exception handling and assertions in tests are modernized, and test method naming is made consistent with Async suffixes.
- The project and build files are updated to clarify Roslynator analyzer usage and remove obsolete netstandard tags.
- General code and test cleanup includes improved null safety, type safety, and removal of deprecated or unused code.
* Improve logging and fix UserNameIdentityToken to return BadIdentityTokenInvalid for failed verification
Refactor DataChangeQueueHandler to return overflow status from QueueValue and Enqueue, updating MonitoredItem to log overflows accurately. Update IDataChangeQueueHandler interface accordingly. Enhance ConsoleTelemetry logger configuration management and ensure proper disposal of old logger factories.
Change UserNameIdentityToken password/nonce failure to return BadIdentityTokenInvalid for more precise error reporting. To prevent the leakage of information useful to attackers, Servers shall ensure that the process of validating UserIdentityTokens completes in a fixed interval independent of whether an error occurs or not. The process of validation includes decrypting, check for padding and checking for a valid nonce. If any errors occur the return code is Bad_IdentityTokenInvalid.
* fix GDS ApplicationNames to include the Locale
* fix ctt testcase by allowing faster sampling for XmlNodeNode
* remove all usages of SoftwareCertificates
- Client
- Server
As per spec they are not relevant for security.
If an SDK User wants to use the SoftwareCertificates ActivateSession can be overriden
* remove from SessionClientBatchTests
* Refactor ApplicationConfiguration serialization for deprecated settings and add tests for configuration behavior
* Update ApplicationConfiguration to prefer modern elements in "hybrid" configurations and add corresponding tests
* Fix GDS Tests on netstandard2.1 custom test target
* Add Test reading file containing ApplicationCertificate and ApplicationCertificates ensuring it is not marked legacy.
* Add legacy config test with only one ApplicationCertificate
---------
Co-authored-by: Roman Ettlinger <romanett98@gmail.com>
* Initial plan
* Fix BadUserAccessDenied when SecurityPolicy/SecurityMode not matching
Modified MatchEndpoints method to throw appropriate exceptions:
- BadSecurityPolicyRejected when requested policy is not supported
- BadSecurityModeRejected when requested mode is not supported
- Maintains backward compatibility when no specific security settings requested
Added comprehensive tests to verify the fix.
Co-authored-by: romanett <7413710+romanett@users.noreply.github.com>
* Improve code readability with extracted boolean variables
Applied code review feedback to extract parameter validation checks
into separate boolean variables for better readability.
Co-authored-by: romanett <7413710+romanett@users.noreply.github.com>
* Add integration test for unsupported security policy
Added ConnectWithUnsupportedSecurityPolicyAsync test that:
- Uses ClientFixture to connect to test server
- Requests a security policy not supported by server
- Verifies BadSecurityPolicyRejected is thrown instead of BadUserAccessDenied
- Tests run successfully on net8.0 and net9.0 targets
Co-authored-by: romanett <7413710+romanett@users.noreply.github.com>
* Add policy that will never work
* ignore faulty test
* update
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: romanett <7413710+romanett@users.noreply.github.com>
Co-authored-by: Roman Ettlinger <romanett98@gmail.com>
* Initial plan
* Fix parent-child references when importing NodeSet2.xml
- Added LinkParentChildRelationships method to establish parent-child links after import
- Sets Parent property and adds child to parent's children collection
- Added test to verify parent-child references work correctly after import
- All existing tests continue to pass
Co-authored-by: romanett <7413710+romanett@users.noreply.github.com>
* Make parent-child linking optional with default false
- Added linkParentChild parameter to Import method (defaults to false)
- Maintains backward compatibility by not establishing parent-child relationships by default
- Added test to verify backward compatibility (default behavior)
- Updated ParentChildReferencesTest to explicitly enable the feature
- All 7 tests pass
Co-authored-by: marcschier <11168470+marcschier@users.noreply.github.com>
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: romanett <7413710+romanett@users.noreply.github.com>
Co-authored-by: marcschier <11168470+marcschier@users.noreply.github.com>
* Initial plan
* Add support for private encodeable factory in server initialization
- Add new ServiceMessageContext constructor that accepts a custom IEncodeableFactory
- Add CreateMessageContext(IEncodeableFactory) overload to ApplicationConfiguration
- Mark CreateMessageContext(bool) as obsolete since the clonedFactory parameter was never used
- Add PrivateEncodeableFactory property to ServerBase for specifying a private factory
- Update all internal calls to use the new parameterless CreateMessageContext()
Co-authored-by: romanett <7413710+romanett@users.noreply.github.com>
* Add unit tests for ServiceMessageContext private factory support
Co-authored-by: romanett <7413710+romanett@users.noreply.github.com>
* Improve documentation for ServiceMessageContext constructors
Co-authored-by: romanett <7413710+romanett@users.noreply.github.com>
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: romanett <7413710+romanett@users.noreply.github.com>
* Initial plan
* Fix ByteString vs Byte array distinction in WrappedValue
Modified BaseVariableState.WrappedValue to use DataType and ValueRank
when creating Variant to correctly distinguish between byte[] (Byte array)
and ByteString. Added tests to verify the fix.
Co-authored-by: romanett <7413710+romanett@users.noreply.github.com>
* Address code review feedback
- Remove redundant null check for NodeId (NodeId.IsNull handles null)
- Update comment in test to be more specific about ByteString testing
Co-authored-by: romanett <7413710+romanett@users.noreply.github.com>
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: romanett <7413710+romanett@users.noreply.github.com>
* Initial plan
* Add enhanced error messages for XML decoding failures
- Updated CreateBadDecodingError to optionally include failed value
- Modified SafeXmlConvert to pass XML value to error handler
- Updated ReadFloat, ReadDouble, ReadDateTime, ReadGuid, ReadNodeId, ReadExpandedNodeId, and ReadEnumerated to include values in error messages
- Added comprehensive tests to validate enhanced error messages
Co-authored-by: romanett <7413710+romanett@users.noreply.github.com>
* Fix parameter order consistency in SafeXmlConvert
Use named parameter for value argument to maintain consistency with other calls
Co-authored-by: romanett <7413710+romanett@users.noreply.github.com>
* Use named parameters consistently in SafeXmlConvert
Use named parameters for both functionName and value for better code clarity
Co-authored-by: romanett <7413710+romanett@users.noreply.github.com>
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: romanett <7413710+romanett@users.noreply.github.com>
Modified TypeInfo.GetDataTypeId(Type) to check if IEncodeable types have a specific TypeId and return it instead of the generic Structure (i=22) DataTypeId. Added comprehensive tests for EUInformation and other well-known IEncodeable types.
Co-authored-by: marcschier <11168470+marcschier@users.noreply.github.com>
* Simplify GetDataTypeId fix based on code review feedback
Removed unnecessary static property check and simplified the instance creation logic. Caught specific exceptions (MissingMethodException, TargetInvocationException) instead of using bare catch.
Co-authored-by: marcschier <11168470+marcschier@users.noreply.github.com>
* Add additional exception handling for GetDataTypeId
Added handling for MethodAccessException and NotSupportedException to provide more comprehensive error handling when creating instances via Activator.CreateInstance.
Co-authored-by: marcschier <11168470+marcschier@users.noreply.github.com>
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: marcschier <11168470+marcschier@users.noreply.github.com>
* Normalize distinguished name field abbreviations for platform compatibility of attribute State/ProvinceName
* Fix warning ca1845
* netstandard2.1 doesn’t support string.Concat with spans.
This change adds a **new Opc.Ua.Types** nuget that contains core types that do not rely on generated code. Why the name? Because almost all code that was in the Types subfolder is part of it, and because we do not want to change the name of the Opc.Ua.Core nuget/assembly because code relies on it. Any other name like base or bootstrap felt out of place due to the current structure already defining the name "types". Key design is to depend on only a small set of libraries with limited transitive dependencies, that includes hashcode, logging.abstraction, and for non standard20 builds System.Text.Json (needed for localizedText mul parsing). Also, key is to support .netstd 2.0 to support source generators and to allow removal of EEC_SUPPORT defines by removing std2.0 from core and all libraries.
The changes are mostly restructuring, and thus small but contain some key changes:
- **Status code** struct now comes with a Symbol field, which is used to carry symbols in case the code is not generated. Currently (until generated) the status code struct must be manually created with a symbol or the ToSymbolicId extension must be called in the core project. Future will generate Status code constants just like NodeId that contain the symbol which also removes the reflection-based lookup. Several tests needed to be adjusted as they checked the status code symbol strings instead of the code.
- **Core identifiers** are copied as they were needed for code to compile, that includes attributes, a subset of status codes and node identifiers. These will never change so no need to generate them.
- The types folder now contains **encoders**, except for json which is still in core. Once the json encoder is ported to system.text.json it will also be included and Newtonsoft.Json dropped as dependency (-> #3329).
- Since types relies on **IOperationContext** and **ISystemContext**, and these export IUserIdentity which relies on crypto, these were split and extended in core with ISessionOperationContext and ISessionSystemContext, which mean changes to ServerSystemContext and introduction of SessionOperationContext and SessionSystemContext classes that extend OperationContext and SystemContext. Some runtime checks in the server are therefore needed to get at the session and auth info, however, those are anyway optional fields and are not on the critical paths, and thus a type check is in order (and was done in the past already, but against OperationContext class).
- **Manifest resources** are now split between Core (nodeset zip, some generated resoures) and Types (built in bsd/xsds). This needs to be revisited later if the bsd/xsd need to be regenerated during type generation. Note that the embedded resource names changed as a result. Since these are only used internally and do not constitute public API this feels reasonable vs duplication of resources in 2 assemblies.
- Reflection however now needs to load not just the built in **encodeables** from Opc.Ua.Types assembly, but also the generated encodeables from Opc.Ua.Core assembly. For this a new helper Utils method was added to get the Core assembly when linked against Opc.Ua.Core otherwise null.
- Whatever utils methods needed to be split out into the new Opc.Ua.Types assembly, they are now in **CoreUtils** static class in Opc.Ua.Types, and Utils.xxxx forwards to them to ensure minimal changes. Later we would want to obsolete them in favor of CoreUtils, although it might make sense to split them again into domain specific utilities, such as networking, files, etc