Пример #1
0
        /// <inheritdoc/>
        /// <seealso href="https://reference.opcfoundation.org/v104/Core/docs/Part4/5.5.2/">OPC UA specification Part 4: Services, 5.5.2</seealso>
        protected override async Task OnOpenAsync(CancellationToken token = default)
        {
            await base.OnOpenAsync(token).ConfigureAwait(false);

            var options = new TransportConnectionOptions
            {
                ReceiveBufferSize = RemoteReceiveBufferSize,
                SendBufferSize    = RemoteSendBufferSize,
                MaxMessageSize    = RemoteMaxMessageSize,
                MaxChunkCount     = RemoteMaxChunkCount
            };

            _conversation = await StackProfile.ConversationProvider.CreateAsync(RemoteEndpoint, LocalDescription, options, CertificateStore, _logger, token).ConfigureAwait(false);

            token.ThrowIfCancellationRequested();

            _receiveResponsesTask = ReceiveResponsesAsync(_channelCts.Token);

            var openSecureChannelRequest = new OpenSecureChannelRequest
            {
                ClientProtocolVersion = ProtocolVersion,
                RequestType           = SecurityTokenRequestType.Issue,
                SecurityMode          = RemoteEndpoint.SecurityMode,
                ClientNonce           = _conversation !.GetNextNonce(),
                RequestedLifetime     = _tokenRequestedLifetime
            };

            var openSecureChannelResponse = (OpenSecureChannelResponse) await RequestAsync(openSecureChannelRequest).ConfigureAwait(false);

            if (openSecureChannelResponse.ServerProtocolVersion < ProtocolVersion)
            {
                throw new ServiceResultException(StatusCodes.BadProtocolVersionUnsupported);
            }
        }
        /// <inheritdoc/>
        protected override async Task OnOpenAsync(CancellationToken token)
        {
            token.ThrowIfCancellationRequested();

            _connection = await StackProfile.TransportConnectionProvider.ConnectAsync(RemoteEndpoint.EndpointUrl !, token).ConfigureAwait(false);

            var localOptions = new TransportConnectionOptions
            {
                ReceiveBufferSize = LocalReceiveBufferSize,
                SendBufferSize    = LocalSendBufferSize,
                MaxMessageSize    = LocalMaxMessageSize,
                MaxChunkCount     = LocalMaxChunkCount
            };

            var remoteOptions = await _connection.OpenAsync(ProtocolVersion, localOptions, token).ConfigureAwait(false);

            RemoteSendBufferSize    = remoteOptions.SendBufferSize;
            RemoteReceiveBufferSize = remoteOptions.ReceiveBufferSize;
            RemoteMaxMessageSize    = remoteOptions.MaxMessageSize;
            RemoteMaxChunkCount     = remoteOptions.MaxChunkCount;
        }
        /// <summary>
        /// Opens the connection. This includes the hello message handshake.
        /// </summary>
        /// <remakes>
        /// The underlying network client is already opened before this class is
        /// constructed. The
        /// connection is closed with <see cref="IAsyncDisposable.DisposeAsync"/>
        /// method.
        /// </remakes>
        /// <param name="protocolVersion">The protocol version.</param>
        /// <param name="localOptions">The requested transport connection options.</param>
        /// <param name="token">A cancellation token used to propagate notification that this operation should be canceled.</param>
        /// <returns>The transport connection options to be used.</returns>
        /// <seealso href="https://reference.opcfoundation.org/v104/Core/docs/Part6/7.1.2/">OPC UA specification Part 6: Mappings, 7.1.2</seealso>
        public async Task <TransportConnectionOptions> OpenAsync(uint protocolVersion, TransportConnectionOptions localOptions, CancellationToken token)
        {
            var sendBuffer    = new byte[MinBufferSize];
            var receiveBuffer = new byte[MinBufferSize];

            // send 'hello'.
            int count;

            using (var encoder = new BinaryEncoder(new MemoryStream(sendBuffer, 0, MinBufferSize, true, false)))
            {
                encoder.WriteUInt32(null, MessageTypes.HELF);
                encoder.WriteUInt32(null, 0u);
                encoder.WriteUInt32(null, protocolVersion);
                encoder.WriteUInt32(null, localOptions.ReceiveBufferSize);
                encoder.WriteUInt32(null, localOptions.SendBufferSize);
                encoder.WriteUInt32(null, localOptions.MaxMessageSize);
                encoder.WriteUInt32(null, localOptions.MaxChunkCount);
                encoder.WriteString(null, Uri.ToString());
                count            = encoder.Position;
                encoder.Position = 4;
                encoder.WriteUInt32(null, (uint)count);
                encoder.Position = count;

                await SendAsync(sendBuffer, 0, count, token).ConfigureAwait(false);
            }

            // receive response
            count = await ReceiveAsync(receiveBuffer, 0, MinBufferSize, token).ConfigureAwait(false);

            if (count == 0)
            {
                throw new ObjectDisposedException("socket");
            }

            // decode 'ack' or 'err'.
            using (var decoder = new BinaryDecoder(new MemoryStream(receiveBuffer, 0, count, false, false)))
            {
                var type = decoder.ReadUInt32(null);
                var len  = decoder.ReadUInt32(null);
                if (type == MessageTypes.ACKF)
                {
                    var remoteProtocolVersion = decoder.ReadUInt32(null);
                    if (remoteProtocolVersion < protocolVersion)
                    {
                        throw new ServiceResultException(StatusCodes.BadProtocolVersionUnsupported);
                    }

                    var remoteOptions = new TransportConnectionOptions
                    {
                        SendBufferSize    = decoder.ReadUInt32(null),
                        ReceiveBufferSize = decoder.ReadUInt32(null),
                        MaxMessageSize    = decoder.ReadUInt32(null),
                        MaxChunkCount     = decoder.ReadUInt32(null)
                    };

                    return(remoteOptions);
                }
                else if (type == MessageTypes.ERRF)
                {
                    var statusCode = decoder.ReadUInt32(null);
                    var message    = decoder.ReadString(null);
                    if (message != null)
                    {
                        throw new ServiceResultException(statusCode, message);
                    }

                    throw new ServiceResultException(statusCode);
                }

                throw new InvalidOperationException($"{nameof(UaClientConnection)}.{nameof(OpenAsync)} received unexpected message type.");
            }
        }
        /// <inheritdoc />
        public async Task <IConversation> CreateAsync(EndpointDescription remoteEndpoint, ApplicationDescription localDescription, TransportConnectionOptions options, ICertificateStore?certificateStore, ILogger?logger, CancellationToken token)
        {
            var conversation = new UaSecureConversation(localDescription, options, certificateStore, logger)
            {
                SecurityMode = remoteEndpoint.SecurityMode
            };

            await conversation.SetRemoteCertificateAsync(remoteEndpoint.SecurityPolicyUri, remoteEndpoint.ServerCertificate, token).ConfigureAwait(false);

            return(conversation);
        }