void QueueExpiry(Action expireAction)
        {
            Task oldExpireTask;

            async Task ExpireAsync()
            {
                var expireAt = DateTimeOffset.UtcNow + TimeSpan.FromMinutes(TicketValidityMinutes);

                try
                {
                    await oldExpireTask.WithToken(disposeCts.Token).ConfigureAwait(false);

                    var now = DateTimeOffset.UtcNow;
                    if (now < expireAt)
                    {
                        await asyncDelayer.Delay(expireAt - now, disposeCts.Token).ConfigureAwait(false);
                    }
                }
                finally
                {
                    expireAction();
                }
            }

            lock (synchronizationLock)
            {
                oldExpireTask = expireTask;
                expireTask    = ExpireAsync();
            }
        }
Ejemplo n.º 2
0
        public void StartFor(IPeer peer, CancellationToken cancellationToken)
        {
            // Initiate handshake
            peer.Send(new VersionMessage(_serverContext.Version));

            Task.Factory.StartNew(async() =>
            {
                while (peer.IsConnected)
                {
                    var message = await peer.Receive();
                    if (message == null)
                    {
                        await _asyncDelayer.Delay(DefaultMessagePollingInterval, cancellationToken);
                        continue;
                    }

                    // TODO: Peer that sending wrong messages has to be disconnected.
                    if (peer.IsReady == message.IsHandshakeMessage())
                    {
                        continue;
                    }

                    await _messageHandler.Handle(message, peer);
                }
            }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Default);
        }
Ejemplo n.º 3
0
        /// <inheritdoc />
        public async Task <BridgeResponse> ProcessBridgeRequest(BridgeParameters parameters, CancellationToken cancellationToken)
        {
            if (parameters == null)
            {
                throw new ArgumentNullException(nameof(parameters));
            }

            IBridgeHandler bridgeHandler = null;

            for (var i = 0; bridgeHandler == null && i < 30; ++i)
            {
                // There's a miniscule time period where we could potentially receive a bridge request and not have the registration ready when we launch DD
                // This is a stopgap
                Task delayTask = Task.CompletedTask;
                lock (bridgeHandlers)
                    if (!bridgeHandlers.TryGetValue(parameters.AccessIdentifier, out bridgeHandler))
                    {
                        delayTask = asyncDelayer.Delay(TimeSpan.FromMilliseconds(100), cancellationToken);
                    }

                await delayTask.ConfigureAwait(false);
            }

            if (bridgeHandler == null)
            {
                lock (bridgeHandlers)
                    if (!bridgeHandlers.TryGetValue(parameters.AccessIdentifier, out bridgeHandler))
                    {
                        logger.LogWarning("Recieved invalid bridge request with accees identifier: {0}", parameters.AccessIdentifier);
                        return(null);
                    }
            }

            return(await bridgeHandler.ProcessBridgeRequest(parameters, cancellationToken).ConfigureAwait(false));
        }
Ejemplo n.º 4
0
        // TODO: We will read the current block from Blockchain
        // because the logic to get that too complicated
        public void Run(Block currentBlock)
        {
            _blockPool.CurrentBlock = currentBlock;

            var cancellationToken = _cancellationTokenSource.Token;

            Task.Factory.StartNew(async() =>
            {
                while (!cancellationToken.IsCancellationRequested)
                {
                    var blockIndex = _blockPool.CurrentBlock?.Index + 1 ?? 0;

                    if (_blockPool.TryGet(blockIndex, out var block) == false)
                    {
                        await _asyncDelayer.Delay(DefaultBlockPollingInterval, cancellationToken);
                        continue;
                    }

                    await Process(block);

                    _blockPool.Remove(blockIndex);
                    _blockPool.CurrentBlock = block;

                    OnBlockProcessed?.Invoke(block);
                }
            }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Default);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Monitors active providers for new <see cref="Message"/>s
        /// </summary>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
        /// <returns>A <see cref="Task"/> representing the running operation</returns>
        async Task MonitorMessages(CancellationToken cancellationToken)
        {
            var messageTasks = new Dictionary <IProvider, Task <Message> >();

            try
            {
                while (!cancellationToken.IsCancellationRequested)
                {
                    // prune disconnected providers
                    foreach (var I in messageTasks.Where(x => !x.Key.Connected).ToList())
                    {
                        messageTasks.Remove(I.Key);
                    }

                    // add new ones
                    Task updatedTask;
                    lock (this)
                        updatedTask = connectionsUpdated.Task;
                    lock (providers)
                        foreach (var I in providers)
                        {
                            if (I.Value.Connected && !messageTasks.ContainsKey(I.Value))
                            {
                                messageTasks.Add(I.Value, I.Value.NextMessage(cancellationToken));
                            }
                        }

                    if (messageTasks.Count == 0)
                    {
                        await asyncDelayer.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false);

                        continue;
                    }

                    // wait for a message
                    await Task.WhenAny(updatedTask, Task.WhenAny(messageTasks.Select(x => x.Value))).ConfigureAwait(false);

                    // process completed ones
                    foreach (var I in messageTasks.Where(x => x.Value.IsCompleted).ToList())
                    {
                        var message = await I.Value.ConfigureAwait(false);

                        await ProcessMessage(I.Key, message, cancellationToken).ConfigureAwait(false);

                        messageTasks.Remove(I.Key);
                    }
                }
            }
            catch (OperationCanceledException)
            {
                logger.LogTrace("Message processing loop cancelled!");
            }
            catch (Exception e)
            {
                logger.LogError("Message monitor crashed! Exception: {0}", e);
            }
        }
Ejemplo n.º 6
0
        public void Run()
        {
            var cancellationToken = _cancellationTokenSource.Token;

            Task.Factory.StartNew(async() =>
            {
                while (!cancellationToken.IsCancellationRequested)
                {
                    if (!_unverifiedTransactionPool.Any())
                    {
                        await _asyncDelayer.Delay(DefaultTransactionPollingInterval, cancellationToken);
                        continue;
                    }

                    var unverifiedTransactionHashes = _unverifiedTransactionPool.Keys;
                    var transactionPool             = _verifiedTransactionPool.Concat(
                        _unverifiedTransactionPool.Values.Where(t => unverifiedTransactionHashes.Contains(t.Hash)))
                                                      .ToArray();

                    foreach (var transactionHash in unverifiedTransactionHashes)
                    {
                        if (!_unverifiedTransactionPool.TryGetValue(transactionHash, out var transaction))
                        {
                            continue;
                        }

                        var valid = this._transactionVerifier.Verify(transaction);

                        if (transactionPool
                            .Where(t => t.Hash != transactionHash)
                            .Where(p => p != transaction)
                            .SelectMany(p => p.Inputs)
                            .Intersect(transaction.Inputs)
                            .Any())
                        {
                            valid = false;
                        }

                        if (valid)
                        {
                            _verifiedTransactionPool.Add(transaction);
                        }

                        _unverifiedTransactionPool.TryRemove(transactionHash, out _);

                        OnTransactionProcessed?.Invoke(this, transaction);
                    }
                }
            }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Default);
        }
Ejemplo n.º 7
0
        public UnpegTests()
        {
            _randomnessHandler = Substitute.For <IRandomnessHandler>();
            _randomnessHandler.Random.Returns(Substitute.For <Random>());
            _chatHelper = Substitute.For <IChatHelper>();
            _chatHelper.Messages.Returns(Substitute.For <IMessageHandler>());
            _asyncDelayer = Substitute.For <IAsyncDelayer>();
            _asyncDelayer.Delay(Arg.Any <TimeSpan>(), Arg.Any <CancellationToken>())
            .ReturnsForAnyArgs(Task.CompletedTask);
            var backgroundTaskQueue = Substitute.For <IBackgroundTaskQueue>();

            backgroundTaskQueue
            .WhenForAnyArgs(x => x.QueueBackgroundWorkItem(Arg.Any <Func <CancellationToken, Task> >()))
            .Do(async x => await((Func <CancellationToken, Task>)x[0])(new CancellationToken()));
            _subject = new Unpeg(_randomnessHandler, _chatHelper, backgroundTaskQueue, _asyncDelayer,
                                 Substitute.For <ILogger <Unpeg> >());
        }
Ejemplo n.º 8
0
        private void SendQueuedMessage(Message message)
        {
            _backgroundTaskQueue.QueueBackgroundWorkItem(async token =>
            {
                try
                {
                    await _asyncDelayer.Delay(TimeSpan.FromSeconds(30), token);
                }
                catch (OperationCanceledException)
                {
                    _logger.LogWarning($"Message sending cancelled.");
                }

                if (!token.IsCancellationRequested)
                {
                    await _chatHelper.Messages.SendMessageAsync(message);
                }
            });
        }
Ejemplo n.º 9
0
        /// <inheritdoc />
        public async Task <Token> CreateToken(Models.User user, bool oAuth, CancellationToken cancellationToken)
        {
            if (user == null)
            {
                throw new ArgumentNullException(nameof(user));
            }

            var now     = DateTimeOffset.UtcNow;
            var nowUnix = now.ToUnixTimeSeconds();

            // this prevents validation conflicts down the line
            // tldr we can (theoretically) send a token the same second we receive it
            // since unix time rounds down, it looks like it came from before the user changed their password
            // this happens occasionally in unit tests
            // just delay a second so we can force a round up
            var lpuUnix = user.LastPasswordUpdate?.ToUnixTimeSeconds();

            if (nowUnix == lpuUnix)
            {
                await asyncDelayer.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false);
            }

            var expiry = now.AddMinutes(oAuth
                                ? securityConfiguration.OAuthTokenExpiryMinutes
                                : securityConfiguration.TokenExpiryMinutes);
            var claims = new Claim[]
            {
                new Claim(JwtRegisteredClaimNames.Sub, user.Id.Value.ToString(CultureInfo.InvariantCulture)),
                new Claim(JwtRegisteredClaimNames.Exp, expiry.ToUnixTimeSeconds().ToString(CultureInfo.InvariantCulture)),
                new Claim(JwtRegisteredClaimNames.Nbf, nowUnix.ToString(CultureInfo.InvariantCulture)),
                new Claim(JwtRegisteredClaimNames.Iss, ValidationParameters.ValidIssuer),
                new Claim(JwtRegisteredClaimNames.Aud, ValidationParameters.ValidAudience)
            };

            var token = new JwtSecurityToken(new JwtHeader(new SigningCredentials(ValidationParameters.IssuerSigningKey, SecurityAlgorithms.HmacSha256)), new JwtPayload(claims));

            return(new Token
            {
                Bearer = new JwtSecurityTokenHandler().WriteToken(token),
                ExpiresAt = expiry
            });
        }
        /// <summary>
        /// Construct an <see cref="IdentityCache"/>
        /// </summary>
        /// <param name="systemIdentity">The value of <see cref="SystemIdentity"/></param>
        /// <param name="asyncDelayer">The <see cref="IAsyncDelayer"/> used to delay the expiry</param>
        /// <param name="onExpiry">The <see cref="Action"/> to take on expiry</param>
        /// <param name="expiry">The <see cref="DateTimeOffset"/></param>
        public IdentityCacheObject(ISystemIdentity systemIdentity, IAsyncDelayer asyncDelayer, Action onExpiry, DateTimeOffset expiry)
        {
            SystemIdentity = systemIdentity ?? throw new ArgumentNullException(nameof(systemIdentity));

            if (asyncDelayer == null)
            {
                throw new ArgumentNullException(nameof(asyncDelayer));
            }

            if (onExpiry == null)
            {
                throw new ArgumentNullException(nameof(onExpiry));
            }
            var now = DateTimeOffset.UtcNow;

            if (expiry < now)
            {
                throw new ArgumentOutOfRangeException(nameof(expiry), expiry, "expiry must be greater than DateTimeOffset.UtcNow!");
            }

            cancellationTokenSource = new CancellationTokenSource();

            async Task DisposeOnExipiry(CancellationToken cancellationToken)
            {
                using (SystemIdentity)
                    try
                    {
                        await asyncDelayer.Delay(expiry - now, cancellationToken).ConfigureAwait(false);
                    }
                    finally
                    {
                        onExpiry();
                    }
            }

            task = DisposeOnExipiry(cancellationTokenSource.Token);
        }
Ejemplo n.º 11
0
        async Task Run(CancellationToken cancellationToken)
        {
            logger.LogDebug("Starting network prompt reaper...");
            try
            {
                while (!cancellationToken.IsCancellationRequested)
                {
                    await asyncDelayer.Delay(TimeSpan.FromMilliseconds(RecheckDelayMs), cancellationToken).ConfigureAwait(false);

                    IntPtr window;
                    int    processId;
                    lock (registeredProcesses)
                    {
                        if (registeredProcesses.Count == 0)
                        {
                            continue;
                        }

                        window = NativeMethods.FindWindow(null, "Network Accessibility");
                        if (window == IntPtr.Zero)
                        {
                            continue;
                        }

                        // found a bitch
                        var threadId = NativeMethods.GetWindowThreadProcessId(window, out processId);
                        if (!registeredProcesses.Any(x => x.Id == processId))
                        {
                            continue;                             // not our bitch
                        }
                    }

                    logger.LogTrace("Identified \"Network Accessibility\" window in owned process {0}", processId);

                    var found = false;
                    foreach (var I in GetAllChildHandles(window))
                    {
                        const int MaxLength     = 10;
                        var       stringBuilder = new StringBuilder(MaxLength + 1);

                        if (NativeMethods.GetWindowText(I, stringBuilder, MaxLength) == 0)
                        {
                            logger.LogWarning("Error calling GetWindowText! Exception: {0}", new Win32Exception());
                            continue;
                        }

                        var windowText = stringBuilder.ToString();
                        if (windowText == "Yes")
                        {
                            // smash_button_meme.jpg
                            logger.LogTrace("Sending \"Yes\" button clicks...");
                            for (var J = 0; J < SendMessageCount; ++J)
                            {
                                const int BM_CLICK = 0x00F5;
                                var       result   = NativeMethods.SendMessage(I, BM_CLICK, IntPtr.Zero, IntPtr.Zero);
                            }

                            found = true;
                            break;
                        }
                    }

                    if (!found)
                    {
                        logger.LogDebug("Unable to find \"Yes\" button for \"Network Accessibility\" window in owned process {0}!", processId);
                    }
                }
            }
            catch (OperationCanceledException)
            {
                logger.LogTrace("Cancelled!");
            }
            finally
            {
                logger.LogDebug("Exiting network prompt reaper...");
            }
        }
Ejemplo n.º 12
0
        /// <inheritdoc />
        public override Task <bool> Connect(CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
        {
            disconnecting = false;
            lock (this)
                try
                {
                    client.Connect(address, port);

                    cancellationToken.ThrowIfCancellationRequested();

                    if (passwordType == IrcPasswordType.Server)
                    {
                        client.Login(nickname, nickname, 0, nickname, password);
                    }
                    else
                    {
                        if (passwordType == IrcPasswordType.Sasl)
                        {
                            client.WriteLine("CAP REQ :sasl", Priority.Critical);                             // needs to be put in the buffer before anything else
                            cancellationToken.ThrowIfCancellationRequested();
                        }

                        client.Login(nickname, nickname, 0, nickname);
                    }

                    if (passwordType == IrcPasswordType.NickServ)
                    {
                        cancellationToken.ThrowIfCancellationRequested();
                        client.SendMessage(SendType.Message, "NickServ", String.Format(CultureInfo.InvariantCulture, "IDENTIFY {0}", password));
                    }
                    else if (passwordType == IrcPasswordType.Sasl)
                    {
                        // wait for the sasl ack or timeout
                        var recievedAck    = false;
                        var recievedPlus   = false;
                        client.OnReadLine += (sender, e) =>
                        {
                            if (e.Line.Contains("ACK :sasl", StringComparison.Ordinal))
                            {
                                recievedAck = true;
                            }
                            else if (e.Line.Contains("AUTHENTICATE +", StringComparison.Ordinal))
                            {
                                recievedPlus = true;
                            }
                        };

                        var startTime = DateTimeOffset.Now;
                        var endTime   = DateTimeOffset.Now.AddSeconds(TimeoutSeconds);
                        cancellationToken.ThrowIfCancellationRequested();

                        var listenTimeSpan = TimeSpan.FromMilliseconds(10);
                        for (; !recievedAck && DateTimeOffset.Now <= endTime; asyncDelayer.Delay(listenTimeSpan, cancellationToken).GetAwaiter().GetResult())
                        {
                            client.Listen(false);
                        }

                        client.WriteLine("AUTHENTICATE PLAIN", Priority.Critical);
                        cancellationToken.ThrowIfCancellationRequested();

                        for (; !recievedPlus && DateTimeOffset.Now <= endTime; asyncDelayer.Delay(listenTimeSpan, cancellationToken).GetAwaiter().GetResult())
                        {
                            client.Listen(false);
                        }

                        // Stolen! https://github.com/znc/znc/blob/1e697580155d5a38f8b5a377f3b1d94aaa979539/modules/sasl.cpp#L196
                        var authString = String.Format(CultureInfo.InvariantCulture, "{0}{1}{0}{1}{2}", nickname, '\0', password);
                        var b64        = Convert.ToBase64String(Encoding.UTF8.GetBytes(authString));
                        var authLine   = String.Format(CultureInfo.InvariantCulture, "AUTHENTICATE {0}", b64);
                        var chars      = authLine.ToCharArray();
                        client.WriteLine(authLine, Priority.Critical);

                        cancellationToken.ThrowIfCancellationRequested();
                        client.WriteLine("CAP END", Priority.Critical);
                    }

                    client.Listen(false);

                    listenTask = Task.Factory.StartNew(() =>
                    {
                        while (!disconnecting && client.IsConnected && client.Nickname != nickname)
                        {
                            client.ListenOnce(true);
                            if (disconnecting || !client.IsConnected)
                            {
                                break;
                            }
                            client.Listen(false);

                            // ensure we have the correct nick
                            if (client.GetIrcUser(nickname) == null)
                            {
                                client.RfcNick(nickname);
                            }
                        }

                        client.Listen();
                    }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
                }
                catch (OperationCanceledException)
                {
                    throw;
                }
            catch (Exception e)
            {
                Logger.LogWarning("Unable to connect to IRC: {0}", e);
                return(false);
            }

            return(true);
        }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
Ejemplo n.º 13
0
        /// <summary>
        /// Saves a given <see cref="Configuration"/> set to <paramref name="userConfigFileName"/>
        /// </summary>
        /// <param name="userConfigFileName">The file to save the <see cref="Configuration"/> to</param>
        /// <param name="hostingPort">The hosting port to save</param>
        /// <param name="databaseConfiguration">The <see cref="DatabaseConfiguration"/> to save</param>
        /// <param name="newGeneralConfiguration">The <see cref="GeneralConfiguration"/> to save</param>
        /// <param name="fileLoggingConfiguration">The <see cref="FileLoggingConfiguration"/> to save</param>
        /// <param name="controlPanelConfiguration">The <see cref="ControlPanelConfiguration"/> to save</param>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
        /// <returns>A <see cref="Task"/> representing the running operation</returns>
        async Task SaveConfiguration(string userConfigFileName, ushort?hostingPort, DatabaseConfiguration databaseConfiguration, GeneralConfiguration newGeneralConfiguration, FileLoggingConfiguration fileLoggingConfiguration, ControlPanelConfiguration controlPanelConfiguration, CancellationToken cancellationToken)
        {
            await console.WriteAsync(String.Format(CultureInfo.InvariantCulture, "Configuration complete! Saving to {0}", userConfigFileName), true, cancellationToken).ConfigureAwait(false);

            var map = new Dictionary <string, object>()
            {
                { DatabaseConfiguration.Section, databaseConfiguration },
                { GeneralConfiguration.Section, newGeneralConfiguration },
                { FileLoggingConfiguration.Section, fileLoggingConfiguration },
                { ControlPanelConfiguration.Section, controlPanelConfiguration }
            };

            if (hostingPort.HasValue)
            {
                map.Add("Kestrel", new
                {
                    EndPoints = new
                    {
                        Http = new
                        {
                            Url = String.Format(CultureInfo.InvariantCulture, "http://0.0.0.0:{0}", hostingPort)
                        }
                    }
                });
            }

            var json        = JsonConvert.SerializeObject(map, Formatting.Indented);
            var configBytes = Encoding.UTF8.GetBytes(json);

            try
            {
                await ioManager.WriteAllBytes(userConfigFileName, configBytes, cancellationToken).ConfigureAwait(false);
            }
            catch (OperationCanceledException)
            {
                throw;
            }
            catch (Exception e)
            {
                await console.WriteAsync(e.Message, true, cancellationToken).ConfigureAwait(false);

                await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);

                await console.WriteAsync("For your convienence, here's the json we tried to write out:", true, cancellationToken).ConfigureAwait(false);

                await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);

                await console.WriteAsync(json, true, cancellationToken).ConfigureAwait(false);

                await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);

                await console.WriteAsync("Press any key to exit...", true, cancellationToken).ConfigureAwait(false);

                await console.PressAnyKeyAsync(cancellationToken).ConfigureAwait(false);

                throw new OperationCanceledException();
            }

            await console.WriteAsync("Waiting for configuration changes to reload...", true, cancellationToken).ConfigureAwait(false);

            // we need to wait for the configuration's file system watcher to read and reload the changes
            await asyncDelayer.Delay(TimeSpan.FromSeconds(5), cancellationToken).ConfigureAwait(false);
        }
Ejemplo n.º 14
0
        /// <summary>
        /// Prompt the user for the <see cref="DatabaseType"/>.
        /// </summary>
        /// <param name="firstTime">If this is the user's first time here.</param>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation.</param>
        /// <returns>A <see cref="Task{TResult}"/> resulting in the input <see cref="DatabaseType"/>.</returns>
        async Task <DatabaseType> PromptDatabaseType(bool firstTime, CancellationToken cancellationToken)
        {
            if (firstTime)
            {
                await console.WriteAsync(String.Empty, true, cancellationToken).ConfigureAwait(false);

                await console.WriteAsync(
                    "NOTE: It is HIGHLY reccommended that TGS runs on a complete relational database, specfically *NOT* Sqlite.",
                    true,
                    cancellationToken)
                .ConfigureAwait(false);

                await console.WriteAsync(
                    "Sqlite, by nature cannot perform several DDL operations. Because of this future compatiblility cannot be guaranteed.",
                    true,
                    cancellationToken)
                .ConfigureAwait(false);

                await console.WriteAsync(
                    "This means that you may not be able to update to the next minor version of TGS4 without a clean re-installation!",
                    true,
                    cancellationToken)
                .ConfigureAwait(false);

                await console.WriteAsync(
                    "Please consider taking the time to set up a relational database if this is meant to be a long-standing server.",
                    true,
                    cancellationToken)
                .ConfigureAwait(false);

                await console.WriteAsync(String.Empty, true, cancellationToken).ConfigureAwait(false);

                await asyncDelayer.Delay(TimeSpan.FromSeconds(3), cancellationToken).ConfigureAwait(false);
            }

            await console.WriteAsync("What SQL database type will you be using?", true, cancellationToken).ConfigureAwait(false);

            do
            {
                await console.WriteAsync(
                    String.Format(
                        CultureInfo.InvariantCulture,
                        "Please enter one of {0}, {1}, {2}, {3} or {4}: ",
                        DatabaseType.MariaDB,
                        DatabaseType.MySql,
                        DatabaseType.PostgresSql,
                        DatabaseType.SqlServer,
                        DatabaseType.Sqlite),
                    false,
                    cancellationToken)
                .ConfigureAwait(false);

                var databaseTypeString = await console.ReadLineAsync(false, cancellationToken).ConfigureAwait(false);

                if (Enum.TryParse <DatabaseType>(databaseTypeString, out var databaseType))
                {
                    return(databaseType);
                }

                await console.WriteAsync("Invalid database type!", true, cancellationToken).ConfigureAwait(false);
            }while (true);
        }
Ejemplo n.º 15
0
    public async Task <int> MethodUnderTest()
    {
        await asyncDelayer.Delay(TimeSpan.FromSeconds(2));

        return(5);
    }