1
0

qt network dialog: don't poll Tor socks proxy, but scan on interaction

Polling is introduces spam in Tor logs.
Also, Tor Browser 12.0 apparently has a bug where our polling renders
the socks proxy unusuable after some time.
see https://gitlab.torproject.org/tpo/applications/tor-browser/-/issues/41549

Instead of trying to detect a Tor socks proxy every 10 seconds, we now
run detection when the Qt network dialog gets opened, and also when
the user switches to the "Proxy" tab in the dialog.

fixes https://github.com/spesmilo/electrum/issues/7317
This commit is contained in:
SomberNight
2023-01-02 11:58:16 +00:00
parent e3485de496
commit 253150cb36
2 changed files with 53 additions and 28 deletions

View File

@@ -40,6 +40,7 @@ from electrum import constants, blockchain, util
from electrum.interface import ServerAddr, PREFERRED_NETWORK_PROTOCOL
from electrum.network import Network
from electrum.logging import get_logger
from electrum.util import detect_tor_socks_proxy
from .util import (Buttons, CloseButton, HelpButton, read_QIcon, char_width_in_lineedit,
PasswordLineEdit)
@@ -66,6 +67,11 @@ class NetworkDialog(QDialog, QtEventListener):
self.register_callbacks()
self._cleaned_up = False
def show(self):
super().show()
if td := self.nlayout.td:
td.trigger_rescan()
@qt_event_listener
def on_event_network_updated(self):
self.nlayout.update()
@@ -203,10 +209,11 @@ class NetworkChoiceLayout(object):
self.tor_proxy = None
self.tabs = tabs = QTabWidget()
proxy_tab = QWidget()
self._proxy_tab = proxy_tab = QWidget()
blockchain_tab = QWidget()
tabs.addTab(blockchain_tab, _('Overview'))
tabs.addTab(proxy_tab, _('Proxy'))
tabs.currentChanged.connect(self._on_tab_changed)
fixed_width_hostname = 24 * char_width_in_lineedit()
fixed_width_port = 6 * char_width_in_lineedit()
@@ -417,6 +424,10 @@ class NetworkChoiceLayout(object):
net_params = net_params._replace(proxy=proxy)
self.network.run_from_another_thread(self.network.set_parameters(net_params))
def _on_tab_changed(self):
if self.tabs.currentWidget() is self._proxy_tab:
self.td.trigger_rescan()
def suggest_proxy(self, found_proxy):
if found_proxy is None:
self.tor_cb.hide()
@@ -457,38 +468,25 @@ class TorDetector(QThread):
def __init__(self):
QThread.__init__(self)
self._stop_event = threading.Event()
self._work_to_do_evt = threading.Event()
self._stopping = False
def run(self):
# Probable ports for Tor to listen at
ports = [9050, 9150]
while True:
for p in ports:
net_addr = ("127.0.0.1", p)
if TorDetector.is_tor_port(net_addr):
self.found_proxy.emit(net_addr)
break
else:
self.found_proxy.emit(None)
stopping = self._stop_event.wait(10)
if stopping:
# do rescan
net_addr = detect_tor_socks_proxy()
self.found_proxy.emit(net_addr)
# wait until triggered
self._work_to_do_evt.wait()
self._work_to_do_evt.clear()
if self._stopping:
return
def trigger_rescan(self) -> None:
self._work_to_do_evt.set()
def stop(self):
self._stop_event.set()
self._stopping = True
self._work_to_do_evt.set()
self.exit()
self.wait()
@staticmethod
def is_tor_port(net_addr: Tuple[str, int]) -> bool:
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.settimeout(0.1)
s.connect(net_addr)
# Tor responds uniquely to HTTP-like requests
s.send(b"GET\n")
if b"Tor is not an HTTP Proxy" in s.recv(1024):
return True
except socket.error:
pass
return False