Add a Startup Timer feature (scheduled start / dead man's switch)

This commit is contained in:
Miguel Jacq 2019-03-05 10:28:27 +11:00
parent d86b13d91c
commit 26d262ccfc
16 changed files with 326 additions and 34 deletions

View file

@ -24,6 +24,7 @@ from onionshare.common import ShutdownTimer
from ..server_status import ServerStatus
from ..threads import OnionThread
from ..threads import StartupTimer
from ..widgets import Alert
class Mode(QtWidgets.QWidget):
@ -35,6 +36,7 @@ class Mode(QtWidgets.QWidget):
starting_server_step2 = QtCore.pyqtSignal()
starting_server_step3 = QtCore.pyqtSignal()
starting_server_error = QtCore.pyqtSignal(str)
starting_server_early = QtCore.pyqtSignal()
set_server_active = QtCore.pyqtSignal(bool)
def __init__(self, common, qtapp, app, status_bar, server_status_label, system_tray, filenames=None, local_only=False):
@ -58,6 +60,7 @@ class Mode(QtWidgets.QWidget):
# Threads start out as None
self.onion_thread = None
self.web_thread = None
self.startup_thread = None
# Server status
self.server_status = ServerStatus(self.common, self.qtapp, self.app, None, self.local_only)
@ -68,6 +71,7 @@ class Mode(QtWidgets.QWidget):
self.stop_server_finished.connect(self.server_status.stop_server_finished)
self.starting_server_step2.connect(self.start_server_step2)
self.starting_server_step3.connect(self.start_server_step3)
self.starting_server_early.connect(self.start_server_early)
self.starting_server_error.connect(self.start_server_error)
# Primary action
@ -142,7 +146,41 @@ class Mode(QtWidgets.QWidget):
self.status_bar.clearMessage()
self.server_status_label.setText('')
# Ensure we always get a new random port each time we might launch an OnionThread
self.app.port = None
# Start the onion thread. If this share was scheduled for a future date,
# the OnionThread will start and exit 'early' to obtain the port, slug
# and onion address, but it will not start the WebThread yet.
if self.server_status.scheduled_start:
self.start_onion_thread(obtain_onion_early=True)
else:
self.start_onion_thread()
# If scheduling a share, delay starting the real share
if self.server_status.scheduled_start:
self.common.log('Mode', 'start_server', 'Starting startup timer')
self.startup_thread = StartupTimer(self)
# Once the timer has finished, start the real share, with a WebThread
self.startup_thread.success.connect(self.start_scheduled_service)
self.startup_thread.error.connect(self.start_server_error)
self.startup_thread.canceled = False
self.startup_thread.start()
def start_onion_thread(self, obtain_onion_early=False):
self.common.log('Mode', 'start_server', 'Starting an onion thread')
self.obtain_onion_early = obtain_onion_early
self.onion_thread = OnionThread(self)
self.onion_thread.success.connect(self.starting_server_step2.emit)
self.onion_thread.success_early.connect(self.starting_server_early.emit)
self.onion_thread.error.connect(self.starting_server_error.emit)
self.onion_thread.start()
def start_scheduled_service(self, obtain_onion_early=False):
# We start a new OnionThread with the saved scheduled key from settings
self.common.settings.load()
self.obtain_onion_early = obtain_onion_early
self.common.log('Mode', 'start_server', 'Starting a scheduled onion thread')
self.onion_thread = OnionThread(self)
self.onion_thread.success.connect(self.starting_server_step2.emit)
self.onion_thread.error.connect(self.starting_server_error.emit)
@ -154,6 +192,14 @@ class Mode(QtWidgets.QWidget):
"""
pass
def start_server_early(self):
"""
An 'early' start of an onion service in order to obtain the onion
address for a scheduled start. Shows the onion address in the UI
in advance of actually starting the share.
"""
self.server_status.show_url()
def start_server_step2(self):
"""
Step 2 in starting the onionshare server.
@ -225,7 +271,11 @@ class Mode(QtWidgets.QWidget):
Cancel the server while it is preparing to start
"""
self.cancel_server_custom()
if self.startup_thread:
self.common.log('Mode', 'cancel_server: quitting startup thread')
self.startup_thread.canceled = True
self.app.onion.scheduled_key = None
self.startup_thread.quit()
if self.onion_thread:
self.common.log('Mode', 'cancel_server: quitting onion thread')
self.onion_thread.quit()