static public void configureNetwork(string externalIp, int port) { // Network configuration UPnP upnp = new UPnP(); IxianHandler.publicPort = port; if (externalIp != "" && IPAddress.TryParse(externalIp, out _)) { IxianHandler.publicIP = externalIp; } else { IxianHandler.publicIP = ""; List <IPAndMask> local_ips = CoreNetworkUtils.GetAllLocalIPAddressesAndMasks(); foreach (IPAndMask local_ip in local_ips) { if (IPv4Subnet.IsPublicIP(local_ip.Address)) { Logging.info(String.Format("Public IP detected: {0}, mask {1}.", local_ip.Address.ToString(), local_ip.SubnetMask.ToString())); IxianHandler.publicIP = local_ip.Address.ToString(); } } if (IxianHandler.publicIP == "") { IPAddress primary_local = CoreNetworkUtils.GetPrimaryIPAddress(); if (primary_local == null) { Logging.warn("Unable to determine primary IP address."); } else { Logging.warn(String.Format("None of the locally configured IP addresses are public. Attempting UPnP...")); Task <IPAddress> public_ip = upnp.GetExternalIPAddress(); if (public_ip.Wait(1000)) { if (public_ip.Result != null) { Logging.info(String.Format("UPNP-determined public IP: {0}. Attempting to configure a port-forwarding rule.", public_ip.Result.ToString())); if (upnp.MapPublicPort(port, primary_local)) { IxianHandler.publicIP = public_ip.Result.ToString(); //upnp.getMappedIP(); Logging.info(string.Format("Network configured. Public IP is: {0}", IxianHandler.publicIP)); } else { Logging.warn("UPnP configuration failed, please set port forwarding for port {0} manually.", port); } } else { Logging.warn("UPnP configuration failed, please set port forwarding for port {0} manually.", port); } } } } } }
// Starts the Network Client Manager. First it connects to one of the seed nodes in order to fetch the Presence List. // Afterwards, it starts the reconnect and keepalive threads public static void start() { if (running) { return; } if (CoreConfig.preventNetworkOperations) { Logging.warn("Not starting NetworkClientManager thread due to preventNetworkOperations flag being set."); return; } running = true; networkClients = new List <NetworkClient>(); PeerStorage.readPeersFile(); // Now add the seed nodes to the list foreach (string[] addr in CoreNetworkUtils.getSeedNodes(CoreConfig.isTestNet)) { byte[] wallet_addr = null; if (addr[1] != null) { wallet_addr = Base58Check.Base58CheckEncoding.DecodePlain(addr[1]); } PeerStorage.addPeerToPeerList(addr[0], wallet_addr, false); } // Connect to a random node first bool firstSeedConnected = false; while (firstSeedConnected == false && IxianHandler.forceShutdown == false) { Peer p = PeerStorage.getRandomMasterNodeAddress(); if (p != null) { firstSeedConnected = connectTo(p.hostname, p.walletAddress); } if (firstSeedConnected == false) { Thread.Sleep(1000); } } // Start the reconnect thread TLC = new ThreadLiveCheck(); reconnectThread = new Thread(reconnectClients); reconnectThread.Name = "Network_Client_Manager_Reconnect"; autoReconnect = true; reconnectThread.Start(); }
// Returns a random new potential neighbor. Returns null if no new neighbor is found. public static Peer scanForNeighbor() { Peer connectToPeer = null; // Find only masternodes while (connectToPeer == null) { Thread.Sleep(10); bool addr_valid = true; if (getConnectedClients(true).Count() == 0) { PeerStorage.resetInitialConnectionCount(); } Peer p = PeerStorage.getRandomMasterNodeAddress(); if (p == null) { break; } // Next, check if we're connecting to a self address of this node string[] server = p.hostname.Split(':'); if (server.Length < 2) { break; } // Resolve the hostname first string resolved_server_name = NetworkUtils.resolveHostname(server[0]); string resolved_server_name_with_port = resolved_server_name + ":" + server[1]; // Check if we are already connected to this address lock (networkClients) { foreach (NetworkClient client in networkClients) { if (client.getFullAddress(true).Equals(resolved_server_name_with_port, StringComparison.Ordinal)) { // Address is already in the client list addr_valid = false; break; } } } // Check if node is already in the server list string[] connectedClients = NetworkServer.getConnectedClients(true); for (int i = 0; i < connectedClients.Length; i++) { if (connectedClients[i].Equals(resolved_server_name_with_port, StringComparison.Ordinal)) { // Address is already in the client list addr_valid = false; break; } } if (addr_valid == false) { continue; } // Check against connecting clients list as well lock (connectingClients) { foreach (string client in connectingClients) { if (resolved_server_name_with_port.Equals(client, StringComparison.Ordinal)) { // Address is already in the connecting client list addr_valid = false; break; } } } if (addr_valid == false) { continue; } if (NetworkServer.isRunning()) { // Get all self addresses and run through them List <string> self_addresses = CoreNetworkUtils.GetAllLocalIPAddresses(); foreach (string self_address in self_addresses) { // Don't connect to self if (resolved_server_name.Equals(self_address, StringComparison.Ordinal)) { if (server[1].Equals(string.Format("{0}", IxianHandler.publicPort), StringComparison.Ordinal)) { addr_valid = false; } } } } // If the address is valid, add it to the candidates if (addr_valid) { connectToPeer = p; } } return(connectToPeer); }
// Starts the Network Client Manager. // If connections_to_wait_for parameter is bigger than 0, it waits until it connects to the specified number of nodes. // Afterwards, it starts the reconnect and keepalive threads public static void start(int connections_to_wait_for = 0) { if (running) { return; } if (CoreConfig.preventNetworkOperations) { Logging.warn("Not starting NetworkClientManager thread due to preventNetworkOperations flag being set."); return; } running = true; networkClients = new List <NetworkClient>(); connectingClients = new List <string>(); PeerStorage.readPeersFile(); // Now add the seed nodes to the list foreach (string[] addr in CoreNetworkUtils.getSeedNodes(IxianHandler.networkType)) { byte[] wallet_addr = null; if (addr[1] != null) { wallet_addr = Base58Check.Base58CheckEncoding.DecodePlain(addr[1]); } PeerStorage.addPeerToPeerList(addr[0], wallet_addr, Clock.getTimestamp(), 0, 1, 0, false); } if (connections_to_wait_for > 0) { Random rnd = new Random(); // Connect to a random node first int i = 0; while (getConnectedClients(true).Count() < connections_to_wait_for && IxianHandler.forceShutdown == false) { new Thread(() => { reconnectClients(rnd); }).Start(); i++; if (i > 10) { i = 0; Thread.Sleep(1000); } else { Thread.Sleep(200); } if (!running) { return; } } } // Start the reconnect thread TLC = new ThreadLiveCheck(); autoReconnect = true; reconnectThread = new Thread(reconnectLoop); reconnectThread.Name = "Network_Client_Manager_Reconnect"; reconnectThread.Start(); }
// Connects to a specified node, with the syntax host:port public static bool connectTo(string host, byte[] wallet_address) { if (host == null || host.Length < 3) { Logging.error(String.Format("Invalid host address {0}", host)); return(false); } string[] server = host.Split(':'); if (server.Count() < 2) { Logging.warn(string.Format("Cannot connect to invalid hostname: {0}", host)); return(false); } // Resolve the hostname first string resolved_server_name = NetworkUtils.resolveHostname(server[0]); // Skip hostnames we can't resolve if (resolved_server_name.Length < 1) { Logging.warn(string.Format("Cannot resolve IP for {0}, skipping connection.", server[0])); return(false); } string resolved_host = string.Format("{0}:{1}", resolved_server_name, server[1]); if (NetworkServer.isRunning()) { // Verify against the publicly disclosed ip // Don't connect to self if (resolved_server_name.Equals(IxianHandler.publicIP, StringComparison.Ordinal)) { if (server[1].Equals(string.Format("{0}", IxianHandler.publicPort), StringComparison.Ordinal)) { Logging.info(string.Format("Skipping connection to public self seed node {0}", host)); return(false); } } // Get all self addresses and run through them List <string> self_addresses = CoreNetworkUtils.GetAllLocalIPAddresses(); foreach (string self_address in self_addresses) { // Don't connect to self if (resolved_server_name.Equals(self_address, StringComparison.Ordinal)) { if (server[1].Equals(string.Format("{0}", IxianHandler.publicPort), StringComparison.Ordinal)) { Logging.info(string.Format("Skipping connection to self seed node {0}", host)); return(false); } } } } lock (connectingClients) { foreach (string client in connectingClients) { if (resolved_host.Equals(client, StringComparison.Ordinal)) { // We're already connecting to this client return(false); } } // The the client to the connecting clients list connectingClients.Add(resolved_host); } // Check if node is already in the client list lock (networkClients) { foreach (NetworkClient client in networkClients) { if (client.getFullAddress(true).Equals(resolved_host, StringComparison.Ordinal)) { // Address is already in the client list return(false); } } } // Check if node is already in the server list string[] connectedClients = NetworkServer.getConnectedClients(true); for (int i = 0; i < connectedClients.Length; i++) { if (connectedClients[i].Equals(resolved_host, StringComparison.Ordinal)) { // Address is already in the client list return(false); } } // Connect to the specified node NetworkClient new_client = new NetworkClient(); // Recompose the connection address from the resolved IP and the original port bool result = new_client.connectToServer(resolved_server_name, Convert.ToInt32(server[1]), wallet_address); // Add this node to the client list if connection was successfull if (result == true) { // Add this node to the client list lock (networkClients) { networkClients.Add(new_client); } } else { new_client.stop(); } // Remove this node from the connecting clients list lock (connectingClients) { connectingClients.Remove(resolved_host); } return(result); }