public async ValueTask AttachAsync(IPeerContext peerContext) { PeerContext = peerContext as ExamplePeerContext ?? throw new ArgumentException("Expected ExamplePeerContext", nameof(peerContext)); _messageWriter = PeerContext.GetMessageWriter(); await OnPeerAttachedAsync().ConfigureAwait(false); }
public PrepareExtensionProtocolHandshakeContext(BDictionary handshakeContent, IPeerContext peerContext, Action <IExtensionProtocolMessage> sendMessage) : base(peerContext, sendMessage) { HandshakeContent = handshakeContent; }
/// <summary> /// Check if the client is allowed to connect based on certain criteria. /// </summary> /// <returns>When criteria is met returns <c>true</c>, to allow connection.</returns> private bool EnsurePeerCanConnect(ConnectionContext connection, IPeerContext peerContext) { if (_serverPeerConnectionGuards == null) { return(false); } ServerPeerConnectionGuardResult?result = ( from guard in _serverPeerConnectionGuards let guardResult = guard.Check(peerContext) where guardResult.IsDenied select guardResult ) .DefaultIfEmpty(ServerPeerConnectionGuardResult.Success) .FirstOrDefault(); if (result == null) { return(true); // no guards } if (result.IsDenied) { _logger.LogDebug("Connection from client '{ConnectingPeerEndPoint}' was rejected because of {ClientDisconnectedReason} and will be closed.", connection.RemoteEndPoint, result.DenyReason); connection.Abort(new ConnectionAbortedException(result.DenyReason)); _eventBus.Publish(new PeerConnectionRejected(peerContext, result.DenyReason)); return(false); } return(true); }
public void SetPeerContext(IPeerContext peerContext) { _networkPeerContext = peerContext as NetworkPeerContext ?? throw new ArgumentException("Expected NetworkPeerContext", nameof(peerContext));; _deserializationContext.SetInitiator(_networkPeerContext.Direction == PeerConnectionDirection.Outbound); LightningEndpoint?lightningEndpoint = null; if (peerContext.Direction == PeerConnectionDirection.Outbound) { OutgoingConnectionEndPoint endpoint = peerContext.Features.Get <OutgoingConnectionEndPoint>(); if (endpoint == null || !endpoint.Items.TryGetValue(nameof(LightningEndpoint), out object?res)) { _logger.LogError("Remote connection was not found "); throw new ApplicationException("Initiator connection must have a public key of the remote node"); } if (res == null) { _logger.LogError("Remote connection type is invalid"); throw new ApplicationException("Remote connection type is invalid"); } lightningEndpoint = (LightningEndpoint)res; } _handshakeProtocol = new HandshakeWithNoiseProtocol(_nodeContext, lightningEndpoint?.NodePubKey, _handshakeProcessor); _networkPeerContext.SetHandshakeProtocol(_handshakeProtocol); }
public ExtensionProtocolMessageReceivedContext(IExtensionProtocolMessage message, IPeerContext peerContext, Action <IExtensionProtocolMessage> sendMessage) : base(peerContext, sendMessage) { Message = message; }
public virtual IPeerContext CreateOutgoingPeerContext(string peerId, EndPoint localEndPoint, OutgoingConnectionEndPoint outgoingConnectionEndPoint, INetworkMessageWriter messageWriter) { IPeerContext peerContext = Create(PeerConnectionDirection.Outbound, peerId, localEndPoint, outgoingConnectionEndPoint.EndPoint, messageWriter); peerContext.Features.Set(outgoingConnectionEndPoint); return(peerContext); }
public override async Task OnConnectedAsync(ConnectionContext connection) { if (connection is null) { throw new ArgumentNullException(nameof(connection)); } using IDisposable loggerScope = _logger.BeginScope("Peer {PeerId} connected to server {ServerEndpoint}", connection.ConnectionId, connection.LocalEndPoint); ProtocolReader reader = connection.CreateReader(); INetworkProtocolMessageSerializer protocol = _serviceProvider.GetRequiredService <INetworkProtocolMessageSerializer>(); using IPeerContext peerContext = _peerContextFactory.CreateIncomingPeerContext(connection.ConnectionId, connection.LocalEndPoint !.AsIPEndPoint().EnsureIPv6(), connection.RemoteEndPoint !.AsIPEndPoint().EnsureIPv6(), new NetworkMessageWriter(protocol, connection.CreateWriter())); using CancellationTokenRegistration cancellationRegistration = peerContext.ConnectionCancellationTokenSource.Token.Register(() => { connection.Abort(new ConnectionAbortedException("Requested by PeerContext")); }); connection.Features.Set(peerContext); protocol.SetPeerContext(peerContext); if (EnsurePeerCanConnect(connection, peerContext)) { _eventBus.Publish(new PeerConnected(peerContext)); await _networkMessageProcessorFactory.StartProcessorsAsync(peerContext).ConfigureAwait(false); while (true) { try { ProtocolReadResult <INetworkMessage> result = await reader.ReadAsync(protocol).ConfigureAwait(false); if (result.IsCompleted) { break; } await ProcessMessageAsync(result.Message, peerContext, connection.ConnectionClosed).ConfigureAwait(false); } catch (Exception ex) { _logger.LogDebug(ex, "Unexpected connection terminated because of {DisconnectionReason}.", ex.Message); break; } finally { reader.Advance(); } } return; } }
internal override string?TryGetDenyReason(IPeerContext peerContext) { if (_peerAddressBook.IsBanned(peerContext)) { return("Inbound connection refused: peer is banned."); } return(null); }
public void OnPeerConnected(IPeerContext context) { foreach (var messageId in MessageIds) { context.RegisterMessageHandler(messageId); } context.Peer.SendMessage(new BitfieldMessage(new Bitfield(context.Metainfo.Pieces.Count, context.DataHandler.CompletedPieces))); }
internal override string?TryGetDenyReason(IPeerContext peerContext) { if (!settings.AllowLoopbackConnection && IPAddress.IsLoopback(peerContext.RemoteEndPoint.Address)) { return($"Loopback peer connection not allowed (set {nameof(settings.AllowLoopbackConnection)} to true to allow such kind of connections)."); } return(null); }
internal override string TryGetDenyReason(IPeerContext peerContext) { if (this.serverPeerStats.ConnectedInboundPeersCount >= this.settings.MaxInboundConnections) { return("Inbound connection refused: max connection threshold reached."); } return(null); }
public BitcoinNetworkProtocolMessageSerializer(ILogger <BitcoinNetworkProtocolMessageSerializer> logger, INetworkDefinition chainDefinition, INetworkMessageSerializerManager networkMessageSerializerManager) { _logger = logger; _chainDefinition = chainDefinition; _networkMessageSerializerManager = networkMessageSerializerManager; _deserializationContext = new DeserializationContext(chainDefinition.MagicBytes); _peerContext = null !; //initialized by SetPeerContext }
public void Serialize(INetworkMessage message, int protocolVersion, IPeerContext peerContext, IBufferWriter <byte> output) { if (message is null) { throw new ArgumentNullException(nameof(message)); } Serialize((TMessageType)message, protocolVersion, (TPeerContext)peerContext, output); }
private void SendMessage(IPeerContext peerContext, Action <BinaryWriter> constructMessage) { using (var ms = new MemoryStream()) { BinaryWriter writer = new BigEndianBinaryWriter(ms); constructMessage(writer); writer.Flush(); peerContext.SendMessage(ExtensionProtocolMessageId, ms.ToArray()); } }
internal override string?TryGetDenyReason(IPeerContext peerContext) { //TODO implement ban check, bitcoin core ref: https://github.com/bitcoin/bitcoin/blob/e8e79958a7b2a0bf1b02adcce9f4d811eac37dfc/src/net.cpp#L984-L993 //if (peer is banned) //{ // return "Current peer is banned."; //} return(null); }
public bool TrySerialize(INetworkMessage message, int protocolVersion, IPeerContext peerContext, IBufferWriter <byte> output) { if (_serializers.TryGetValue(message.Command, out INetworkMessageSerializer? serializer)) { serializer.Serialize(message, protocolVersion, peerContext, output); return(true); } return(false); }
public void SetPeerContext(IPeerContext peerContext) { // we know it's an ExamplePeerContext in our example. _peerContext = (ExamplePeerContext)peerContext; if (_peerContext.MyExtraInformation != null) { _logger.LogDebug("I'm ExampleNetworkProtocolMessageSerializer and I know that I've some information for you: {AdditionalInformation}", _peerContext.MyExtraInformation); } }
private async Task ProcessMessageAsync(INetworkMessage message, IPeerContext peerContext, CancellationToken cancellation) { using IDisposable logScope = _logger.BeginScope("Processing message '{Command}'", message.Command); if (!(message is UnknownMessage)) { await _networkMessageProcessorFactory.ProcessMessageAsync(message, peerContext, cancellation).ConfigureAwait(false); _eventBus.Publish(new PeerMessageReceived(peerContext, message)); } }
public int GetScore(IPeerContext peerContext) { if (!_connectedPeers.TryGetValue(peerContext.PeerId, out PeerScore? score)) { _logger.LogWarning("Peer {PeerId} not found, returning neutral score.", peerContext.PeerId); return(0); } else { return(score.Score); } }
public void AddBonus(IPeerContext peerContext, uint bonus, string reason) { if (!_connectedPeers.TryGetValue(peerContext.PeerId, out PeerScore? score)) { _logger.LogWarning("Cannot attribute positive points to the peer {PeerId} because the peer isn't connected.", peerContext.PeerId); } else { _logger.LogDebug("Peer {PeerId} got a bonus {PeerBonus}: {MisbehaveReason}.", peerContext.PeerId, bonus, reason); score.UpdateScore((int)bonus); } }
public ServerPeerConnectionGuardResult Check(IPeerContext peerContext) { string denyReason = this.TryGetDenyReason(peerContext); if (!string.IsNullOrEmpty(denyReason)) { this.logger.LogDebug("Peer connection guard not passed: {denyReason}", denyReason); return(ServerPeerConnectionGuardResult.Deny(denyReason)); } return(ServerPeerConnectionGuardResult.Allow()); }
internal override string?TryGetDenyReason(IPeerContext peerContext) { if (_peerStats.ConnectedInboundPeersCount >= settings.MaxInboundConnections) { /// TODO: try to evict eventual bad connection to let a space for this connection /// ref: https://github.com/bitcoin/bitcoin/blob/e8e79958a7b2a0bf1b02adcce9f4d811eac37dfc/src/net.cpp#L995-L1003 /// I'd consider another approach: accept a connection that exceed the maximum allowed connection, try to handshake /// and if successful then decide either if evict one connect and keep this, or drop the connection attempt return("Inbound connection refused: max connection threshold reached."); } return(null); }
private void SendExtensionMessage(IPeerContext peerContext, IExtensionProtocolMessage message) { var peerMessageIds = peerContext.GetValue <Dictionary <string, byte> >(ExtensionProtocolMessageIds); if (!peerMessageIds.TryGetValue(message.MessageType, out byte messageType)) { throw new InvalidOperationException($"Peer does not support message type {message.MessageType}"); } SendMessage(peerContext, writer => { writer.Write(messageType); writer.Write(message.Serialize()); }); }
internal override string?TryGetDenyReason(IPeerContext peerContext) { if (_initialBlockDownloadState.IsDownloadingBlocks()) { bool clientIsWhiteListed = settings.Listeners .Any(binding => binding.IsWhitelistingEndpoint && binding.Matches(peerContext.LocalEndPoint)); if (!clientIsWhiteListed) { return("Node is in IBD and the peer is not white-listed."); } } return(null); }
void IModule.OnPeerConnected(IPeerContext context) { // Check for extension protocol support bool supportsExtensionProtocol = (context.Peer.ReservedBytes[5] & 0x10) != 0; if (!supportsExtensionProtocol) { return; } // Register to receive extension protocol messages context.RegisterMessageHandler(ExtensionProtocolMessageId); // Send handshake message var handshake = new ExtensionProtocolHandshake { MessageIds = _supportedMessages, Client = "TorrentCore 0.1", // todo }; var handshakeDict = handshake.Serialize(); var prepareHandshakeContext = new PrepareExtensionProtocolHandshakeContext( handshakeDict, context, msg => SendExtensionMessage(context, msg)); foreach (var handler in _registeredHandlers) { handler.PrepareExtensionProtocolHandshake(prepareHandshakeContext); } SendMessage(context, writer => { writer.Write((byte)0); writer.Flush(); handshakeDict.EncodeTo(writer.BaseStream); }); }
/// <summary> /// Attaches known processors to specified peer. /// </summary> /// <param name="peerContext">The peer context.</param> public async Task StartProcessorsAsync(IPeerContext peerContext) { if (peerContext is null) { ThrowHelper.ThrowArgumentNullException(nameof(peerContext)); } IEnumerable <INetworkMessageProcessor> processors = _serviceProvider.GetService <IEnumerable <INetworkMessageProcessor> >() !; foreach (INetworkMessageProcessor processor in processors) { // skip processors that aren't enabled if (!processor.Enabled) { continue; } peerContext.AttachNetworkMessageProcessor(processor); await processor.AttachAsync(peerContext).ConfigureAwait(false); } peerContext.Features.Set(new PeerNetworkMessageProcessorContainer(_serviceProvider.GetRequiredService <ILogger <PeerNetworkMessageProcessorContainer> >(), processors)); }
public void Misbehave(IPeerContext peerContext, uint penality, string reason) { if (penality == 0) { return; } if (!_connectedPeers.TryGetValue(peerContext.PeerId, out PeerScore? score)) { _logger.LogWarning("Cannot attribute bad behavior to the peer {PeerId} because the peer isn't connected.", peerContext.PeerId); // did we have to add it to banned peers anyway? return; } _logger.LogDebug("Peer {PeerId} misbehave: {MisbehaveReason}.", peerContext.PeerId, reason); int currentResult = score.UpdateScore(-(int)penality); if (currentResult < _connectivitySettings.BanScore) { //if threshold of bad behavior has been exceeded, this peer need to be banned _logger.LogDebug("Peer {RemoteEndPoint} BAN threshold exceeded.", peerContext.RemoteEndPoint); _peerAddressBook.Ban(peerContext, DateTimeOffset.UtcNow + TimeSpan.FromSeconds(_connectivitySettings.MisbehavingBanTime), "Peer Misbehaving"); } }
public async ValueTask ProcessMessageAsync(INetworkMessage message, IPeerContext peerContext, CancellationToken cancellation) { await peerContext.Features.Get <PeerNetworkMessageProcessorContainer>().ProcessMessageAsync(message, cancellation).ConfigureAwait(false); }
internal void SetPeerContext(IPeerContext peerContext) { this.peerContext = peerContext; }
internal override void Completed(MediatorContext mediatorContext, IClientContext clientContext, IPeerContext peerContext, OperationCompletedEventArgs oce) { ClientConst.OperationResult operationResult = oce.Result; if (operationResult == ClientConst.OperationResult.Successful) { Logger.GetLog().Info("接続を維持しています(接続数: " + peerContext.Connections + ")。"); mediatorContext.State = new ConnectedState(); } else if (operationResult == ClientConst.OperationResult.Restartable) { Logger.GetLog().Info("IPアドレスが変化しているため、再接続します。"); peerContext.DisconnectAll(); Logger.GetLog().Info("ピア接続をすべて切断しました(接続数: " + peerContext.Connections + ")"); mediatorContext.State = new DisconnectedState(); bool result = mediatorContext.Connect(); if (!result) { mediatorContext.State = new ConnectedState(); } } else if (operationResult == ClientConst.OperationResult.Retryable) { // FIXME: 暫定。本当はすぐに再試行したい Logger.GetLog().Info("接続維持に失敗しました。再試行可能なエラーです。"); mediatorContext.State = new ConnectedState(); } else { throw new NotSupportedException(); } }