Exemplo n.º 1
0
        protected async Task ConnectAsyncCore(CancellationToken cancellationToken)
        {
            try
            {
                await OnConnectAsync(cancellationToken).ConfigureAwait(false);

                cancellationToken.ThrowIfCancellationRequested();

                System.Diagnostics.Debug.Assert(_connectedStream != null, "Connected stream must be not null here!");

                if (_connectionSettings.UseBufferedStream)
                {
                    //_sendingStream = new NetworkWriteStream(new BufferedStream(_connectedStream));
                    //_receivingStream = new NetworkReadStream(new BufferedStream(_connectedStream));
                    _sendingStream   = new BufferedStream(_connectedStream);
                    _receivingStream = new BufferedStream(_connectedStream);
                }
                else
                {
                    //_sendingStream = new NetworkWriteStream(_connectedStream);
                    //_receivingStream = new NetworkReadStream(_connectedStream);
                    _sendingStream   = _connectedStream;
                    _receivingStream = _connectedStream;
                }

                ServiceRef.Call(this, async() =>
                {
                    if (State == ConnectionState.Connecting ||
                        State == ConnectionState.LinkError)
                    {
                        //await SetStateAsync(ConnectionTrigger.Connected).ConfigureAwait(false);
                        SetState(ConnectionTrigger.Connected);

                        await RunConnection();
                    }
                });
            }
            catch (OperationCanceledException)
            {
            }
#if DEBUG
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"{GetType()}{Environment.NewLine}{ex}");
#else
            catch (Exception)
            {
#endif
                ServiceRef.Call(this, () =>
                {
                    if (State == ConnectionState.Connecting)
                    {
                        SetState(ConnectionTrigger.LinkError);
                    }
                });
            }
            finally
            {
            }
        }
Exemplo n.º 2
0
            public Task GetOrDownloadAsync(string url)
            {
                //simulate image download
                IPendingOperation pendingOperation = null;

                Console.WriteLine($"Downloading {url}");
                Task.Delay(2000).ContinueWith(_ =>
                {
                    Console.WriteLine($"Downloaded {url}");
                    pendingOperation.Complete();
                });

                pendingOperation = ServiceRef.RegisterPendingOperation(this, actionOnCompletion: (res) =>
                {
                    //Accessing _images here would be risky, just wrap the call...
                    ServiceRef.Call(this, () =>
                    {
                        Console.WriteLine($"Adding to images {url}");
                        _images.Add(new ImageStuff()
                        {
                            Url = url, Data = new byte[] { 0x01 }
                        });
                        Console.WriteLine($"Added to images {url}");
                    });
                });

                return(Task.CompletedTask);
            }
Exemplo n.º 3
0
        private void StartChildConnections()
        {
            foreach (var childConnection in _connections)
            {
                childConnection.Start(

                    receivedActionStreamAsync:
                    (connection, networkStream, cancellationToken)
                    => ServiceRef.CallAndWaitAsync(this, async() => await OnReceivedDataFromChildChannel(connection, networkStream, cancellationToken)),

                    connectionStateChangedAction:
                    (connection, fromState, toState)
                    => ServiceRef.Call(this, () => OnChildChannelConnectionStateChanged(connection, fromState, toState)));
            }
        }
Exemplo n.º 4
0
        private async Task ReceiveLoopAsync(CancellationToken cancellationToken)
        {
#pragma warning disable IDE0068 // Use recommended dispose pattern
            var refToThis = ServiceRef.Create <IConnection>(this);
#pragma warning restore IDE0068 // Use recommended dispose pattern
            try
            {
                //if (_receiveLoopCancellationTokenSource != null)
                //{
                //    _receiveLoopCancellationTokenSource.Dispose();
                //    _receiveLoopCancellationTokenSource = null;
                //}

                //_receiveLoopCancellationTokenSource = new CancellationTokenSource();
                _receiveLoopTaskIsRunningEvent.Set();

                //var cancellationToken = _receiveLoopCancellationTokenSource.Token;
                while (true)
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    int messageLength = -1;
                    if (_messageFramingEnabled)
                    {
                        await _receivingStream.ReadBufferedAsync(_messageSizeBuffer, cancellationToken).ConfigureAwait(false);

                        messageLength = BitConverter.ToInt32(_messageSizeBuffer, 0);
                        if (messageLength == 0)
                        {
                            continue;
                        }

                        cancellationToken.ThrowIfCancellationRequested();
                    }

                    if (messageLength == -1)
                    {
                        if (_receivedActionStreamAsync != null)
                        {
                            //await ServiceRef.CallAndWaitAsync(this, () =>
                            //    _receivedActionStreamAsync(refToThis, _receivingStream, cancellationToken)).ConfigureAwait(false);
                            await _receivedActionStreamAsync(refToThis, _receivingStream, cancellationToken);
                        }
                        else
                        {
                            throw new InvalidOperationException("ReceiveActionStreamAsync must be specified to handle variable length messages");
                        }
                    }
                    else
                    {
                        if (_receivedActionStreamAsync != null)
                        {
#pragma warning disable IDE0067 // Dispose objects before losing scope
                            var bufferedStream = new NetworkBufferedReadStream(_receivingStream, messageLength);
#pragma warning restore IDE0067 // Dispose objects before losing scope
                            await ServiceRef.CallAndWaitAsync(this, async() =>
                                                              await _receivedActionStreamAsync(refToThis, bufferedStream, cancellationToken).ConfigureAwait(false)).ConfigureAwait(false);

                            await bufferedStream.FlushAsync().ConfigureAwait(false);
                        }
                        else
                        {
                            var messageBuffer = new byte[messageLength];

                            await _receivingStream.ReadBufferedAsync(messageBuffer, cancellationToken).ConfigureAwait(false);

                            if (_receivedActionAsync != null)
                            {
                                await ServiceRef.CallAndWaitAsync(this, async() =>
                                                                  await _receivedActionAsync(refToThis, messageBuffer, cancellationToken).ConfigureAwait(false)).ConfigureAwait(false);
                            }
                            else //if (_receivedAction != null)
                            {
                                ServiceRef.CallAndWait(this, () => _receivedAction(refToThis, messageBuffer));
                            }
                        }
                    }
                }
            }
            catch (OperationCanceledException)
            {
                System.Diagnostics.Debug.WriteLine($"{GetType()} ReceiveLoopAsync Cancelled");
            }
#if DEBUG
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"{GetType()}{Environment.NewLine}{ex}");
#else
            catch (Exception)
            {
#endif
                //_receiveLoopCancellationTokenSource = null;

                ServiceRef.Call(this, () =>
                {
                    if (State == ConnectionState.Connected)
                    {
                        SetState(ConnectionTrigger.LinkError);
                    }
                });
            }
            finally
            {
                //_receiveLoopCancellationTokenSource = null;
            }
        }
Exemplo n.º 5
0
        //protected virtual async Task SetStateAsync(ConnectionTrigger connectionTrigger)
        //{
        //    var currentState = State;
        //    var newState = State;

        //    System.Diagnostics.Debug.WriteLine($"{GetType()} SetStateAsync({currentState}) -> {connectionTrigger}");

        //    switch (currentState)
        //    {
        //        case ConnectionState.Connecting:
        //            {
        //                if (connectionTrigger == ConnectionTrigger.Connected)
        //                {
        //                    await RunConnection();
        //                    newState = ConnectionState.Connected;
        //                }
        //                else throw new InvalidOperationException();
        //            }
        //            break;
        //        case ConnectionState.Disconnected:
        //            {
        //                throw new InvalidOperationException();
        //            }
        //        case ConnectionState.Connected:
        //            {
        //                throw new InvalidOperationException();
        //            }
        //        case ConnectionState.LinkError:
        //            {
        //                if (connectionTrigger == ConnectionTrigger.Connected)
        //                {
        //                    await RunConnection();
        //                    newState = ConnectionState.Connected;
        //                }
        //            }
        //            break;
        //    }

        //    if (newState == currentState)
        //        return;

        //    State = newState;

        //    System.Diagnostics.Debug.WriteLine($"{GetType()} SetState({currentState}) -> {connectionTrigger} -> {newState}");

        //    _connectionStateChangedAction?.Invoke(ServiceRef.Create<IConnection>(this), currentState, newState);
        //}

        //protected virtual void ConfigureStateMachine()
        //{
        //    _connectionStateMachine.Configure(ConnectionState.Disconnected)
        //        .Permit(ConnectionTrigger.Connect, ConnectionState.Connecting)
        //        .OnEntryFromAsync(ConnectionTrigger.Disconnect, async () =>
        //        {
        //            await OnDisconnect().ConfigureAwait(false);
        //        });

        //    _connectionStateMachine.Configure(ConnectionState.Connecting)
        //        .Permit(ConnectionTrigger.Connected, ConnectionState.Connected)
        //        .Permit(ConnectionTrigger.LinkError, ConnectionState.LinkError)
        //        .Permit(ConnectionTrigger.Disconnect, ConnectionState.Disconnected)
        //        .OnEntryAsync(async () => await ConnectAsyncCore().ConfigureAwait(false))
        //        .OnExitAsync(() =>
        //        {
        //            _connectCancellationTokenSource?.Cancel();
        //            return Task.CompletedTask;
        //        })
        //        .OnExit(() => _connectCancellationTokenSource?.Cancel());

        //    _connectionStateMachine.Configure(ConnectionState.Connected)
        //        .Permit(ConnectionTrigger.Disconnect, ConnectionState.Disconnected)
        //        .Permit(ConnectionTrigger.LinkError, ConnectionState.LinkError)
        //        .OnEntryAsync(async () =>
        //        {
        //            _receiveLoopTaskIsRunningEvent = new AsyncAutoResetEvent();
        //            _sendKeepAliveTaskIsRunningEvent = new AsyncAutoResetEvent();

        //            _receiveLoopTask = Task.Run(ReceiveLoopAsync);
        //            if (_connectionSettings.KeepAliveMilliseconds > 0)
        //            {
        //                _sendKeepAliveLoopTask = Task.Run(() => SendKeepAliveLoopAsync());
        //            }

        //            await _receiveLoopTaskIsRunningEvent.WaitAsync().ConfigureAwait(false);

        //            if (_connectionSettings.KeepAliveMilliseconds > 0)
        //            {
        //                await _sendKeepAliveTaskIsRunningEvent.WaitAsync().ConfigureAwait(false);
        //            }

        //            _receiveLoopTaskIsRunningEvent = null;
        //            _sendKeepAliveTaskIsRunningEvent = null;
        //        })
        //        .OnExitAsync(() =>
        //        {
        //            _receiveLoopCancellationTokenSource?.Cancel();
        //            _sendKeepAliveLoopCancellationTokenSource?.Cancel();
        //            _sendKeepAliveResetEvent?.Set();
        //            return Task.CompletedTask;
        //        });

        //    _connectionStateMachine.Configure(ConnectionState.LinkError)
        //        .Permit(ConnectionTrigger.Disconnect, ConnectionState.Disconnected)
        //        .Permit(ConnectionTrigger.Connected, ConnectionState.Connected)
        //        .Permit(ConnectionTrigger.Connect, ConnectionState.Connecting)
        //        .OnEntryFromAsync(ConnectionTrigger.LinkError, async () =>
        //        {
        //            await OnDisconnect().ConfigureAwait(false);
        //        });
        //}

        private async Task SendKeepAliveLoopAsync(AsyncAutoResetEvent sendKeepAliveResetEvent, CancellationToken cancellationToken)
        {
            try
            {
                //_sendKeepAliveResetEvent = new AsyncAutoResetEvent(false);

                //if (_sendKeepAliveLoopCancellationTokenSource != null)
                //{
                //    _sendKeepAliveLoopCancellationTokenSource.Dispose();
                //    _sendKeepAliveLoopCancellationTokenSource = null;
                //}

                //_sendKeepAliveLoopCancellationTokenSource = new CancellationTokenSource();

                _sendKeepAliveTaskIsRunningEvent.Set();

                if (_connectedStream.CanTimeout)
                {
                    _connectedStream.ReadTimeout = _connectionSettings.KeepAliveMilliseconds * 2;
                }

                while (true)
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    if (!await sendKeepAliveResetEvent.WaitAsync(_connectionSettings.KeepAliveMilliseconds, cancellationToken).ConfigureAwait(false))
                    {
                        cancellationToken.ThrowIfCancellationRequested();

                        await ServiceRef.CallAndWaitAsync(this, async() =>
                        {
                            if (State == ConnectionState.Connected && IsStreamConnected)
                            {
                                await _sendingStream.WriteAsync(_keepAlivePacket, 0, _keepAlivePacket.Length, cancellationToken).ConfigureAwait(false);
                            }
                        }).ConfigureAwait(false);
                    }
                }
            }
            catch (OperationCanceledException)
            {
                System.Diagnostics.Debug.WriteLine($"{GetType()} SendKeepAliveLoop Cancelled");
            }
#if DEBUG
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex);
#else
            catch (Exception)
            {
#endif
                //_sendKeepAliveLoopCancellationTokenSource = null;
                //_sendKeepAliveResetEvent = null;

                ServiceRef.Call(this, () =>
                {
                    if (State == ConnectionState.Connected)
                    {
                        //await _connectionStateMachine.FireAsync(ConnectionTrigger.LinkError).ConfigureAwait(false);
                        SetState(ConnectionTrigger.LinkError);
                    }
                });
            }
            finally
            {
                //_sendKeepAliveLoopCancellationTokenSource = null;
                //_sendKeepAliveResetEvent = null;
            }
        }