From cb598ee6979aa8b5fc6a719aea1abbffa6ad50e8 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Tue, 24 Nov 2020 21:52:15 -0800 Subject: [PATCH 01/12] Change --autostop-sharing option to --no-autostop-sharing, so that it can default to being disabled (so autostop sharing can be enabled by default) --- cli/onionshare_cli/__init__.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cli/onionshare_cli/__init__.py b/cli/onionshare_cli/__init__.py index 7361ac9e..dac42514 100644 --- a/cli/onionshare_cli/__init__.py +++ b/cli/onionshare_cli/__init__.py @@ -180,11 +180,11 @@ def main(cwd=None): ) # Share args parser.add_argument( - "--autostop-sharing", + "--no-autostop-sharing", action="store_true", - dest="autostop_sharing", - default=True, - help="Share files: Stop sharing after files have been sent", + dest="no_autostop_sharing", + default=False, + help="Share files: Continue sharing after files have been sent (default is to stop sharing)", ) # Receive args parser.add_argument( @@ -233,7 +233,7 @@ def main(cwd=None): autostop_timer = int(args.autostop_timer) legacy = bool(args.legacy) client_auth = bool(args.client_auth) - autostop_sharing = bool(args.autostop_sharing) + autostop_sharing = not bool(args.no_autostop_sharing) data_dir = args.data_dir disable_csp = bool(args.disable_csp) verbose = bool(args.verbose) From 0eee8ce05baa0a3bb70d1320305efb37957fca9d Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Wed, 25 Nov 2020 11:25:32 -0800 Subject: [PATCH 02/12] If using bundled Tor, wait for rendezvous circuits to close before killing the tor process --- cli/onionshare_cli/onion.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/cli/onionshare_cli/onion.py b/cli/onionshare_cli/onion.py index 6a42638a..89b678f8 100644 --- a/cli/onionshare_cli/onion.py +++ b/cli/onionshare_cli/onion.py @@ -749,6 +749,32 @@ class Onion(object): if stop_tor: # Stop tor process if self.tor_proc: + rendevouz_circuit_ids = [] + for c in self.c.get_circuits(): + if c.purpose == "HS_SERVICE_REND": + rendevouz_circuit_ids.append(c.id) + # print(f"id={c.id} purpose={c.purpose} rend_query={c.rend_query} type={c.type}") + + while True: + num_rend_circuits = 0 + for c in self.c.get_circuits(): + if c.id in rendevouz_circuit_ids: + num_rend_circuits += 1 + + if num_rend_circuits == 0: + print("Tor rendevous circuits have closed" + " " * 20) + break + + if num_rend_circuits == 1: + circuits = "circuit" + else: + circuits = "circuits" + print( + f"\rWaiting for {num_rend_circuits} Tor rendezvous {circuits} to close ... ", + end="", + ) + time.sleep(1) + self.tor_proc.terminate() time.sleep(0.2) if self.tor_proc.poll() is None: From 3871fcf5ebad4c6645ca238a9c7bf21219b9c292 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Wed, 25 Nov 2020 11:52:36 -0800 Subject: [PATCH 03/12] Improve output when rendezvous circuits all close --- cli/onionshare_cli/onion.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/onionshare_cli/onion.py b/cli/onionshare_cli/onion.py index 89b678f8..c6862a4f 100644 --- a/cli/onionshare_cli/onion.py +++ b/cli/onionshare_cli/onion.py @@ -762,7 +762,7 @@ class Onion(object): num_rend_circuits += 1 if num_rend_circuits == 0: - print("Tor rendevous circuits have closed" + " " * 20) + print("\rTor rendezvous circuits have closed" + " " * 20) break if num_rend_circuits == 1: From 752afcaa3a62785296d06baeb44ba00a4f30ad46 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 27 Nov 2020 11:08:58 -0800 Subject: [PATCH 04/12] Put wait for circuits to close login in a try/except, so Ctrl-C does not cause a crash --- cli/onionshare_cli/onion.py | 49 ++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/cli/onionshare_cli/onion.py b/cli/onionshare_cli/onion.py index c6862a4f..f10401da 100644 --- a/cli/onionshare_cli/onion.py +++ b/cli/onionshare_cli/onion.py @@ -749,31 +749,36 @@ class Onion(object): if stop_tor: # Stop tor process if self.tor_proc: - rendevouz_circuit_ids = [] - for c in self.c.get_circuits(): - if c.purpose == "HS_SERVICE_REND": - rendevouz_circuit_ids.append(c.id) - # print(f"id={c.id} purpose={c.purpose} rend_query={c.rend_query} type={c.type}") - - while True: - num_rend_circuits = 0 + # Wait for Tor rendezvous circuits to close + # Catch exceptions to prevent crash on Ctrl-C + try: + rendevouz_circuit_ids = [] for c in self.c.get_circuits(): - if c.id in rendevouz_circuit_ids: - num_rend_circuits += 1 + if c.purpose == "HS_SERVICE_REND": + rendevouz_circuit_ids.append(c.id) + # print(f"id={c.id} purpose={c.purpose} rend_query={c.rend_query} type={c.type}") - if num_rend_circuits == 0: - print("\rTor rendezvous circuits have closed" + " " * 20) - break + while True: + num_rend_circuits = 0 + for c in self.c.get_circuits(): + if c.id in rendevouz_circuit_ids: + num_rend_circuits += 1 - if num_rend_circuits == 1: - circuits = "circuit" - else: - circuits = "circuits" - print( - f"\rWaiting for {num_rend_circuits} Tor rendezvous {circuits} to close ... ", - end="", - ) - time.sleep(1) + if num_rend_circuits == 0: + print("\rTor rendezvous circuits have closed" + " " * 20) + break + + if num_rend_circuits == 1: + circuits = "circuit" + else: + circuits = "circuits" + print( + f"\rWaiting for {num_rend_circuits} Tor rendezvous {circuits} to close ... ", + end="", + ) + time.sleep(1) + except: + pass self.tor_proc.terminate() time.sleep(0.2) From 7927ef83b235e1219f7825e740db9ce216147aee Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 27 Nov 2020 11:22:29 -0800 Subject: [PATCH 05/12] Only wait for share mode rendezvous circuits to close, ignore the rest --- cli/onionshare_cli/__init__.py | 6 +++--- cli/onionshare_cli/onion.py | 15 ++++++++++++--- cli/onionshare_cli/onionshare.py | 4 ++-- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/cli/onionshare_cli/__init__.py b/cli/onionshare_cli/__init__.py index dac42514..12808375 100644 --- a/cli/onionshare_cli/__init__.py +++ b/cli/onionshare_cli/__init__.py @@ -353,7 +353,7 @@ def main(cwd=None): ) sys.exit() - app.start_onion_service(mode_settings, False, True) + app.start_onion_service(mode, mode_settings, False, True) url = build_url(mode_settings, app, web) schedule = datetime.now() + timedelta(seconds=autostart_timer) if mode == "receive": @@ -389,9 +389,9 @@ def main(cwd=None): print("Waiting for the scheduled time before starting...") app.onion.cleanup(False) time.sleep(autostart_timer) - app.start_onion_service(mode_settings) + app.start_onion_service(mode, mode_settings) else: - app.start_onion_service(mode_settings) + app.start_onion_service(mode, mode_settings) except KeyboardInterrupt: print("") sys.exit() diff --git a/cli/onionshare_cli/onion.py b/cli/onionshare_cli/onion.py index f10401da..b801997d 100644 --- a/cli/onionshare_cli/onion.py +++ b/cli/onionshare_cli/onion.py @@ -188,6 +188,9 @@ class Onion(object): # Assigned later if we are using stealth mode self.auth_string = None + # Keep track of onions where it's important to gracefully close to prevent truncated downloads + self.graceful_close_onions = [] + def connect( self, custom_settings=None, @@ -611,7 +614,7 @@ class Onion(object): else: return False - def start_onion_service(self, mode_settings, port, await_publication): + def start_onion_service(self, mode, mode_settings, port, await_publication): """ Start a onion service on port 80, pointing to the given port, and return the onion hostname. @@ -691,6 +694,10 @@ class Onion(object): onion_host = res.service_id + ".onion" + # Gracefully close share mode rendezvous circuits + if mode == "share": + self.graceful_close_onions.append(res.service_id) + # Save the service_id mode_settings.set("general", "service_id", res.service_id) @@ -754,9 +761,11 @@ class Onion(object): try: rendevouz_circuit_ids = [] for c in self.c.get_circuits(): - if c.purpose == "HS_SERVICE_REND": + if ( + c.purpose == "HS_SERVICE_REND" + and c.rend_query in self.graceful_close_onions + ): rendevouz_circuit_ids.append(c.id) - # print(f"id={c.id} purpose={c.purpose} rend_query={c.rend_query} type={c.type}") while True: num_rend_circuits = 0 diff --git a/cli/onionshare_cli/onionshare.py b/cli/onionshare_cli/onionshare.py index f74672ce..6fead913 100644 --- a/cli/onionshare_cli/onionshare.py +++ b/cli/onionshare_cli/onionshare.py @@ -63,7 +63,7 @@ class OnionShare(object): except: raise OSError("Cannot find an available OnionShare port") - def start_onion_service(self, mode_settings, await_publication=True): + def start_onion_service(self, mode, mode_settings, await_publication=True): """ Start the onionshare onion service. """ @@ -80,7 +80,7 @@ class OnionShare(object): return self.onion_host = self.onion.start_onion_service( - mode_settings, self.port, await_publication + mode, mode_settings, self.port, await_publication ) if mode_settings.get("general", "client_auth"): From 6d38b8e0c4a19386a6f1d040f078f4351a06cd65 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 27 Nov 2020 11:27:11 -0800 Subject: [PATCH 06/12] Add terminal animation while waiting for circuits to close --- cli/onionshare_cli/onion.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cli/onionshare_cli/onion.py b/cli/onionshare_cli/onion.py index b801997d..08b3652a 100644 --- a/cli/onionshare_cli/onion.py +++ b/cli/onionshare_cli/onion.py @@ -767,6 +767,9 @@ class Onion(object): ): rendevouz_circuit_ids.append(c.id) + symbols = [c for c in "\\|/-"] + symbols_i = 0 + while True: num_rend_circuits = 0 for c in self.c.get_circuits(): @@ -782,9 +785,10 @@ class Onion(object): else: circuits = "circuits" print( - f"\rWaiting for {num_rend_circuits} Tor rendezvous {circuits} to close ... ", + f"\rWaiting for {num_rend_circuits} Tor rendezvous {circuits} to close {symbols[symbols_i]} ", end="", ) + symbols_i = (symbols_i + 1) % len(symbols) time.sleep(1) except: pass From 2aefe0ff4ef68f856cdcd24f4346438bbd905be2 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 27 Nov 2020 12:15:49 -0800 Subject: [PATCH 07/12] Make GUI pass the mode type into start_onion_service --- desktop/src/onionshare/tab/mode/__init__.py | 6 ++++++ desktop/src/onionshare/tab/mode/chat_mode/__init__.py | 6 ++++++ desktop/src/onionshare/tab/mode/receive_mode/__init__.py | 6 ++++++ desktop/src/onionshare/tab/mode/share_mode/__init__.py | 6 ++++++ desktop/src/onionshare/tab/mode/website_mode/__init__.py | 6 ++++++ desktop/src/onionshare/threads.py | 6 +++--- 6 files changed, 33 insertions(+), 3 deletions(-) diff --git a/desktop/src/onionshare/tab/mode/__init__.py b/desktop/src/onionshare/tab/mode/__init__.py index f92632f0..7738f567 100644 --- a/desktop/src/onionshare/tab/mode/__init__.py +++ b/desktop/src/onionshare/tab/mode/__init__.py @@ -107,6 +107,12 @@ class Mode(QtWidgets.QWidget): """ pass + def get_type(self): + """ + Returns the type of mode as a string (e.g. "share", "receive", etc.) + """ + pass + def human_friendly_time(self, secs): """ Returns a human-friendly time delta from given seconds. diff --git a/desktop/src/onionshare/tab/mode/chat_mode/__init__.py b/desktop/src/onionshare/tab/mode/chat_mode/__init__.py index 25a02969..a7c2929b 100644 --- a/desktop/src/onionshare/tab/mode/chat_mode/__init__.py +++ b/desktop/src/onionshare/tab/mode/chat_mode/__init__.py @@ -101,6 +101,12 @@ class ChatMode(Mode): self.wrapper_layout.addLayout(self.column_layout) self.setLayout(self.wrapper_layout) + def get_type(self): + """ + Returns the type of mode as a string (e.g. "share", "receive", etc.) + """ + return "chat" + def get_stop_server_autostop_timer_text(self): """ Return the string to put on the stop server button, if there's an auto-stop timer diff --git a/desktop/src/onionshare/tab/mode/receive_mode/__init__.py b/desktop/src/onionshare/tab/mode/receive_mode/__init__.py index 95d1ecbe..95a68dcb 100644 --- a/desktop/src/onionshare/tab/mode/receive_mode/__init__.py +++ b/desktop/src/onionshare/tab/mode/receive_mode/__init__.py @@ -149,6 +149,12 @@ class ReceiveMode(Mode): self.wrapper_layout.addLayout(self.column_layout) self.setLayout(self.wrapper_layout) + def get_type(self): + """ + Returns the type of mode as a string (e.g. "share", "receive", etc.) + """ + return "receive" + def data_dir_button_clicked(self): """ Browse for a new OnionShare data directory, and save to tab settings diff --git a/desktop/src/onionshare/tab/mode/share_mode/__init__.py b/desktop/src/onionshare/tab/mode/share_mode/__init__.py index ccf85dbd..bf1498d5 100644 --- a/desktop/src/onionshare/tab/mode/share_mode/__init__.py +++ b/desktop/src/onionshare/tab/mode/share_mode/__init__.py @@ -173,6 +173,12 @@ class ShareMode(Mode): # Always start with focus on file selection self.file_selection.setFocus() + def get_type(self): + """ + Returns the type of mode as a string (e.g. "share", "receive", etc.) + """ + return "share" + def autostop_sharing_checkbox_clicked(self): """ Save autostop sharing setting to the tab settings diff --git a/desktop/src/onionshare/tab/mode/website_mode/__init__.py b/desktop/src/onionshare/tab/mode/website_mode/__init__.py index 325b22f1..6df6ff02 100644 --- a/desktop/src/onionshare/tab/mode/website_mode/__init__.py +++ b/desktop/src/onionshare/tab/mode/website_mode/__init__.py @@ -173,6 +173,12 @@ class WebsiteMode(Mode): # Always start with focus on file selection self.file_selection.setFocus() + def get_type(self): + """ + Returns the type of mode as a string (e.g. "share", "receive", etc.) + """ + return "website" + def disable_csp_checkbox_clicked(self): """ Save disable CSP setting to the tab settings diff --git a/desktop/src/onionshare/threads.py b/desktop/src/onionshare/threads.py index 338bbf27..d5e2dc6c 100644 --- a/desktop/src/onionshare/threads.py +++ b/desktop/src/onionshare/threads.py @@ -74,7 +74,7 @@ class OnionThread(QtCore.QThread): try: if self.mode.obtain_onion_early: self.mode.app.start_onion_service( - self.mode.settings, await_publication=False + self.mode.get_type(), self.mode.settings, await_publication=False ) # wait for modules in thread to load, preventing a thread-related cx_Freeze crash time.sleep(0.2) @@ -83,7 +83,7 @@ class OnionThread(QtCore.QThread): self.mode.app.stop_onion_service(self.mode.settings) else: self.mode.app.start_onion_service( - self.mode.settings, await_publication=True + self.mode.get_type(), self.mode.settings, await_publication=True ) # wait for modules in thread to load, preventing a thread-related cx_Freeze crash time.sleep(0.2) @@ -174,7 +174,7 @@ class AutoStartTimer(QtCore.QThread): class EventHandlerThread(QtCore.QThread): """ - To trigger an event, write a JSON line to the events file. When that file changes, + To trigger an event, write a JSON line to the events file. When that file changes, each line will be handled as an event. Valid events are: {"type": "new_tab"} {"type": "new_share_tab", "filenames": ["file1", "file2"]} From f69cbbd3893ef00380a46b054e2c9b624d26401e Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 27 Nov 2020 12:16:04 -0800 Subject: [PATCH 08/12] Update desktop readme to include instructions on using verbose mode --- desktop/README.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/desktop/README.md b/desktop/README.md index a1406b47..039124fe 100644 --- a/desktop/README.md +++ b/desktop/README.md @@ -86,12 +86,19 @@ While your virtual environment is active, install briefcase from pip. pip install briefcase ``` -Run OnionShare from the source tree like this: +Run OnionShare from the source tree like this (`-d` re-installs dependencies, which you'll have to do each time you update the `onionshare-cli` wheel): ``` briefcase dev -d ``` +If you want to pass arguments into `onionshare`, such as to use verbose mode: + +``` +cd src +python -c "import onionshare; onionshare.main()" --help +``` + ## Running tests Install these packages inside your virtual environment: From 184f1261896855fcfadf09d36ade36dd9c275d57 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 27 Nov 2020 12:38:00 -0800 Subject: [PATCH 09/12] When quitting OnionShare with services started, make sure the web services get stopped --- desktop/src/onionshare/main_window.py | 1 + desktop/src/onionshare/tab/tab.py | 2 ++ desktop/src/onionshare/tab_widget.py | 2 ++ 3 files changed, 5 insertions(+) diff --git a/desktop/src/onionshare/main_window.py b/desktop/src/onionshare/main_window.py index c1e0cd1a..5a099cbc 100644 --- a/desktop/src/onionshare/main_window.py +++ b/desktop/src/onionshare/main_window.py @@ -285,6 +285,7 @@ class MainWindow(QtWidgets.QMainWindow): e.accept() def cleanup(self): + self.common.log("MainWindow", "cleanup") self.tabs.cleanup() self.common.gui.onion.cleanup() diff --git a/desktop/src/onionshare/tab/tab.py b/desktop/src/onionshare/tab/tab.py index 5e819405..f474b9ba 100644 --- a/desktop/src/onionshare/tab/tab.py +++ b/desktop/src/onionshare/tab/tab.py @@ -663,7 +663,9 @@ class Tab(QtWidgets.QWidget): return False def cleanup(self): + self.common.log("Tab", "cleanup", f"tab_id={self.tab_id}") if self.get_mode() and self.get_mode().web_thread: + self.get_mode().web.stop(self.get_mode().app.port) self.get_mode().web_thread.quit() self.get_mode().web_thread.wait() self.app.cleanup() diff --git a/desktop/src/onionshare/tab_widget.py b/desktop/src/onionshare/tab_widget.py index 84d16e83..b78e67dd 100644 --- a/desktop/src/onionshare/tab_widget.py +++ b/desktop/src/onionshare/tab_widget.py @@ -81,6 +81,8 @@ class TabWidget(QtWidgets.QTabWidget): self.event_handler_t.start() def cleanup(self): + self.common.log("TabWidget", "cleanup") + # Stop the event thread self.event_handler_t.should_quit = True self.event_handler_t.quit() From 134611a3253cc61904c10a61d3434c7bed2d2975 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 27 Nov 2020 14:50:07 -0800 Subject: [PATCH 10/12] Show a dialog while waiting for Tor rendezvous nodes to close, and let the user quit early --- cli/onionshare_cli/onion.py | 71 ++++++++++--------- desktop/src/onionshare/main_window.py | 26 ++++++- .../src/onionshare/resources/locale/en.json | 4 +- desktop/src/onionshare/threads.py | 15 ++++ 4 files changed, 80 insertions(+), 36 deletions(-) diff --git a/cli/onionshare_cli/onion.py b/cli/onionshare_cli/onion.py index 08b3652a..311de936 100644 --- a/cli/onionshare_cli/onion.py +++ b/cli/onionshare_cli/onion.py @@ -729,7 +729,7 @@ class Onion(object): "Onion", "stop_onion_service", f"failed to remove {onion_host}" ) - def cleanup(self, stop_tor=True): + def cleanup(self, stop_tor=True, wait=True): """ Stop onion services that were created earlier. If there's a tor subprocess running, kill it. """ @@ -756,42 +756,45 @@ class Onion(object): if stop_tor: # Stop tor process if self.tor_proc: - # Wait for Tor rendezvous circuits to close - # Catch exceptions to prevent crash on Ctrl-C - try: - rendevouz_circuit_ids = [] - for c in self.c.get_circuits(): - if ( - c.purpose == "HS_SERVICE_REND" - and c.rend_query in self.graceful_close_onions - ): - rendevouz_circuit_ids.append(c.id) - - symbols = [c for c in "\\|/-"] - symbols_i = 0 - - while True: - num_rend_circuits = 0 + if wait: + # Wait for Tor rendezvous circuits to close + # Catch exceptions to prevent crash on Ctrl-C + try: + rendevouz_circuit_ids = [] for c in self.c.get_circuits(): - if c.id in rendevouz_circuit_ids: - num_rend_circuits += 1 + if ( + c.purpose == "HS_SERVICE_REND" + and c.rend_query in self.graceful_close_onions + ): + rendevouz_circuit_ids.append(c.id) - if num_rend_circuits == 0: - print("\rTor rendezvous circuits have closed" + " " * 20) - break + symbols = [c for c in "\\|/-"] + symbols_i = 0 - if num_rend_circuits == 1: - circuits = "circuit" - else: - circuits = "circuits" - print( - f"\rWaiting for {num_rend_circuits} Tor rendezvous {circuits} to close {symbols[symbols_i]} ", - end="", - ) - symbols_i = (symbols_i + 1) % len(symbols) - time.sleep(1) - except: - pass + while True: + num_rend_circuits = 0 + for c in self.c.get_circuits(): + if c.id in rendevouz_circuit_ids: + num_rend_circuits += 1 + + if num_rend_circuits == 0: + print( + "\rTor rendezvous circuits have closed" + " " * 20 + ) + break + + if num_rend_circuits == 1: + circuits = "circuit" + else: + circuits = "circuits" + print( + f"\rWaiting for {num_rend_circuits} Tor rendezvous {circuits} to close {symbols[symbols_i]} ", + end="", + ) + symbols_i = (symbols_i + 1) % len(symbols) + time.sleep(1) + except: + pass self.tor_proc.terminate() time.sleep(0.2) diff --git a/desktop/src/onionshare/main_window.py b/desktop/src/onionshare/main_window.py index 5a099cbc..a1b44032 100644 --- a/desktop/src/onionshare/main_window.py +++ b/desktop/src/onionshare/main_window.py @@ -30,6 +30,7 @@ from .widgets import Alert from .update_checker import UpdateThread from .tab_widget import TabWidget from .gui_common import GuiCommon +from .threads import OnionCleanupThread class MainWindow(QtWidgets.QMainWindow): @@ -287,7 +288,30 @@ class MainWindow(QtWidgets.QMainWindow): def cleanup(self): self.common.log("MainWindow", "cleanup") self.tabs.cleanup() - self.common.gui.onion.cleanup() + + alert = Alert( + self.common, + strings._("gui_rendezvous_cleanup"), + QtWidgets.QMessageBox.Information, + buttons=QtWidgets.QMessageBox.NoButton, + autostart=False, + ) + quit_early_button = QtWidgets.QPushButton( + strings._("gui_rendezvous_cleanup_quit_early") + ) + alert.addButton(quit_early_button, QtWidgets.QMessageBox.RejectRole) + + self.onion_cleanup_thread = OnionCleanupThread(self.common) + self.onion_cleanup_thread.finished.connect(alert.accept) + self.onion_cleanup_thread.start() + + alert.exec_() + if alert.clickedButton() == quit_early_button: + self.common.log("MainWindow", "cleanup", "quitting early") + if self.onion_cleanup_thread.isRunning(): + self.onion_cleanup_thread.terminate() + self.onion_cleanup_thread.wait() + self.common.gui.onion.cleanup(wait=False) # Wait 1 second for threads to close gracefully, so tests finally pass time.sleep(1) diff --git a/desktop/src/onionshare/resources/locale/en.json b/desktop/src/onionshare/resources/locale/en.json index 1f98d7a7..aa34fd82 100644 --- a/desktop/src/onionshare/resources/locale/en.json +++ b/desktop/src/onionshare/resources/locale/en.json @@ -187,5 +187,7 @@ "settings_error_unreadable_cookie_file": "Connected to the Tor controller, but password may be wrong, or your user is not permitted to read the cookie file.", "settings_error_bundled_tor_not_supported": "Using the Tor version that comes with OnionShare does not work in developer mode on Windows or macOS.", "settings_error_bundled_tor_timeout": "Taking too long to connect to Tor. Maybe you aren't connected to the Internet, or have an inaccurate system clock?", - "settings_error_bundled_tor_broken": "OnionShare could not connect to Tor:\n{}" + "settings_error_bundled_tor_broken": "OnionShare could not connect to Tor:\n{}", + "gui_rendezvous_cleanup": "Waiting for Tor rendezvous circuits to close to be sure that the files you shared downloaded successfully.\n\nThis might take a few minutes.", + "gui_rendezvous_cleanup_quit_early": "Quit Early" } \ No newline at end of file diff --git a/desktop/src/onionshare/threads.py b/desktop/src/onionshare/threads.py index d5e2dc6c..22e264e5 100644 --- a/desktop/src/onionshare/threads.py +++ b/desktop/src/onionshare/threads.py @@ -252,3 +252,18 @@ class EventHandlerThread(QtCore.QThread): if self.should_quit: break time.sleep(0.2) + + +class OnionCleanupThread(QtCore.QThread): + """ + Wait for Tor rendezvous circuits to close in a separate thread + """ + + def __init__(self, common): + super(OnionCleanupThread, self).__init__() + self.common = common + self.common.log("OnionCleanupThread", "__init__") + + def run(self): + self.common.log("OnionCleanupThread", "run") + self.common.gui.onion.cleanup() From af5dda0d4a3ad1ed0a0ebdfe32fb20abf9b56162 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 27 Nov 2020 14:57:49 -0800 Subject: [PATCH 11/12] Fix start_onion_service test --- cli/tests/test_cli.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cli/tests/test_cli.py b/cli/tests/test_cli.py index 99f26547..be71240b 100644 --- a/cli/tests/test_cli.py +++ b/cli/tests/test_cli.py @@ -15,7 +15,7 @@ class MyOnion: @staticmethod def start_onion_service( - self, mode_settings_obj, await_publication=True, save_scheduled_key=False + self, mode, mode_settings_obj, await_publication=True, save_scheduled_key=False ): return "test_service_id.onion" @@ -40,13 +40,13 @@ class TestOnionShare: assert onionshare_obj.local_only is False def test_start_onion_service(self, onionshare_obj, mode_settings_obj): - onionshare_obj.start_onion_service(mode_settings_obj) + onionshare_obj.start_onion_service("share", mode_settings_obj) assert 17600 <= onionshare_obj.port <= 17650 assert onionshare_obj.onion_host == "test_service_id.onion" def test_start_onion_service_local_only(self, onionshare_obj, mode_settings_obj): onionshare_obj.local_only = True - onionshare_obj.start_onion_service(mode_settings_obj) + onionshare_obj.start_onion_service("share", mode_settings_obj) assert onionshare_obj.onion_host == "127.0.0.1:{}".format(onionshare_obj.port) def test_cleanup(self, onionshare_obj, temp_dir_1024, temp_file_1024): From ae621b4001dc44d7f07a9fad43376439b855ccd8 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Sun, 29 Nov 2020 09:30:45 -0800 Subject: [PATCH 12/12] Change wording of waiting for Tor circuits message --- desktop/src/onionshare/resources/locale/en.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/desktop/src/onionshare/resources/locale/en.json b/desktop/src/onionshare/resources/locale/en.json index aa34fd82..81984273 100644 --- a/desktop/src/onionshare/resources/locale/en.json +++ b/desktop/src/onionshare/resources/locale/en.json @@ -188,6 +188,6 @@ "settings_error_bundled_tor_not_supported": "Using the Tor version that comes with OnionShare does not work in developer mode on Windows or macOS.", "settings_error_bundled_tor_timeout": "Taking too long to connect to Tor. Maybe you aren't connected to the Internet, or have an inaccurate system clock?", "settings_error_bundled_tor_broken": "OnionShare could not connect to Tor:\n{}", - "gui_rendezvous_cleanup": "Waiting for Tor rendezvous circuits to close to be sure that the files you shared downloaded successfully.\n\nThis might take a few minutes.", + "gui_rendezvous_cleanup": "Waiting for Tor circuits to close to be sure your files have successfully transferred.\n\nThis might take a few minutes.", "gui_rendezvous_cleanup_quit_early": "Quit Early" } \ No newline at end of file