Merge pull request #10378 from SomberNight/202512_network_gui_disconnected_servers
network gui: always show bookmarked servers in list
This commit is contained in:
@@ -111,28 +111,18 @@ class QEServerListModel(QAbstractListModel, QtEventListener):
|
|||||||
servers.append(server)
|
servers.append(server)
|
||||||
|
|
||||||
# disconnected servers
|
# disconnected servers
|
||||||
all_servers = self.network.get_servers()
|
for s in self.network.get_disconnected_server_addrs():
|
||||||
connected_hosts = set([iface.host for ifaces in chains.values() for iface in ifaces])
|
server = {
|
||||||
protocol = PREFERRED_NETWORK_PROTOCOL
|
'chain': '',
|
||||||
for _host, d in sorted(all_servers.items()):
|
'chain_height': 0,
|
||||||
if _host in connected_hosts:
|
'height': 0,
|
||||||
continue
|
'is_primary': False,
|
||||||
if _host.endswith('.onion') and not self.network.is_proxy_tor:
|
'is_connected': False,
|
||||||
continue
|
'name': s.to_friendly_name()
|
||||||
port = d.get(protocol)
|
}
|
||||||
if port:
|
server['address'] = server['name']
|
||||||
s = ServerAddr(_host, port, protocol=protocol)
|
|
||||||
server = {
|
|
||||||
'chain': '',
|
|
||||||
'chain_height': 0,
|
|
||||||
'height': 0,
|
|
||||||
'is_primary': False,
|
|
||||||
'is_connected': False,
|
|
||||||
'name': s.net_addr_str()
|
|
||||||
}
|
|
||||||
server['address'] = server['name']
|
|
||||||
|
|
||||||
servers.append(server)
|
servers.append(server)
|
||||||
|
|
||||||
self.beginInsertRows(QModelIndex(), 0, len(servers) - 1)
|
self.beginInsertRows(QModelIndex(), 0, len(servers) - 1)
|
||||||
self._servers = servers
|
self._servers = servers
|
||||||
|
|||||||
@@ -149,9 +149,6 @@ class NodesListWidget(QTreeWidget):
|
|||||||
def update(self):
|
def update(self):
|
||||||
self.clear()
|
self.clear()
|
||||||
network = self.network
|
network = self.network
|
||||||
servers = self.network.get_servers()
|
|
||||||
|
|
||||||
use_tor = bool(network.is_proxy_tor)
|
|
||||||
|
|
||||||
# connected servers
|
# connected servers
|
||||||
connected_servers_item = QTreeWidgetItem([_("Connected nodes"), ''])
|
connected_servers_item = QTreeWidgetItem([_("Connected nodes"), ''])
|
||||||
@@ -185,19 +182,8 @@ class NodesListWidget(QTreeWidget):
|
|||||||
# disconnected servers
|
# disconnected servers
|
||||||
disconnected_servers_item = QTreeWidgetItem([_("Other known servers"), ""])
|
disconnected_servers_item = QTreeWidgetItem([_("Other known servers"), ""])
|
||||||
disconnected_servers_item.setData(0, self.ITEMTYPE_ROLE, self.ItemType.TOPLEVEL)
|
disconnected_servers_item.setData(0, self.ITEMTYPE_ROLE, self.ItemType.TOPLEVEL)
|
||||||
connected_hosts = set([iface.host for ifaces in chains.values() for iface in ifaces])
|
for server in network.get_disconnected_server_addrs():
|
||||||
protocol = PREFERRED_NETWORK_PROTOCOL
|
item = QTreeWidgetItem([server.to_friendly_name(), ""])
|
||||||
server_addrs = [
|
|
||||||
ServerAddr(_host, port, protocol=protocol)
|
|
||||||
for _host, d in servers.items()
|
|
||||||
if (port := d.get(protocol))]
|
|
||||||
server_addrs.sort(key=lambda x: (-network.is_server_bookmarked(x), str(x)))
|
|
||||||
for server in server_addrs:
|
|
||||||
if server.host in connected_hosts:
|
|
||||||
continue
|
|
||||||
if server.host.endswith('.onion') and not use_tor:
|
|
||||||
continue
|
|
||||||
item = QTreeWidgetItem([server.net_addr_str(), ""])
|
|
||||||
item.setData(0, self.ITEMTYPE_ROLE, self.ItemType.DISCONNECTED_SERVER)
|
item.setData(0, self.ITEMTYPE_ROLE, self.ItemType.DISCONNECTED_SERVER)
|
||||||
item.setData(0, self.SERVER_ADDR_ROLE, server)
|
item.setData(0, self.SERVER_ADDR_ROLE, server)
|
||||||
if network.is_server_bookmarked(server):
|
if network.is_server_bookmarked(server):
|
||||||
|
|||||||
@@ -75,9 +75,9 @@ ca_path = certifi.where()
|
|||||||
|
|
||||||
BUCKET_NAME_OF_ONION_SERVERS = 'onion'
|
BUCKET_NAME_OF_ONION_SERVERS = 'onion'
|
||||||
|
|
||||||
_KNOWN_NETWORK_PROTOCOLS = {'t', 's'}
|
KNOWN_ELEC_PROTOCOL_TRANSPORTS = {'t', 's'}
|
||||||
PREFERRED_NETWORK_PROTOCOL = 's'
|
PREFERRED_NETWORK_PROTOCOL = 's'
|
||||||
assert PREFERRED_NETWORK_PROTOCOL in _KNOWN_NETWORK_PROTOCOLS
|
assert PREFERRED_NETWORK_PROTOCOL in KNOWN_ELEC_PROTOCOL_TRANSPORTS
|
||||||
|
|
||||||
MAX_NUM_HEADERS_PER_REQUEST = 2016
|
MAX_NUM_HEADERS_PER_REQUEST = 2016
|
||||||
assert MAX_NUM_HEADERS_PER_REQUEST >= CHUNK_SIZE
|
assert MAX_NUM_HEADERS_PER_REQUEST >= CHUNK_SIZE
|
||||||
@@ -462,7 +462,7 @@ class ServerAddr:
|
|||||||
net_addr = NetAddress(host, port) # this validates host and port
|
net_addr = NetAddress(host, port) # this validates host and port
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise ValueError(f"cannot construct ServerAddr: invalid host or port (host={host}, port={port})") from e
|
raise ValueError(f"cannot construct ServerAddr: invalid host or port (host={host}, port={port})") from e
|
||||||
if protocol not in _KNOWN_NETWORK_PROTOCOLS:
|
if protocol not in KNOWN_ELEC_PROTOCOL_TRANSPORTS:
|
||||||
raise ValueError(f"invalid network protocol: {protocol}")
|
raise ValueError(f"invalid network protocol: {protocol}")
|
||||||
self.host = str(net_addr.host) # canonical form (if e.g. IPv6 address)
|
self.host = str(net_addr.host) # canonical form (if e.g. IPv6 address)
|
||||||
self.port = int(net_addr.port)
|
self.port = int(net_addr.port)
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ import threading
|
|||||||
import json
|
import json
|
||||||
from typing import (
|
from typing import (
|
||||||
NamedTuple, Optional, Sequence, List, Dict, Tuple, TYPE_CHECKING, Iterable, Set, Any, TypeVar,
|
NamedTuple, Optional, Sequence, List, Dict, Tuple, TYPE_CHECKING, Iterable, Set, Any, TypeVar,
|
||||||
Callable
|
Callable, Mapping,
|
||||||
)
|
)
|
||||||
import copy
|
import copy
|
||||||
import functools
|
import functools
|
||||||
@@ -53,7 +53,7 @@ from .transaction import Transaction
|
|||||||
from .blockchain import Blockchain
|
from .blockchain import Blockchain
|
||||||
from .interface import (
|
from .interface import (
|
||||||
Interface, PREFERRED_NETWORK_PROTOCOL, RequestTimedOut, NetworkTimeout, BUCKET_NAME_OF_ONION_SERVERS,
|
Interface, PREFERRED_NETWORK_PROTOCOL, RequestTimedOut, NetworkTimeout, BUCKET_NAME_OF_ONION_SERVERS,
|
||||||
NetworkException, RequestCorrupted, ServerAddr, TxBroadcastError,
|
NetworkException, RequestCorrupted, ServerAddr, TxBroadcastError, KNOWN_ELEC_PROTOCOL_TRANSPORTS,
|
||||||
)
|
)
|
||||||
from .version import PROTOCOL_VERSION_MIN
|
from .version import PROTOCOL_VERSION_MIN
|
||||||
from .i18n import _
|
from .i18n import _
|
||||||
@@ -624,7 +624,7 @@ class Network(Logger, NetworkRetryManager[ServerAddr]):
|
|||||||
|
|
||||||
|
|
||||||
@with_recent_servers_lock
|
@with_recent_servers_lock
|
||||||
def get_servers(self):
|
def get_servers(self) -> Mapping[str, Mapping[str, str]]:
|
||||||
# note: order of sources when adding servers here is crucial!
|
# note: order of sources when adding servers here is crucial!
|
||||||
# don't let "server_peers" overwrite anything,
|
# don't let "server_peers" overwrite anything,
|
||||||
# otherwise main server can eclipse the client
|
# otherwise main server can eclipse the client
|
||||||
@@ -659,6 +659,31 @@ class Network(Logger, NetworkRetryManager[ServerAddr]):
|
|||||||
out = filter_noonion(out)
|
out = filter_noonion(out)
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
def get_disconnected_server_addrs(self) -> Sequence[ServerAddr]:
|
||||||
|
hostmap = self.get_servers()
|
||||||
|
disconnected_server_addrs = [] # type: List[ServerAddr]
|
||||||
|
chains = self.get_blockchains()
|
||||||
|
connected_hosts = set([iface.host for ifaces in chains.values() for iface in ifaces])
|
||||||
|
# convert hostmap to list of ServerAddrs (one-to-many mapping)
|
||||||
|
server_addrs = []
|
||||||
|
for host, portmap in hostmap.items():
|
||||||
|
for protocol in KNOWN_ELEC_PROTOCOL_TRANSPORTS:
|
||||||
|
if port := portmap.get(protocol):
|
||||||
|
server_addrs.append(ServerAddr(host, port, protocol=protocol))
|
||||||
|
# sort bookmarked servers to appear first
|
||||||
|
server_addrs.sort(key=lambda x: (-self.is_server_bookmarked(x), str(x)))
|
||||||
|
# filter out stuff
|
||||||
|
for server in server_addrs:
|
||||||
|
if server.host in connected_hosts:
|
||||||
|
continue
|
||||||
|
if not self.is_server_bookmarked(server):
|
||||||
|
if server.protocol != PREFERRED_NETWORK_PROTOCOL:
|
||||||
|
continue
|
||||||
|
if server.host.endswith('.onion') and not self.is_proxy_tor:
|
||||||
|
continue
|
||||||
|
disconnected_server_addrs.append(server)
|
||||||
|
return disconnected_server_addrs
|
||||||
|
|
||||||
def _get_next_server_to_try(self) -> Optional[ServerAddr]:
|
def _get_next_server_to_try(self) -> Optional[ServerAddr]:
|
||||||
now = time.time()
|
now = time.time()
|
||||||
with self.interfaces_lock:
|
with self.interfaces_lock:
|
||||||
@@ -1122,7 +1147,7 @@ class Network(Logger, NetworkRetryManager[ServerAddr]):
|
|||||||
self._blockchain = interface.blockchain
|
self._blockchain = interface.blockchain
|
||||||
return self._blockchain
|
return self._blockchain
|
||||||
|
|
||||||
def get_blockchains(self):
|
def get_blockchains(self) -> Mapping[str, Sequence[Interface]]:
|
||||||
out = {} # blockchain_id -> list(interfaces)
|
out = {} # blockchain_id -> list(interfaces)
|
||||||
with blockchain.blockchains_lock: blockchain_items = list(blockchain.blockchains.items())
|
with blockchain.blockchains_lock: blockchain_items = list(blockchain.blockchains.items())
|
||||||
with self.interfaces_lock: interfaces_values = list(self.interfaces.values())
|
with self.interfaces_lock: interfaces_values = list(self.interfaces.values())
|
||||||
|
|||||||
Reference in New Issue
Block a user