/// <summary> /// Opens the session with the remote endpoint. /// </summary> /// <param name="cancellationToken">A cancellation token.</param> /// <returns>A task.</returns> private async Task OpenSessionAsync(CancellationToken cancellationToken = default(CancellationToken)) { await this.semaphore.WaitAsync(cancellationToken).ConfigureAwait(false); try { if (this.RemoteEndpoint == null) { // If specific endpoint is not provided, use discovery to select endpoint with highest // security level. try { Log.Info($"Discovering endpoints of '{this.discoveryUrl}'."); var getEndpointsRequest = new GetEndpointsRequest { EndpointUrl = this.discoveryUrl, ProfileUris = new[] { TransportProfileUris.UaTcpTransport } }; var getEndpointsResponse = await UaTcpDiscoveryClient.GetEndpointsAsync(getEndpointsRequest); if (getEndpointsResponse.Endpoints == null || getEndpointsResponse.Endpoints.Length == 0) { throw new InvalidOperationException($"'{this.discoveryUrl}' returned no endpoints."); } this.RemoteEndpoint = getEndpointsResponse.Endpoints.OrderBy(e => e.SecurityLevel).Last(); } catch (Exception ex) { Log.Warn($"Error discovering endpoints of '{this.discoveryUrl}'. {ex.Message}"); throw; } } // throw here to exit state machine. cancellationToken.ThrowIfCancellationRequested(); try { Log.Info($"Opening UaTcpSessionChannel with endpoint '{this.RemoteEndpoint.EndpointUrl}'."); this.innerChannel = new UaTcpSessionChannel(this.LocalDescription, this.LocalCertificate, this.UserIdentity, this.RemoteEndpoint) { SessionTimeout = this.SessionTimeout, TimeoutHint = this.TimeoutHint, DiagnosticsHint = this.DiagnosticsHint, LocalSendBufferSize = this.LocalSendBufferSize, LocalReceiveBufferSize = this.LocalReceiveBufferSize, LocalMaxMessageSize = this.LocalMaxMessageSize, LocalMaxChunkCount = this.LocalMaxChunkCount, }; await this.innerChannel.OpenAsync(cancellationToken); } catch (Exception ex) { Log.Warn($"Error opening UaTcpSessionChannel with endpoint '{this.RemoteEndpoint.EndpointUrl}'. {ex.Message}"); throw; } } finally { this.semaphore.Release(); } }
/// <summary> /// Initializes a new instance of the <see cref="UaTcpSessionClient"/> class. /// </summary> /// <param name="localDescription">The <see cref="ApplicationDescription"/> of the local application.</param> /// <param name="localCertificate">The <see cref="X509Certificate2"/> of the local application.</param> /// <param name="userIdentity">The user identity or null if anonymous. Supports <see cref="AnonymousIdentity"/>, <see cref="UserNameIdentity"/>, <see cref="IssuedIdentity"/> and <see cref="X509Identity"/>.</param> /// <param name="remoteEndpoint">The <see cref="EndpointDescription"/> of the remote application. Obtained from a prior call to UaTcpDiscoveryClient.GetEndpoints.</param> public UaTcpSessionClient(ApplicationDescription localDescription, X509Certificate2 localCertificate, IUserIdentity userIdentity, EndpointDescription remoteEndpoint) { this.innerChannel = new UaTcpSessionChannel(localDescription, localCertificate, userIdentity, remoteEndpoint); this.semaphore = new SemaphoreSlim(1); }