コード例 #1
0
ファイル: DeviceBase.cs プロジェクト: MadhumiPerera/Second
        /// <summary>
        /// Starts the send event loop and runs the receive loop in the background
        /// to listen for commands that are sent to the device
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public async Task StartAsync(CancellationToken token)
        {
            try
            {
                await InitializeAsync();

                var loopTasks = new List <Task>
                {
                    StartReceiveLoopAsync(token),
                    StartSendLoopAsync(token)
                };

                // Wait both the send and receive loops
                await Task.WhenAll(loopTasks.ToArray());
            }
            catch (Exception ex)
            {
                Logger.LogError($"Exception raise while starting device {DeviceID}: {ex}");
            }
            finally
            {
                // once the code makes it here the token has been canceled
                await Transport.CloseAsync();
            }
        }
コード例 #2
0
        public async Task CleanupAsync()
        {
            await _transportListener.StopAsync(_cancellationToken);

            _serverTransport.CloseAsync(_cancellationToken);
            _clientTransport.CloseAsync(_cancellationToken);
        }
コード例 #3
0
        /// <summary>
        /// Receives an envelope from the buffer.
        /// </summary>
        private async Task <T> ReceiveFromBufferAsync <T>(ChannelReader <T> reader, IEnumerable <IChannelModule <T> > modules, CancellationToken cancellationToken)
            where T : Envelope, new()
        {
            if (_channelInformation.State < SessionState.Established)
            {
                throw new InvalidOperationException($"Cannot receive envelopes in the '{_channelInformation.State}' session state");
            }

            try
            {
                T   envelope;
                var modulesList = modules.ToList();

                do
                {
                    envelope = await reader.ReadAsync(cancellationToken).ConfigureAwait(false);

                    foreach (var module in modulesList)
                    {
                        if (envelope == null)
                        {
                            break;
                        }
                        envelope = await module.OnReceivingAsync(envelope, cancellationToken);
                    }
                } while (envelope == null);

                return(envelope);
            }
            catch (OperationCanceledException) when(cancellationToken.IsCancellationRequested)
            {
                throw;
            }
            catch (Exception ex)
            {
                // Closes the transport in case of any exception
                if (_transport.IsConnected)
                {
                    using var cts = new CancellationTokenSource(_consumeTimeout ?? TimeSpan.FromSeconds(5));
                    try
                    {
                        await _transport.CloseAsync(cts.Token).ConfigureAwait(false);
                    }
                    catch (Exception ex2)
                    {
                        RaiseReceiverException(ex2);
                    }
                }

                if (ex is ChannelClosedException && reader.Completion.IsCompleted)
                {
                    throw new InvalidOperationException(
                              "The channel listener task is complete and cannot receive envelopes", ex);
                }

                throw;
            }
        }
コード例 #4
0
        /// <summary>
        /// Sends the envelope to the specified target.
        /// </summary>
        private async Task SendToBufferAsync <T>(T envelope, IEnumerable <IChannelModule <T> > modules, CancellationToken cancellationToken)
            where T : Envelope, new()
        {
            if (envelope == null)
            {
                throw new ArgumentNullException(nameof(envelope));
            }
            if (_channelInformation.State != SessionState.Established)
            {
                throw new InvalidOperationException(
                          $"Cannot send a {typeof(T).Name} in the '{_channelInformation.State}' session state");
            }

            if (!_transport.IsConnected)
            {
                throw new InvalidOperationException("The transport is not connected");
            }

            try
            {
                if (_envelopeBuffer.Reader.Completion.IsCompleted)
                {
                    throw new InvalidOperationException("The send buffer is complete",
                                                        _envelopeBuffer.Reader.Completion.Exception?.GetBaseException());
                }

                foreach (var module in modules.ToList())
                {
                    if (envelope == null)
                    {
                        break;
                    }
                    cancellationToken.ThrowIfCancellationRequested();
                    envelope = await module.OnSendingAsync(envelope, cancellationToken).ConfigureAwait(false);
                }

                await _envelopeBuffer.Writer.WriteAsync(envelope, cancellationToken).ConfigureAwait(false);
            }
            catch (OperationCanceledException) when(cancellationToken.IsCancellationRequested)
            {
                throw;
            }
            catch when(_transport.IsConnected)
                {
                    // Closes the transport in case of any exception
                    using var cts = new CancellationTokenSource(_closeTimeout);
                    try
                    {
                        await _transport.CloseAsync(cts.Token).ConfigureAwait(false);
                    }
                    catch (Exception ex)
                    {
                        RaiseSenderException(ex);
                    }
                    throw;
                }
        }
コード例 #5
0
        public async Task SendAsync_AfterServerDisconnect_ClientAutomaticallyReconnects()
        {
            ITransport         clientTransport   = null;
            ITransport         serverTransport   = null;
            ITransportListener transportListener = null;

            try
            {
                // Arrange
                transportListener = CreateTransportListener(ListenerUri, EnvelopeSerializer);
                await transportListener.StartAsync(CancellationToken);

                clientTransport = CreateClientTransport(EnvelopeSerializer);
                var serverTransportTask = transportListener.AcceptTransportAsync(CancellationToken);
                await clientTransport.OpenAsync(ListenerUri, CancellationToken);

                serverTransport = await serverTransportTask;
                await serverTransport.OpenAsync(ListenerUri, CancellationToken);

                var message = Dummy.CreateMessage(Dummy.CreateTextContent());

                // Act
                await transportListener.StopAsync(CancellationToken);

                await serverTransport.CloseAsync(CancellationToken);

                transportListener = CreateTransportListener(ListenerUri, EnvelopeSerializer);
                await transportListener.StartAsync(CancellationToken);

                serverTransport = await transportListener.AcceptTransportAsync(CancellationToken);

                await serverTransport.OpenAsync(ListenerUri, CancellationToken);

                await clientTransport.SendAsync(message, CancellationToken);

                var actual = await serverTransport.ReceiveAsync(CancellationToken);

                // Assert
                var actualMessage = actual.ShouldBeOfType <Message>();
                CompareMessages(message, actualMessage);
            }
            finally
            {
                (clientTransport as IDisposable)?.Dispose();
                (serverTransport as IDisposable)?.Dispose();
                (transportListener as IDisposable)?.Dispose();
            }
        }
コード例 #6
0
        /// <summary>
        /// Starts the send event loop and runs the receive loop in the background
        /// to listen for commands that are sent to the device
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public async Task StartAsync(CancellationToken token)
        {
            Transport.Open();

            var loopTasks = new List <Task>
            {
                StartReceiveLoopAsync(token),
                StartSendLoopAsync(token)
            };

            // Wait both the send and receive loops
            await Task.WhenAll(loopTasks.ToArray());

            // once the code makes it here the token has been canceled
            await Transport.CloseAsync();
        }
コード例 #7
0
        public async Task TearDown()
        {
            _cts.Dispose();
            using (var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5)))
            {
                await Task.WhenAll(
                    _serverTransport.CloseAsync(cts.Token),
                    _clientTransport.CloseAsync(cts.Token));

                await _transportListener.StopAsync(cts.Token);
            }

            _clientTransport.DisposeIfDisposable();
            _serverTransport.DisposeIfDisposable();
            _transportListener.DisposeIfDisposable();

            // Set null to avoid issues with NUnit reusing the test class instance
            _clientTransport   = null;
            _serverTransport   = null;
            _transportListener = null;
        }
コード例 #8
0
        /// <summary>
        /// Starts the send event loop and runs the receive loop in the background
        /// to listen for commands that are sent to the device
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public async Task StartAsync(CancellationToken token)
        {
            try
            {
                Transport.Open();

                var loopTasks = new List <Task>
                {
                    StartReceiveLoopAsync(token),
                    StartSendLoopAsync(token)
                };

                // Wait both the send and receive loops
                await Task.WhenAll(loopTasks.ToArray());

                // once the code makes it here the token has been canceled
                await Transport.CloseAsync();
            }
            catch (Exception ex)
            {
                Logger.LogError("Unexpected Exception starting device: {0}", ex.ToString());
            }
        }
コード例 #9
0
 public void Dispose()
 {
     _clientTransport.CloseAsync(CancellationToken.None);
     _serverTransport.CloseAsync(CancellationToken.None);
     _transportListener.StopAsync(_cancellationToken).Wait();
 }
コード例 #10
0
 public Task CloseAsync(CancellationToken cancellationToken)
 {
     return(_transport.CloseAsync(cancellationToken).WithCancellation(cancellationToken));
 }