Esempio n. 1
0
        private void ProcessConnect(SocketAsyncEventArgs connectEventArgs)
        {
            if (connectEventArgs.SocketError == SocketError.Success)
            {
                Node node = new Node(blockchain, settings);
                peers.Add(node);
                SocketAsyncEventArgs srEventArgs = node.sendReceivePool.Pop();

                // Pass the socket from the "connect" SAEA to "send/receive" SAEA.
                srEventArgs.AcceptSocket = connectEventArgs.AcceptSocket;

                MessageManager msgMan = srEventArgs.UserToken as MessageManager;
                msgMan.StartHandShake(srEventArgs);

                node.StartSend(srEventArgs);

                // Remove "connect" SAEA socket and put it back in pool to be used for the next connect operation.
                connectEventArgs.AcceptSocket = null;
                connectPool.Push(connectEventArgs);
            }
            else
            {
                connectEventArgs.AcceptSocket.Close();
                connectPool.Push(connectEventArgs);
            }
        }
Esempio n. 2
0
        private void ProcessAccept(SocketAsyncEventArgs acceptEventArgs)
        {
            if (acceptEventArgs.SocketError == SocketError.Success)
            {
                Node node = new Node(blockchain, settings);
                peers.Add(node);
                SocketAsyncEventArgs srEventArgs = node.sendReceivePool.Pop();

                // Pass the socket from the "accept" SAEA to "send/receive" SAEA.
                srEventArgs.AcceptSocket = acceptEventArgs.AcceptSocket;
                node.StartReceive(srEventArgs);

                // Remove "accept" SAEA socket and put it back in pool to be used for the next accept operation.
                acceptEventArgs.AcceptSocket = null;
                acceptPool.Push(acceptEventArgs);
                StartAccept();
            }
            else
            {
                acceptEventArgs.AcceptSocket = null;
                acceptPool.Push(acceptEventArgs);
                maxConnectionEnforcer.Release();
                StartAccept();
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Initializes a new instance of <see cref="ClientSettings"/> with the given parameters.
        /// </summary>
        /// <param name="pver">Protocol version</param>
        /// <param name="relay">True to relay blocks and transactions; false otherwise</param>
        /// <param name="ua">User agent as defined by <see cref="BIP0014"/></param>
        /// <param name="netType">Network type</param>
        /// <param name="servs">Services supported by this node</param>
        public ClientSettings(int pver, bool relay, string ua, NetworkType netType, NodeServiceFlags servs)
        {
            ProtocolVersion = pver;
            Relay           = relay;
            UserAgent       = ua;
            Network         = netType;
            Services        = servs;

            // TODO: the following values are for testing, they should be set by the caller
            //       they need more checks for correct and optimal values

            MaxConnectionCount = 5;
            BufferLength       = 16384; // 16 KB
            int totalBytes = BufferLength * MaxConnectionCount * 2;

            MaxConnectionEnforcer = new Semaphore(MaxConnectionCount, MaxConnectionCount);
            SendReceivePool       = new SocketAsyncEventArgsPool(MaxConnectionCount * 2);
            var buffMan = new BufferManager(totalBytes, BufferLength);

            for (int i = 0; i < MaxConnectionCount * 2; i++)
            {
                var sArg = new SocketAsyncEventArgs();
                buffMan.SetBuffer(sArg);
                SendReceivePool.Push(sArg);
            }
        }
        /// <summary>
        /// Initializes a new instance of <see cref="Node"/> using the given parameters.
        /// </summary>
        /// <param name="bc">The blockchain (database) manager</param>
        /// <param name="cs">Client settings</param>
        internal Node(IBlockchain bc, IClientSettings cs)
        {
            // TODO: the following values are for testing, they should be set by the caller
            // they need more checks for correct and optimal values
            buffLen = 200;
            int bytesPerSaea         = buffLen;
            int sendReceiveSaeaCount = 10;
            int totalBytes           = bytesPerSaea * sendReceiveSaeaCount;

            buffMan    = new BufferManager(totalBytes, bytesPerSaea);
            NodeStatus = new NodeStatus();
            repMan     = new ReplyManager(NodeStatus, bc, cs);

            sendReceivePool = new SocketAsyncEventArgsPool(sendReceiveSaeaCount);
            for (int i = 0; i < sendReceiveSaeaCount; i++)
            {
                SocketAsyncEventArgs sArg = new SocketAsyncEventArgs();

                buffMan.SetBuffer(sArg);
                sArg.Completed += new EventHandler <SocketAsyncEventArgs>(IO_Completed);
                sArg.UserToken  = new MessageManager(bytesPerSaea, repMan, NodeStatus, cs.Network);

                sendReceivePool.Push(sArg);
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Initializes a new instance of the <see cref="NodeConnector"/> using the given parameters.
        /// </summary>
        /// <param name="peerList">List of peers (is used to add the connected node to)</param>
        /// <param name="cs">Client settings</param>
        public NodeConnector(ICollection <Node> peerList, IClientSettings cs)
        {
            peers    = peerList;
            settings = cs;

            connectPool = new SocketAsyncEventArgsPool(cs.MaxConnectionCount);
            for (int i = 0; i < cs.MaxConnectionCount; i++)
            {
                var connectEventArg = new SocketAsyncEventArgs();
                connectEventArg.Completed += new EventHandler <SocketAsyncEventArgs>((sender, e) => ProcessConnect(e));
                connectPool.Push(connectEventArg);
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Initializes a new instance of <see cref="ClientSettings"/> with the given parameters.
        /// </summary>
        /// <exception cref="ArgumentException"/>
        /// <exception cref="ArgumentNullException"/>
        /// <param name="listen">True to open a listening socket; false otherwise</param>
        /// <param name="netType">Network type</param>
        /// <param name="servs">Services supported by this node</param>
        /// <param name="nodes">List of peers (can be null)</param>
        /// <param name="fileMan">File manager</param>
        /// <param name="utxoDb">UTXO database</param>
        /// <param name="memPool">Memory pool</param>
        /// <param name="maxConnection">Maximum number of connections</param>
        public ClientSettings(bool listen, NetworkType netType, int maxConnection, NodeServiceFlags servs,
                              NodePool nodes, IFileManager fileMan, IUtxoDatabase utxoDb, IMemoryPool memPool)
        {
            // TODO: add AcceptSAEAPool here based on listen
            AcceptIncomingConnections = listen;
            Network            = netType;
            MaxConnectionCount = maxConnection;
            Services           = servs;
            AllNodes           = nodes ?? new NodePool(maxConnection);
            FileMan            = fileMan ?? throw new ArgumentNullException();

            DefaultPort = Network switch
            {
                NetworkType.MainNet => Constants.MainNetPort,
                NetworkType.TestNet => Constants.TestNetPort,
                NetworkType.RegTest => Constants.RegTestPort,
                _ => throw new ArgumentException("Undefined network"),
            };

            ListenPort = DefaultPort;

            // TODO: the following values are for testing, they should be set by the caller
            //       they need more checks for correct and optimal values
            BufferLength = 16384; // 16 KB
            int totalBytes = BufferLength * MaxConnectionCount * 2;

            MaxConnectionEnforcer = new Semaphore(MaxConnectionCount, MaxConnectionCount);
            SendReceivePool       = new SocketAsyncEventArgsPool(MaxConnectionCount * 2);
            // TODO: can Memory<byte> be used here instead of byte[]?
            byte[] bufferBlock = new byte[totalBytes];
            for (int i = 0; i < MaxConnectionCount * 2; i++)
            {
                var sArg = new SocketAsyncEventArgs();
                sArg.SetBuffer(bufferBlock, i * BufferLength, BufferLength);
                SendReceivePool.Push(sArg);
            }

            // TODO: find a better way for this
            supportsIpV6 = NetworkInterface.GetAllNetworkInterfaces().All(x => x.Supports(NetworkInterfaceComponent.IPv6));

            var c     = new Consensus(netType);
            var txVer = new TransactionVerifier(false, utxoDb, memPool, c);

            Blockchain = new Blockchain.Blockchain(FileMan, new BlockVerifier(txVer, c), c)
            {
                Time  = Time,
                State = BlockchainState.None
            };
        }
Esempio n. 7
0
        /// <summary>
        /// Initializes a new instance of the <see cref="NodeListener"/> using the given parameters.
        /// </summary>
        /// <param name="peerList">List of peers (is used to add the connected node to)</param>
        /// <param name="cs">Client settings</param>
        public NodeListener(ICollection <Node> peerList, IClientSettings cs)
        {
            peers    = peerList;
            settings = cs;

            backlog = 3;

            acceptPool = new SocketAsyncEventArgsPool(cs.MaxConnectionCount);
            for (int i = 0; i < cs.MaxConnectionCount; i++)
            {
                var acceptEventArg = new SocketAsyncEventArgs();
                acceptEventArg.Completed += new EventHandler <SocketAsyncEventArgs>((sender, e) => ProcessAccept(e));
                acceptPool.Push(acceptEventArg);
            }
        }
Esempio n. 8
0
        private void ProcessAccept(SocketAsyncEventArgs acceptEventArgs)
        {
            if (acceptEventArgs.SocketError == SocketError.Success)
            {
                Node node = new Node(blockchain, settings, acceptEventArgs.AcceptSocket);
                peers.Add(node);
                node.StartReceiving();
            }
            else
            {
                settings.MaxConnectionEnforcer.Release();
            }

            // Remove "accept" SAEA socket and put it back in pool to be used for the next accept operation.
            acceptEventArgs.AcceptSocket = null;
            acceptPool.Push(acceptEventArgs);
            StartAccept();
        }
        private void CloseClientSocket(SocketAsyncEventArgs srEventArgs)
        {
            try
            {
                srEventArgs.AcceptSocket.Shutdown(SocketShutdown.Both);
            }
            catch (Exception)
            {
            }

            srEventArgs.AcceptSocket.Close();

            MessageManager msgMan = srEventArgs.UserToken as MessageManager;

            msgMan.Init();

            sendReceivePool.Push(srEventArgs);
        }
Esempio n. 10
0
        private void ProcessConnect(SocketAsyncEventArgs connectEventArgs)
        {
            if (connectEventArgs.SocketError == SocketError.Success)
            {
                Node node = new Node(blockchain, settings, connectEventArgs.AcceptSocket);
                peers.Add(node);

                node.StartHandShake();
            }
            else
            {
                connectEventArgs.AcceptSocket.Close();
                settings.MaxConnectionEnforcer.Release();
            }

            // Remove "connect" SAEA socket before putting it back in pool to be used for the next connect operation.
            connectEventArgs.AcceptSocket = null;
            connectPool.Push(connectEventArgs);
        }
Esempio n. 11
0
        /// <summary>
        /// Initializes a new instance of the <see cref="NodeConnector"/> using the given parameters.
        /// </summary>
        /// <param name="peerList">List of peers (is used to add the connected node to)</param>
        /// <param name="bc">Blockchain database to use</param>
        /// <param name="cs">Client settings</param>
        public NodeConnector(ICollection <Node> peerList, IBlockchain bc, IClientSettings cs)
        {
            peers      = peerList;
            blockchain = bc;
            settings   = cs;

            int MaxConnections = 3;

            maxConnectionEnforcer = new Semaphore(MaxConnections, MaxConnections);

            int MaxConnectOps = 10;

            connectPool = new SocketAsyncEventArgsPool(MaxConnectOps);
            for (int i = 0; i < MaxConnectOps; i++)
            {
                var connectEventArg = new SocketAsyncEventArgs();
                connectEventArg.Completed += new EventHandler <SocketAsyncEventArgs>((sender, e) => ProcessConnect(e));
                connectPool.Push(connectEventArg);
            }
        }