Browse Source

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
master
Sander van Grieken 2 years ago
parent
commit
667485b17e
No known key found for this signature in database
GPG Key ID: 9BCF8209EA402EBA
  1. 19
      electrum/commands.py
  2. 20
      electrum/gui/text.py
  3. 72
      electrum/network.py
  4. 2
      electrum/simple_config.py

19
electrum/commands.py

@ -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')

20
electrum/gui/text.py

@ -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))

72
electrum/network.py

@ -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

2
electrum/simple_config.py

@ -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)

Loading…
Cancel
Save