From 621a1ad0e953d779bfd449e7409be3a01f9a5f7a Mon Sep 17 00:00:00 2001 From: Roman Ettlinger Date: Tue, 15 Apr 2025 16:30:18 +0200 Subject: [PATCH 1/9] Extend Session.Open Method with new overload allowing to specify if the used channel is closed when the Session.Open fails Add Missing Event Handler m_RenewUserIdentity om Session constructor taking a template --- Libraries/Opc.Ua.Client/Session/ISession.cs | 11 +++++++++++ Libraries/Opc.Ua.Client/Session/Session.cs | 21 +++++++++++++++++---- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/Libraries/Opc.Ua.Client/Session/ISession.cs b/Libraries/Opc.Ua.Client/Session/ISession.cs index 4b614452a7..f6eb521659 100644 --- a/Libraries/Opc.Ua.Client/Session/ISession.cs +++ b/Libraries/Opc.Ua.Client/Session/ISession.cs @@ -607,6 +607,17 @@ Task> LoadDataTypeSystem( /// If set to true then the domain in the certificate must match the endpoint used. void Open(string sessionName, uint sessionTimeout, IUserIdentity identity, IList preferredLocales, bool checkDomain); + /// + /// Establishes a session with the server. + /// + /// The name to assign to the session. + /// The session timeout. + /// The user identity. + /// The list of preferred locales. + /// If set to true then the domain in the certificate must match the endpoint used. + /// If set to true then the channel is closed when the Open fails. + void Open(string sessionName, uint sessionTimeout, IUserIdentity identity, IList preferredLocales, bool checkDomain, bool closeChannel); + /// /// Updates the preferred locales used for the session. /// diff --git a/Libraries/Opc.Ua.Client/Session/Session.cs b/Libraries/Opc.Ua.Client/Session/Session.cs index 633f4bc773..2a5ffcf067 100644 --- a/Libraries/Opc.Ua.Client/Session/Session.cs +++ b/Libraries/Opc.Ua.Client/Session/Session.cs @@ -153,6 +153,7 @@ public Session(ITransportChannel channel, Session template, bool copyEventHandle m_SubscriptionsChanged = template.m_SubscriptionsChanged; m_SessionClosing = template.m_SessionClosing; m_SessionConfigurationChanged = template.m_SessionConfigurationChanged; + m_RenewUserIdentity = template.m_RenewUserIdentity; } foreach (Subscription subscription in template.Subscriptions) @@ -1355,7 +1356,8 @@ public static Session Recreate(Session template, ITransportChannel transportChan (uint)template.m_sessionTimeout, template.m_identity, template.m_preferredLocales, - template.m_checkDomain); + template.m_checkDomain, + false); // create the subscriptions. foreach (Subscription subscription in session.Subscriptions) @@ -2286,7 +2288,17 @@ public void Open( IUserIdentity identity, IList preferredLocales) { - Open(sessionName, sessionTimeout, identity, preferredLocales, true); + Open(sessionName, sessionTimeout, identity, preferredLocales, true, true); + } + /// + public void Open( + string sessionName, + uint sessionTimeout, + IUserIdentity identity, + IList preferredLocales, + bool checkDomain) + { + Open(sessionName, sessionTimeout, identity, preferredLocales, true, true); } /// @@ -2296,7 +2308,8 @@ public void Open( uint sessionTimeout, IUserIdentity identity, IList preferredLocales, - bool checkDomain) + bool checkDomain, + bool closeChannel) { OpenValidateIdentity(ref identity, out var identityToken, out var identityPolicy, out string securityPolicyUri, out bool requireEncryption); @@ -2555,7 +2568,7 @@ public void Open( { try { - Close(true); + Close(closeChannel); } catch (Exception e) { From 72abba74282195caafcd856cb8ed01f33f09dfb4 Mon Sep 17 00:00:00 2001 From: Roman Ettlinger Date: Wed, 16 Apr 2025 07:56:29 +0200 Subject: [PATCH 2/9] Implement Traceable Session Create Async open overload --- Libraries/Opc.Ua.Client/Session/ISession.cs | 12 ++++++++++++ .../Opc.Ua.Client/Session/SessionAsync.cs | 18 +++++++++++++++++- .../Opc.Ua.Client/Session/TraceableSession.cs | 18 ++++++++++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/Libraries/Opc.Ua.Client/Session/ISession.cs b/Libraries/Opc.Ua.Client/Session/ISession.cs index f6eb521659..c784468488 100644 --- a/Libraries/Opc.Ua.Client/Session/ISession.cs +++ b/Libraries/Opc.Ua.Client/Session/ISession.cs @@ -680,6 +680,18 @@ Task> LoadDataTypeSystem( /// The cancellation token. Task OpenAsync(string sessionName, uint sessionTimeout, IUserIdentity identity, IList preferredLocales, bool checkDomain, CancellationToken ct); + /// + /// Establishes a session with the server. + /// + /// The name to assign to the session. + /// The session timeout. + /// The user identity. + /// The list of preferred locales. + /// If set to true then the domain in the certificate must match the endpoint used. + /// If set to true then the channel is closed when the Open fails. + /// The cancellation token. + Task OpenAsync(string sessionName, uint sessionTimeout, IUserIdentity identity, IList preferredLocales, bool checkDomain, bool closeChannel, CancellationToken ct); + /// /// Reads the values for the node attributes and returns a node object collection. /// diff --git a/Libraries/Opc.Ua.Client/Session/SessionAsync.cs b/Libraries/Opc.Ua.Client/Session/SessionAsync.cs index 4387d90e12..8b6ddafa57 100644 --- a/Libraries/Opc.Ua.Client/Session/SessionAsync.cs +++ b/Libraries/Opc.Ua.Client/Session/SessionAsync.cs @@ -67,6 +67,18 @@ public Task OpenAsync( return OpenAsync(sessionName, sessionTimeout, identity, preferredLocales, true, ct); } + /// + public Task OpenAsync( + string sessionName, + uint sessionTimeout, + IUserIdentity identity, + IList preferredLocales, + bool checkDomain, + CancellationToken ct) + { + return OpenAsync(sessionName, sessionTimeout, identity, preferredLocales, checkDomain, true, ct); + } + /// public async Task OpenAsync( string sessionName, @@ -74,6 +86,7 @@ public async Task OpenAsync( IUserIdentity identity, IList preferredLocales, bool checkDomain, + bool closeChannel, CancellationToken ct) { OpenValidateIdentity(ref identity, out var identityToken, out var identityPolicy, out string securityPolicyUri, out bool requireEncryption); @@ -322,7 +335,10 @@ public async Task OpenAsync( try { await base.CloseSessionAsync(null, false, CancellationToken.None).ConfigureAwait(false); - await CloseChannelAsync(CancellationToken.None).ConfigureAwait(false); + if (closeChannel) + { + await CloseChannelAsync(CancellationToken.None).ConfigureAwait(false); + } } catch (Exception e) { diff --git a/Libraries/Opc.Ua.Client/Session/TraceableSession.cs b/Libraries/Opc.Ua.Client/Session/TraceableSession.cs index f2c2620d8a..fb820c1a36 100644 --- a/Libraries/Opc.Ua.Client/Session/TraceableSession.cs +++ b/Libraries/Opc.Ua.Client/Session/TraceableSession.cs @@ -626,6 +626,15 @@ public void Open(string sessionName, uint sessionTimeout, IUserIdentity identity } } + /// + public void Open(string sessionName, uint sessionTimeout, IUserIdentity identity, IList preferredLocales, bool checkDomain, bool closeChannel) + { + using (Activity activity = ActivitySource.StartActivity()) + { + m_session.Open(sessionName, sessionTimeout, identity, preferredLocales, checkDomain, closeChannel); + } + } + /// public void ChangePreferredLocales(StringCollection preferredLocales) { @@ -707,6 +716,15 @@ public async Task OpenAsync(string sessionName, uint sessionTimeout, IUserIdenti } } + /// + public async Task OpenAsync(string sessionName, uint sessionTimeout, IUserIdentity identity, IList preferredLocales, bool checkDomain, bool closeChannel, CancellationToken ct) + { + using (Activity activity = ActivitySource.StartActivity()) + { + await m_session.OpenAsync(sessionName, sessionTimeout, identity, preferredLocales, checkDomain, closeChannel, ct).ConfigureAwait(false); + } + } + /// public async Task FetchNamespaceTablesAsync(CancellationToken ct = default) From 8e4d07420d8317293d8c489c3fbe977866846072 Mon Sep 17 00:00:00 2001 From: Roman Ettlinger Date: Wed, 16 Apr 2025 08:02:39 +0200 Subject: [PATCH 3/9] keep channel open on ReCreateAsync with provided channel --- Libraries/Opc.Ua.Client/Session/SessionAsync.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Libraries/Opc.Ua.Client/Session/SessionAsync.cs b/Libraries/Opc.Ua.Client/Session/SessionAsync.cs index 8b6ddafa57..b1f62c75fb 100644 --- a/Libraries/Opc.Ua.Client/Session/SessionAsync.cs +++ b/Libraries/Opc.Ua.Client/Session/SessionAsync.cs @@ -1627,6 +1627,7 @@ await session.OpenAsync( sessionTemplate.m_identity, sessionTemplate.m_preferredLocales, sessionTemplate.m_checkDomain, + false, ct).ConfigureAwait(false); // create the subscriptions. From 8a5be1050d90ff756bdd4f8b6d96a5b8dd9c828f Mon Sep 17 00:00:00 2001 From: Roman Ettlinger Date: Fri, 2 May 2025 13:57:27 +0200 Subject: [PATCH 4/9] Add Test executing Recreate using existing channel --- Tests/Opc.Ua.Client.Tests/ClientTest.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Tests/Opc.Ua.Client.Tests/ClientTest.cs b/Tests/Opc.Ua.Client.Tests/ClientTest.cs index 9030d89a48..e91a701404 100644 --- a/Tests/Opc.Ua.Client.Tests/ClientTest.cs +++ b/Tests/Opc.Ua.Client.Tests/ClientTest.cs @@ -49,6 +49,7 @@ using System.Security.Cryptography; using System.Runtime.InteropServices; using Opc.Ua.Security.Certificates; +using Opc.Ua.Server; namespace Opc.Ua.Client.Tests { @@ -613,7 +614,8 @@ public async Task ConnectMultipleSessionsAsync() var session2 = ClientFixture.CreateSession(channel, endpoint); session2.Open("Session2", null); - _ = session1.ReadValue(VariableIds.Server_ServerStatus, typeof(ServerStatusDataType)); + + session1.Close(closeChannel: false); session1.DetachChannel(); @@ -625,6 +627,12 @@ public async Task ConnectMultipleSessionsAsync() session2.DetachChannel(); session2.Dispose(); + + //Recreate session using same channel + var session3 = await ClientFixture.SessionFactory.RecreateAsync(session1, channel); + + _ = session3.ReadValue(VariableIds.Server_ServerStatus, typeof(ServerStatusDataType)); + channel.Dispose(); } From dc0a82d9374b70cfe4014f17c80283908e9a4fb3 Mon Sep 17 00:00:00 2001 From: Roman Ettlinger Date: Fri, 2 May 2025 13:57:41 +0200 Subject: [PATCH 5/9] fix test --- Tests/Opc.Ua.Client.Tests/ClientTest.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Tests/Opc.Ua.Client.Tests/ClientTest.cs b/Tests/Opc.Ua.Client.Tests/ClientTest.cs index e91a701404..4fd4f15c27 100644 --- a/Tests/Opc.Ua.Client.Tests/ClientTest.cs +++ b/Tests/Opc.Ua.Client.Tests/ClientTest.cs @@ -49,7 +49,6 @@ using System.Security.Cryptography; using System.Runtime.InteropServices; using Opc.Ua.Security.Certificates; -using Opc.Ua.Server; namespace Opc.Ua.Client.Tests { @@ -614,8 +613,7 @@ public async Task ConnectMultipleSessionsAsync() var session2 = ClientFixture.CreateSession(channel, endpoint); session2.Open("Session2", null); - - + _ = session1.ReadValue(VariableIds.Server_ServerStatus, typeof(ServerStatusDataType)); session1.Close(closeChannel: false); session1.DetachChannel(); From 400a14ae4860c13609101bb15070f3a900f4f423 Mon Sep 17 00:00:00 2001 From: Roman Ettlinger Date: Mon, 5 May 2025 17:04:00 +0200 Subject: [PATCH 6/9] Add RenewUserIdentity Handler in case of a RecreateSession --- Libraries/Opc.Ua.Client/Session/Session.cs | 14 ++++++++++++++ Libraries/Opc.Ua.Client/Session/SessionAsync.cs | 3 +++ 2 files changed, 17 insertions(+) diff --git a/Libraries/Opc.Ua.Client/Session/Session.cs b/Libraries/Opc.Ua.Client/Session/Session.cs index 2a5ffcf067..9e692c08fd 100644 --- a/Libraries/Opc.Ua.Client/Session/Session.cs +++ b/Libraries/Opc.Ua.Client/Session/Session.cs @@ -1269,6 +1269,7 @@ public static Session Recreate(Session template) try { + session.RecreateRenewUserIdentity(); // open the session. session.Open( template.SessionName, @@ -1315,6 +1316,7 @@ public static Session Recreate(Session template, ITransportWaitingConnection con try { + session.RecreateRenewUserIdentity(); // open the session. session.Open( template.m_sessionName, @@ -1350,6 +1352,7 @@ public static Session Recreate(Session template, ITransportChannel transportChan try { + session.RecreateRenewUserIdentity(); // open the session. session.Open( template.m_sessionName, @@ -5359,6 +5362,17 @@ public bool ResendData(IEnumerable subscriptions, out IList + /// Helper to refresh the identity (reprompt for password, refresh token) in case of a Recreate of the Session. + /// + public virtual void RecreateRenewUserIdentity() + { + if (m_RenewUserIdentity != null) + { + m_identity = m_RenewUserIdentity(this, m_identity); + } + } #endregion #region Private Methods diff --git a/Libraries/Opc.Ua.Client/Session/SessionAsync.cs b/Libraries/Opc.Ua.Client/Session/SessionAsync.cs index b1f62c75fb..e6233ff635 100644 --- a/Libraries/Opc.Ua.Client/Session/SessionAsync.cs +++ b/Libraries/Opc.Ua.Client/Session/SessionAsync.cs @@ -1530,6 +1530,7 @@ public static async Task RecreateAsync(Session sessionTemplate, Cancell try { + session.RecreateRenewUserIdentity(); // open the session. await session.OpenAsync( sessionTemplate.SessionName, @@ -1578,6 +1579,7 @@ public static async Task RecreateAsync(Session sessionTemplate, ITransp try { + session.RecreateRenewUserIdentity(); // open the session. await session.OpenAsync( sessionTemplate.m_sessionName, @@ -1620,6 +1622,7 @@ public static async Task RecreateAsync(Session sessionTemplate, ITransp try { + session.RecreateRenewUserIdentity(); // open the session. await session.OpenAsync( sessionTemplate.m_sessionName, From 3e285cf02d920958b83850d82ed06fe6c9b1f511 Mon Sep 17 00:00:00 2001 From: Roman Ettlinger Date: Mon, 5 May 2025 18:23:38 +0200 Subject: [PATCH 7/9] Add Test, fix Recreate to use new Token --- Libraries/Opc.Ua.Client/Session/Session.cs | 6 +- .../Opc.Ua.Client/Session/SessionAsync.cs | 6 +- Tests/Opc.Ua.Client.Tests/ClientTest.cs | 64 +++++++++++++++++++ 3 files changed, 70 insertions(+), 6 deletions(-) diff --git a/Libraries/Opc.Ua.Client/Session/Session.cs b/Libraries/Opc.Ua.Client/Session/Session.cs index 9e692c08fd..3677b0eeb2 100644 --- a/Libraries/Opc.Ua.Client/Session/Session.cs +++ b/Libraries/Opc.Ua.Client/Session/Session.cs @@ -1274,7 +1274,7 @@ public static Session Recreate(Session template) session.Open( template.SessionName, (uint)template.SessionTimeout, - template.Identity, + session.Identity, template.PreferredLocales, template.m_checkDomain); @@ -1321,7 +1321,7 @@ public static Session Recreate(Session template, ITransportWaitingConnection con session.Open( template.m_sessionName, (uint)template.m_sessionTimeout, - template.m_identity, + session.Identity, template.m_preferredLocales, template.m_checkDomain); @@ -1357,7 +1357,7 @@ public static Session Recreate(Session template, ITransportChannel transportChan session.Open( template.m_sessionName, (uint)template.m_sessionTimeout, - template.m_identity, + session.Identity, template.m_preferredLocales, template.m_checkDomain, false); diff --git a/Libraries/Opc.Ua.Client/Session/SessionAsync.cs b/Libraries/Opc.Ua.Client/Session/SessionAsync.cs index e6233ff635..a7e8e1bf92 100644 --- a/Libraries/Opc.Ua.Client/Session/SessionAsync.cs +++ b/Libraries/Opc.Ua.Client/Session/SessionAsync.cs @@ -1535,7 +1535,7 @@ public static async Task RecreateAsync(Session sessionTemplate, Cancell await session.OpenAsync( sessionTemplate.SessionName, (uint)sessionTemplate.SessionTimeout, - sessionTemplate.Identity, + session.Identity, sessionTemplate.PreferredLocales, sessionTemplate.m_checkDomain, ct).ConfigureAwait(false); @@ -1584,7 +1584,7 @@ public static async Task RecreateAsync(Session sessionTemplate, ITransp await session.OpenAsync( sessionTemplate.m_sessionName, (uint)sessionTemplate.m_sessionTimeout, - sessionTemplate.m_identity, + session.Identity, sessionTemplate.m_preferredLocales, sessionTemplate.m_checkDomain, ct).ConfigureAwait(false); @@ -1627,7 +1627,7 @@ public static async Task RecreateAsync(Session sessionTemplate, ITransp await session.OpenAsync( sessionTemplate.m_sessionName, (uint)sessionTemplate.m_sessionTimeout, - sessionTemplate.m_identity, + session.Identity, sessionTemplate.m_preferredLocales, sessionTemplate.m_checkDomain, false, diff --git a/Tests/Opc.Ua.Client.Tests/ClientTest.cs b/Tests/Opc.Ua.Client.Tests/ClientTest.cs index 4fd4f15c27..da7dedadcf 100644 --- a/Tests/Opc.Ua.Client.Tests/ClientTest.cs +++ b/Tests/Opc.Ua.Client.Tests/ClientTest.cs @@ -857,6 +857,70 @@ public async Task ReconnectSessionOnAlternateChannelWithSavedSessionSecrets(stri Utils.SilentDispose(session2); } + /// + /// Open a session on a channel, then recreate using the session as a template, verify the renewUserIdentityHandler is brought to the new session and called before Session.Open + /// /// + [Test, Order(270)] + public async Task RecreateSessionWithRenewUserIdentity() + { + IUserIdentity userIdentityAnonymous = new UserIdentity() ; + IUserIdentity userIdentityPW = new UserIdentity("user1", "password"); + + // the first channel determines the endpoint + ConfiguredEndpoint endpoint = await ClientFixture.GetEndpointAsync(ServerUrl, SecurityPolicies.Basic256Sha256, Endpoints).ConfigureAwait(false); + Assert.NotNull(endpoint); + + UserTokenPolicy identityPolicy = endpoint.Description.FindUserTokenPolicy(userIdentityAnonymous.TokenType, + userIdentityAnonymous.IssuedTokenType, + endpoint.Description.SecurityPolicyUri); + if (identityPolicy == null) + { + Assert.Ignore($"No UserTokenPolicy found for {userIdentityAnonymous.TokenType} / {userIdentityAnonymous.IssuedTokenType}"); + } + + // the active channel + ISession session1 = await ClientFixture.ConnectAsync(endpoint, userIdentityAnonymous).ConfigureAwait(false); + Assert.NotNull(session1); + + ServerStatusDataType value1 = (ServerStatusDataType)session1.ReadValue(VariableIds.Server_ServerStatus, typeof(ServerStatusDataType)); + Assert.NotNull(value1); + + // hook callback to renew the user identity + session1.RenewUserIdentity += (session, identity) => { + return userIdentityPW; + }; + + var session2 = Client.Session.Recreate((Session)((TraceableSession)session1).Session); + + // create new channel + ITransportChannel channel2 = await ClientFixture.CreateChannelAsync(session1.ConfiguredEndpoint, false).ConfigureAwait(false); + + Assert.NotNull(channel2); + var session3 = await Client.Session.RecreateAsync((Session)((TraceableSession)session1).Session, channel2); + + //validate new Session Ids are used and also UserName PW identity token is injected as renewed token + Assert.AreNotEqual(session1.SessionId, session2.SessionId); + Assert.AreEqual(userIdentityPW.TokenType, session2.Identity.TokenType); + Assert.AreNotEqual(session1.SessionId, session3.SessionId); + Assert.AreEqual(userIdentityPW.TokenType, session3.Identity.TokenType); + + ServerStatusDataType value2 = (ServerStatusDataType)session2.ReadValue(VariableIds.Server_ServerStatus, typeof(ServerStatusDataType)); + Assert.NotNull(value2); + + + session1.DeleteSubscriptionsOnClose = true; + session1.Close(1000); + Utils.SilentDispose(session1); + + session2.DeleteSubscriptionsOnClose = true; + session2.Close(1000); + Utils.SilentDispose(session2); + + session3.DeleteSubscriptionsOnClose = true; + session3.Close(1000); + Utils.SilentDispose(session2); + } + [Test, Order(300)] public new void GetOperationLimits() { From 119a69f7c3c99bf3267eb457975de7806112352a Mon Sep 17 00:00:00 2001 From: Roman Ettlinger Date: Tue, 6 May 2025 07:18:09 +0200 Subject: [PATCH 8/9] Improve code coverage with async test overload --- Tests/Opc.Ua.Client.Tests/ClientTest.cs | 29 ++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/Tests/Opc.Ua.Client.Tests/ClientTest.cs b/Tests/Opc.Ua.Client.Tests/ClientTest.cs index da7dedadcf..4674af9f15 100644 --- a/Tests/Opc.Ua.Client.Tests/ClientTest.cs +++ b/Tests/Opc.Ua.Client.Tests/ClientTest.cs @@ -861,7 +861,9 @@ public async Task ReconnectSessionOnAlternateChannelWithSavedSessionSecrets(stri /// Open a session on a channel, then recreate using the session as a template, verify the renewUserIdentityHandler is brought to the new session and called before Session.Open /// /// [Test, Order(270)] - public async Task RecreateSessionWithRenewUserIdentity() + [TestCase(false)] + [TestCase(true)] + public async Task RecreateSessionWithRenewUserIdentity(bool async) { IUserIdentity userIdentityAnonymous = new UserIdentity() ; IUserIdentity userIdentityPW = new UserIdentity("user1", "password"); @@ -890,13 +892,30 @@ public async Task RecreateSessionWithRenewUserIdentity() return userIdentityPW; }; - var session2 = Client.Session.Recreate((Session)((TraceableSession)session1).Session); + Client.Session session2; + if (async) + { + session2 = await Client.Session.RecreateAsync((Session)((TraceableSession)session1).Session).ConfigureAwait(false); + } + else + { + session2 = Client.Session.Recreate((Session)((TraceableSession)session1).Session); + } // create new channel ITransportChannel channel2 = await ClientFixture.CreateChannelAsync(session1.ConfiguredEndpoint, false).ConfigureAwait(false); - Assert.NotNull(channel2); - var session3 = await Client.Session.RecreateAsync((Session)((TraceableSession)session1).Session, channel2); + + Client.Session session3; + if (async) + { + session3 = await Client.Session.RecreateAsync((Session)((TraceableSession)session1).Session, channel2).ConfigureAwait(false); + + } + else + { + session3 = Client.Session.Recreate((Session)((TraceableSession)session1).Session, channel2); + } //validate new Session Ids are used and also UserName PW identity token is injected as renewed token Assert.AreNotEqual(session1.SessionId, session2.SessionId); @@ -918,7 +937,7 @@ public async Task RecreateSessionWithRenewUserIdentity() session3.DeleteSubscriptionsOnClose = true; session3.Close(1000); - Utils.SilentDispose(session2); + Utils.SilentDispose(session3); } [Test, Order(300)] From df80db20630813c5e0af975354b8a0a83210df1c Mon Sep 17 00:00:00 2001 From: Roman Ettlinger Date: Thu, 15 May 2025 19:16:01 +0200 Subject: [PATCH 9/9] fix Parameter checkDomain in Open Session overload --- Libraries/Opc.Ua.Client/Session/Session.cs | 4 ++-- Tests/Opc.Ua.Client.Tests/ClientTest.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Libraries/Opc.Ua.Client/Session/Session.cs b/Libraries/Opc.Ua.Client/Session/Session.cs index 3677b0eeb2..1fcd5ebcae 100644 --- a/Libraries/Opc.Ua.Client/Session/Session.cs +++ b/Libraries/Opc.Ua.Client/Session/Session.cs @@ -2291,7 +2291,7 @@ public void Open( IUserIdentity identity, IList preferredLocales) { - Open(sessionName, sessionTimeout, identity, preferredLocales, true, true); + Open(sessionName, sessionTimeout, identity, preferredLocales, true); } /// public void Open( @@ -2301,7 +2301,7 @@ public void Open( IList preferredLocales, bool checkDomain) { - Open(sessionName, sessionTimeout, identity, preferredLocales, true, true); + Open(sessionName, sessionTimeout, identity, preferredLocales, checkDomain, true); } /// diff --git a/Tests/Opc.Ua.Client.Tests/ClientTest.cs b/Tests/Opc.Ua.Client.Tests/ClientTest.cs index 4674af9f15..51802d5d7f 100644 --- a/Tests/Opc.Ua.Client.Tests/ClientTest.cs +++ b/Tests/Opc.Ua.Client.Tests/ClientTest.cs @@ -627,7 +627,7 @@ public async Task ConnectMultipleSessionsAsync() //Recreate session using same channel - var session3 = await ClientFixture.SessionFactory.RecreateAsync(session1, channel); + var session3 = await ClientFixture.SessionFactory.RecreateAsync(session1, channel).ConfigureAwait(false); _ = session3.ReadValue(VariableIds.Server_ServerStatus, typeof(ServerStatusDataType));