Exemple #1
0
        public void HandleHello(HelloMessage hello)
        {
            Logger.Info($"{P2PSession.RemoteNodeId} P2P received hello.");
            if (!hello.NodeId.Equals(P2PSession.RemoteNodeId))
            {
                throw new NodeDetailsMismatchException();
            }

            //P2PSession.RemoteNodeId = hello.NodeId;
            //P2PSession.RemotePort = hello.ListenPort;
            RemoteClientId = hello.ClientId;

            Logger.Info(!_sentHello
                ? $"{P2PSession.RemoteNodeId} P2P initiating inbound {hello.Protocol} v{hello.P2PVersion} protocolHandler on {hello.ListenPort} ({hello.ClientId})"
                : $"{P2PSession.RemoteNodeId} P2P initiating outbound {hello.Protocol} v{hello.P2PVersion} protocolHandler on {hello.ListenPort} ({hello.ClientId})");

            // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-8.md
            // Clients implementing a newer version simply send a packet with higher version and possibly additional list elements.
            // * If such a packet is received by a node with lower version, it will blindly assume that the remote end is backwards-compatible and respond with the old handshake.
            // * If the packet is received by a node with equal version, new features of the protocol can be used.
            // * If the packet is received by a node with higher version, it can enable backwards-compatibility logic or drop the connection.

            //Moved that validation to PeerManager
            //if (hello.P2PVersion < 4 || hello.P2PVersion > 5)
            //{
            //    //triggers disconnect on the session, which will trigger it on all protocol handlers
            //    P2PSession.InitiateDisconnectAsync(DisconnectReason.IncompatibleP2PVersion);
            //    //Disconnect(DisconnectReason.IncompatibleP2PVersion);
            //    return;
            //}

            ProtocolVersion = hello.P2PVersion;

            //TODO Check required capabilities and disconnect if not supported

            foreach (Capability remotePeerCapability in hello.Capabilities)
            {
                if (SupportedCapabilities.Contains(remotePeerCapability))
                {
                    Logger.Info($"{P2PSession.RemoteNodeId} Agreed on {remotePeerCapability.ProtocolCode} v{remotePeerCapability.Version}");
                    AgreedCapabilities.Add(remotePeerCapability);
                }
                else
                {
                    Logger.Info($"{P2PSession.RemoteNodeId} Capability not supported {remotePeerCapability.ProtocolCode} v{remotePeerCapability.Version}");
                }
            }

            //if (!_sentHello)
            //{
            //    throw new InvalidOperationException($"Handling {nameof(HelloMessage)} from peer before sending our own");
            //}
            _isInitialized = true;
            ReceivedProtocolInitMsg(hello);

            var eventArgs = new P2PProtocolInitializedEventArgs(this)
            {
                P2PVersion   = hello.P2PVersion,
                ClientId     = hello.ClientId,
                Capabilities = hello.Capabilities
            };

            ProtocolInitialized?.Invoke(this, eventArgs);
        }
        private void HandleHello(HelloMessage hello)
        {
            ReportIn(hello);
            bool isInbound = !_sentHello;

            if (Logger.IsTrace)
            {
                Logger.Trace($"{Session} P2P received hello.");
            }

            if (!hello.NodeId.Equals(Session.RemoteNodeId))
            {
                if (Logger.IsDebug)
                {
                    Logger.Debug($"Inconsistent Node ID details - expected {Session.RemoteNodeId}, " +
                                 $"received hello with {hello.NodeId} " +
                                 $"on {(isInbound ? "IN connection" : "OUT connection")}");
                }
                // it does not really matter if there is mismatch - we do not use it anywhere
//                throw new NodeDetailsMismatchException();
            }

            RemoteClientId        = hello.ClientId;
            Session.Node.ClientId = hello.ClientId;

            if (Logger.IsTrace)
            {
                Logger.Trace(!_sentHello
                ? $"{Session.RemoteNodeId} P2P initiating inbound {hello.Protocol}.{hello.P2PVersion} " +
                             $"on {hello.ListenPort} ({hello.ClientId})"
                : $"{Session.RemoteNodeId} P2P initiating outbound {hello.Protocol}.{hello.P2PVersion} " +
                             $"on {hello.ListenPort} ({hello.ClientId})");
            }

            // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-8.md
            // Clients implementing a newer version simply send a packet with higher version and possibly additional list elements.
            // * If such a packet is received by a node with lower version,
            //   it will blindly assume that the remote end is backwards-compatible and respond with the old handshake.
            // * If the packet is received by a node with equal version,
            //   new features of the protocol can be used.
            // * If the packet is received by a node with higher version,
            //   it can enable backwards-compatibility logic or drop the connection.

            ProtocolVersion = hello.P2PVersion;

            List <Capability> capabilities = hello.Capabilities;

            AvailableCapabilities = new List <Capability>(capabilities);
            foreach (Capability theirCapability in capabilities)
            {
                if (SupportedCapabilities.Contains(theirCapability))
                {
                    if (Logger.IsTrace)
                    {
                        Logger.Trace($"{Session.RemoteNodeId} Agreed on {theirCapability.ProtocolCode} v{theirCapability.Version}");
                    }
                    AgreedCapabilities.Add(theirCapability);
                }
                else
                {
                    if (Logger.IsTrace)
                    {
                        Logger.Trace($"{Session.RemoteNodeId} Capability not supported " +
                                     $"{theirCapability.ProtocolCode} v{theirCapability.Version}");
                    }
                }
            }

            if (!capabilities.Any(c => SupportedCapabilities.Contains(c)))
            {
                Session.InitiateDisconnect(
                    DisconnectReason.UselessPeer,
                    $"capabilities: {string.Join(", ", capabilities)}");
            }

            ReceivedProtocolInitMsg(hello);

            P2PProtocolInitializedEventArgs eventArgs = new P2PProtocolInitializedEventArgs(this)
            {
                P2PVersion   = ProtocolVersion,
                ClientId     = RemoteClientId,
                Capabilities = capabilities,
                ListenPort   = hello.ListenPort
            };

            ProtocolInitialized?.Invoke(this, eventArgs);
        }
        public void HandleHello(HelloMessage hello)
        {
            bool isInbound = !_sentHello;

            if (Logger.IsTrace)
            {
                Logger.Trace($"{P2PSession.RemoteNodeId} P2P received hello.");
            }


            if (!hello.NodeId.Equals(P2PSession.RemoteNodeId))
            {
                if (Logger.IsDebug)
                {
                    Logger.Debug($"Inconsistent Node ID details - expected {P2PSession.RemoteNodeId}, received hello with {hello.NodeId} on " + (isInbound ? "IN connection" : "OUT connection"));
                }
                // it does not really matter if there is mismatch - we do not use it anywhere
//                throw new NodeDetailsMismatchException();
            }

            RemoteClientId = hello.ClientId;

            Logger.Trace(!_sentHello
                ? $"{P2PSession.RemoteNodeId} P2P initiating inbound {hello.Protocol} v{hello.P2PVersion} on {hello.ListenPort} ({hello.ClientId})"
                : $"{P2PSession.RemoteNodeId} P2P initiating outbound {hello.Protocol} v{hello.P2PVersion} on {hello.ListenPort} ({hello.ClientId})");

            // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-8.md
            // Clients implementing a newer version simply send a packet with higher version and possibly additional list elements.
            // * If such a packet is received by a node with lower version, it will blindly assume that the remote end is backwards-compatible and respond with the old handshake.
            // * If the packet is received by a node with equal version, new features of the protocol can be used.
            // * If the packet is received by a node with higher version, it can enable backwards-compatibility logic or drop the connection.

            ProtocolVersion = hello.P2PVersion;

            var capabilities = hello.Capabilities;

            foreach (Capability remotePeerCapability in capabilities)
            {
                if (SupportedCapabilities.Contains(remotePeerCapability))
                {
                    if (Logger.IsTrace)
                    {
                        Logger.Trace($"{P2PSession.RemoteNodeId} Agreed on {remotePeerCapability.ProtocolCode} v{remotePeerCapability.Version}");
                    }
                    AgreedCapabilities.Add(remotePeerCapability);
                }
                else
                {
                    if (Logger.IsTrace)
                    {
                        Logger.Trace($"{P2PSession.RemoteNodeId} Capability not supported {remotePeerCapability.ProtocolCode} v{remotePeerCapability.Version}");
                    }
                }
            }

            _isInitialized = true;

            if (!capabilities.Any(x => x.ProtocolCode == Protocol.Eth && (x.Version == 62 || x.Version == 63)))
            {
                Disconnect(DisconnectReason.UselessPeer);
            }

            ReceivedProtocolInitMsg(hello);

            var eventArgs = new P2PProtocolInitializedEventArgs(this)
            {
                P2PVersion   = ProtocolVersion,
                ClientId     = RemoteClientId,
                Capabilities = capabilities,
                ListenPort   = hello.ListenPort
            };

            ProtocolInitialized?.Invoke(this, eventArgs);
        }