public void ApplyCommand(IpTablesCommand command) { var chain = Chains.GetChain(command.ChainName, command.Table); switch (command.Type) { case IpTablesCommandType.Add: chain.AddRule(command.Rule); return; case IpTablesCommandType.Delete: chain.DeleteRule(command.Offset); return; case IpTablesCommandType.Replace: chain.ReplaceRule(command.Offset, command.Rule); return; case IpTablesCommandType.Insert: chain.InsertRule(command.Offset, command.Rule); return; } throw new IpTablesNetException("Unknown command"); }
private async Task Listen() { try { while (await _Channel.Reader.WaitToReadAsync(_Cts.Token) && _Channel.Reader.TryRead(out var item)) { if (!_Progress.TryGetValue(item, out var workItem)) { Logs.Explorer.LogError($"{workItem.Network.CryptoCode}: Work has been scheduled for {item}, but the work has not been found in _Progress dictionary. This is likely a bug, contact NBXplorer developers."); continue; } Logs.Explorer.LogInformation($"{workItem.Network.CryptoCode}: Start scanning {workItem.DerivationStrategy.ToPrettyString()} from index {workItem.Options.From} with gap limit {workItem.Options.GapLimit}, batch size {workItem.Options.BatchSize}"); var rpc = RpcClients.GetRPCClient(workItem.Network); var chain = Chains.GetChain(workItem.Network); try { var repo = Repositories.GetRepository(workItem.Network); workItem.State.Progress = new ScanUTXOProgress() { Count = Math.Max(1, Math.Min(workItem.Options.BatchSize, workItem.Options.GapLimit)), From = workItem.Options.From, StartedAt = DateTimeOffset.UtcNow }; foreach (var feature in workItem.Options.DerivationFeatures) { workItem.State.Progress.HighestKeyIndexFound.Add(feature, null); } workItem.State.Progress.UpdateRemainingBatches(workItem.Options.GapLimit); workItem.State.Status = ScanUTXOStatus.Pending; var scannedItems = GetScannedItems(workItem, workItem.State.Progress); var scanning = rpc.StartScanTxoutSetAsync(scannedItems.Descriptors.ToArray()); while (true) { var progress = await rpc.GetStatusScanTxoutSetAsync(); if (progress != null) { workItem.State.Progress.CurrentBatchProgress = (int)Math.Round(progress.Value); workItem.State.Progress.UpdateOverallProgress(); } using (var cts = CancellationTokenSource.CreateLinkedTokenSource(_Cts.Token)) { cts.CancelAfter(TimeSpan.FromSeconds(5.0)); try { var result = await scanning.WithCancellation(cts.Token); var progressObj = workItem.State.Progress.Clone(); progressObj.BatchNumber++; progressObj.From += progressObj.Count; progressObj.Found += result.Outputs.Length; progressObj.TotalSearched += scannedItems.Descriptors.Count; progressObj.UpdateRemainingBatches(workItem.Options.GapLimit); progressObj.UpdateOverallProgress(); Logs.Explorer.LogInformation($"{workItem.Network.CryptoCode}: Scanning of batch {workItem.State.Progress.BatchNumber} for {workItem.DerivationStrategy.ToPrettyString()} complete with {result.Outputs.Length} UTXOs fetched"); await UpdateRepository(workItem.DerivationStrategy, repo, chain, result.Outputs, scannedItems, progressObj); if (progressObj.RemainingBatches <= -1) { progressObj.BatchNumber--; progressObj.From -= progressObj.Count; progressObj.TotalSizeOfUTXOSet = result.SearchedItems; progressObj.CompletedAt = DateTimeOffset.UtcNow; progressObj.RemainingBatches = 0; progressObj.CurrentBatchProgress = 100; progressObj.UpdateRemainingBatches(workItem.Options.GapLimit); progressObj.UpdateOverallProgress(); workItem.State.Progress = progressObj; workItem.State.Status = ScanUTXOStatus.Complete; Logs.Explorer.LogInformation($"{workItem.Network.CryptoCode}: Scanning {workItem.DerivationStrategy.ToPrettyString()} complete {progressObj.Found} UTXOs found in total"); break; } else { scannedItems = GetScannedItems(workItem, progressObj); workItem.State.Progress = progressObj; scanning = rpc.StartScanTxoutSetAsync(scannedItems.Descriptors.ToArray()); } } catch (OperationCanceledException) when(cts.Token.IsCancellationRequested) { } } } } catch (Exception ex) when(!_Cts.IsCancellationRequested) { workItem.State.Status = ScanUTXOStatus.Error; workItem.State.Error = ex.Message; var progress = workItem.State.Progress.Clone(); progress.CompletedAt = DateTimeOffset.UtcNow; workItem.State.Progress = progress; Logs.Explorer.LogError(ex, $"{workItem.Network.CryptoCode}: Error while scanning {workItem.DerivationStrategy.ToPrettyString()}"); } finally { await rpc.AbortScanTxoutSetAsync(); } workItem.Finished = true; } } catch (OperationCanceledException) when(_Cts.IsCancellationRequested) { } }