private static async Task RebuildConnectionAsync( KademliaProtocol protocol, CancellationToken cancellationToken) { while (!cancellationToken.IsCancellationRequested) { try { await Task.Delay(TimeSpan.FromMinutes(10), cancellationToken); await protocol.RebuildConnectionAsync(Kademlia.MaxDepth, cancellationToken); } catch (OperationCanceledException e) { Log.Warning(e, $"{nameof(RebuildConnectionAsync)}() is cancelled."); throw; } catch (Exception e) { var msg = "Unexpected exception occurred during " + $"{nameof(RebuildConnectionAsync)}(): {{0}}"; Log.Warning(e, msg, e); } } }
public TestTransport( Dictionary <Address, TestTransport> transports, PrivateKey privateKey, int?tableSize, int?bucketSize, TimeSpan?networkDelay) { _privateKey = privateKey; var loggerId = _privateKey.PublicKey.ToAddress().ToHex(); _logger = Log.ForContext <TestTransport>() .ForContext("Address", loggerId); _peersToReply = new ConcurrentDictionary <byte[], Address>(); _replyToReceive = new ConcurrentDictionary <byte[], Message>(); ReceivedMessages = new ConcurrentBag <Message>(); MessageReceived = new AsyncAutoResetEvent(); _transports = transports; _transports[privateKey.PublicKey.ToAddress()] = this; _networkDelay = networkDelay ?? TimeSpan.Zero; _requests = new AsyncCollection <Request>(); _ignoreTestMessageWithData = new List <string>(); _random = new Random(); Protocol = new KademliaProtocol(this, Address, 0, _logger, tableSize, bucketSize); }
private static async Task RefreshTableAsync( KademliaProtocol protocol, CancellationToken cancellationToken) { while (!cancellationToken.IsCancellationRequested) { try { await Task.Delay(TimeSpan.FromSeconds(10), cancellationToken); await protocol.RefreshTableAsync(TimeSpan.FromSeconds(60), cancellationToken); await protocol.CheckReplacementCacheAsync(cancellationToken); } catch (OperationCanceledException e) { Log.Warning(e, $"{nameof(RefreshTableAsync)}() is cancelled."); throw; } catch (Exception e) { var msg = "Unexpected exception occurred during " + $"{nameof(RefreshTableAsync)}(): {{0}}"; Log.Warning(e, msg, e); } } }
public TestTransport( Dictionary <Address, TestTransport> transports, PrivateKey privateKey, bool blockBroadcast, int tableSize, int bucketSize, TimeSpan?networkDelay) { _runningEvent = new TaskCompletionSource <object>(); _privateKey = privateKey; _blockBroadcast = blockBroadcast; var loggerId = _privateKey.ToAddress().ToHex(); _logger = Log.ForContext <TestTransport>() .ForContext("Address", loggerId); _peersToReply = new ConcurrentDictionary <byte[], Address>(); _replyToReceive = new ConcurrentDictionary <byte[], Message>(); ReceivedMessages = new ConcurrentBag <Message>(); MessageReceived = new AsyncAutoResetEvent(); _transports = transports; _transports[privateKey.ToAddress()] = this; _networkDelay = networkDelay ?? TimeSpan.Zero; _requests = new AsyncCollection <Request>(); _ignoreTestMessageWithData = new List <string>(); _random = new Random(); Table = new RoutingTable(Address, tableSize, bucketSize); ProcessMessageHandler = new AsyncDelegate <Message>(); Protocol = new KademliaProtocol(Table, this, Address); MessageHistory = new FixedSizedQueue <Message>(30); }
private static async Task CheckStaticPeersAsync( IEnumerable <BoundPeer> peers, RoutingTable table, KademliaProtocol protocol, CancellationToken cancellationToken) { var boundPeers = peers as BoundPeer[] ?? peers.ToArray(); while (!cancellationToken.IsCancellationRequested) { try { await Task.Delay(TimeSpan.FromMinutes(1), cancellationToken); Log.Warning("Checking static peers. {@Peers}", boundPeers); var peersToAdd = boundPeers.Where(peer => !table.Contains(peer)).ToArray(); if (peersToAdd.Any()) { Log.Warning("Some of peers are not in routing table. {@Peers}", peersToAdd); await protocol.AddPeersAsync( peersToAdd, TimeSpan.FromSeconds(5), cancellationToken); } } catch (OperationCanceledException e) { Log.Warning(e, $"{nameof(CheckStaticPeersAsync)}() is cancelled."); throw; } catch (Exception e) { var msg = "Unexpected exception occurred during " + $"{nameof(CheckStaticPeersAsync)}(): {{0}}"; Log.Warning(e, msg, e); } } }
#pragma warning disable MEN003 // Method Main must be no longer than 120 lines public static async Task Main(string[] args) { Options options = Options.Parse(args, Console.Error); var loggerConfig = new LoggerConfiguration(); switch (options.LogLevel) { case "error": loggerConfig = loggerConfig.MinimumLevel.Error(); break; case "warning": loggerConfig = loggerConfig.MinimumLevel.Warning(); break; case "information": loggerConfig = loggerConfig.MinimumLevel.Information(); break; case "debug": loggerConfig = loggerConfig.MinimumLevel.Debug(); break; case "verbose": loggerConfig = loggerConfig.MinimumLevel.Verbose(); break; default: loggerConfig = loggerConfig.MinimumLevel.Information(); break; } loggerConfig = loggerConfig .MinimumLevel.Override("Microsoft", LogEventLevel.Information) .Enrich.FromLogContext() .WriteTo.Console(); Log.Logger = loggerConfig.CreateLogger(); if (options.IceServer is null && options.Host is null) { Log.Error( "-h/--host is required if -I/--ice-server is not given." ); Environment.Exit(1); return; } if (!(options.IceServer is null || options.Host is null)) { Log.Warning("-I/--ice-server will not work because -h/--host is given."); } try { var privateKey = options.PrivateKey ?? new PrivateKey(); RoutingTable table = new RoutingTable(privateKey.ToAddress()); ITransport transport; switch (options.TransportType) { case "tcp": transport = new TcpTransport( privateKey, AppProtocolVersion.FromToken(options.AppProtocolVersionToken), null, host: options.Host, listenPort: options.Port, iceServers: new[] { options.IceServer }, differentAppProtocolVersionEncountered: null); break; case "netmq": transport = new NetMQTransport( privateKey, AppProtocolVersion.FromToken(options.AppProtocolVersionToken), null, workers: options.Workers, host: options.Host, listenPort: options.Port, iceServers: new[] { options.IceServer }, differentAppProtocolVersionEncountered: null); break; default: Log.Error( "-t/--transport-type must be either \"tcp\" or \"netmq\"."); Environment.Exit(1); return; } KademliaProtocol peerDiscovery = new KademliaProtocol( table, transport, privateKey.ToAddress()); Startup.TableSingleton = table; IWebHost webHost = WebHost.CreateDefaultBuilder() .UseStartup <SeedStartup <Startup> >() .UseSerilog() .UseUrls($"http://{options.GraphQLHost}:{options.GraphQLPort}/") .Build(); using (var cts = new CancellationTokenSource()) { Console.CancelKeyPress += (sender, eventArgs) => { eventArgs.Cancel = true; cts.Cancel(); }; try { var tasks = new List <Task> { webHost.RunAsync(cts.Token), StartTransportAsync(transport, cts.Token), RefreshTableAsync(peerDiscovery, cts.Token), RebuildConnectionAsync(peerDiscovery, cts.Token), }; if (!(options.Peers is null) && options.Peers.Any()) { tasks.Add(CheckStaticPeersAsync( options.Peers, table, peerDiscovery, cts.Token)); } await Task.WhenAll(tasks); } catch (OperationCanceledException) { await transport.StopAsync(TimeSpan.FromSeconds(1)); } } } catch (InvalidOptionValueException e) { string expectedValues = string.Join(", ", e.ExpectedValues); Console.Error.WriteLine($"Unexpected value given through '{e.OptionName}'\n" + $" given value: {e.OptionValue}\n" + $" expected values: {expectedValues}"); } }
public static async Task Main(string[] args) { Options options = Options.Parse(args, Console.Error); var loggerConfig = new LoggerConfiguration(); loggerConfig = options.Debug ? loggerConfig.MinimumLevel.Debug() : loggerConfig.MinimumLevel.Information(); loggerConfig = loggerConfig .MinimumLevel.Override("Microsoft", LogEventLevel.Information) .Enrich.FromLogContext() .WriteTo.Console(); Log.Logger = loggerConfig.CreateLogger(); try { var privateKey = options.PrivateKey ?? new PrivateKey(); RoutingTable table = new RoutingTable(privateKey.ToAddress()); NetMQTransport transport = new NetMQTransport( table, privateKey, AppProtocolVersion.FromToken(options.AppProtocolVersionToken), null, options.Workers, options.Host, options.Port, new[] { options.IceServer }, null); KademliaProtocol peerDiscovery = new KademliaProtocol( table, transport, privateKey.ToAddress()); Startup.TableSingleton = table; IWebHost webHost = WebHost.CreateDefaultBuilder() .UseStartup <SeedStartup <Startup> >() .UseSerilog() .UseUrls($"http://{options.GraphQLHost}:{options.GraphQLPort}/") .Build(); using (var cts = new CancellationTokenSource()) { Console.CancelKeyPress += (sender, eventArgs) => { eventArgs.Cancel = true; cts.Cancel(); }; try { var tasks = new List <Task> { webHost.RunAsync(cts.Token), StartTransportAsync(transport, cts.Token), RefreshTableAsync(peerDiscovery, cts.Token), RebuildConnectionAsync(peerDiscovery, cts.Token), }; if (!(options.Peers is null) && options.Peers.Any()) { tasks.Add(CheckStaticPeersAsync( options.Peers, table, peerDiscovery, cts.Token)); } await Task.WhenAll(tasks); } catch (OperationCanceledException) { await transport.StopAsync(TimeSpan.FromSeconds(1)); } } } catch (InvalidOptionValueException e) { string expectedValues = string.Join(", ", e.ExpectedValues); Console.Error.WriteLine($"Unexpected value given through '{e.OptionName}'\n" + $" given value: {e.OptionValue}\n" + $" expected values: {expectedValues}"); } }