diff options
-rw-r--r-- | poetry.lock | 14 | ||||
-rw-r--r-- | pyproject.toml | 1 | ||||
-rwxr-xr-x[-rw-r--r--] | service.py | 37 | ||||
-rw-r--r-- | session.py | 92 | ||||
-rwxr-xr-x[-rw-r--r--] | test_client.py | 3 |
5 files changed, 116 insertions, 31 deletions
diff --git a/poetry.lock b/poetry.lock index 1759d95..c872566 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,5 +1,13 @@ [[package]] category = "main" +description = "Python command-line parsing library" +name = "argparse" +optional = false +python-versions = "*" +version = "1.4.0" + +[[package]] +category = "main" description = "Python package for providing Mozilla's CA Bundle." name = "certifi" optional = false @@ -188,10 +196,14 @@ dev = ["pytest", "pytest-timeout", "coverage", "tox", "sphinx", "pallets-sphinx- watchdog = ["watchdog"] [metadata] -content-hash = "b0f18bcb0fae5ffa552ced8d8334169e085cecbc91cc84431c9f6af8635757d9" +content-hash = "09076fec39be67188ddcbeff179911de7f3dc0a88bc7157a996b6404676a17dd" python-versions = "^3.5" [metadata.files] +argparse = [ + {file = "argparse-1.4.0-py2.py3-none-any.whl", hash = "sha256:c31647edb69fd3d465a847ea3157d37bed1f95f19760b11a47aa91c04b666314"}, + {file = "argparse-1.4.0.tar.gz", hash = "sha256:62b089a55be1d8949cd2bc7e0df0bddb9e028faefc8c32038cc84862aefdd6e4"}, +] certifi = [ {file = "certifi-2020.6.20-py2.py3-none-any.whl", hash = "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41"}, {file = "certifi-2020.6.20.tar.gz", hash = "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3"}, diff --git a/pyproject.toml b/pyproject.toml index 7f2b787..204dc99 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,6 +14,7 @@ requests = "^2.24.0" websockify = "^0.9.0" psutil = "^5.7.2" flask = "^1.1.2" +argparse = "^1.0.10" [tool.poetry.dev-dependencies] diff --git a/service.py b/service.py index 21737ac..eb6d311 100644..100755 --- a/service.py +++ b/service.py @@ -1,3 +1,6 @@ +#!/usr/bin/env python3 +import argparse + import json import time from threading import Thread @@ -7,9 +10,12 @@ import dbus.service from session import Session +from typing import Union class RWAService(dbus.service.Object): - def __init__(self): + def __init__(self, mockup_mode: bool): + self.mockup_mode = mockup_mode + self.bus = dbus.SessionBus() name = dbus.service.BusName("org.ArcticaProject.RWA", bus=self.bus) @@ -21,7 +27,7 @@ class RWAService(dbus.service.Object): def start(self): """Start a new remote session.""" # Start session - session = Session() + session = Session(mockup_mode) # Add session to sessions list self.sessions[session.pid] = session @@ -84,13 +90,38 @@ class RWAService(dbus.service.Object): self.update_service_running = False # TODO Probably kill daemon here (quit main loop) +def str2bool(v: Union[str, bool, int]) -> bool: + """Return true or false if the given string can be interpreted as a boolean otherwise raise an exception.""" + if isinstance(v, bool): + return v + if v.lower() in ('yes', 'true', 't', 'y', '1', 1): + return True + elif v.lower() in ('no', 'false', 'f', 'n', '0', 0): + return False + else: + raise argparse.ArgumentTypeError('Boolean value expected.') if __name__ == "__main__": + parser = argparse.ArgumentParser(description='DBus session service for ' + + 'ArcticaProject\'s ' + + 'Remote Web App') + parser.add_argument("-m", "--mockup-mode", type=str2bool, nargs='?', + const=True, default=False, + help="Activate mockup mode. Act like the session " + + "service but don\'t do changes or call other " + + "parts of RWA.") + + args = parser.parse_args() + mockup_mode = args.mockup_mode + + if mockup_mode: + print("All API responses are faked and should NOT BE USED IN " + + "PRODUCTION!") import dbus.mainloop.glib from gi.repository import GLib dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) loop = GLib.MainLoop() - object = RWAService() + object = RWAService(mockup_mode) loop.run() @@ -3,6 +3,8 @@ import secrets import signal from multiprocessing import Process +import random, string + import psutil import requests @@ -23,7 +25,8 @@ class Session: #: Remote has joined the session STATUS_JOINED = "joined" - def __init__(self): + def __init__(self, mockup_session: bool): + self.mockup_session = mockup_session self._generate_password() self._start_vnc() self._start_trigger_service() @@ -44,35 +47,61 @@ class Session: def _generate_password(self): """Generate password for x11vnc and save it.""" self.password = secrets.token_urlsafe(20) - self.pw_filename = save_password(self.password) + + # Don't actually save a password if we just pretend to be a session. + if not self.mockup_session: + self.pw_filename = save_password(self.password) def _start_vnc(self): - """Start x11vnc server.""" - process_info = run_vnc(self.pw_filename) + """Start x11vnc server if not in mockup_session mode.""" + if not self.mockup_session: + process_info = run_vnc(self.pw_filename) + + self.vnc_pid = process_info["vnc"]["pid"] + self.vnc_port = process_info["vnc"]["port"] + self.ws_pid = process_info["ws"]["pid"] + self.ws_port = process_info["ws"]["port"] + else: + self.ws_port = port_for.select_random() + self.vnc_port = port_for.select_random() + + # Use negative values to ensure we don't do something harmful + # to random processes + self.ws_pid = int('-' + ''.join(random.choice(string.digits) for _ in range(5))) + self.vnc_pid = int('-' + ''.join(random.choice(string.digits) for _ in range(5))) + + # Create a temporary file to indicate that this process is still 'Running' + filename = f"/tmp/rwa/{str(self.ws_port) + str(self.vnc_port) + str(self.ws_pid) + str(self.vnc_pid)}.lock" + new_file = open(filename, "w"); + new_file.write('this session is running') - self.vnc_pid = process_info["vnc"]["pid"] - self.vnc_port = process_info["vnc"]["port"] - self.ws_pid = process_info["ws"]["pid"] - self.ws_port = process_info["ws"]["port"] def _register_session(self): - """Register session in RWA.""" - r = requests.post( - REGISTER_URL, - json={ - "port": self.ws_port, - "password": self.password, - "pid": self.vnc_pid, - "trigger_port": self.trigger_port, - "trigger_token": self.trigger_token, - }, - ) - print(r) - self.meta = r.json() - self.session_id = self.meta["session_id"] - self.web_url = self.meta["url"] - self.api_token = self.meta["token"] - self.pin = self.meta["pin"] + """Register session in RWA if not in mockup_session mode.""" + if not self.mockup_session: + r = requests.post( + REGISTER_URL, + json={ + "port": self.ws_port, + "password": self.password, + "pid": self.vnc_pid, + "trigger_port": self.trigger_port, + "trigger_token": self.trigger_token, + }, + ) + print(r) + self.meta = r.json() + self.session_id = self.meta["session_id"] + self.web_url = self.meta["url"] + self.api_token = self.meta["token"] + self.pin = self.meta["pin"] + else: + print("\"Registered\" in RWA") + self.meta = {} + self.session_id = int(''.join(random.choice(string.digits) for _ in range(10))) + self.web_url = "testhostname:" + ''.join(random.choice(string.digits) for _ in range(5)) + "/RWA/test/" + self.api_token = ''.join(random.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits) for _ in range(10)) + self.pin = int(''.join(random.choice(string.digits) for _ in range(5))) def _start_trigger_service(self): self.trigger_port = port_for.select_random() @@ -109,6 +138,15 @@ class Session: def stop(self, triggered: bool =False): """Stop session and clean up.""" + if self.mockup_session: + filename = f"/tmp/rwa/{str(self.ws_port) + str(self.vnc_port) + str(self.ws_pid) + str(self.vnc_pid)}.lock" + if os.path.isfile(filename): + os.remove(filename) + + # Delete self + del self + return + # Kill VNC if self.vnc_pid in psutil.pids(): print("Kill VNC.") @@ -141,6 +179,10 @@ class Session: @property def vnc_process_running(self): """Check if the VNC process is still running.""" + if self.mockup_session: + filename = f"/tmp/rwa/{str(self.ws_port) + str(self.vnc_port) + str(self.ws_pid) + str(self.vnc_pid)}.lock" + return os.path.isfile(filename) + if self.vnc_pid in psutil.pids(): p = psutil.Process(self.vnc_pid) if p.status() == "zombie": diff --git a/test_client.py b/test_client.py index 927dfd3..4e60c29 100644..100755 --- a/test_client.py +++ b/test_client.py @@ -1,10 +1,9 @@ +#!/usr/bin/env python3 import dbus bus = dbus.SessionBus() - time = bus.get_object("org.ArcticaProject.RWA", "/RWA") - curr = time.start() print("Your VNC session is", curr) |