/// <summary> /// Creates a channel/client pair with the appropriate options and interceptors. /// </summary> /// <returns>A tuple of the channel and client</returns> private async Task <GrpcClient> CreateClientAsync(DnsEndPoint remoteEndpoint) { var certificate = await RetrieveServerCertificateAsync(remoteEndpoint); if (certificate == null) { return(null); } Logger.LogDebug($"Upgrading connection to TLS: {certificate}."); ChannelCredentials credentials = new SslCredentials(TlsHelper.ObjectToPem(certificate), _clientKeyCertificatePair); var channel = new Channel(remoteEndpoint.ToString(), credentials, new List <ChannelOption> { new ChannelOption(ChannelOptions.MaxSendMessageLength, GrpcConstants.DefaultMaxSendMessageLength), new ChannelOption(ChannelOptions.MaxReceiveMessageLength, GrpcConstants.DefaultMaxReceiveMessageLength), new ChannelOption(ChannelOptions.SslTargetNameOverride, GrpcConstants.DefaultTlsCommonName) }); var nodePubkey = AsyncHelper.RunSync(() => _accountService.GetPublicKeyAsync()).ToHex(); var interceptedChannel = channel.Intercept(metadata => { metadata.Add(GrpcConstants.PubkeyMetadataKey, nodePubkey); return(metadata); }).Intercept(new RetryInterceptor()); var client = new PeerService.PeerServiceClient(interceptedChannel); return(new GrpcClient(channel, client, certificate)); }
public GrpcPeer(GrpcClient client, DnsEndPoint remoteEndpoint, PeerConnectionInfo peerConnectionInfo) { _channel = client.Channel; _client = client.Client; RemoteEndpoint = remoteEndpoint; Info = peerConnectionInfo; _knownTransactionCache = new BoundedExpirationCache(TransactionCacheMaxItems, QueuedItemTimeout); _knownBlockCache = new BoundedExpirationCache(BlockCacheMaxItems, QueuedItemTimeout); _recentRequestsRoundtripTimes = new ConcurrentDictionary <string, ConcurrentQueue <RequestMetric> >(); RecentRequestsRoundtripTimes = new ReadOnlyDictionary <string, ConcurrentQueue <RequestMetric> >(_recentRequestsRoundtripTimes); _recentRequestsRoundtripTimes.TryAdd(nameof(MetricNames.Announce), new ConcurrentQueue <RequestMetric>()); _recentRequestsRoundtripTimes.TryAdd(nameof(MetricNames.GetBlock), new ConcurrentQueue <RequestMetric>()); _recentRequestsRoundtripTimes.TryAdd(nameof(MetricNames.GetBlocks), new ConcurrentQueue <RequestMetric>()); _sendAnnouncementJobs = new ActionBlock <StreamJob>(SendStreamJobAsync, new ExecutionDataflowBlockOptions { BoundedCapacity = NetworkConstants.DefaultMaxBufferedAnnouncementCount }); _sendBlockJobs = new ActionBlock <StreamJob>(SendStreamJobAsync, new ExecutionDataflowBlockOptions { BoundedCapacity = NetworkConstants.DefaultMaxBufferedBlockCount }); _sendTransactionJobs = new ActionBlock <StreamJob>(SendStreamJobAsync, new ExecutionDataflowBlockOptions { BoundedCapacity = NetworkConstants.DefaultMaxBufferedTransactionCount }); }
public static GrpcPeer CreateNewPeer(string ipAddress = "127.0.0.1:2000", bool isValid = true, string publicKey = null) { var pubkey = publicKey ?? NetworkTestConstants.FakePubkey; var channel = new Channel(ipAddress, ChannelCredentials.Insecure); PeerService.PeerServiceClient client; if (isValid) { client = new PeerService.PeerServiceClient(channel.Intercept(metadata => { metadata.Add(GrpcConstants.PubkeyMetadataKey, pubkey); return(metadata); })); } else { client = new PeerService.PeerServiceClient(channel); } var connectionInfo = new PeerConnectionInfo { Pubkey = pubkey, ProtocolVersion = KernelConstants.ProtocolVersion, ConnectionTime = TimestampHelper.GetUtcNow(), SessionId = new byte[] { 0, 1, 2 }, IsInbound = true }; var peer = new GrpcPeer(new GrpcClient(channel, client), IpEndPointHelper.Parse(ipAddress), connectionInfo); peer.InboundSessionId = new byte[] { 0, 1, 2 }; return(peer); }
public static GrpcPeer CreatePeerWithClient(string ip, string pubkey, PeerService.PeerServiceClient client) { var peer = new GrpcPeer(new GrpcClient(CreateMockChannel(), client), IpEndPointHelper.Parse(ip), new PeerConnectionInfo { Pubkey = pubkey, SessionId = new byte[] { 0, 1, 2 } }); peer.InboundSessionId = new byte[] { 0, 1, 2 }; return(peer); }
public async Task RemovePeerByAddress() { var channel = new Channel(TestIp, ChannelCredentials.Insecure); var client = new PeerService.PeerServiceClient(channel); _pool.AddPeer(new GrpcPeer(channel, client, _testPubKey, TestIp)); _pool.FindPeerByAddress(TestIp).ShouldNotBeNull(); await _pool.RemovePeerByAddressAsync(TestIp); _pool.FindPeerByAddress(TestIp).ShouldBeNull(); }
public GrpcPeer(Channel channel, PeerService.PeerServiceClient client, string pubKey, string peerIpAddress) { _channel = channel; _client = client; PeerIpAddress = peerIpAddress; PubKey = pubKey; _recentBlockHeightAndHashMappings = new ConcurrentDictionary <long, Hash>(); RecentBlockHeightAndHashMappings = new ReadOnlyDictionary <long, Hash>(_recentBlockHeightAndHashMappings); }
private async Task <TResp> RequestAsync <TResp>(PeerService.PeerServiceClient client, Func <PeerService.PeerServiceClient, AsyncUnaryCall <TResp> > func, string errorMessage) { try { return(await func(client)); } catch (RpcException e) { HandleFailure(e, errorMessage); } return(default(TResp)); }
private GrpcPeer CreateNewPeer() { var pubkey = "048f5ced21f8d687cb9ade1c22dc0e183b05f87124c82073f5d82a09b139cc466efbfb6f28494d0a9d7366fcb769fe5436cfb7b5d322a2b0f69c4bcb1c33ac24ad"; var ipAddress = "127.0.0.1:888"; var remoteEndpoint = IpEndPointHelper.Parse(ipAddress); var channel = new Channel(ipAddress, ChannelCredentials.Insecure); var client = new PeerService.PeerServiceClient(channel); var connectionInfo = new PeerConnectionInfo { Pubkey = pubkey, ProtocolVersion = KernelConstants.ProtocolVersion, ConnectionTime = TimestampHelper.GetUtcNow(), IsInbound = true }; return(new GrpcPeer(new GrpcClient(channel, client), remoteEndpoint, connectionInfo)); }
public GrpcPeer(GrpcClient client, IPEndPoint remoteEndpoint, PeerInfo peerInfo) { _channel = client.Channel; _client = client.Client; RemoteEndpoint = remoteEndpoint; Info = peerInfo; _recentBlockHeightAndHashMappings = new ConcurrentDictionary <long, Hash>(); RecentBlockHeightAndHashMappings = new ReadOnlyDictionary <long, Hash>(_recentBlockHeightAndHashMappings); _recentRequestsRoundtripTimes = new ConcurrentDictionary <string, ConcurrentQueue <RequestMetric> >(); RecentRequestsRoundtripTimes = new ReadOnlyDictionary <string, ConcurrentQueue <RequestMetric> >(_recentRequestsRoundtripTimes); _recentRequestsRoundtripTimes.TryAdd(nameof(MetricNames.Announce), new ConcurrentQueue <RequestMetric>()); _recentRequestsRoundtripTimes.TryAdd(nameof(MetricNames.GetBlock), new ConcurrentQueue <RequestMetric>()); _recentRequestsRoundtripTimes.TryAdd(nameof(MetricNames.GetBlocks), new ConcurrentQueue <RequestMetric>()); }
/// <summary> /// Creates a channel/client pair with the appropriate options and interceptors. /// </summary> /// <returns>A tuple of the channel and client</returns> public GrpcClient CreateClient(IPEndPoint endpoint) { var channel = new Channel(endpoint.ToString(), ChannelCredentials.Insecure, new List <ChannelOption> { new ChannelOption(ChannelOptions.MaxSendMessageLength, GrpcConstants.DefaultMaxSendMessageLength), new ChannelOption(ChannelOptions.MaxReceiveMessageLength, GrpcConstants.DefaultMaxReceiveMessageLength) }); var nodePubkey = AsyncHelper.RunSync(() => _accountService.GetPublicKeyAsync()).ToHex(); var interceptedChannel = channel.Intercept(metadata => { metadata.Add(GrpcConstants.PubkeyMetadataKey, nodePubkey); return(metadata); }).Intercept(new RetryInterceptor()); var client = new PeerService.PeerServiceClient(interceptedChannel); return(new GrpcClient(channel, client)); }
// todo consider removing client from the lambda as it is not used. It can be capture by the func. private async Task <TResp> RequestAsync <TResp>(PeerService.PeerServiceClient client, Func <PeerService.PeerServiceClient, AsyncUnaryCall <TResp> > func, GrpcRequest requestParams) { var metricsName = requestParams.MetricName; bool timeRequest = !string.IsNullOrEmpty(metricsName); var requestStartTime = TimestampHelper.GetUtcNow(); Stopwatch requestTimer = null; if (timeRequest) { requestTimer = Stopwatch.StartNew(); } try { var response = await func(client); if (timeRequest) { requestTimer.Stop(); RecordMetric(requestParams, requestStartTime, requestTimer.ElapsedMilliseconds); } return(response); } catch (AggregateException e) { HandleFailure(e.Flatten(), requestParams.ErrorMessage); } finally { if (timeRequest) { requestTimer.Stop(); RecordMetric(requestParams, requestStartTime, requestTimer.ElapsedMilliseconds); } } return(default(TResp)); }
private GrpcPeer CreateNewPeer(string ipAddress = "127.0.0.1:2000", bool isValid = true) { var channel = new Channel(ipAddress, ChannelCredentials.Insecure); var publicKey = AsyncHelper.RunSync(() => _acc.GetPublicKeyAsync()).ToHex(); PeerService.PeerServiceClient client = null; if (isValid) { client = new PeerService.PeerServiceClient(channel.Intercept(metadata => { metadata.Add(GrpcConsts.PubkeyMetadataKey, publicKey); return(metadata); })); } else { client = new PeerService.PeerServiceClient(channel); } return(new GrpcPeer(channel, client, publicKey, ipAddress)); }
public async Task Calling_DisposedPeer_ThrowsUnrecoverableNEtException() { await _networkServer.StartAsync(); Channel channel = new Channel("localhost", 2001, ChannelCredentials.Insecure); PeerService.PeerServiceClient peerClient = new PeerService.PeerServiceClient(channel); GrpcClient grpcClient = new GrpcClient(channel, peerClient); AElfPeerEndpointHelper.TryParse("127.0.0.1:2001", out var endpoint); GrpcPeer peer = new GrpcPeer(grpcClient, endpoint, new PeerConnectionInfo { SessionId = new byte[] { 1, 2, 3 } }); await peer.DisconnectAsync(false); var exHealthCheck = await Assert.ThrowsAsync <NetworkException>(async() => await peer.CheckHealthAsync()); exHealthCheck.ExceptionType.ShouldBe(NetworkExceptionType.Unrecoverable); var exGetBlocks = await Assert.ThrowsAsync <NetworkException>( async() => await peer.GetBlocksAsync(Hash.FromString("blockHash"), 10)); exGetBlocks.ExceptionType.ShouldBe(NetworkExceptionType.Unrecoverable); var exGetBlock = await Assert.ThrowsAsync <NetworkException>( async() => await peer.GetBlockByHashAsync(Hash.FromString("blockHash"))); exGetBlock.ExceptionType.ShouldBe(NetworkExceptionType.Unrecoverable); var exGetNodes = await Assert.ThrowsAsync <NetworkException>( async() => await peer.GetNodesAsync()); exGetNodes.ExceptionType.ShouldBe(NetworkExceptionType.Unrecoverable); await _networkServer.StopAsync(); }
public GrpcClient(Channel channel, PeerService.PeerServiceClient client) { Channel = channel; Client = client; }
public static GrpcPeer CreatePeerWithClient(string ip, string pubkey, PeerService.PeerServiceClient client) { return(new GrpcPeer(new GrpcClient(CreateMockChannel(), client), IpEndpointHelper.Parse(ip), new PeerInfo { Pubkey = pubkey })); }
public GrpcClient(Channel channel, PeerService.PeerServiceClient client, X509Certificate certificate = null) { Channel = channel; Client = client; Certificate = certificate; }
/// <summary> /// First step of the connect/auth process. Used to initiate a connection. The provided payload should be the /// clients authentication information. When receiving this call, protocol dictates you send the client your auth /// information. The response says whether or not you can connect. /// </summary> public override async Task <ConnectReply> Connect(Handshake handshake, ServerCallContext context) { Logger.LogTrace($"{context.Peer} has initiated a connection request."); if (handshake?.HskData == null) { return new ConnectReply { Err = AuthError.InvalidHandshake } } ; // verify chain id if (handshake.HskData.ChainId != _blockChainService.GetChainId()) { return new ConnectReply { Err = AuthError.ChainMismatch } } ; // verify protocol if (handshake.HskData.Version != KernelConstants.ProtocolVersion) { return new ConnectReply { Err = AuthError.ProtocolMismatch } } ; // verify signature var validData = await _accountService.VerifySignatureAsync(handshake.Sig.ToByteArray(), Hash.FromMessage(handshake.HskData).ToByteArray(), handshake.HskData.PublicKey.ToByteArray()); if (!validData) { return new ConnectReply { Err = AuthError.WrongSig } } ; var peer = GrpcUrl.Parse(context.Peer); if (peer == null) { return new ConnectReply { Err = AuthError.InvalidPeer } } ; var peerAddress = peer.IpAddress + ":" + handshake.HskData.ListeningPort; Logger.LogDebug($"Attempting to create channel to {peerAddress}"); Channel channel = new Channel(peerAddress, ChannelCredentials.Insecure); var client = new PeerService.PeerServiceClient(channel.Intercept(metadata => { metadata.Add(GrpcConsts.PubkeyMetadataKey, AsyncHelper.RunSync(() => _accountService.GetPublicKeyAsync()).ToHex()); return(metadata); })); if (channel.State != ChannelState.Ready) { var c = channel.WaitForStateChangedAsync(channel.State); } var pubKey = handshake.HskData.PublicKey.ToHex(); var grpcPeer = new GrpcPeer(channel, client, pubKey, peerAddress); // Verify auth bool valid = _peerPool.IsAuthenticatePeer(pubKey); if (!valid) { await channel.ShutdownAsync(); Logger.LogDebug($"Failed to reach {grpcPeer}"); return(new ConnectReply { Err = AuthError.WrongAuth }); } // send our credentials var hsk = await _peerPool.GetHandshakeAsync(); // If auth ok -> add it to our peers _peerPool.AddPeer(grpcPeer); return(new ConnectReply { Handshake = hsk }); }
public RemotePeer(string host, int port) { var peerConnection = new grpc.Channel(host, port, grpc.ChannelCredentials.Insecure); client = new PeerService.PeerServiceClient(peerConnection); }
private async Task <bool> DialAsync(string ipAddress) { Logger.LogTrace($"Attempting to reach {ipAddress}."); Channel channel = new Channel(ipAddress, ChannelCredentials.Insecure); var client = new PeerService.PeerServiceClient(channel.Intercept(metadata => { metadata.Add(GrpcConsts.PubkeyMetadataKey, AsyncHelper.RunSync(() => _accountService.GetPublicKeyAsync()).ToHex()); return(metadata); })); var hsk = await BuildHandshakeAsync(); if (channel.State == ChannelState.TransientFailure) { // if failing give it some time to recover await channel.TryWaitForStateChangedAsync(channel.State, DateTime.UtcNow.AddSeconds(_networkOptions.PeerDialTimeout)); } ConnectReply connectReply; try { connectReply = await client.ConnectAsync(hsk, new CallOptions().WithDeadline(DateTime.UtcNow.AddSeconds(_networkOptions.PeerDialTimeout))); } catch (RpcException e) { await channel.ShutdownAsync(); Logger.LogError(e, $"Could not connect to {ipAddress}."); return(false); } // todo refactor so that connect returns the handshake and we'll check here // todo if not correct we kill the channel. if (connectReply?.Handshake?.HskData == null || connectReply.Err != AuthError.None) { Logger.LogWarning($"Incorrect handshake for {ipAddress}, {connectReply?.Err}."); await channel.ShutdownAsync(); return(false); } var pubKey = connectReply.Handshake.HskData.PublicKey.ToHex(); var peer = new GrpcPeer(channel, client, pubKey, ipAddress); if (!_authenticatedPeers.TryAdd(pubKey, peer)) { Logger.LogWarning($"Peer {pubKey} is already in list."); await channel.ShutdownAsync(); return(false); } peer.DisconnectionEvent += PeerOnDisconnectionEvent; Logger.LogTrace($"Connected to {peer}."); return(true); }
private GrpcPeer CreatePeer(PeerService.PeerServiceClient client) { return(GrpcTestPeerHelper.CreatePeerWithClient("127.0.0.1:2000", NetworkTestConstants.FakePubkey, client)); }