network: split off proxy_user and proxy_pass from serialized proxy string and add separate cmdline params and config keys for them.
support parsing both old style mode:host:port:user:pass and new mode:host:port, where new form also accepts IPv6 addresses
This commit is contained in:
@@ -1563,11 +1563,20 @@ def add_network_options(parser):
|
||||
parser.add_argument("-f", "--serverfingerprint", dest=SimpleConfig.NETWORK_SERVERFINGERPRINT.key(), default=None,
|
||||
help="only allow connecting to servers with a matching SSL certificate SHA256 fingerprint. " +
|
||||
"To calculate this yourself: '$ openssl x509 -noout -fingerprint -sha256 -inform pem -in mycertfile.crt'. Enter as 64 hex chars.")
|
||||
parser.add_argument("-1", "--oneserver", action="store_true", dest=SimpleConfig.NETWORK_ONESERVER.key(), default=None, help="connect to one server only")
|
||||
parser.add_argument("-s", "--server", dest=SimpleConfig.NETWORK_SERVER.key(), default=None, help="set server host:port:protocol, where protocol is either t (tcp) or s (ssl)")
|
||||
parser.add_argument("-p", "--proxy", dest=SimpleConfig.NETWORK_PROXY.key(), default=None, help="set proxy [type:]host[:port] (or 'none' to disable proxy), where type is socks4,socks5 or http")
|
||||
parser.add_argument("--noonion", action="store_true", dest=SimpleConfig.NETWORK_NOONION.key(), default=None, help="do not try to connect to onion servers")
|
||||
parser.add_argument("--skipmerklecheck", action="store_true", dest=SimpleConfig.NETWORK_SKIPMERKLECHECK.key(), default=None, help="Tolerate invalid merkle proofs from server")
|
||||
parser.add_argument("-1", "--oneserver", action="store_true", dest=SimpleConfig.NETWORK_ONESERVER.key(), default=None,
|
||||
help="connect to one server only")
|
||||
parser.add_argument("-s", "--server", dest=SimpleConfig.NETWORK_SERVER.key(), default=None,
|
||||
help="set server host:port:protocol, where protocol is either t (tcp) or s (ssl)")
|
||||
parser.add_argument("-p", "--proxy", dest=SimpleConfig.NETWORK_PROXY.key(), default=None,
|
||||
help="set proxy [type:]host:port (or 'none' to disable proxy), where type is socks4 or socks5")
|
||||
parser.add_argument("--proxyuser", dest=SimpleConfig.NETWORK_PROXY_USER.key(), default=None,
|
||||
help="set proxy username")
|
||||
parser.add_argument("--proxypassword", dest=SimpleConfig.NETWORK_PROXY_PASSWORD.key(), default=None,
|
||||
help="set proxy password")
|
||||
parser.add_argument("--noonion", action="store_true", dest=SimpleConfig.NETWORK_NOONION.key(), default=None,
|
||||
help="do not try to connect to onion servers")
|
||||
parser.add_argument("--skipmerklecheck", action="store_true", dest=SimpleConfig.NETWORK_SKIPMERKLECHECK.key(), default=None,
|
||||
help="Tolerate invalid merkle proofs from server")
|
||||
|
||||
def add_global_options(parser):
|
||||
group = parser.add_argument_group('global options')
|
||||
|
||||
@@ -470,6 +470,8 @@ class ElectrumGui(BaseElectrumGui, EventListener):
|
||||
out = self.run_popup('', ['Transaction ID:', self.txid[self.pos]])
|
||||
|
||||
def edit_str(self, target, c, is_num=False):
|
||||
if target is None:
|
||||
target = ''
|
||||
# detect backspace
|
||||
cc = curses.unctrl(c).decode()
|
||||
if c in [8, 127, 263] and target:
|
||||
@@ -721,10 +723,13 @@ class ElectrumGui(BaseElectrumGui, EventListener):
|
||||
proxy_config, auto_connect = net_params.proxy, net_params.auto_connect
|
||||
srv = 'auto-connect' if auto_connect else str(self.network.default_server)
|
||||
out = self.run_dialog('Network', [
|
||||
{'label':'server', 'type':'str', 'value':srv},
|
||||
{'label':'proxy', 'type':'str', 'value':self.config.NETWORK_PROXY},
|
||||
], buttons = 1)
|
||||
{'label': 'server', 'type': 'str', 'value': srv},
|
||||
{'label': 'proxy', 'type': 'str', 'value': self.config.NETWORK_PROXY},
|
||||
{'label': 'proxy user', 'type': 'str', 'value': self.config.NETWORK_PROXY_USER},
|
||||
{'label': 'proxy pass', 'type': 'str', 'value': self.config.NETWORK_PROXY_PASSWORD},
|
||||
], buttons=1)
|
||||
if out:
|
||||
self.show_message(repr(proxy_config))
|
||||
if out.get('server'):
|
||||
server_str = out.get('server')
|
||||
auto_connect = server_str == 'auto-connect'
|
||||
@@ -734,11 +739,14 @@ class ElectrumGui(BaseElectrumGui, EventListener):
|
||||
except Exception:
|
||||
self.show_message("Error:" + server_str + "\nIn doubt, type \"auto-connect\"")
|
||||
return False
|
||||
if out.get('server') or out.get('proxy'):
|
||||
proxy = electrum.network.deserialize_proxy(out.get('proxy')) if out.get('proxy') else proxy_config
|
||||
if out.get('server') or out.get('proxy') or out.get('proxy user') or out.get('proxy pass'):
|
||||
new_proxy_config = electrum.network.deserialize_proxy(out.get('proxy')) if out.get('proxy') else proxy_config
|
||||
if new_proxy_config:
|
||||
new_proxy_config['user'] = out.get('proxy user') if 'proxy user' in out else proxy_config['user']
|
||||
new_proxy_config['pass'] = out.get('proxy pass') if 'proxy pass' in out else proxy_config['pass']
|
||||
net_params = NetworkParameters(
|
||||
server=server_addr,
|
||||
proxy=proxy,
|
||||
proxy=new_proxy_config,
|
||||
auto_connect=auto_connect)
|
||||
self.network.run_from_another_thread(self.network.set_parameters(net_params))
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ import functools
|
||||
from enum import IntEnum
|
||||
|
||||
import aiorpcx
|
||||
from aiorpcx import ignore_after
|
||||
from aiorpcx import ignore_after, NetAddress
|
||||
from aiohttp import ClientResponse
|
||||
|
||||
from . import util
|
||||
@@ -168,35 +168,52 @@ proxy_modes = ['socks4', 'socks5']
|
||||
def serialize_proxy(p):
|
||||
if not isinstance(p, dict):
|
||||
return None
|
||||
return ':'.join([p.get('mode'), p.get('host'), p.get('port'),
|
||||
p.get('user', ''), p.get('password', '')])
|
||||
return ':'.join([p.get('mode'), p.get('host'), p.get('port')])
|
||||
|
||||
|
||||
def deserialize_proxy(s: Optional[str]) -> Optional[dict]:
|
||||
def deserialize_proxy(s: Optional[str], user: str = None, password: str = None) -> Optional[dict]:
|
||||
if not isinstance(s, str):
|
||||
return None
|
||||
if s.lower() == 'none':
|
||||
return None
|
||||
proxy = {"mode":"socks5", "host":"localhost"}
|
||||
# FIXME raw IPv6 address fails here
|
||||
proxy = {"mode": "socks5", "host": "localhost"}
|
||||
|
||||
args = s.split(':')
|
||||
n = 0
|
||||
if proxy_modes.count(args[n]) == 1:
|
||||
proxy["mode"] = args[n]
|
||||
n += 1
|
||||
if len(args) > n:
|
||||
proxy["host"] = args[n]
|
||||
n += 1
|
||||
if len(args) > n:
|
||||
proxy["port"] = args[n]
|
||||
n += 1
|
||||
else:
|
||||
proxy["port"] = "8080" if proxy["mode"] == "http" else "1080"
|
||||
if len(args) > n:
|
||||
proxy["user"] = args[n]
|
||||
n += 1
|
||||
if len(args) > n:
|
||||
proxy["password"] = args[n]
|
||||
if args[0] in proxy_modes:
|
||||
proxy['mode'] = args[0]
|
||||
args = args[1:]
|
||||
|
||||
def is_valid_port(ps: str):
|
||||
try:
|
||||
assert 0 < int(ps) < 65535
|
||||
except (ValueError, AssertionError):
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_valid_host(ph: str):
|
||||
try:
|
||||
NetAddress(ph, '1')
|
||||
except ValueError:
|
||||
return False
|
||||
return True
|
||||
|
||||
# detect migrate from old settings
|
||||
if len(args) == 4 and is_valid_host(args[0]) and is_valid_port(args[1]): # host:port:user:pass,
|
||||
proxy['host'] = args[0]
|
||||
proxy['port'] = args[1]
|
||||
proxy['user'] = args[2]
|
||||
proxy['password'] = args[3]
|
||||
return proxy
|
||||
|
||||
proxy['host'] = ':'.join(args[:-1])
|
||||
proxy['port'] = args[-1]
|
||||
|
||||
if not is_valid_host(proxy['host']) or not is_valid_port(proxy['port']):
|
||||
return None
|
||||
|
||||
proxy['user'] = user
|
||||
proxy['password'] = password
|
||||
|
||||
return proxy
|
||||
|
||||
|
||||
@@ -496,7 +513,8 @@ class Network(Logger, NetworkRetryManager[ServerAddr]):
|
||||
def _init_parameters_from_config(self) -> None:
|
||||
self.auto_connect = self.config.NETWORK_AUTO_CONNECT
|
||||
self._set_default_server()
|
||||
self._set_proxy(deserialize_proxy(self.config.NETWORK_PROXY))
|
||||
self._set_proxy(deserialize_proxy(self.config.NETWORK_PROXY, self.config.NETWORK_PROXY_USER,
|
||||
self.config.NETWORK_PROXY_PASSWORD))
|
||||
self._maybe_set_oneserver()
|
||||
|
||||
def get_donation_address(self):
|
||||
@@ -625,6 +643,8 @@ class Network(Logger, NetworkRetryManager[ServerAddr]):
|
||||
async def set_parameters(self, net_params: NetworkParameters):
|
||||
proxy = net_params.proxy
|
||||
proxy_str = serialize_proxy(proxy)
|
||||
proxy_user = proxy['user'] if proxy else None
|
||||
proxy_pass = proxy['password'] if proxy else None
|
||||
server = net_params.server
|
||||
# sanitize parameters
|
||||
try:
|
||||
@@ -636,10 +656,14 @@ class Network(Logger, NetworkRetryManager[ServerAddr]):
|
||||
self.config.NETWORK_AUTO_CONNECT = net_params.auto_connect
|
||||
self.config.NETWORK_ONESERVER = net_params.oneserver
|
||||
self.config.NETWORK_PROXY = proxy_str
|
||||
self.config.NETWORK_PROXY_USER = proxy_user
|
||||
self.config.NETWORK_PROXY_PASSWORD = proxy_pass
|
||||
self.config.NETWORK_SERVER = str(server)
|
||||
# abort if changes were not allowed by config
|
||||
if self.config.NETWORK_SERVER != str(server) \
|
||||
or self.config.NETWORK_PROXY != proxy_str \
|
||||
or self.config.NETWORK_PROXY_USER != proxy_user \
|
||||
or self.config.NETWORK_PROXY_PASSWORD != proxy_pass \
|
||||
or self.config.NETWORK_ONESERVER != net_params.oneserver:
|
||||
return
|
||||
|
||||
|
||||
@@ -926,6 +926,8 @@ class SimpleConfig(Logger):
|
||||
NETWORK_AUTO_CONNECT = ConfigVar('auto_connect', default=True, type_=bool)
|
||||
NETWORK_ONESERVER = ConfigVar('oneserver', default=False, type_=bool)
|
||||
NETWORK_PROXY = ConfigVar('proxy', default=None)
|
||||
NETWORK_PROXY_USER = ConfigVar('proxy_user', default=None)
|
||||
NETWORK_PROXY_PASSWORD = ConfigVar('proxy_password', default=None)
|
||||
NETWORK_SERVER = ConfigVar('server', default=None, type_=str)
|
||||
NETWORK_NOONION = ConfigVar('noonion', default=False, type_=bool)
|
||||
NETWORK_OFFLINE = ConfigVar('offline', default=False, type_=bool)
|
||||
|
||||
Reference in New Issue
Block a user