From a91d9016a81198af3f170711dd5934a8e1268387 Mon Sep 17 00:00:00 2001 From: ardocrat Date: Fri, 19 Jun 2026 14:46:49 +0300 Subject: [PATCH] node: ability to launch API, P2P and Stratum at all interfaces with IPv6 support --- locales/de.yml | 1 + locales/en.yml | 1 + locales/fr.yml | 1 + locales/ru.yml | 1 + locales/tr.yml | 1 + locales/zh-CN.yml | 1 + src/gui/views/network/connections.rs | 11 +- src/gui/views/network/settings.rs | 98 +++++++---- src/gui/views/network/setup/node.rs | 9 +- src/gui/views/network/setup/p2p.rs | 36 +++- src/node/config.rs | 246 +++++++++++++++++++-------- src/tor/tor.rs | 3 - src/wallet/wallet.rs | 5 +- 13 files changed, 289 insertions(+), 125 deletions(-) diff --git a/locales/de.yml b/locales/de.yml index 0adefba..9a05bba 100644 --- a/locales/de.yml +++ b/locales/de.yml @@ -302,6 +302,7 @@ network_settings: max_outbound_count: 'Maximale Anzahl von ausgehenden Peer-Verbindungen:' reset_data_desc: Reset-Knotendaten. Verwenden Sie diese Funktion nur, wenn es Probleme mit der Synchronisation gibt. reset_data: Daten zurücksetzten + ip_listen_all: Hören Sie auf allen Schnittstellen modal: cancel: Abbrechen save: Speichern diff --git a/locales/en.yml b/locales/en.yml index 27e4bed..bf04432 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -302,6 +302,7 @@ network_settings: max_outbound_count: 'Maximum number of outbound peer connections:' reset_data_desc: Reset the node data. Use it with a caution only if there are problems with synchronization. reset_data: Reset data + ip_listen_all: Listen on all interfaces modal: cancel: Cancel save: Save diff --git a/locales/fr.yml b/locales/fr.yml index 6e3b272..1da1aee 100644 --- a/locales/fr.yml +++ b/locales/fr.yml @@ -302,6 +302,7 @@ network_settings: max_outbound_count: 'Nombre maximum de connexions de pairs sortants :' reset_data_desc: Réinitialisez les données du noeud. Utilisez-le avec prudence uniquement en cas de problème de synchronisation. reset_data: Réinitialisation des données + ip_listen_all: Écoutez sur toutes les interfaces modal: cancel: Annuler save: Sauvegarder diff --git a/locales/ru.yml b/locales/ru.yml index aff6ca4..d65d576 100644 --- a/locales/ru.yml +++ b/locales/ru.yml @@ -302,6 +302,7 @@ network_settings: max_outbound_count: 'Максимальное количество исходящих подключений к пирам:' reset_data_desc: Сбросить данные узла. Используйте с осторожностью, только при наличии проблем с синхронизацией. reset_data: Сброс данных + ip_listen_all: Слушать на всех интерфейсах modal: cancel: Отмена save: Сохранить diff --git a/locales/tr.yml b/locales/tr.yml index dc30887..b15bd91 100644 --- a/locales/tr.yml +++ b/locales/tr.yml @@ -302,6 +302,7 @@ network_settings: max_outbound_count: 'Maksimum giden Peer baglanti sayisi:' reset_data_desc: Node verisini sifirlama. Sadece senkronizasyonda sorun varsa dikkatli kullanin. reset_data: Verileri sifirlama + ip_listen_all: Tüm arayüzlerde dinle modal: cancel: Iptal save: Kaydet diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml index fe9d118..e830520 100644 --- a/locales/zh-CN.yml +++ b/locales/zh-CN.yml @@ -302,6 +302,7 @@ network_settings: max_outbound_count: '最大出站网络对点连接数:' reset_data_desc: 重置节点数据。只有在出现同步问题时才需谨慎使用. reset_data: 重置数据 + ip_listen_all: 在所有接口上监听 modal: cancel: 取消 save: 保存 diff --git a/src/gui/views/network/connections.rs b/src/gui/views/network/connections.rs index b21f4f0..f941dfc 100644 --- a/src/gui/views/network/connections.rs +++ b/src/gui/views/network/connections.rs @@ -105,8 +105,9 @@ impl ContentContainer for ConnectionsContent { |ui| { let r = View::item_rounding(0, 1, true); View::item_button(ui, r, QR_CODE, None, || { + let (api_address, api_port) = NodeConfig::get_api_address(); if let Ok(c) = ShareConnectionContent::new(ShareConnection { - url: format!("http://{}", NodeConfig::get_api_address()), + url: format!("http://{}:{}", api_address, api_port), username: "grin".to_string(), secret: NodeConfig::get_api_secret(true).unwrap_or("".to_string()), }) { @@ -277,9 +278,11 @@ impl ConnectionsContent { ui.add_space(1.0); // Setup node API address text. - let api_address = NodeConfig::get_api_address(); - let address_text = - format!("{} http://{}", COMPUTER_TOWER, api_address); + let (api_address, api_port) = NodeConfig::get_api_address(); + let address_text = format!( + "{} http://{}:{}", + COMPUTER_TOWER, api_address, api_port + ); ui.label( RichText::new(address_text).size(15.0).color(Colors::gray()), ); diff --git a/src/gui/views/network/settings.rs b/src/gui/views/network/settings.rs index 17606c2..322234b 100644 --- a/src/gui/views/network/settings.rs +++ b/src/gui/views/network/settings.rs @@ -12,9 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -use egui::scroll_area::ScrollBarVisibility; -use egui::{RichText, ScrollArea}; - use crate::gui::Colors; use crate::gui::icons::{ARROW_COUNTER_CLOCKWISE, TRASH}; use crate::gui::platform::PlatformCallbacks; @@ -26,6 +23,9 @@ use crate::gui::views::types::{ContentContainer, ModalPosition}; use crate::gui::views::{Content, Modal, View}; use crate::node::{Node, NodeConfig}; +use egui::scroll_area::ScrollBarVisibility; +use egui::{RichText, ScrollArea}; + /// Integrated node settings tab content. pub struct NetworkSettings { /// Integrated node general setup content. @@ -162,39 +162,75 @@ impl NetworkSettings { ips: &Vec, on_change: impl FnOnce(&String), ) { - let mut selected_ip = saved_ip; - - // Set first IP address as current if saved is not present at system. - if !ips.contains(saved_ip) { - selected_ip = ips.get(0).unwrap(); + let mut all = NodeConfig::ALL_INTERFACES.to_string(); + let all_ips = saved_ip == &all || saved_ip == &format!("[{}]", &all); + if all_ips { + all = saved_ip.clone(); } - ui.add_space(2.0); + let mut selected_ip = saved_ip.clone(); - // Show available IP addresses on the system. - let _ = ips - .chunks(2) - .map(|x| { - if x.len() == 2 { - ui.columns(2, |columns| { - let ip_left = x.get(0).unwrap(); - columns[0].vertical_centered(|ui| { - View::radio_value(ui, &mut selected_ip, ip_left, ip_left.to_string()); + let mut listen_all_changed = false; + View::checkbox(ui, all_ips, t!("network_settings.ip_listen_all"), || { + listen_all_changed = true; + }); + if listen_all_changed { + let new_ip = if all_ips { + ips.get(0).unwrap_or(&all).clone() + } else { + all.clone() + }; + selected_ip = new_ip; + } + + ui.add_space(8.0); + + if selected_ip != all { + // Set first IP address as current if saved is not present at system. + if !ips.contains(&saved_ip) { + selected_ip = ips.get(0).unwrap().clone(); + } + + // Show available IP addresses on the system. + let _ = ips + .chunks(2) + .map(|x| { + if x.len() == 2 { + ui.columns(2, |columns| { + let ip_left = x.get(0).unwrap(); + let val = if all_ips { + &mut ip_left.clone() + } else { + &mut selected_ip + }; + columns[0].vertical_centered(|ui| { + View::radio_value(ui, val, ip_left.clone(), ip_left.to_string()); + }); + let ip_right = x.get(1).unwrap(); + let val = if all_ips { + &mut ip_right.clone() + } else { + &mut selected_ip + }; + columns[1].vertical_centered(|ui| { + View::radio_value(ui, val, ip_right.clone(), ip_right.to_string()); + }) }); - let ip_right = x.get(1).unwrap(); - columns[1].vertical_centered(|ui| { - View::radio_value(ui, &mut selected_ip, ip_right, ip_right.to_string()); - }) - }); - } else { - let ip = x.get(0).unwrap(); - View::radio_value(ui, &mut selected_ip, ip, ip.to_string()); - } - ui.add_space(12.0); - }) - .collect::>(); + } else { + let ip = x.get(0).unwrap(); + let val = if all_ips { + &mut ip.clone() + } else { + &mut selected_ip + }; + View::radio_value(ui, val, ip.clone(), ip.to_string()); + } + ui.add_space(12.0); + }) + .collect::>(); + } - if saved_ip != selected_ip { + if saved_ip != &selected_ip { on_change(&selected_ip.to_string()); } } diff --git a/src/gui/views/network/setup/node.rs b/src/gui/views/network/setup/node.rs index 1f03040..d3c49ae 100644 --- a/src/gui/views/network/setup/node.rs +++ b/src/gui/views/network/setup/node.rs @@ -67,7 +67,7 @@ const FTL_MODAL: &'static str = "node_ftl"; impl Default for NodeSetup { fn default() -> Self { - let (api_ip, api_port) = NodeConfig::get_api_ip_port(); + let (api_ip, api_port) = NodeConfig::get_api_address(); let is_api_port_available = NodeConfig::is_api_port_available(&api_ip, &api_port); Self { data_path_edit: NodeConfig::get_chain_data_path(), @@ -204,7 +204,7 @@ impl ContentContainer for NodeSetup { ui.add_space(6.0); // Show API IP addresses to select. - let (api_ip, api_port) = NodeConfig::get_api_ip_port(); + let (api_ip, api_port) = NodeConfig::get_api_address(); NetworkSettings::ip_addrs_ui(ui, &api_ip, &self.available_ips, |selected_ip| { let api_available = NodeConfig::is_api_port_available(selected_ip, &api_port); self.is_api_port_available = api_available; @@ -416,7 +416,7 @@ impl NodeSetup { ); ui.add_space(6.0); - let (_, port) = NodeConfig::get_api_ip_port(); + let (_, port) = NodeConfig::get_api_address(); View::button( ui, format!("{} {}", PLUG, &port), @@ -436,6 +436,7 @@ impl NodeSetup { ui.add_space(6.0); if !self.is_api_port_available { + ui.add_space(6.0); // Show error when API server port is unavailable. ui.label( RichText::new(t!("network_settings.port_unavailable")) @@ -451,7 +452,7 @@ impl NodeSetup { fn api_port_modal(&mut self, ui: &mut egui::Ui, modal: &Modal, cb: &dyn PlatformCallbacks) { let on_save = |c: &mut NodeSetup| { // Check if port is available. - let (api_ip, _) = NodeConfig::get_api_ip_port(); + let (api_ip, _) = NodeConfig::get_api_address(); let available = NodeConfig::is_api_port_available(&api_ip, &c.api_port_edit); c.api_port_available_edit = available; if available { diff --git a/src/gui/views/network/setup/p2p.rs b/src/gui/views/network/setup/p2p.rs index 4dfdbf9..acd4dc5 100644 --- a/src/gui/views/network/setup/p2p.rs +++ b/src/gui/views/network/setup/p2p.rs @@ -45,6 +45,9 @@ pub struct P2PSetup { /// Flag to check if p2p port is available. port_available_edit: bool, + /// IP Addresses available at system. + available_ips: Vec, + /// Flag to check if p2p port from saved config value is available. is_port_available: bool, @@ -90,7 +93,8 @@ pub const MAX_OUTBOUND_MODAL: &'static str = "p2p_max_outbound"; impl Default for P2PSetup { fn default() -> Self { let port = NodeConfig::get_p2p_port(); - let is_port_available = NodeConfig::is_p2p_port_available(&port); + let ip = NodeConfig::get_p2p_host(); + let is_port_available = NodeConfig::is_p2p_port_available(&ip, &port); let default_main_seeds = Node::MAINNET_DNS_SEEDS .iter() .map(|s| s.to_string()) @@ -102,9 +106,10 @@ impl Default for P2PSetup { Self { port_edit: port, port_available_edit: is_port_available, + available_ips: NodeConfig::get_ip_addrs(), + is_port_available, address_check: Bind::new(false), address_available: Some(true), - is_port_available, peer_edit: "".to_string(), default_main_seeds, default_test_seeds, @@ -152,8 +157,8 @@ impl ContentContainer for P2PSetup { ui.add_space(6.0); ui.vertical_centered(|ui| { - // Show p2p port setup. - self.port_ui(ui); + // Show p2p address setup. + self.address_ui(ui); ui.add_space(6.0); View::horizontal_line(ui, Colors::item_stroke()); @@ -229,8 +234,14 @@ impl ContentContainer for P2PSetup { const DNS_SEEDS_TITLE: &'static str = "DNS Seeds"; impl P2PSetup { - /// Draw p2p port setup content. - fn port_ui(&mut self, ui: &mut egui::Ui) { + /// Draw p2p address setup content. + fn address_ui(&mut self, ui: &mut egui::Ui) { + // Show message when IP addresses are not available on the system. + if self.available_ips.is_empty() { + NetworkSettings::no_ip_address_ui(ui); + return; + } + ui.label( RichText::new(t!("network_settings.p2p_port")) .size(16.0) @@ -238,7 +249,17 @@ impl P2PSetup { ); ui.add_space(6.0); + let ip = NodeConfig::get_p2p_host(); let port = NodeConfig::get_p2p_port(); + + NetworkSettings::ip_addrs_ui(ui, &ip, &self.available_ips, |selected_ip| { + NodeConfig::save_p2p_host(selected_ip); + let p2p_available = NodeConfig::is_p2p_port_available(selected_ip, &port); + self.is_port_available = p2p_available; + }); + + ui.add_space(6.0); + View::button( ui, format!("{} {}", PLUG, &port), @@ -272,7 +293,8 @@ impl P2PSetup { fn port_modal(&mut self, ui: &mut egui::Ui, modal: &Modal, cb: &dyn PlatformCallbacks) { let on_save = |c: &mut P2PSetup| { // Check if port is available. - let available = NodeConfig::is_p2p_port_available(&c.port_edit); + let ip = NodeConfig::get_p2p_host(); + let available = NodeConfig::is_p2p_port_available(&ip, &c.port_edit); c.port_available_edit = available; // Save port at config if it's available. diff --git a/src/node/config.rs b/src/node/config.rs index 04286c5..e3df15e 100644 --- a/src/node/config.rs +++ b/src/node/config.rs @@ -16,7 +16,7 @@ use local_ip_address::list_afinet_netifas; use serde::{Deserialize, Serialize}; use std::fs::File; use std::io::{BufRead, BufReader, Write}; -use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, TcpListener, ToSocketAddrs}; +use std::net::{IpAddr, SocketAddr, TcpListener, ToSocketAddrs}; use std::path::PathBuf; use std::str::FromStr; @@ -29,6 +29,7 @@ use grin_p2p::msg::PeerAddrs; use grin_p2p::{PeerAddr, Seeding}; use grin_servers::common::types::ChainValidationMode; use rand::Rng; +use url::Url; use crate::node::Node; use crate::{AppConfig, Settings}; @@ -136,6 +137,9 @@ pub struct NodeConfig { } impl NodeConfig { + /// To launch on all available interfaces (including IPv6). + pub const ALL_INTERFACES: &str = "::"; + /// Initialize config fields from provided [`ChainTypes`]. pub fn for_chain_type(chain_type: &ChainTypes) -> Self { // Check secret files for current chain type. @@ -210,8 +214,7 @@ impl NodeConfig { (api, p2p) } }; - let api_addr = config.server.api_http_addr.split_once(":").unwrap().0; - config.server.api_http_addr = format!("{}:{}", api_addr, api); + config.server.api_http_addr = format!("127.0.0.1:{}", api); config.server.p2p_config.port = p2p; } @@ -290,30 +293,18 @@ impl NodeConfig { /// Check whether a port is available on the provided host. fn is_host_port_available(host: &String, port: &String) -> bool { + if host == Self::ALL_INTERFACES { + return true; + } if let Ok(p) = port.parse::() { - let ip_addr = Ipv4Addr::from_str(host.as_str()).unwrap(); - let ipv4 = SocketAddrV4::new(ip_addr, p); - return TcpListener::bind(ipv4).is_ok(); + if let Ok(ip) = IpAddr::from_str(&host) { + let addr = SocketAddr::new(ip, p); + return TcpListener::bind(addr).is_ok(); + } } false } - /// Check whether a port is available across the system at all hosts. - fn is_port_available(port: &String) -> bool { - if let Ok(p) = port.parse::() { - for ip in Self::get_ip_addrs() { - let ip_addr = Ipv4Addr::from_str(ip.as_str()).unwrap(); - let ipv4 = SocketAddrV4::new(ip_addr, p); - if TcpListener::bind(ipv4).is_err() { - return false; - } - } - } else { - return false; - } - true - } - /// Get chain data path. pub fn get_chain_data_path() -> String { let r_config = Settings::node_config_to_read(); @@ -327,6 +318,60 @@ impl NodeConfig { w_config.save(); } + /// Get default Stratum server port. + fn default_stratum_port() -> u16 { + match AppConfig::chain_type() { + ChainTypes::Mainnet => 3416, + _ => 13416, + } + } + + /// Format address to support ipv6. + fn format_address(ip: &String, port: &String) -> String { + let addr = if ip.contains(Self::ALL_INTERFACES) { + &format!("[{}]", ip) + } else { + ip + }; + format!("{}:{}", addr, port) + } + + /// Parse host to support ipv6. + fn parse_host(host: &String) -> String { + if host.contains(Self::ALL_INTERFACES) { + host.replace("[", "").replace("]", "") + } else { + host.to_string() + } + } + + /// Parse saved address, returning default host or port on fail. + fn parse_address_port( + addr: &String, + default_host: &str, + default_port: u16, + ) -> (String, String) { + let addr = if addr.contains("http") { + addr.to_string() + } else { + format!("http://{}", addr) + }; + if let Ok(url) = Url::parse(addr.as_str()) { + let host = if let Some(h) = url.host() { + Self::parse_host(&h.to_string()) + } else { + default_host.to_string() + }; + let port = if let Some(p) = url.port() { + p.to_string() + } else { + default_port.to_string() + }; + return (host, port); + } + (default_host.to_string(), default_port.to_string()) + } + /// Get stratum server IP address and port. pub fn get_stratum_address() -> (String, String) { let r_config = Settings::node_config_to_read(); @@ -339,13 +384,16 @@ impl NodeConfig { .stratum_server_addr .as_ref() .unwrap(); - let (addr, port) = saved_stratum_addr.split_once(":").unwrap(); - (addr.into(), port.into()) + Self::parse_address_port( + saved_stratum_addr, + "127.0.0.1", + Self::default_stratum_port(), + ) } /// Save stratum server IP address and port. - pub fn save_stratum_address(addr: &String, port: &String) { - let addr_to_save = format!("{}:{}", addr, port); + pub fn save_stratum_address(host: &String, port: &String) { + let addr_to_save = Self::format_address(host, port); let mut w_config = Settings::node_config_to_update(); w_config .node @@ -358,28 +406,32 @@ impl NodeConfig { } /// Check if stratum server port is available across the system and config. - pub fn is_stratum_port_available(ip: &String, port: &String) -> bool { - if Node::get_stratum_stats().is_running { - // Check if Stratum server with same address is running. - let (cur_ip, cur_port) = Self::get_stratum_address(); - let same_running = ip == &cur_ip && port == &cur_port; - return same_running || Self::is_not_running_stratum_port_available(ip, port); - } - Self::is_not_running_stratum_port_available(&ip, &port) - } + pub fn is_stratum_port_available(host: &String, port: &String) -> bool { + let host = Self::parse_host(host); - /// Check if stratum port is available when server is not running. - fn is_not_running_stratum_port_available(ip: &String, port: &String) -> bool { - if Self::is_host_port_available(&ip, &port) { - if &Self::get_p2p_port() != port { - let (api_ip, api_port) = Self::get_api_ip_port(); - return if &api_ip == ip { - &api_port != port - } else { - true - }; + // Check if Stratum server with same address is running. + if Node::get_stratum_stats().is_running { + let (cur_ip, cur_port) = Self::get_stratum_address(); + let same_running = host == cur_ip && port == &cur_port; + if same_running { + return true; } } + + // Check if address not conflicts with p2p and api. + if Self::is_host_port_available(&host, &port) { + let p2p_ip = Self::get_p2p_host(); + let p2p_port = Self::get_p2p_port(); + if p2p_ip == host && &p2p_port == port { + return false; + } + let (api_ip, api_port) = Self::get_api_address(); + return if api_ip == host { + &api_port != port + } else { + true + }; + } false } @@ -493,38 +545,55 @@ impl NodeConfig { w_config.save(); } - /// Get API server address. - pub fn get_api_address() -> String { - let r_config = Settings::node_config_to_read(); - r_config.node.server.api_http_addr.clone() + /// Get default Stratum server port. + fn default_api_port() -> u16 { + match AppConfig::chain_type() { + ChainTypes::Mainnet => 3413, + _ => 13413, + } } /// Get API server IP and port. - pub fn get_api_ip_port() -> (String, String) { - let saved_addr = Self::get_api_address(); - let (addr, port) = saved_addr.split_once(":").unwrap(); - (addr.into(), port.into()) + pub fn get_api_address() -> (String, String) { + let r_config = Settings::node_config_to_read(); + let saved_api_addr = r_config.node.server.api_http_addr.clone(); + Self::parse_address_port(&saved_api_addr, "127.0.0.1", Self::default_api_port()) } /// Save API server IP address and port. pub fn save_api_address(addr: &String, port: &String) { - let addr_to_save = format!("{}:{}", addr, port); + let addr_to_save = Self::format_address(addr, port); let mut w_config = Settings::node_config_to_update(); w_config.node.server.api_http_addr = addr_to_save; w_config.save(); } /// Check if api server port is available across the system and config. - pub fn is_api_port_available(ip: &String, port: &String) -> bool { + pub fn is_api_port_available(host: &String, port: &String) -> bool { + let host = Self::parse_host(host); + + // Check if API server with same address is running. if Node::is_running() { - // Check if API server with same address is running. - let same_running = NodeConfig::get_api_address() == format!("{}:{}", ip, port); - if same_running || Self::is_host_port_available(ip, port) { - return &Self::get_p2p_port() != port; + let (cur_ip, cur_port) = Self::get_api_address(); + let same_running = host == cur_ip && port == &cur_port; + if same_running { + return true; } - return false; - } else if Self::is_host_port_available(ip, port) { - return &Self::get_p2p_port() != port; + } + + // Check if address not conflicts with p2p and stratum. + if Self::is_host_port_available(&host, port) { + let p2p_ip = Self::get_p2p_host(); + let p2p_port = Self::get_p2p_port(); + if p2p_ip == host && &p2p_port == port { + return false; + } + let (str_ip, str_port) = Self::get_stratum_address(); + return if str_ip == host { + &str_port != port + } else { + true + }; } false } @@ -662,6 +731,25 @@ impl NodeConfig { w_config.save(); } + /// Get P2P server IP address. + pub fn get_p2p_host() -> String { + let host = Settings::node_config_to_read() + .node + .server + .p2p_config + .host + .to_string(); + Self::parse_host(&host) + } + + /// Get P2P server IP address. + pub fn save_p2p_host(host: &String) { + let mut w_config = Settings::node_config_to_update(); + w_config.node.server.p2p_config.host = + IpAddr::from_str(host).unwrap_or(IpAddr::from_str(Self::ALL_INTERFACES).unwrap()); + w_config.save(); + } + /// Get P2P server port. pub fn get_p2p_port() -> String { Settings::node_config_to_read() @@ -673,20 +761,30 @@ impl NodeConfig { } /// Check if P2P server port is available across the system and config. - pub fn is_p2p_port_available(port: &String) -> bool { - if port.parse::().is_err() { - return false; - } - let (_, api_port) = Self::get_api_ip_port(); + pub fn is_p2p_port_available(host: &String, port: &String) -> bool { + let host = Self::parse_host(host); + + // Check if P2P server with same address is running. if Node::is_running() { - // Check if P2P server with same port is running. - let same_running = &NodeConfig::get_p2p_port() == port; - if same_running || Self::is_port_available(port) { - return &api_port != port; + let same_running = + &NodeConfig::get_p2p_port() == port && NodeConfig::get_p2p_host() == host; + if same_running { + return true; } - return false; - } else if Self::is_port_available(port) { - return &api_port != port; + } + + // Check if address not conflicts with stratum and api. + if Self::is_host_port_available(&host, &port) { + let (str_ip, str_port) = Self::get_stratum_address(); + if str_ip == host && &str_port == port { + return false; + } + let (api_ip, api_port) = Self::get_api_address(); + return if api_ip == host { + &api_port != port + } else { + true + }; } false } diff --git a/src/tor/tor.rs b/src/tor/tor.rs index f9b8688..c376a90 100644 --- a/src/tor/tor.rs +++ b/src/tor/tor.rs @@ -29,13 +29,10 @@ use safelog::DisplayRedacted; use sha2::Sha512; use std::collections::{BTreeMap, BTreeSet}; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; -use std::str::FromStr; use std::sync::Arc; use std::sync::atomic::{AtomicBool, Ordering}; use std::time::Duration; use std::{fs, thread}; -use tls_api::{TlsConnector as TlsConnectorTrait, TlsConnectorBuilder}; -use tls_api_native_tls::TlsConnector; use tor_hscrypto::pk::{HsIdKey, HsIdKeypair}; use tor_hsrproxy::OnionServiceReverseProxy; use tor_hsrproxy::config::{ diff --git a/src/wallet/wallet.rs b/src/wallet/wallet.rs index 48d04c8..a26692c 100644 --- a/src/wallet/wallet.rs +++ b/src/wallet/wallet.rs @@ -235,7 +235,8 @@ impl Wallet { /// Create [`HTTPNodeClient`] from provided config. fn create_node_client(config: &WalletConfig) -> Result { let integrated = || { - let api_url = format!("http://{}", NodeConfig::get_api_address()); + let (api_address, api_port) = NodeConfig::get_api_address(); + let api_url = format!("http://{}:{}", api_address, api_port); let api_secret = NodeConfig::get_api_secret(true); (api_url, api_secret) }; @@ -2222,7 +2223,7 @@ fn start_api_server(wallet: &Wallet) -> Result<(ApiServer, u16), Error> { return match TcpListener::bind((host, port.to_owned())) { Ok(_) => { let node_p2p_port = NodeConfig::get_p2p_port(); - let node_api_port = NodeConfig::get_api_ip_port().1; + let node_api_port = NodeConfig::get_api_address().1; let free = port.to_string() != node_p2p_port && port.to_string() != node_api_port; if free {