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(); } }
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); }
/// <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)); }
// 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); }
/// <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); } }
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); }
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> >()); }
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); } }); }
/// <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); }
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..."); } }
/// <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);
/// <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); }
/// <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); }
public async Task <int> MethodUnderTest() { await asyncDelayer.Delay(TimeSpan.FromSeconds(2)); return(5); }