diff --git a/Libraries/Opc.Ua.Client/Session.cs b/Libraries/Opc.Ua.Client/Session.cs index 0973fd1257..750a953cc8 100644 --- a/Libraries/Opc.Ua.Client/Session.cs +++ b/Libraries/Opc.Ua.Client/Session.cs @@ -67,44 +67,31 @@ namespace Opc.Ua.Client /// /// The channel used to communicate with the server. /// The configuration for the client application. - /// The endpoint use to initialize the channel. + /// The endpoint used to initialize the channel. /// The certificate to use for the client. + /// The list of available endpoints returned by server in GetEndpoints() response. + /// The value of profileUris used in GetEndpoints() request. /// /// The application configuration is used to look up the certificate if none is provided. /// The clientCertificate must have the private key. This will require that the certificate /// be loaded from a certicate store. Converting a DER encoded blob to a X509Certificate2 /// will not include a private key. + /// The availableEndpoints and discoveryProfileUris parameters are used to validate + /// that the list of EndpointDescriptions returned at GetEndpoints matches the list returned at CreateSession. /// - public Session( - ITransportChannel channel, - ApplicationConfiguration configuration, - ConfiguredEndpoint endpoint, - X509Certificate2 clientCertificate) - : - base(channel) - { - Initialize(channel, configuration, endpoint, clientCertificate); - } - - /// - /// Constructs a new instance of the class. - /// - /// The channel used to communicate with the server. - /// The configuration for the client application. - /// The endpoint use to initialize the channel. - /// The certificate to use for the client. - /// A collection of available endpoints to connect to the server. public Session( ITransportChannel channel, ApplicationConfiguration configuration, ConfiguredEndpoint endpoint, X509Certificate2 clientCertificate, - EndpointDescriptionCollection availableEndpoints) + EndpointDescriptionCollection availableEndpoints = null, + StringCollection discoveryProfileUris = null) : base(channel) { Initialize(channel, configuration, endpoint, clientCertificate); - m_expectedServerEndpoints = availableEndpoints; + m_discoveryServerEndpoints = availableEndpoints; + m_discoveryProfileUris = discoveryProfileUris; } /// @@ -2585,20 +2572,41 @@ namespace Opc.Ua.Client // "Server signature is null or empty."); } - if (m_expectedServerEndpoints != null && m_expectedServerEndpoints.Count > 0) + if (m_discoveryServerEndpoints != null && m_discoveryServerEndpoints.Count > 0) { - // verify that the list of endpoints returned by CreateSession matches the list returned at GetEndpoints. - if (m_expectedServerEndpoints.Count != serverEndpoints.Count) + // Compare EndpointDescriptions returned at GetEndpoints with values returned at CreateSession + EndpointDescriptionCollection expectedServerEndpoints = null; + + if (m_discoveryProfileUris != null && m_discoveryProfileUris.Count > 0) + { + // Select EndpointDescriptions with a transportProfileUri that matches the + // profileUris specified in the original GetEndpoints() request. + expectedServerEndpoints = new EndpointDescriptionCollection(); + + foreach (EndpointDescription serverEndpoint in serverEndpoints) + { + if (m_discoveryProfileUris.Contains(serverEndpoint.TransportProfileUri)) + { + expectedServerEndpoints.Add(serverEndpoint); + } + } + } + else + { + expectedServerEndpoints = serverEndpoints; + } + + if (m_discoveryServerEndpoints.Count != expectedServerEndpoints.Count) { throw ServiceResultException.Create( StatusCodes.BadSecurityChecksFailed, "Server did not return a number of ServerEndpoints that matches the one from GetEndpoints."); } - for (int ii = 0; ii < serverEndpoints.Count; ii++) + for (int ii = 0; ii < expectedServerEndpoints.Count; ii++) { - EndpointDescription serverEndpoint = serverEndpoints[ii]; - EndpointDescription expectedServerEndpoint = m_expectedServerEndpoints[ii]; + EndpointDescription serverEndpoint = expectedServerEndpoints[ii]; + EndpointDescription expectedServerEndpoint = m_discoveryServerEndpoints[ii]; if (serverEndpoint.SecurityMode != expectedServerEndpoint.SecurityMode || serverEndpoint.SecurityPolicyUri != expectedServerEndpoint.SecurityPolicyUri || @@ -4679,7 +4687,8 @@ namespace Opc.Ua.Client private bool m_reconnecting; private LinkedList m_outstandingRequests; - private EndpointDescriptionCollection m_expectedServerEndpoints; + private EndpointDescriptionCollection m_discoveryServerEndpoints; + private StringCollection m_discoveryProfileUris; private class AsyncRequestState {