Esempio n. 1
0
            public static bool broadcastGetBlock(ulong block_num, RemoteEndpoint skipEndpoint = null, RemoteEndpoint endpoint = null, byte include_transactions = 0, bool full_header = false)
            {
                using (MemoryStream mw = new MemoryStream())
                {
                    using (BinaryWriter writerw = new BinaryWriter(mw))
                    {
                        writerw.WriteIxiVarInt(block_num);
                        writerw.Write(include_transactions);
                        writerw.Write(full_header);
#if TRACE_MEMSTREAM_SIZES
                        Logging.info(String.Format("NetworkProtocol::broadcastGetBlock: {0}", mw.Length));
#endif

                        if (endpoint != null)
                        {
                            if (endpoint.isConnected())
                            {
                                endpoint.sendData(ProtocolMessageCode.getBlock3, mw.ToArray());
                                return(true);
                            }
                        }
                        return(CoreProtocolMessage.broadcastProtocolMessageToSingleRandomNode(new char[] { 'M', 'H' }, ProtocolMessageCode.getBlock3, mw.ToArray(), block_num, skipEndpoint));
                    }
                }
            }
Esempio n. 2
0
            public static bool broadcastGetBlockSignatures(ulong block_num, byte[] block_checksum, RemoteEndpoint endpoint)
            {
                using (MemoryStream mw = new MemoryStream())
                {
                    using (BinaryWriter writerw = new BinaryWriter(mw))
                    {
                        writerw.WriteIxiVarInt(block_num);

                        writerw.WriteIxiVarInt(block_checksum.Length);
                        writerw.Write(block_checksum);
#if TRACE_MEMSTREAM_SIZES
                        Logging.info(String.Format("NetworkProtocol::broadcastGetBlockSignatures: {0}", mw.Length));
#endif

                        if (endpoint != null)
                        {
                            if (endpoint.isConnected())
                            {
                                endpoint.sendData(ProtocolMessageCode.getBlockSignatures2, mw.ToArray());
                                return(true);
                            }
                        }
                        return(CoreProtocolMessage.broadcastProtocolMessageToSingleRandomNode(new char[] { 'M', 'H' }, ProtocolMessageCode.getBlockSignatures2, mw.ToArray(), block_num));
                    }
                }
            }
Esempio n. 3
0
 public static bool broadcastNewBlock(Block b, RemoteEndpoint skipEndpoint = null, RemoteEndpoint endpoint = null, bool force_broadcast = false)
 {
     if (!Node.isMasterNode())
     {
         return(true);
     }
     if (endpoint != null)
     {
         if (endpoint.isConnected())
         {
             endpoint.sendData(ProtocolMessageCode.blockData, b.getBytes(false), BitConverter.GetBytes(b.blockNum));
             return(true);
         }
         return(false);
     }
     else
     {
         if (force_broadcast)
         {
             return(CoreProtocolMessage.broadcastProtocolMessage(new char[] { 'M', 'H' }, ProtocolMessageCode.blockData, b.getBytes(false), BitConverter.GetBytes(b.blockNum), skipEndpoint));
         }
         else
         {
             return(CoreProtocolMessage.addToInventory(new char[] { 'M', 'H' }, new InventoryItemBlock(b.blockChecksum, b.blockNum), skipEndpoint, ProtocolMessageCode.blockData, b.getBytes(false), BitConverter.GetBytes(b.blockNum)));
         }
     }
 }
Esempio n. 4
0
 public override bool addTransaction(Transaction tx, bool force_broadcast)
 {
     // TODO Send to peer if directly connectable
     CoreProtocolMessage.broadcastProtocolMessage(new char[] { 'M', 'H' }, ProtocolMessageCode.transactionData, tx.getBytes(), null);
     PendingTransactions.addPendingLocalTransaction(tx);
     return(true);
 }
Esempio n. 5
0
        private static void acceptConnection(Socket clientSocket)
        {
            IPEndPoint clientEndpoint = (IPEndPoint)clientSocket.RemoteEndPoint;

            // Add timeouts and set socket options
            //clientSocket.ReceiveTimeout = 5000;
            //clientSocket.SendTimeout = 5000;
            clientSocket.LingerState = new LingerOption(true, 3);
            clientSocket.NoDelay     = true;
            clientSocket.Blocking    = true;

            if (!IxianHandler.isAcceptingConnections())
            {
                Thread.Sleep(100); // wait a bit for check connectivity purposes
                clientSocket.Send(CoreProtocolMessage.prepareProtocolMessage(ProtocolMessageCode.bye, new byte[1]));
                clientSocket.Shutdown(SocketShutdown.Both);
                clientSocket.Disconnect(true);
                return;
            }

            lastIncomingConnectionTime = DateTime.UtcNow;
            connectable = true;

            // Setup the remote endpoint
            RemoteEndpoint remoteEndpoint = new RemoteEndpoint();

            lock (connectedClients)
            {
                if (connectedClients.Count + 1 > CoreConfig.maximumServerMasterNodes)
                {
                    Logging.warn(string.Format("Maximum number of connected clients reached. Disconnecting client: {0}:{1}",
                                               clientEndpoint.Address.ToString(), clientEndpoint.Port));
                    clientSocket.Send(CoreProtocolMessage.prepareProtocolMessage(ProtocolMessageCode.bye, new byte[1]));
                    clientSocket.Shutdown(SocketShutdown.Both);
                    clientSocket.Disconnect(true);
                    return;
                }

                var existing_clients = connectedClients.Where(re => re.remoteIP.Address == clientEndpoint.Address);
                if (existing_clients.Count() > 0)
                {
                    Logging.warn(String.Format("Client {0}:{1} already connected as {2}.",
                                               clientEndpoint.Address.ToString(), clientEndpoint.Port, existing_clients.First().ToString()));
                    clientSocket.Send(CoreProtocolMessage.prepareProtocolMessage(ProtocolMessageCode.bye, new byte[1]));
                    clientSocket.Shutdown(SocketShutdown.Both);
                    clientSocket.Disconnect(true);
                    return;
                }

                connectedClients.Add(remoteEndpoint);

                Logging.info(String.Format("Client connection accepted: {0} | #{1}/{2}", clientEndpoint.ToString(), connectedClients.Count + 1, CoreConfig.maximumServerMasterNodes));

                remoteEndpoint.start(clientSocket);
            }
        }
Esempio n. 6
0
 static void handleHello(byte[] data, RemoteEndpoint endpoint)
 {
     using (MemoryStream m = new MemoryStream(data))
     {
         using (BinaryReader reader = new BinaryReader(m))
         {
             CoreProtocolMessage.processHelloMessageV6(endpoint, reader);
         }
     }
 }
Esempio n. 7
0
        private static void acceptConnection(Socket clientSocket)
        {
            IPEndPoint clientEndpoint = (IPEndPoint)clientSocket.RemoteEndPoint;

            // Add timeouts and set socket options
            //clientSocket.ReceiveTimeout = 5000;
            //clientSocket.SendTimeout = 5000;
            clientSocket.LingerState = new LingerOption(true, 3);
            clientSocket.NoDelay     = true;
            clientSocket.Blocking    = true;

            if (!IxianHandler.isAcceptingConnections())
            {
                CoreProtocolMessage.sendBye(clientSocket, ProtocolByeCode.notReady, string.Format("The node isn't ready yet, please try again later."), "");
                clientSocket.Shutdown(SocketShutdown.Both);
                clientSocket.Disconnect(true);
                return;
            }

            lastIncomingConnectionTime = DateTime.UtcNow;
            connectable = true;

            // Setup the remote endpoint
            RemoteEndpoint remoteEndpoint = new RemoteEndpoint();

            lock (connectedClients)
            {
                if (connectedClients.Count + 1 > CoreConfig.maximumServerMasterNodes)
                {
                    Logging.warn("Maximum number of connected clients reached. Disconnecting client: {0}:{1}",
                                 clientEndpoint.Address.ToString(), clientEndpoint.Port);
                    CoreProtocolMessage.sendBye(clientSocket, ProtocolByeCode.rejected, "Too many clients already connected.", "");
                    clientSocket.Shutdown(SocketShutdown.Both);
                    clientSocket.Disconnect(true);
                    return;
                }

                var existing_clients = connectedClients.Where(re => re.remoteIP.Address == clientEndpoint.Address);
                if (existing_clients.Count() > 0)
                {
                    Logging.warn("Client {0}:{1} already connected as {2}.",
                                 clientEndpoint.Address.ToString(), clientEndpoint.Port, existing_clients.First().ToString());
                    CoreProtocolMessage.sendBye(clientSocket, ProtocolByeCode.rejected, "You are already connected.", "");
                    clientSocket.Shutdown(SocketShutdown.Both);
                    clientSocket.Disconnect(true);
                    return;
                }

                connectedClients.Add(remoteEndpoint);

                Logging.info("Client connection accepted: {0} | #{1}/{2}", clientEndpoint.ToString(), connectedClients.Count + 1, CoreConfig.maximumServerMasterNodes);

                remoteEndpoint.start(clientSocket);
            }
        }
Esempio n. 8
0
        public static void processPendingTransactions()
        {
            // TODO TODO improve to include failed transactions
            ulong last_block_height = IxianHandler.getLastBlockHeight();

            lock (PendingTransactions.pendingTransactions)
            {
                long cur_time = Clock.getTimestamp();
                List <PendingTransaction> tmp_pending_transactions = new List <PendingTransaction>(PendingTransactions.pendingTransactions);
                int idx = 0;
                foreach (var entry in tmp_pending_transactions)
                {
                    Transaction t       = entry.transaction;
                    long        tx_time = entry.addedTimestamp;

                    if (t.applied != 0)
                    {
                        PendingTransactions.pendingTransactions.RemoveAll(x => x.transaction.id.SequenceEqual(t.id));
                        continue;
                    }

                    // if transaction expired, remove it from pending transactions
                    if (last_block_height > ConsensusConfig.getRedactedWindowSize() && t.blockHeight < last_block_height - ConsensusConfig.getRedactedWindowSize())
                    {
                        ActivityStorage.updateStatus(t.id, ActivityStatus.Error, 0);
                        PendingTransactions.pendingTransactions.RemoveAll(x => x.transaction.id.SequenceEqual(t.id));
                        continue;
                    }

                    if (cur_time - tx_time > 40) // if the transaction is pending for over 40 seconds, resend
                    {
                        CoreProtocolMessage.broadcastProtocolMessage(new char[] { 'M', 'H' }, ProtocolMessageCode.transactionData, t.getBytes(), null);
                        entry.addedTimestamp = cur_time;
                        entry.confirmedNodeList.Clear();
                    }

                    if (entry.confirmedNodeList.Count() >= 3) // if we get transaction from 3 nodes, we can consider it as confirmed
                    {
                        if (entry.messageId != null)
                        {
                            StreamProcessor.confirmMessage(entry.messageId);
                        }
                        continue;
                    }

                    if (cur_time - tx_time > 20) // if the transaction is pending for over 20 seconds, send inquiry
                    {
                        CoreProtocolMessage.broadcastGetTransaction(t.id, 0, null, false);
                    }

                    idx++;
                }
            }
        }
Esempio n. 9
0
        /// <summary>
        ///  Attempts to connect to the given host name or IP address and transmit some data.
        ///  Note: This function has a possible delay of about 2 seconds.
        /// </summary>
        /// <param name="full_hostname">Hostname or IP address of the remote endpoint.</param>
        /// <returns>True, if the IP address is reachable.</returns>
        public static bool PingAddressReachable(String full_hostname)
        {
            // TODO TODO TODO TODO move this to another thread

            if (String.IsNullOrWhiteSpace(full_hostname))
            {
                return(false);
            }

            String[] hn_port = full_hostname.Split(':');
            if (hn_port.Length != 2)
            {
                return(false);
            }
            String hostname = hn_port[0];

            if (!IXICore.Utils.IxiUtils.validateIPv4(hostname))
            {
                return(false);
            }
            int port;

            if (int.TryParse(hn_port[1], out port) == false)
            {
                return(false);
            }
            if (port <= 0)
            {
                return(false);
            }

            TcpClient temp      = new TcpClient();
            bool      connected = false;

            try
            {
                Logging.info("Testing client connectivity for {0}.", full_hostname);
                if (!temp.ConnectAsync(hostname, port).Wait(1000))
                {
                    return(false);
                }
                temp.Client.SendTimeout    = 500;
                temp.Client.ReceiveTimeout = 500;
                temp.Client.Blocking       = false;
                temp.Client.Send(new byte[1], 1, 0);
                connected = temp.Client.Connected;
                CoreProtocolMessage.sendBye(temp.Client, ProtocolByeCode.bye, "Test OK", "");
                temp.Client.Shutdown(SocketShutdown.Both);
                temp.Close();
                temp.Dispose();
            }
            catch (Exception) { connected = false; }
            return(connected);
        }
Esempio n. 10
0
        private static void subscribeToEvents(RemoteEndpoint endpoint)
        {
            CoreProtocolMessage.subscribeToEvents(endpoint);

            byte[] friend_matcher = FriendList.getFriendCuckooFilter();
            if (friend_matcher != null)
            {
                byte[] event_data = NetworkEvents.prepareEventMessageData(NetworkEvents.Type.keepAlive, friend_matcher);
                endpoint.sendData(ProtocolMessageCode.attachEvent, event_data);
            }
        }
Esempio n. 11
0
        private bool handleSignature(InventoryItem item, RemoteEndpoint endpoint)
        {
            InventoryItemSignature iis = (InventoryItemSignature)item;
            ulong last_block_height    = IxianHandler.getLastBlockHeight();

            byte[] address   = iis.address;
            ulong  block_num = iis.blockNum;

            if (block_num + 5 > last_block_height && block_num <= last_block_height + 1)
            {
                if (block_num == last_block_height + 1)
                {
                    lock (Node.blockProcessor.localBlockLock)
                    {
                        Block local_block = Node.blockProcessor.localNewBlock;
                        if (local_block == null || local_block.blockNum != block_num)
                        {
                            return(false);
                        }
                        if (!local_block.blockChecksum.SequenceEqual(iis.blockHash) ||
                            local_block.hasNodeSignature(address))
                        {
                            return(false);
                        }
                    }
                }
                else
                {
                    Block sf_block = Node.blockChain.getBlock(block_num);
                    if (!sf_block.blockChecksum.SequenceEqual(iis.blockHash) ||
                        sf_block.hasNodeSignature(address))
                    {
                        return(false);
                    }
                }
                byte[] block_num_bytes = block_num.GetIxiVarIntBytes();
                byte[] addr_len_bytes  = ((ulong)address.Length).GetIxiVarIntBytes();
                byte[] data            = new byte[block_num_bytes.Length + 1 + addr_len_bytes.Length + address.Length];
                Array.Copy(block_num_bytes, data, block_num_bytes.Length);
                data[block_num_bytes.Length] = 1;
                Array.Copy(addr_len_bytes, 0, data, block_num_bytes.Length + 1, addr_len_bytes.Length);
                Array.Copy(address, 0, data, block_num_bytes.Length + 1 + addr_len_bytes.Length, address.Length);
                if (endpoint == null)
                {
                    CoreProtocolMessage.broadcastProtocolMessageToSingleRandomNode(new char[] { 'M', 'H' }, ProtocolMessageCode.getSignatures, data, block_num);
                }
                else
                {
                    endpoint.sendData(ProtocolMessageCode.getSignatures, data, null);
                }
                return(true);
            }
            return(false);
        }
Esempio n. 12
0
        private void stopSyncStartBlockProcessing()
        {
            if (CoreConfig.preventNetworkOperations)
            {
                Logging.info("Data verification successfully completed.");

                IxianHandler.forceShutdown = true;

                syncDone      = true;
                synchronizing = false;
                return;
            }

            // Don't finish sync if we never synchronized from network
            if (noNetworkSynchronization == true)
            {
                Thread.Sleep(500);
                return;
            }

            IxianHandler.status = NodeStatus.ready;

            // if we reach here, we are synchronized
            syncDone = true;

            synchronizing = false;

            Node.blockProcessor.firstBlockAfterSync = true;
            Node.blockProcessor.resumeOperation();

            lock (pendingBlocks)
            {
                lock (requestedBlockTimes)
                {
                    requestedBlockTimes.Clear();
                }
                pendingBlocks.Clear();
                if (missingBlocks != null)
                {
                    missingBlocks.Clear();
                    missingBlocks = null;
                }
            }

            if (!Config.recoverFromFile)
            {
                CoreProtocolMessage.broadcastProtocolMessageToSingleRandomNode(new char[] { 'M' }, ProtocolMessageCode.getUnappliedTransactions, new byte[1], IxianHandler.getHighestKnownNetworkBlockHeight());

                Node.miner.start();

                Node.walletStorage.scanForLostAddresses();
            }
        }
Esempio n. 13
0
            public static void handleUpdatePresence(byte[] data, RemoteEndpoint endpoint)
            {
                // Parse the data and update entries in the presence list
                Presence updated_presence = PresenceList.updateFromBytes(data);

                // If a presence entry was updated, broadcast this message again
                if (updated_presence != null)
                {
                    CoreProtocolMessage.broadcastProtocolMessage(new char[] { 'M', 'H', 'W' }, ProtocolMessageCode.updatePresence, data, updated_presence.wallet, endpoint);

                    // Send this keepalive message to all subscribed clients
                    CoreProtocolMessage.broadcastEventDataMessage(NetworkEvents.Type.keepAlive, updated_presence.wallet, ProtocolMessageCode.updatePresence, data, updated_presence.wallet, endpoint);
                }
            }
Esempio n. 14
0
        public static FriendMessage addMessageWithType(byte[] id, FriendMessageType type, byte[] wallet_address, string message, bool local_sender = false)
        {
            foreach (Friend friend in friends)
            {
                if (friend.walletAddress.SequenceEqual(wallet_address))
                {
                    Node.shouldRefreshContacts = true;

                    if (!friend.online)
                    {
                        using (MemoryStream mw = new MemoryStream())
                        {
                            using (BinaryWriter writer = new BinaryWriter(mw))
                            {
                                writer.Write(wallet_address.Length);
                                writer.Write(wallet_address);

                                CoreProtocolMessage.broadcastProtocolMessage(new char[] { 'M' }, ProtocolMessageCode.getPresence, mw.ToArray(), null);
                            }
                        }
                    }
                    // TODO: message date should be fetched, not generated here
                    FriendMessage friend_message = new FriendMessage(id, message, Clock.getTimestamp(), local_sender, type);
                    friend.messages.Add(friend_message);

                    // If a chat page is visible, insert the message directly
                    if (friend.chat_page != null)
                    {
                        friend.chat_page.insertMessage(friend_message);
                    }
                    else
                    {
                        //CrossLocalNotifications.Current.Show(string.Format("New message from {0}",friend.nickname), message, 100, DateTime.Now.AddSeconds(1));
                    }

                    // Write to chat history
                    Node.localStorage.writeMessagesFile(wallet_address, friend.messages);

                    return(friend_message);
                }
            }

            // No matching contact found in friendlist
            // Add the contact, then issue the message again
            // TODO: need to fetch the stage 1 public key somehow here
            // Ignoring such messages for now
            //addFriend(wallet_address, "pubkey", "Unknown");
            //addMessage(wallet_address, message);
            return(null);
        }
Esempio n. 15
0
        // Request transaction data
        private void requestTransactionData()
        {
            Logging.info("Requesting transaction data for: {0}", transaction.id);
            using (MemoryStream m = new MemoryStream())
            {
                using (BinaryWriter writer = new BinaryWriter(m))
                {
                    writer.Write(transaction.id);
                    writer.Write((ulong)0);

                    CoreProtocolMessage.broadcastProtocolMessageToSingleRandomNode(new char[] { 'M' }, IXICore.Network.ProtocolMessageCode.getTransaction, m.ToArray(), 0, null);
                }
            }
        }
Esempio n. 16
0
        public static void processPendingTransactions()
        {
            // TODO TODO improve to include failed transactions
            ulong last_block_height = IxianHandler.getLastBlockHeight();

            lock (PendingTransactions.pendingTransactions)
            {
                long cur_time = Clock.getTimestamp();
                List <PendingTransaction> tmp_pending_transactions = new List <PendingTransaction>(PendingTransactions.pendingTransactions);
                int idx = 0;
                foreach (var entry in tmp_pending_transactions)
                {
                    Transaction t       = entry.transaction;
                    long        tx_time = entry.addedTimestamp;

                    if (t.applied != 0)
                    {
                        PendingTransactions.pendingTransactions.RemoveAll(x => x.transaction.id.SequenceEqual(t.id));
                        continue;
                    }

                    // if transaction expired, remove it from pending transactions
                    if (last_block_height > ConsensusConfig.getRedactedWindowSize() && t.blockHeight < last_block_height - ConsensusConfig.getRedactedWindowSize())
                    {
                        Console.WriteLine("Error sending the transaction {0}", Transaction.txIdV8ToLegacy(t.id));
                        PendingTransactions.pendingTransactions.RemoveAll(x => x.transaction.id.SequenceEqual(t.id));
                        continue;
                    }

                    if (cur_time - tx_time > 40) // if the transaction is pending for over 40 seconds, resend
                    {
                        CoreProtocolMessage.broadcastProtocolMessage(new char[] { 'M', 'H' }, ProtocolMessageCode.transactionData, t.getBytes(), null);
                        entry.addedTimestamp = cur_time;
                        entry.confirmedNodeList.Clear();
                    }

                    if (entry.confirmedNodeList.Count() > 3) // already received 3+ feedback
                    {
                        continue;
                    }

                    if (cur_time - tx_time > 20) // if the transaction is pending for over 20 seconds, send inquiry
                    {
                        CoreProtocolMessage.broadcastGetTransaction(Transaction.txIdV8ToLegacy(t.id), 0);
                    }

                    idx++;
                }
            }
        }
Esempio n. 17
0
        // Handle timer routines
        static public void mainLoop()
        {
            byte[] primaryAddress = IxianHandler.getWalletStorage().getPrimaryAddress();
            if (primaryAddress == null)
            {
                return;
            }

            byte[] getBalanceBytes;
            using (MemoryStream mw = new MemoryStream())
            {
                using (BinaryWriter writer = new BinaryWriter(mw))
                {
                    writer.WriteIxiVarInt(primaryAddress.Length);
                    writer.Write(primaryAddress);
                }
                getBalanceBytes = mw.ToArray();
            }

            while (running)
            {
                try
                {
                    // Update the friendlist
                    FriendList.Update();

                    // Request initial wallet balance
                    if (balance.blockHeight == 0 || balance.lastUpdate + 300 < Clock.getTimestamp())
                    {
                        CoreProtocolMessage.broadcastProtocolMessage(new char[] { 'M', 'H' }, ProtocolMessageCode.getBalance2, getBalanceBytes, null);
                    }

                    if (Config.enablePushNotifications)
                    {
                        OfflinePushMessages.fetchPushMessages();
                    }

                    // Cleanup the presence list
                    // TODO: optimize this by using a different thread perhaps
                    PresenceList.performCleanup();
                }
                catch (Exception e)
                {
                    Logging.error("Exception occured in mainLoop: " + e);
                }
                Thread.Sleep(2500);
            }
        }
Esempio n. 18
0
        // Sends perioding keepalive network messages
        private static void keepAlive()
        {
            while (autoKeepalive)
            {
                TLC.Report();
                // Wait x seconds before rechecking
                for (int i = 0; i < CoreConfig.keepAliveInterval; i++)
                {
                    if (autoKeepalive == false)
                    {
                        Thread.Yield();
                        return;
                    }
                    // Sleep for one second
                    Thread.Sleep(1000);
                }

                if (curNodePresenceAddress.type == 'W')
                {
                    continue; // no need to send PL for worker nodes
                }

                try
                {
                    byte[] ka_bytes = null;
                    ka_bytes = keepAlive_v1();

                    byte[] address = null;

                    // Update self presence
                    PresenceList.receiveKeepAlive(ka_bytes, out address);

                    // Send this keepalive to all connected non-clients
                    CoreProtocolMessage.broadcastProtocolMessage(new char[] { 'M', 'R', 'H', 'W' }, ProtocolMessageCode.keepAlivePresence, ka_bytes, address);

                    // Send this keepalive message to all connected clients
                    CoreProtocolMessage.broadcastEventDataMessage(NetworkEvents.Type.keepAlive, address, ProtocolMessageCode.keepAlivePresence, ka_bytes, address);
                }
                catch (Exception)
                {
                    continue;
                }
            }

            Thread.Yield();
        }
Esempio n. 19
0
        // Retrieve a presence entry connected S2 node. Returns null if not found
        public static string getRelayHostname(byte[] wallet_address)
        {
            string   hostname = null;
            Presence presence = PresenceList.getPresenceByAddress(wallet_address);

            if (presence == null)
            {
                using (MemoryStream mw = new MemoryStream())
                {
                    using (BinaryWriter writer = new BinaryWriter(mw))
                    {
                        writer.Write(wallet_address.Length);
                        writer.Write(wallet_address);

                        CoreProtocolMessage.broadcastProtocolMessage(new char[] { 'M' }, ProtocolMessageCode.getPresence, mw.ToArray(), null);
                    }
                }
                return(null);
            }

            byte[] wallet = presence.wallet;

            lock (presence)
            {
                // Go through each presence address searching for C nodes
                foreach (PresenceAddress addr in presence.addresses)
                {
                    // Only check Client nodes
                    if (addr.type == 'C')
                    {
                        // We have a potential candidate here, store it
                        hostname = addr.address;

                        string[] hostname_split = hostname.Split(':');

                        if (hostname_split.Count() == 2 && NetworkUtils.validateIP(hostname_split[0]))
                        {
                            break;
                        }
                    }
                }
            }

            // Finally, return the ip address of the node
            return(hostname);
        }
Esempio n. 20
0
        // Checks for missing clients
        private static void reconnectClients(Random rnd)
        {
            try
            {
                handleDisconnectedClients();

                if (CoreConfig.simultaneousConnectedNeighbors < 4)
                {
                    Logging.error("Setting CoreConfig.simultanousConnectedNeighbors should be at least 4.");
                    IxianHandler.shutdown();
                    throw new Exception("Setting CoreConfig.simultanousConnectedNeighbors should be at least 4.");
                }

                // Check if we need to connect to more neighbors
                if (getConnectedClients().Count() < CoreConfig.simultaneousConnectedNeighbors)
                {
                    // Scan for and connect to a new neighbor
                    connectToRandomNeighbor();
                    return;
                }
                else if (getConnectedClients(true).Count() > CoreConfig.simultaneousConnectedNeighbors)
                {
                    NetworkClient client;
                    lock (networkClients)
                    {
                        client = networkClients[0];
                        networkClients.RemoveAt(0);
                    }
                    CoreProtocolMessage.sendBye(client, ProtocolByeCode.bye, "Disconnected for shuffling purposes.", "", false);
                    client.stop();
                }

                // Connect randomly to a new node. Currently a 1% chance to reconnect during this iteration
                if (rnd.Next(100) == 1)
                {
                    connectToRandomNeighbor();
                }
            }
            catch (ThreadAbortException)
            {
            }
            catch (Exception e)
            {
                Logging.error("Fatal exception occured in NetworkClientManager.reconnectClients: " + e);
            }
        }
Esempio n. 21
0
            public static void handleHelloData(byte[] data, RemoteEndpoint endpoint)
            {
                using (MemoryStream m = new MemoryStream(data))
                {
                    using (BinaryReader reader = new BinaryReader(m))
                    {
                        if (!CoreProtocolMessage.processHelloMessageV6(endpoint, reader))
                        {
                            return;
                        }
                        char node_type = endpoint.presenceAddress.type;
                        if (node_type != 'M' && node_type != 'H')
                        {
                            CoreProtocolMessage.sendBye(endpoint, ProtocolByeCode.expectingMaster, string.Format("Expecting master node."), "", true);
                            return;
                        }

                        ulong last_block_num = reader.ReadIxiVarUInt();

                        int    bcLen          = (int)reader.ReadIxiVarUInt();
                        byte[] block_checksum = reader.ReadBytes(bcLen);

                        endpoint.blockHeight = last_block_num;

                        if (Node.checkCurrentBlockDeprecation(last_block_num) == false)
                        {
                            CoreProtocolMessage.sendBye(endpoint, ProtocolByeCode.deprecated, string.Format("This node deprecated or will deprecate on block {0}, your block height is {1}, disconnecting.", Config.nodeDeprecationBlock, last_block_num), last_block_num.ToString(), true);
                            return;
                        }

                        int block_version = (int)reader.ReadIxiVarUInt();

                        ulong highest_block_height = IxianHandler.getHighestKnownNetworkBlockHeight();
                        if (last_block_num + 15 < highest_block_height)
                        {
                            CoreProtocolMessage.sendBye(endpoint, ProtocolByeCode.tooFarBehind, string.Format("Your node is too far behind, your block height is {0}, highest network block height is {1}.", last_block_num, highest_block_height), highest_block_height.ToString(), true);
                            return;
                        }

                        // Process the hello data
                        Node.blockSync.onHelloDataReceived(last_block_num, block_checksum, block_version, null, 0, 0, true);
                        endpoint.helloReceived = true;
                        NetworkClientManager.recalculateLocalTimeDifference();
                    }
                }
            }
Esempio n. 22
0
        // Receive thread
        protected override void recvLoop()
        {
            try
            {
                Random rnd = new Random();
                CoreProtocolMessage.sendHelloMessageV6(this, false, rnd.Next());

                base.recvLoop();
            }catch (Exception e)
            {
                if (running)
                {
                    Logging.warn(string.Format("recvRE: Disconnected client {0} with exception {1}", getFullAddress(), e.ToString()));
                }
                state   = RemoteEndpointState.Closed;
                running = false;
            }
        }
Esempio n. 23
0
 // Sends data over the network
 public static void sendData(ProtocolMessageCode code, byte[] data)
 {
     byte[] ba = CoreProtocolMessage.prepareProtocolMessage(code, data);
     NetDump.Instance.appendSent(tcpClient.Client, ba, ba.Length);
     try
     {
         tcpClient.Client.Send(ba, SocketFlags.None);
         if (tcpClient.Client.Connected == false)
         {
             Logging.error("Failed senddata to client. Reconnecting.");
         }
     }
     catch (Exception e)
     {
         Logging.error(String.Format("CLN: Socket exception, attempting to reconnect {0}", e));
     }
     //Console.WriteLine("sendData done");
 }
Esempio n. 24
0
        // Internal function that sends data through the socket
        protected void sendDataInternal(ProtocolMessageCode code, byte[] data, byte[] checksum)
        {
            byte[] ba = CoreProtocolMessage.prepareProtocolMessage(code, data, checksum);
            NetDump.Instance.appendSent(clientSocket, ba, ba.Length);
            try
            {
                for (int sentBytes = 0; sentBytes < ba.Length && running;)
                {
                    int bytesToSendCount = ba.Length - sentBytes;
                    if (bytesToSendCount > 8000)
                    {
                        bytesToSendCount = 8000;
                    }


                    int curSentBytes = clientSocket.Send(ba, sentBytes, bytesToSendCount, SocketFlags.None);

                    lastDataSentTime = Clock.getTimestamp();


                    // Sleep a bit to allow other threads to do their thing
                    Thread.Yield();

                    sentBytes += curSentBytes;
                    // TODO TODO TODO timeout
                }
                if (clientSocket.Connected == false)
                {
                    if (running)
                    {
                        Logging.warn(String.Format("sendRE: Failed senddata to remote endpoint {0}, Closing.", getFullAddress()));
                    }
                    state = RemoteEndpointState.Closed;
                }
            }
            catch (Exception e)
            {
                if (running)
                {
                    Logging.warn(String.Format("sendRE: Socket exception for {0}, closing. {1}", getFullAddress(), e));
                }
                state = RemoteEndpointState.Closed;
            }
        }
Esempio n. 25
0
            public static void handleKeepAlivesChunk(byte[] data, RemoteEndpoint endpoint)
            {
                using (MemoryStream m = new MemoryStream(data))
                {
                    using (BinaryReader reader = new BinaryReader(m))
                    {
                        int ka_count = (int)reader.ReadIxiVarUInt();

                        int max_ka_per_chunk = CoreConfig.maximumKeepAlivesPerChunk;
                        if (ka_count > max_ka_per_chunk)
                        {
                            ka_count = max_ka_per_chunk;
                        }

                        for (int i = 0; i < ka_count; i++)
                        {
                            if (m.Position == m.Length)
                            {
                                break;
                            }

                            int    ka_len   = (int)reader.ReadIxiVarUInt();
                            byte[] ka_bytes = reader.ReadBytes(ka_len);
                            byte[] hash     = Crypto.sha512sqTrunc(ka_bytes);

                            Node.inventoryCache.setProcessedFlag(InventoryItemTypes.keepAlive, hash, true);

                            byte[] address;
                            long   last_seen;
                            byte[] device_id;
                            bool   updated = PresenceList.receiveKeepAlive(ka_bytes, out address, out last_seen, out device_id, endpoint);

                            // If a presence entry was updated, broadcast this message again
                            if (updated)
                            {
                                CoreProtocolMessage.addToInventory(new char[] { 'M', 'H', 'W' }, new InventoryItemKeepAlive(hash, last_seen, address, device_id), endpoint, ProtocolMessageCode.keepAlivePresence, ka_bytes, address);

                                // Send this keepalive message to all subscribed clients
                                CoreProtocolMessage.broadcastEventDataMessage(NetworkEvents.Type.keepAlive, address, ProtocolMessageCode.keepAlivePresence, ka_bytes, address, endpoint);
                            }
                        }
                    }
                }
            }
Esempio n. 26
0
            // Broadcast the current block height. Called after accepting a new block once the node is fully synced
            // Returns false when no RemoteEndpoints found to send the message to
            public static bool broadcastBlockHeight(ulong blockNum, byte[] checksum)
            {
                using (MemoryStream mw = new MemoryStream())
                {
                    using (BinaryWriter writerw = new BinaryWriter(mw))
                    {
                        Block tmp_block = IxianHandler.getLastBlock();

                        // Send the block height
                        writerw.Write(blockNum);

                        // Send the block checksum for this balance
                        writerw.Write(checksum.Length);
                        writerw.Write(checksum);

                        return(CoreProtocolMessage.broadcastProtocolMessage(new char[] { 'C' }, ProtocolMessageCode.blockHeight, mw.ToArray(), null, null));
                    }
                }
            }
        // Checks for missing clients
        private static void reconnectClients()
        {
            Random rnd = new Random();

            // Wait 5 seconds before starting the loop
            Thread.Sleep(CoreConfig.networkClientReconnectInterval);

            while (autoReconnect)
            {
                TLC.Report();
                handleDisconnectedClients();

                // Check if we need to connect to more neighbors
                if (getConnectedClients().Count() < CoreConfig.simultaneousConnectedNeighbors)
                {
                    // Scan for and connect to a new neighbor
                    connectToRandomNeighbor();
                }
                else if (getConnectedClients().Count() > CoreConfig.simultaneousConnectedNeighbors)
                {
                    List <NetworkClient> netClients = null;
                    lock (networkClients)
                    {
                        netClients = new List <NetworkClient>(networkClients);
                    }
                    CoreProtocolMessage.sendBye(netClients[0], ProtocolByeCode.bye, "Disconnected for shuffling purposes.", "", false);

                    lock (networkClients)
                    {
                        networkClients.Remove(netClients[0]);
                    }
                }

                // Connect randomly to a new node. Currently a 1% chance to reconnect during this iteration
                if (rnd.Next(100) == 1)
                {
                    connectToRandomNeighbor();
                }

                // Wait 5 seconds before rechecking
                Thread.Sleep(CoreConfig.networkClientReconnectInterval);
            }
        }
Esempio n. 28
0
        private int getDataLengthFromMessageHeader(List <byte> header)
        {
            int data_length = -1;

            // we should have the full header, save the data length
            using (MemoryStream m = new MemoryStream(header.ToArray()))
            {
                using (BinaryReader reader = new BinaryReader(m))
                {
                    reader.ReadByte();                           // skip start byte
                    int code = reader.ReadInt32();               // skip message code
                    data_length = reader.ReadInt32();            // finally read data length
                    byte[] data_checksum = reader.ReadBytes(32); // skip checksum sha512qu/sha512sq, 32 bytes
                    byte   checksum      = reader.ReadByte();    // header checksum byte
                    byte   endByte       = reader.ReadByte();    // end byte

                    if (endByte != 'I')
                    {
                        Logging.warn("Header end byte was not 'I'");
                        return(-1);
                    }

                    if (CoreProtocolMessage.getHeaderChecksum(header.Take(41).ToArray()) != checksum)
                    {
                        Logging.warn(String.Format("Header checksum mismatch"));
                        return(-1);
                    }

                    if (data_length <= 0)
                    {
                        Logging.warn(String.Format("Data length was {0}, code {1}", data_length, code));
                        return(-1);
                    }

                    if (data_length > CoreConfig.maxMessageSize)
                    {
                        Logging.warn(String.Format("Received data length was bigger than max allowed message size - {0}, code {1}.", data_length, code));
                        return(-1);
                    }
                }
            }
            return(data_length);
        }
Esempio n. 29
0
        // Parse thread
        protected void parseLoop()
        {
            // Prepare an special message object to use while sending, without locking up the queue messages
            QueueMessageRaw active_message = new QueueMessageRaw();

            while (running)
            {
                TLC.Report();
                try
                {
                    bool message_found = false;
                    lock (recvRawQueueMessages)
                    {
                        if (recvRawQueueMessages.Count > 0)
                        {
                            // Pick the oldest message
                            QueueMessageRaw candidate = recvRawQueueMessages[0];
                            active_message.data     = candidate.data;
                            active_message.endpoint = candidate.endpoint;
                            // Remove it from the queue
                            recvRawQueueMessages.Remove(candidate);
                            message_found = true;
                        }
                    }

                    if (message_found)
                    {
                        // Active message set, add it to Network Queue
                        CoreProtocolMessage.readProtocolMessage(active_message.data, this);
                    }
                    else
                    {
                        Thread.Sleep(10);
                    }
                }
                catch (Exception e)
                {
                    Logging.error(String.Format("Exception occured for client {0} in parseLoopRE: {1} ", getFullAddress(), e));
                }
                // Sleep a bit to prevent cpu waste
                Thread.Yield();
            }
        }
Esempio n. 30
0
        // Called when receiving a transaction signature from a client
        public static void receivedTransactionSignature(byte[] bytes, RemoteEndpoint endpoint)
        {
            using (MemoryStream m = new MemoryStream(bytes))
            {
                using (BinaryReader reader = new BinaryReader(m))
                {
                    // Read the message ID
                    string messageID  = reader.ReadString();
                    int    sig_length = reader.ReadInt32();
                    if (sig_length <= 0)
                    {
                        Logging.warn("Incorrect signature length received.");
                        return;
                    }

                    // Read the signature
                    byte[] signature = reader.ReadBytes(sig_length);

                    lock (transactions)
                    {
                        // Find the transaction with a matching message id
                        StreamTransaction tx = transactions.Find(x => x.messageID.Equals(messageID, StringComparison.Ordinal));
                        if (tx == null)
                        {
                            Logging.warn("No transaction found to match signature messageID.");
                            return;
                        }

                        // Compose a new transaction and apply the received signature
                        Transaction transaction = new Transaction(tx.transaction);
                        transaction.signature = signature;

                        // Verify the signed transaction
                        if (transaction.verifySignature(transaction.pubKey, null))
                        {
                            // Broadcast the transaction
                            CoreProtocolMessage.broadcastProtocolMessage(new char[] { 'M', 'H' }, ProtocolMessageCode.transactionData, transaction.getBytes(), null, endpoint);
                        }
                        return;
                    }
                }
            }
        }