Exemplo n.º 1
0
        /// <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 AllowClientConnection(TcpClient tcpClient)
        {
            if (this.networkPeerDisposer.ConnectedInboundPeersCount >= this.connectionManagerSettings.MaxInboundConnections)
            {
                this.logger.LogTrace("(-)[MAX_CONNECTION_THRESHOLD_REACHED]:false");
                return(false);
            }

            if (!this.initialBlockDownloadState.IsInitialBlockDownload())
            {
                this.logger.LogTrace("(-)[IBD_COMPLETE_ALLOW_CONNECTION]:true");
                return(true);
            }

            var clientRemoteEndPoint = tcpClient.Client.RemoteEndPoint as IPEndPoint;

            NodeServerEndpoint endpoint = this.connectionManagerSettings.Listen.FirstOrDefault(e => e.Endpoint.Match(clientRemoteEndPoint));

            if ((endpoint != null) && endpoint.Whitelisted)
            {
                this.logger.LogTrace("(-)[ENDPOINT_WHITELISTED_ALLOW_CONNECTION]:true");
                return(true);
            }

            this.logger.LogTrace("Node '{0}' is not white listed during initial block download.", clientRemoteEndPoint);

            return(false);
        }
        /// <summary>
        /// Initializes an instance of the object from the node configuration.
        /// </summary>
        /// <param name="nodeSettings">The node configuration.</param>
        public ConnectionManagerSettings(NodeSettings nodeSettings)
        {
            Guard.NotNull(nodeSettings, nameof(nodeSettings));

            this.logger = nodeSettings.LoggerFactory.CreateLogger(typeof(ConnectionManagerSettings).FullName);

            this.Connect   = new List <IPEndPoint>();
            this.AddNode   = new List <IPEndPoint>();
            this.Bind      = new List <NodeServerEndpoint>();
            this.Whitelist = new List <IPEndPoint>();

            TextFileConfiguration config = nodeSettings.ConfigReader;

            try
            {
                this.Connect.AddRange(config.GetAll("connect", this.logger).Select(c => c.ToIPEndPoint(nodeSettings.Network.DefaultPort)));
            }
            catch (FormatException)
            {
                throw new ConfigurationException("Invalid 'connect' parameter.");
            }

            try
            {
                this.AddNode.AddRange(config.GetAll("addnode", this.logger).Select(c => c.ToIPEndPoint(nodeSettings.Network.DefaultPort)));
            }
            catch (FormatException)
            {
                throw new ConfigurationException("Invalid 'addnode' parameter.");
            }

            this.Port = config.GetOrDefault <int>("port", nodeSettings.Network.DefaultPort, this.logger);

            try
            {
                this.Bind.AddRange(config.GetAll("bind").Select(c => new NodeServerEndpoint(c.ToIPEndPoint(this.Port), false)));
            }
            catch (FormatException)
            {
                throw new ConfigurationException("Invalid 'bind' parameter");
            }

            try
            {
                IEnumerable <IPEndPoint> whitebindEndpoints = config.GetAll("whitebind", this.logger).Select(s => s.ToIPEndPoint(this.Port));

                List <IPEndPoint> networkEndpoints = this.Bind.Select(x => x.Endpoint).ToList();

                foreach (IPEndPoint whiteBindEndpoint in whitebindEndpoints)
                {
                    if (whiteBindEndpoint.CanBeMappedTo(networkEndpoints, out IPEndPoint outEndpoint))
                    {
                        // White-list white-bind endpoint if we are currently listening to it.
                        NodeServerEndpoint listenToThisEndpoint = this.Bind.SingleOrDefault(x => x.Endpoint.Equals(outEndpoint));

                        if (listenToThisEndpoint != null)
                        {
                            listenToThisEndpoint.Whitelisted = true;
                        }
                    }
                    else
                    {
                        // Add to list of network interfaces if we are not.
                        this.Bind.Add(new NodeServerEndpoint(whiteBindEndpoint, true));
                    }
                }
            }
            catch (FormatException)
            {
                throw new ConfigurationException("Invalid 'whitebind' parameter");
            }

            if (this.Bind.Count == 0)
            {
                this.Bind.Add(new NodeServerEndpoint(new IPEndPoint(IPAddress.Parse("0.0.0.0"), this.Port), false));
            }
            else
            {
                var ports = this.Bind.Select(l => l.Endpoint.Port).ToList();

                if (ports.Count != ports.Distinct().Count())
                {
                    throw new ConfigurationException("Invalid attempt to bind the same port twice");
                }
            }

            try
            {
                this.Whitelist.AddRange(config.GetAll("whitelist", this.logger).Select(c => c.ToIPEndPoint(nodeSettings.Network.DefaultPort)));
            }
            catch (FormatException)
            {
                throw new ConfigurationException("Invalid 'whitelist' parameter.");
            }

            string externalIp = config.GetOrDefault <string>("externalip", null, this.logger);

            if (externalIp != null)
            {
                try
                {
                    this.ExternalEndpoint = externalIp.ToIPEndPoint(this.Port);
                }
                catch (FormatException)
                {
                    throw new ConfigurationException("Invalid 'externalip' parameter");
                }
            }

            if (this.ExternalEndpoint == null)
            {
                this.ExternalEndpoint = new IPEndPoint(IPAddress.Loopback, this.Port);
            }

            this.BanTimeSeconds = config.GetOrDefault <int>("bantime", nodeSettings.Network.IsTest() ? DefaultMisbehavingBantimeSecondsTestnet : DefaultMisbehavingBantimeSeconds, this.logger);

            // Listen option will default to true in case there are no connect option specified.
            // When running the node with connect option listen flag has to be explicitly passed to the node to enable listen flag.
            this.Listen = config.GetOrDefault <bool>("listen", !this.Connect.Any(), this.logger);

            this.MaxOutboundConnections = config.GetOrDefault <int>("maxoutboundconnections", nodeSettings.Network.DefaultMaxOutboundConnections, this.logger);
            if (this.MaxOutboundConnections <= 0)
            {
                throw new ConfigurationException("The 'maxoutboundconnections' must be greater than zero.");
            }

            this.MaxInboundConnections = config.GetOrDefault <int>("maxinboundconnections", nodeSettings.Network.DefaultMaxInboundConnections, this.logger);
            if (this.MaxInboundConnections < 0)
            {
                throw new ConfigurationException("The 'maxinboundconnections' must be greater or equal to zero.");
            }

            this.InitialConnectionTarget = config.GetOrDefault("initialconnectiontarget", 1, this.logger);
            this.SyncTimeEnabled         = config.GetOrDefault <bool>("synctime", true, this.logger);
            this.RelayTxes        = !config.GetOrDefault("blocksonly", DefaultBlocksOnly, this.logger);
            this.IpRangeFiltering = config.GetOrDefault <bool>("IpRangeFiltering", true, this.logger);

            var agentPrefix = config.GetOrDefault("agentprefix", string.Empty, this.logger).Replace("-", string.Empty);

            if (agentPrefix.Length > MaximumAgentPrefixLength)
            {
                agentPrefix = agentPrefix.Substring(0, MaximumAgentPrefixLength);
            }

            this.Agent = string.IsNullOrEmpty(agentPrefix) ? nodeSettings.Agent : $"{agentPrefix}-{nodeSettings.Agent}";
            this.logger.LogDebug("Agent set to '{0}'.", this.Agent);

            this.IsGateway = config.GetOrDefault <bool>("gateway", false, this.logger);
        }