diff --git a/.gitignore b/.gitignore index 7deda24..fb323d3 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ dist/ *.egg-info/ setup.cfg temp/ +.drc-sim/ \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 17e416b..70eb7a4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,7 +11,7 @@ RUN apt-get update \ python-pip \ libffi-dev \ zlib1g-dev \ - libjpeg62-turbo-dev \ + libjpeg-dev \ net-tools \ wireless-tools \ sysvinit-utils \ @@ -19,7 +19,9 @@ RUN apt-get update \ libavcodec-dev \ libswscale-dev \ rfkill \ - isc-dhcp-client + isc-dhcp-client \ + ifmetric \ + python-tk ADD drc*.py /root/ ADD setup.py /root/ @@ -29,4 +31,4 @@ ADD MANIFEST.in /root/ RUN cd /root/ && python setup.py install && rm -rf /root/* ENV TERM xterm -ENTRYPOINT ["drc-sim-helper.py"] +ENTRYPOINT ["drc-sim-backend.py"] diff --git a/debian/changelog b/debian/changelog deleted file mode 100644 index f546147..0000000 --- a/debian/changelog +++ /dev/null @@ -1,5 +0,0 @@ -drc-sim (1.2) stable; urgency=low - - * Initial packaged release. - - -- Rolando Islas Thu, 09 Mar 2017 16:44:18 -0700 diff --git a/debian/compat b/debian/compat deleted file mode 100644 index f11c82a..0000000 --- a/debian/compat +++ /dev/null @@ -1 +0,0 @@ -9 \ No newline at end of file diff --git a/debian/control b/debian/control deleted file mode 100644 index 09504d3..0000000 --- a/debian/control +++ /dev/null @@ -1,14 +0,0 @@ -Source: drc-sim -Section: python -Priority: extra -Maintainer: Rolando Islas -Build-Depends: debhelper (>= 9), python, dh-virtualenv (>= 0.8) -Standards-Version: 3.9.5 - -Package: drc-sim -Architecture: any -Pre-Depends: dpkg (>= 1.16.1), python2.7, ${misc:Pre-Depends} -Depends: ${python:Depends}, ${misc:Depends}, python2.7-dev, python-pip, libffi-dev, zlib1g-dev, - libjpeg62-turbo-dev | libjpeg8-dev, net-tools, wireless-tools, sysvinit-utils, psmisc, libavcodec-dev, libswscale-dev, - rfkill, isc-dhcp-client, wpasupplicant-drc -Description: Wii U gamepad emulator. \ No newline at end of file diff --git a/debian/drcsim.triggers b/debian/drcsim.triggers deleted file mode 100644 index a7d09a0..0000000 --- a/debian/drcsim.triggers +++ /dev/null @@ -1,7 +0,0 @@ -# Register interest in Python interpreter changes (Python 2 for now); and -# don't make the Python package dependent on the virtualenv package -# processing (noawait) -interest-noawait /usr/bin/python2.7 - -# Also provide a symbolic trigger for all dh-virtualenv packages -interest dh-virtualenv-interpreter-update \ No newline at end of file diff --git a/debian/rules b/debian/rules deleted file mode 100644 index 566be75..0000000 --- a/debian/rules +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/make -f - -override_dh_strip: - dh_strip --exclude=cffi --exclude=PIL - -override_dh_shlibdeps: - dh_shlibdeps --exclude=cffi --exclude=PIL - -%: - dh $@ --with python-virtualenv \ No newline at end of file diff --git a/setup.py b/setup.py index b77912b..36ed314 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ from setuptools import find_packages setup(name='drcsim', - version='1.1', + version='1.3', description='Wii U gamepad simulator.', install_requires=['construct<2.8', 'Pillow==3.4.2', 'cffi==1.9.1', 'netifaces==0.10.5', 'pexpect==4.2.1'], packages=find_packages(), diff --git a/src/server/data/args.py b/src/server/data/args.py index 864f619..ee53d2c 100644 --- a/src/server/data/args.py +++ b/src/server/data/args.py @@ -1,5 +1,7 @@ import argparse +import sys + class Args: args = None @@ -10,6 +12,7 @@ def __init__(self): @staticmethod def parse_args(): arg_parser = argparse.ArgumentParser(description="Drc-sim backend decodes packets and serves clients") + # Logging arg_parser.add_argument("-d", "--debug", action="store_const", const=True, default=False, help="debug output") arg_parser.add_argument("-e", "--extra", action="store_const", const=True, default=False, @@ -20,4 +23,27 @@ def parse_args(): help="verbose debug output") arg_parser.add_argument("-c", "--cli", action="store_const", const=True, default=False, help="disable gui") + # CLI + args = ["-c", "--cli", "-h", "--help"] + found = False + for arg in args: + if arg in sys.argv: + found = True + if found: + subparsers = arg_parser.add_subparsers() + # Run Server + run_server = subparsers.add_parser("run_server") + run_server.add_argument("wii_u_interface", type=str) + run_server.add_argument("normal_interface", type=str) + # Get Key + get_key = subparsers.add_parser("get_key") + get_key.add_argument("wii_u_interface", type=str) + get_key.add_argument("wps_pin", type=str) Args.args = arg_parser.parse_args() + # Add sub arguments + Args.args.run_server = False + Args.args.get_key = False + if "run_server" in sys.argv: + Args.args.run_server = True + elif "get_key" in sys.argv: + Args.args.get_key = True diff --git a/src/server/data/resource.py b/src/server/data/resource.py index 365fce9..c67f785 100644 --- a/src/server/data/resource.py +++ b/src/server/data/resource.py @@ -13,4 +13,17 @@ class Resource: def __init__(self, in_path): pre = "resources/" Logger.debug("Loading resource \"%s\"", join(pre, in_path)) + current_dir = os.path.dirname(__file__).split(os.sep) + # Check local files first + file_path = "/" + if current_dir >= 3: + for path in range(0, len(current_dir) - 3): + file_path = join(file_path, current_dir[path]) + file_path = join(file_path, pre, in_path) + if os.path.exists(file_path): + self.resource = open(file_path).read() + Logger.extra("Found resource in local resource directory.") + return + # Attempt to get from package self.resource = pkg_resources.resource_string(pkg_resources.Requirement.parse("drcsim"), join(pre, in_path)) + Logger.extra("Found resource in package.") diff --git a/src/server/ui/cli/cli_main.py b/src/server/ui/cli/cli_main.py index d491c29..0da329d 100644 --- a/src/server/ui/cli/cli_main.py +++ b/src/server/ui/cli/cli_main.py @@ -1,9 +1,103 @@ +import time + +from src.server.control.gamepad import Gamepad +from src.server.data import constants +from src.server.data.args import Args +from src.server.util.interface_util import InterfaceUtil from src.server.util.logging.logger_cli import LoggerCli +from src.server.util.wpa_supplicant import WpaSupplicant class CliMain: def __init__(self): - LoggerCli.throw(NotImplementedError("CLI not implemented")) + self.getting_key = False + self.gamepad = None + self.wpa_supplicant = None def start(self): - LoggerCli.throw(NotImplementedError("CLI not implemented")) + LoggerCli.warn("The CLI not user friendly. It is here to provide a way to automate" + " the server via a shell. The GUI is a better alternative for normal use.") + if Args.args.run_server: + self.run_server() + elif Args.args.get_key: + self.get_key() + else: + self.stop() + + def stop(self): + LoggerCli.info("Stopping") + self.getting_key = False + if self.gamepad and self.gamepad.running: + self.gamepad.close() + if self.wpa_supplicant: + self.wpa_supplicant.stop() + + def run_server(self): + LoggerCli.info("Starting server") + normal_interface = Args.args.normal_interface + wii_u_interface = Args.args.wii_u_interface + self.check_interfaces(normal_interface, wii_u_interface) + self.prompt_unmanaged(wii_u_interface) + self.wpa_supplicant = WpaSupplicant() + self.wpa_supplicant.connect(constants.PATH_CONF_CONNECT, wii_u_interface) + self.wpa_supplicant.add_status_change_listener(self.status_changed) + InterfaceUtil.dhclient(wii_u_interface) + InterfaceUtil.set_metric(normal_interface, 0) + InterfaceUtil.set_metric(wii_u_interface, 1) + self.gamepad = Gamepad() + self.gamepad.start() + while self.gamepad.running: + time.sleep(1) + + def check_interfaces(self, normal_interface, wii_u_interface): + if normal_interface == wii_u_interface: + LoggerCli.throw(Exception("The Wii U and normal interfaces cannot be the same.")) + try: + InterfaceUtil.get_mac(normal_interface) + InterfaceUtil.get_mac(wii_u_interface) + except ValueError: + LoggerCli.throw(Exception("Invalid interface selected.")) + + def status_changed(self, status): + LoggerCli.info("Connection status changed to %s.", status) + if status in (WpaSupplicant.TERMINATED, WpaSupplicant.NOT_FOUND, WpaSupplicant.DISCONNECTED, + WpaSupplicant.FAILED_START): + self.stop() + + def status_changed_key(self, status): + LoggerCli.info("Connection status changed to %s.", status) + if status == WpaSupplicant.DISCONNECTED: + LoggerCli.info("Successfully received PSK from the Wii U.") + self.stop() + elif status in (WpaSupplicant.TERMINATED, WpaSupplicant.NOT_FOUND, WpaSupplicant.FAILED_START): + self.stop() + + def get_key(self): + LoggerCli.info("Getting key") + wii_u_interface = Args.args.wii_u_interface + try: + InterfaceUtil.get_mac(wii_u_interface) + except ValueError: + LoggerCli.throw(Exception("Invalid interface selected.")) + if len(Args.args.wps_pin) != 4: + LoggerCli.throw(Exception("WPS PIN should be 4 digits")) + self.prompt_unmanaged(wii_u_interface) + self.wpa_supplicant = WpaSupplicant() + self.wpa_supplicant.get_psk(constants.PATH_CONF_CONNECT_TMP, wii_u_interface, Args.args.wps_pin) + self.wpa_supplicant.add_status_change_listener(self.status_changed_key) + self.getting_key = True + while self.getting_key: + time.sleep(1) + + def prompt_unmanaged(self, interface): + if not InterfaceUtil.is_managed_by_network_manager(interface): + return + LoggerCli.info("The interface \"%s\" is managed by Network Manager. It must be set to " + "unmanaged to function with DRC Sim. Network manager will not be able to " + "use this interface after it is set to unmanaged.", interface) + response = raw_input("Set %s as unmanaged? (y/n)" % interface) + LoggerCli.debug(response) + if response in ("y", "yes", "Y", "Yes", "YES"): + InterfaceUtil.set_unmanaged_by_network_manager(interface) + else: + LoggerCli.throw(Exception("Interface is managed by Network Manager.")) diff --git a/src/server/ui/gui/frame/frame_run_server.py b/src/server/ui/gui/frame/frame_run_server.py index 3b9f062..c4a6bd1 100644 --- a/src/server/ui/gui/frame/frame_run_server.py +++ b/src/server/ui/gui/frame/frame_run_server.py @@ -99,7 +99,7 @@ def wpa_status_changed(self, status): self.label_wpa_status.config(text=status) if status == WpaSupplicant.CONNECTED: LoggerGui.debug("Routing") - InterfaceUtil.dhclient() + InterfaceUtil.dhclient(self.wii_u_interface) InterfaceUtil.set_metric(self.normal_interface, 0) InterfaceUtil.set_metric(self.wii_u_interface, 1) LoggerGui.debug("Starting backend") diff --git a/src/server/util/interface_util.py b/src/server/util/interface_util.py index cfb8250..966a8ab 100644 --- a/src/server/util/interface_util.py +++ b/src/server/util/interface_util.py @@ -57,9 +57,9 @@ def set_metric(cls, interface, metric): ProcessUtil.call(["ifmetric", interface, str(metric)]) @classmethod - def dhclient(cls): + def dhclient(cls, interface): ProcessUtil.call(["killall", "dhclient"]) - ProcessUtil.call(["dhclient"]) + ProcessUtil.call(["dhclient", interface]) @classmethod def is_managed_by_network_manager(cls, interface): diff --git a/src/server/util/wpa_supplicant.py b/src/server/util/wpa_supplicant.py index e64d841..10e783a 100644 --- a/src/server/util/wpa_supplicant.py +++ b/src/server/util/wpa_supplicant.py @@ -184,8 +184,6 @@ def get_psk_thread(self, code): wii_u_bssids = [] while self.running and scan_tries > 0: self.psk_thread_cli.sendline("scan") - LoggerWpa.debug("CLI expect waiting for scan start") - self.psk_thread_cli.expect("OK") LoggerWpa.debug("CLI expect waiting for scan results available event") self.psk_thread_cli.expect("<3>CTRL-EVENT-SCAN-RESULTS", timeout=60) self.psk_thread_cli.sendline("scan_results")