mirror of
https://github.com/LBRYFoundation/LBRY-Vault.git
synced 2025-09-01 17:55:20 +00:00
network/gui: unify host/port input fields to single server str
This allows optionally specifying the protocol for the main server. fixes #6095 fixes #5278
This commit is contained in:
parent
b2cfaddff2
commit
9e57ae630b
5 changed files with 42 additions and 68 deletions
|
@ -145,13 +145,11 @@ class ElectrumWindow(App):
|
||||||
servers = self.network.get_servers()
|
servers = self.network.get_servers()
|
||||||
ChoiceDialog(_('Choose a server'), sorted(servers), popup.ids.host.text, cb2).open()
|
ChoiceDialog(_('Choose a server'), sorted(servers), popup.ids.host.text, cb2).open()
|
||||||
|
|
||||||
def maybe_switch_to_server(self, *, host: str, port: str):
|
def maybe_switch_to_server(self, server_str: str):
|
||||||
from electrum.interface import ServerAddr
|
from electrum.interface import ServerAddr
|
||||||
net_params = self.network.get_parameters()
|
net_params = self.network.get_parameters()
|
||||||
try:
|
try:
|
||||||
server = ServerAddr(host=host,
|
server = ServerAddr.from_str_with_inference(server_str)
|
||||||
port=port,
|
|
||||||
protocol=net_params.server.protocol)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.show_error(_("Invalid server details: {}").format(repr(e)))
|
self.show_error(_("Invalid server details: {}").format(repr(e)))
|
||||||
return
|
return
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
#:import ServerAddr electrum.interface.ServerAddr
|
|
||||||
|
|
||||||
Popup:
|
Popup:
|
||||||
id: nd
|
id: nd
|
||||||
title: _('Server')
|
title: _('Server')
|
||||||
|
@ -18,27 +16,14 @@ Popup:
|
||||||
height: '36dp'
|
height: '36dp'
|
||||||
size_hint_x: 1
|
size_hint_x: 1
|
||||||
size_hint_y: None
|
size_hint_y: None
|
||||||
text: _('Host') + ':'
|
text: _('Server') + ':'
|
||||||
TextInput:
|
TextInput:
|
||||||
id: host
|
id: server_str
|
||||||
multiline: False
|
multiline: False
|
||||||
height: '36dp'
|
height: '36dp'
|
||||||
size_hint_x: 3
|
size_hint_x: 3
|
||||||
size_hint_y: None
|
size_hint_y: None
|
||||||
text: app.network.get_parameters().server.host
|
text: app.network.get_parameters().server.net_addr_str()
|
||||||
Label:
|
|
||||||
height: '36dp'
|
|
||||||
size_hint_x: 1
|
|
||||||
size_hint_y: None
|
|
||||||
text: _('Port') + ':'
|
|
||||||
TextInput:
|
|
||||||
id: port
|
|
||||||
multiline: False
|
|
||||||
input_type: 'number'
|
|
||||||
height: '36dp'
|
|
||||||
size_hint_x: 3
|
|
||||||
size_hint_y: None
|
|
||||||
text: str(app.network.get_parameters().server.port)
|
|
||||||
Widget
|
Widget
|
||||||
Button:
|
Button:
|
||||||
id: chooser
|
id: chooser
|
||||||
|
@ -58,5 +43,5 @@ Popup:
|
||||||
height: '48dp'
|
height: '48dp'
|
||||||
text: _('OK')
|
text: _('OK')
|
||||||
on_release:
|
on_release:
|
||||||
app.maybe_switch_to_server(host=str(root.ids.host.text), port=str(root.ids.port.text))
|
app.maybe_switch_to_server(str(root.ids.server_str.text))
|
||||||
nd.dismiss()
|
nd.dismiss()
|
||||||
|
|
|
@ -36,8 +36,8 @@ from PyQt5.QtGui import QFontMetrics
|
||||||
|
|
||||||
from electrum.i18n import _
|
from electrum.i18n import _
|
||||||
from electrum import constants, blockchain, util
|
from electrum import constants, blockchain, util
|
||||||
from electrum.interface import ServerAddr
|
from electrum.interface import ServerAddr, PREFERRED_NETWORK_PROTOCOL
|
||||||
from electrum.network import Network, PREFERRED_NETWORK_PROTOCOL
|
from electrum.network import Network
|
||||||
from electrum.logging import get_logger
|
from electrum.logging import get_logger
|
||||||
|
|
||||||
from .util import (Buttons, CloseButton, HelpButton, read_QIcon, char_width_in_lineedit,
|
from .util import (Buttons, CloseButton, HelpButton, read_QIcon, char_width_in_lineedit,
|
||||||
|
@ -171,8 +171,7 @@ class ServerListWidget(QTreeWidget):
|
||||||
menu.exec_(self.viewport().mapToGlobal(position))
|
menu.exec_(self.viewport().mapToGlobal(position))
|
||||||
|
|
||||||
def set_server(self, server: ServerAddr):
|
def set_server(self, server: ServerAddr):
|
||||||
self.parent.server_host.setText(server.host)
|
self.parent.server_e.setText(server.net_addr_str())
|
||||||
self.parent.server_port.setText(str(server.port))
|
|
||||||
self.parent.set_server()
|
self.parent.set_server()
|
||||||
|
|
||||||
def keyPressEvent(self, event):
|
def keyPressEvent(self, event):
|
||||||
|
@ -230,15 +229,12 @@ class NetworkChoiceLayout(object):
|
||||||
grid = QGridLayout(server_tab)
|
grid = QGridLayout(server_tab)
|
||||||
grid.setSpacing(8)
|
grid.setSpacing(8)
|
||||||
|
|
||||||
self.server_host = QLineEdit()
|
self.server_e = QLineEdit()
|
||||||
self.server_host.setFixedWidth(fixed_width_hostname)
|
self.server_e.setFixedWidth(fixed_width_hostname + fixed_width_port)
|
||||||
self.server_port = QLineEdit()
|
|
||||||
self.server_port.setFixedWidth(fixed_width_port)
|
|
||||||
self.autoconnect_cb = QCheckBox(_('Select server automatically'))
|
self.autoconnect_cb = QCheckBox(_('Select server automatically'))
|
||||||
self.autoconnect_cb.setEnabled(self.config.is_modifiable('auto_connect'))
|
self.autoconnect_cb.setEnabled(self.config.is_modifiable('auto_connect'))
|
||||||
|
|
||||||
self.server_host.editingFinished.connect(self.set_server)
|
self.server_e.editingFinished.connect(self.set_server)
|
||||||
self.server_port.editingFinished.connect(self.set_server)
|
|
||||||
self.autoconnect_cb.clicked.connect(self.set_server)
|
self.autoconnect_cb.clicked.connect(self.set_server)
|
||||||
self.autoconnect_cb.clicked.connect(self.update)
|
self.autoconnect_cb.clicked.connect(self.update)
|
||||||
|
|
||||||
|
@ -250,8 +246,7 @@ class NetworkChoiceLayout(object):
|
||||||
grid.addWidget(HelpButton(msg), 0, 4)
|
grid.addWidget(HelpButton(msg), 0, 4)
|
||||||
|
|
||||||
grid.addWidget(QLabel(_('Server') + ':'), 1, 0)
|
grid.addWidget(QLabel(_('Server') + ':'), 1, 0)
|
||||||
grid.addWidget(self.server_host, 1, 1, 1, 2)
|
grid.addWidget(self.server_e, 1, 1, 1, 3)
|
||||||
grid.addWidget(self.server_port, 1, 3)
|
|
||||||
|
|
||||||
label = _('Server peers') if network.is_connected() else _('Default Servers')
|
label = _('Server peers') if network.is_connected() else _('Default Servers')
|
||||||
grid.addWidget(QLabel(label), 2, 0, 1, 5)
|
grid.addWidget(QLabel(label), 2, 0, 1, 5)
|
||||||
|
@ -355,20 +350,18 @@ class NetworkChoiceLayout(object):
|
||||||
def enable_set_server(self):
|
def enable_set_server(self):
|
||||||
if self.config.is_modifiable('server'):
|
if self.config.is_modifiable('server'):
|
||||||
enabled = not self.autoconnect_cb.isChecked()
|
enabled = not self.autoconnect_cb.isChecked()
|
||||||
self.server_host.setEnabled(enabled)
|
self.server_e.setEnabled(enabled)
|
||||||
self.server_port.setEnabled(enabled)
|
|
||||||
self.servers_list.setEnabled(enabled)
|
self.servers_list.setEnabled(enabled)
|
||||||
else:
|
else:
|
||||||
for w in [self.autoconnect_cb, self.server_host, self.server_port, self.servers_list]:
|
for w in [self.autoconnect_cb, self.server_e, self.servers_list]:
|
||||||
w.setEnabled(False)
|
w.setEnabled(False)
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
net_params = self.network.get_parameters()
|
net_params = self.network.get_parameters()
|
||||||
server = net_params.server
|
server = net_params.server
|
||||||
proxy_config, auto_connect = net_params.proxy, net_params.auto_connect
|
proxy_config, auto_connect = net_params.proxy, net_params.auto_connect
|
||||||
if not self.server_host.hasFocus() and not self.server_port.hasFocus():
|
if not self.server_e.hasFocus():
|
||||||
self.server_host.setText(server.host)
|
self.server_e.setText(server.net_addr_str())
|
||||||
self.server_port.setText(str(server.port))
|
|
||||||
self.autoconnect_cb.setChecked(auto_connect)
|
self.autoconnect_cb.setChecked(auto_connect)
|
||||||
|
|
||||||
interface = self.network.interface
|
interface = self.network.interface
|
||||||
|
@ -425,33 +418,13 @@ class NetworkChoiceLayout(object):
|
||||||
self.network.run_from_another_thread(self.network.follow_chain_given_server(server))
|
self.network.run_from_another_thread(self.network.follow_chain_given_server(server))
|
||||||
self.update()
|
self.update()
|
||||||
|
|
||||||
def change_server(self, host, protocol):
|
|
||||||
pp = self.servers.get(host, constants.net.DEFAULT_PORTS)
|
|
||||||
if protocol and protocol not in protocol_letters:
|
|
||||||
protocol = None
|
|
||||||
if protocol:
|
|
||||||
port = pp.get(protocol)
|
|
||||||
if port is None:
|
|
||||||
protocol = None
|
|
||||||
if not protocol:
|
|
||||||
if 's' in pp.keys():
|
|
||||||
protocol = 's'
|
|
||||||
port = pp.get(protocol)
|
|
||||||
else:
|
|
||||||
protocol = list(pp.keys())[0]
|
|
||||||
port = pp.get(protocol)
|
|
||||||
self.server_host.setText(host)
|
|
||||||
self.server_port.setText(port)
|
|
||||||
|
|
||||||
def accept(self):
|
def accept(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def set_server(self):
|
def set_server(self):
|
||||||
net_params = self.network.get_parameters()
|
net_params = self.network.get_parameters()
|
||||||
try:
|
try:
|
||||||
server = ServerAddr(host=str(self.server_host.text()),
|
server = ServerAddr.from_str_with_inference(str(self.server_e.text()))
|
||||||
port=str(self.server_port.text()),
|
|
||||||
protocol=net_params.server.protocol)
|
|
||||||
except Exception:
|
except Exception:
|
||||||
return
|
return
|
||||||
net_params = net_params._replace(server=server,
|
net_params = net_params._replace(server=server,
|
||||||
|
|
|
@ -65,6 +65,10 @@ BUCKET_NAME_OF_ONION_SERVERS = 'onion'
|
||||||
|
|
||||||
MAX_INCOMING_MSG_SIZE = 1_000_000 # in bytes
|
MAX_INCOMING_MSG_SIZE = 1_000_000 # in bytes
|
||||||
|
|
||||||
|
_KNOWN_NETWORK_PROTOCOLS = {'t', 's'}
|
||||||
|
PREFERRED_NETWORK_PROTOCOL = 's'
|
||||||
|
assert PREFERRED_NETWORK_PROTOCOL in _KNOWN_NETWORK_PROTOCOLS
|
||||||
|
|
||||||
|
|
||||||
class NetworkTimeout:
|
class NetworkTimeout:
|
||||||
# seconds
|
# seconds
|
||||||
|
@ -212,7 +216,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 ('s', 't'):
|
if protocol not in _KNOWN_NETWORK_PROTOCOLS:
|
||||||
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)
|
||||||
|
@ -225,6 +229,24 @@ class ServerAddr:
|
||||||
host, port, protocol = str(s).rsplit(':', 2)
|
host, port, protocol = str(s).rsplit(':', 2)
|
||||||
return ServerAddr(host=host, port=port, protocol=protocol)
|
return ServerAddr(host=host, port=port, protocol=protocol)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_str_with_inference(cls, s: str) -> Optional['ServerAddr']:
|
||||||
|
"""Construct ServerAddr from str, guessing missing details.
|
||||||
|
Ongoing compatibility not guaranteed.
|
||||||
|
"""
|
||||||
|
if not s:
|
||||||
|
return None
|
||||||
|
items = str(s).rsplit(':', 2)
|
||||||
|
if len(items) < 2:
|
||||||
|
return None # although maybe we could guess the port too?
|
||||||
|
host = items[0]
|
||||||
|
port = items[1]
|
||||||
|
if len(items) >= 3:
|
||||||
|
protocol = items[2]
|
||||||
|
else:
|
||||||
|
protocol = PREFERRED_NETWORK_PROTOCOL
|
||||||
|
return ServerAddr(host=host, port=port, protocol=protocol)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return '{}:{}'.format(self.net_addr_str(), self.protocol)
|
return '{}:{}'.format(self.net_addr_str(), self.protocol)
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,7 @@ from . import bitcoin
|
||||||
from . import dns_hacks
|
from . import dns_hacks
|
||||||
from .transaction import Transaction
|
from .transaction import Transaction
|
||||||
from .blockchain import Blockchain, HEADER_SIZE
|
from .blockchain import Blockchain, HEADER_SIZE
|
||||||
from .interface import (Interface,
|
from .interface import (Interface, PREFERRED_NETWORK_PROTOCOL,
|
||||||
RequestTimedOut, NetworkTimeout, BUCKET_NAME_OF_ONION_SERVERS,
|
RequestTimedOut, NetworkTimeout, BUCKET_NAME_OF_ONION_SERVERS,
|
||||||
NetworkException, RequestCorrupted, ServerAddr)
|
NetworkException, RequestCorrupted, ServerAddr)
|
||||||
from .version import PROTOCOL_VERSION
|
from .version import PROTOCOL_VERSION
|
||||||
|
@ -75,10 +75,6 @@ NUM_TARGET_CONNECTED_SERVERS = 10
|
||||||
NUM_STICKY_SERVERS = 4
|
NUM_STICKY_SERVERS = 4
|
||||||
NUM_RECENT_SERVERS = 20
|
NUM_RECENT_SERVERS = 20
|
||||||
|
|
||||||
_KNOWN_NETWORK_PROTOCOLS = {'t', 's'}
|
|
||||||
PREFERRED_NETWORK_PROTOCOL = 's'
|
|
||||||
assert PREFERRED_NETWORK_PROTOCOL in _KNOWN_NETWORK_PROTOCOLS
|
|
||||||
|
|
||||||
|
|
||||||
def parse_servers(result: Sequence[Tuple[str, str, List[str]]]) -> Dict[str, dict]:
|
def parse_servers(result: Sequence[Tuple[str, str, List[str]]]) -> Dict[str, dict]:
|
||||||
""" parse servers list into dict format"""
|
""" parse servers list into dict format"""
|
||||||
|
|
Loading…
Add table
Reference in a new issue