Tweaks to CensorshipCircumvention and also Meek cleanup fixes that were causing a crazy read loop on the stdout queue

This commit is contained in:
Miguel Jacq 2021-12-15 18:22:18 +11:00
parent 042fed2e55
commit 4f40a9b501
No known key found for this signature in database
GPG key ID: EEA4341C6D97A0B6
3 changed files with 53 additions and 102 deletions

View file

@ -20,8 +20,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import os import os
import subprocess import subprocess
import time import time
from queue import Queue, Empty
from threading import Thread
class Meek(object): class Meek(object):
@ -67,14 +65,6 @@ class Meek(object):
Start the Meek Client and populate the SOCKS proxies dict Start the Meek Client and populate the SOCKS proxies dict
for use with requests to the Tor Moat API. for use with requests to the Tor Moat API.
""" """
# Small method to read stdout from the subprocess.
# We use this to obtain the random port that Meek
# started on
def enqueue_output(out, queue):
for line in iter(out.readline, b""):
queue.put(line)
out.close()
# Abort early if we can't find the Meek client # Abort early if we can't find the Meek client
if self.meek_client_file_path is None or not os.path.exists( if self.meek_client_file_path is None or not os.path.exists(
self.meek_client_file_path self.meek_client_file_path
@ -124,21 +114,8 @@ class Meek(object):
universal_newlines=True, universal_newlines=True,
) )
# Queue up the stdout from the subprocess for polling later # Obtain the host and port that meek is running on
q = Queue() for line in iter(self.meek_proc.stdout.readline, b""):
t = Thread(target=enqueue_output, args=(self.meek_proc.stdout, q))
t.daemon = True # thread dies with the program
t.start()
while True:
# read stdout without blocking
try:
line = q.get_nowait()
self.common.log("Meek", "start", line.strip())
except Empty:
# no stdout yet?
pass
else: # we got stdout
if "CMETHOD meek socks5" in line: if "CMETHOD meek socks5" in line:
self.meek_host = line.split(" ")[3].split(":")[0] self.meek_host = line.split(" ")[3].split(":")[0]
self.meek_port = line.split(" ")[3].split(":")[1] self.meek_port = line.split(" ")[3].split(":")[1]
@ -152,6 +129,7 @@ class Meek(object):
if "CMETHOD-ERROR" in line: if "CMETHOD-ERROR" in line:
self.cleanup() self.cleanup()
raise MeekNotRunning() raise MeekNotRunning()
break
if self.meek_port: if self.meek_port:
self.meek_proxies = { self.meek_proxies = {

View file

@ -24,11 +24,15 @@ import random
import time import time
from PySide2 import QtCore, QtWidgets, QtGui from PySide2 import QtCore, QtWidgets, QtGui
from onionshare_cli.censorship import CensorshipCircumvention
from onionshare_cli.meek import (
MeekNotRunning,
MeekNotFound,
)
from onionshare_cli.settings import Settings from onionshare_cli.settings import Settings
from . import strings from . import strings
from .gui_common import GuiCommon, ToggleCheckbox from .gui_common import GuiCommon, ToggleCheckbox
from .threads import CensorshipCircumventionThread
from .tor_connection import TorConnectionWidget from .tor_connection import TorConnectionWidget
from .update_checker import UpdateThread from .update_checker import UpdateThread
from .widgets import Alert from .widgets import Alert
@ -158,14 +162,12 @@ class AutoConnectTab(QtWidgets.QWidget):
"_got_bridges", "_got_bridges",
"Got bridges. Trying to reconnect to Tor", "Got bridges. Trying to reconnect to Tor",
) )
self.active = False
self.tor_con.show() self.tor_con.show()
self.tor_con.start(self.curr_settings) self.tor_con.start(self.curr_settings)
def _got_no_bridges(self): def _got_no_bridges(self):
self.use_bridge_widget.progress.hide() self.use_bridge_widget.progress.hide()
self.use_bridge_widget.progress_label.hide() self.use_bridge_widget.progress_label.hide()
self.active = False
self.tor_con.fail.emit() self.tor_con.fail.emit()
Alert( Alert(
@ -203,16 +205,39 @@ class AutoConnectTab(QtWidgets.QWidget):
else: else:
country = self.use_bridge_widget.country_code country = self.use_bridge_widget.country_code
t = CensorshipCircumventionThread(self.common, self.curr_settings, country) self._censorship_progress_update(
t.progress_update.connect(self._censorship_progress_update) 50, strings._("gui_autoconnect_circumventing_censorship_starting_meek")
t.got_bridges.connect(self._got_bridges) )
t.got_no_bridges.connect(self._got_no_bridges) try:
t.start() self.common.gui.meek.start()
self.use_bridge_widget.progress.setValue(0) self.censorship_circumvention = CensorshipCircumvention(
self.active = True self.common, self.common.gui.meek
while self.active: )
time.sleep(0.1) self._censorship_progress_update(
self.common.gui.qtapp.processEvents() 75, strings._("gui_autoconnect_circumventing_censorship_requesting_bridges")
)
bridge_settings = self.censorship_circumvention.request_settings(
country=country
)
self.common.gui.meek.cleanup()
if bridge_settings and self.censorship_circumvention.save_settings(
self.curr_settings, bridge_settings
):
self._censorship_progress_update(
100, strings._("gui_autoconnect_circumventing_censorship_got_bridges")
)
self._got_bridges()
else:
self._censorship_progress_update(
100, strings._("gui_autoconnect_circumventing_censorship_no_bridges")
)
self._got_no_bridges()
except (
MeekNotRunning,
MeekNotFound,
) as e:
self._got_no_bridges()
def back_clicked(self): def back_clicked(self):
""" """

View file

@ -39,8 +39,6 @@ from onionshare_cli.onion import (
PortNotAvailable, PortNotAvailable,
) )
from onionshare_cli.censorship import CensorshipCircumvention
from . import strings from . import strings
@ -270,53 +268,3 @@ class OnionCleanupThread(QtCore.QThread):
def run(self): def run(self):
self.common.log("OnionCleanupThread", "run") self.common.log("OnionCleanupThread", "run")
self.common.gui.onion.cleanup() self.common.gui.onion.cleanup()
class CensorshipCircumventionThread(QtCore.QThread):
progress_update = QtCore.Signal(int, str)
got_bridges = QtCore.Signal()
got_no_bridges = QtCore.Signal()
def __init__(self, common, settings, country):
super(CensorshipCircumventionThread, self).__init__()
self.common = common
self.progress_update.emit(
25,
strings._(
"gui_autoconnect_circumventing_censorship_starting_circumvention"
),
)
self.common.log("CensorshipCircumventionThread", "__init__")
self.settings = settings
self.country = country
def run(self):
self.common.log("CensorshipCircumventionThread", "run")
self.progress_update.emit(
50, strings._("gui_autoconnect_circumventing_censorship_starting_meek")
)
self.common.gui.meek.start()
self.censorship_circumvention = CensorshipCircumvention(
self.common, self.common.gui.meek
)
self.progress_update.emit(
75, strings._("gui_autoconnect_circumventing_censorship_requesting_bridges")
)
bridge_settings = self.censorship_circumvention.request_settings(
country=self.country
)
self.common.gui.meek.cleanup()
if bridge_settings and self.censorship_circumvention.save_settings(
self.settings, bridge_settings
):
self.progress_update.emit(
100, strings._("gui_autoconnect_circumventing_censorship_got_bridges")
)
self.got_bridges.emit()
else:
self.progress_update.emit(
100, strings._("gui_autoconnect_circumventing_censorship_no_bridges")
)
self.got_no_bridges.emit()