/// <summary> /// This Service returns the Servers known to a Server or Discovery Server. /// </summary> /// <param name="request">a request.</param> /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns> public static async Task<FindServersResponse> FindServersAsync(FindServersRequest request) { if (request == null) { throw new ArgumentNullException("request"); } var client = new UaTcpDiscoveryClient( new EndpointDescription { EndpointUrl = request.EndpointUrl, SecurityMode = MessageSecurityMode.None, SecurityPolicyUri = SecurityPolicyUris.None }); try { await client.OpenAsync().ConfigureAwait(false); var response = await client.innerChannel.RequestAsync(request).ConfigureAwait(false); await client.CloseAsync().ConfigureAwait(false); return (FindServersResponse)response; } catch (Exception) { await client.AbortAsync().ConfigureAwait(false); throw; } }
/// <summary> /// This Service returns the Endpoints supported by a Server and all of the configuration information required to establish a SecureChannel and a Session. /// </summary> /// <param name="request">a request.</param> /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns> public static async Task <GetEndpointsResponse> GetEndpointsAsync(GetEndpointsRequest request) { if (request == null) { throw new ArgumentNullException("request"); } var client = new UaTcpDiscoveryClient( new EndpointDescription { EndpointUrl = request.EndpointUrl, SecurityMode = MessageSecurityMode.None, SecurityPolicyUri = SecurityPolicyUris.None }); try { await client.OpenAsync().ConfigureAwait(false); var response = await client.innerChannel.RequestAsync(request).ConfigureAwait(false); await client.CloseAsync().ConfigureAwait(false); return((GetEndpointsResponse)response); } catch (Exception) { await client.AbortAsync().ConfigureAwait(false); throw; } }
/// <summary> /// Opens a session with the remote endpoint. /// </summary> /// <param name="token">A cancellation token.</param> /// <returns>A task.</returns> private async Task OpenAsync(CancellationToken token = default(CancellationToken)) { await this.semaphore.WaitAsync(token).ConfigureAwait(false); try { if (this.RemoteEndpoint == null) { // If specific endpoint is not provided, use discovery to select endpoint with highest // security level. try { this.Logger?.LogInformation($"Discovering endpoints of '{this.discoveryUrl}'."); var getEndpointsRequest = new GetEndpointsRequest { EndpointUrl = this.discoveryUrl, ProfileUris = new[] { TransportProfileUris.UaTcpTransport } }; var getEndpointsResponse = await UaTcpDiscoveryClient.GetEndpointsAsync(getEndpointsRequest).ConfigureAwait(false); 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(); this.Logger?.LogTrace($"Success discovering endpoints of '{this.discoveryUrl}'."); } catch (Exception ex) { this.Logger?.LogError($"Error discovering endpoints of '{this.discoveryUrl}'. {ex.Message}"); throw; } } // throw here to exit state machine. token.ThrowIfCancellationRequested(); // evaluate the user identity provider (may show a dialog). var userIdentity = await this.UserIdentityProvider(this.RemoteEndpoint); try { this.linkToken?.Dispose(); if (this.innerChannel != null && this.innerChannel.State != CommunicationState.Closed) { await this.innerChannel.AbortAsync(); } this.innerChannel = new UaTcpSessionChannel( this.LocalDescription, this.CertificateStore, userIdentity, this.RemoteEndpoint, this.loggerFactory, this.SessionTimeout, this.TimeoutHint, this.DiagnosticsHint, this.LocalReceiveBufferSize, this.LocalSendBufferSize, this.LocalMaxMessageSize, this.LocalMaxChunkCount); await this.innerChannel.OpenAsync(token).ConfigureAwait(false); this.linkToken = this.pendingRequests.LinkTo(this.innerChannel); //// create an internal subscription. //var subscriptionRequest = new CreateSubscriptionRequest //{ // RequestedPublishingInterval = DefaultPublishingInterval, // RequestedMaxKeepAliveCount = DefaultKeepaliveCount, // RequestedLifetimeCount = (uint)(this.SessionTimeout / DefaultPublishingInterval), // PublishingEnabled = true, // Priority = 0 //}; //var subscriptionResponse = await this.CreateSubscriptionAsync(subscriptionRequest).ConfigureAwait(false); //this.subscriptionId = subscriptionResponse.SubscriptionId; } catch (Exception ex) { this.Logger?.LogError($"Error opening channel with endpoint '{this.RemoteEndpoint.EndpointUrl}'. {ex.Message}"); throw; } } finally { this.semaphore.Release(); } }
/// <summary> /// Opens a session with the remote endpoint. /// </summary> /// <param name="token">A cancellation token.</param> /// <returns>A task.</returns> private async Task OpenAsync(CancellationToken token = default(CancellationToken)) { await this.semaphore.WaitAsync(token).ConfigureAwait(false); try { if (this.RemoteEndpoint == null) { // If specific endpoint is not provided, use discovery to select endpoint with highest // security level. try { Trace.TraceInformation($"UaTcpSessionClient discovering endpoints of '{this.discoveryUrl}'."); var getEndpointsRequest = new GetEndpointsRequest { EndpointUrl = this.discoveryUrl, ProfileUris = new[] { TransportProfileUris.UaTcpTransport } }; var getEndpointsResponse = await UaTcpDiscoveryClient.GetEndpointsAsync(getEndpointsRequest).ConfigureAwait(false); 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) { Trace.TraceWarning($"UaTcpSessionClient error discovering endpoints of '{this.discoveryUrl}'. {ex.Message}"); throw; } } // throw here to exit state machine. token.ThrowIfCancellationRequested(); try { this.linkToken?.Dispose(); Trace.TraceInformation($"UaTcpSessionClient opening channel with endpoint '{this.RemoteEndpoint.EndpointUrl}'."); this.innerChannel = new UaTcpSessionChannel( this.LocalDescription, this.LocalCertificate, this.UserIdentity, this.RemoteEndpoint, this.SessionTimeout, this.TimeoutHint, this.DiagnosticsHint, this.LocalReceiveBufferSize, this.LocalSendBufferSize, this.LocalMaxMessageSize, this.LocalMaxChunkCount); await this.innerChannel.OpenAsync(token).ConfigureAwait(false); this.linkToken = this.pendingRequests.LinkTo(this.innerChannel); // create an internal subscription. this.publishEvent.Subscribe(this.OnPublishResponse, ThreadOption.PublisherThread, false); var subscriptionRequest = new CreateSubscriptionRequest { RequestedPublishingInterval = DefaultPublishingInterval, RequestedMaxKeepAliveCount = DefaultKeepaliveCount, RequestedLifetimeCount = (uint)(this.SessionTimeout / DefaultPublishingInterval), PublishingEnabled = true, Priority = 0 }; var subscriptionResponse = await this.CreateSubscriptionAsync(subscriptionRequest).ConfigureAwait(false); this.subscriptionId = subscriptionResponse.SubscriptionId; } catch (Exception ex) { Trace.TraceWarning($"UaTcpSessionClient error opening channel with endpoint '{this.RemoteEndpoint.EndpointUrl}'. {ex.Message}"); throw; } } finally { this.semaphore.Release(); } }