예제 #1
0
class FrameRunServer(FrameTab):
    def __init__(self, master=None, **kw):
        """
        GUI tab that handles interface and region selection and starting the server.
        :param master: root window
        :param kw: args
        """
        FrameTab.__init__(self, master, **kw)
        self.wii_u_interface = None
        self.normal_interface = None
        self.drc_sim_c = None
        self.wpa_supplicant = None
        LoggerGui.extra("Initializing FrameRunServer")
        # Create Widgets
        self.label_wpa = Label(self, text="Wii U Connection:")
        self.label_backend = Label(self, text="Server Status:")
        self.label_wpa_status = Label(self)
        self.label_backend_status = Label(self)
        self.button_start = Button(self, text="Start")
        self.button_stop = Button(self, text="Stop")
        self.label_wiiu_interface = Label(self, text="Wii U Interface")
        self.label_normal_interface = Label(self, text="Normal Interface")
        self.dropdown_wiiu_interface = Combobox(self, state="readonly")
        self.dropdown_normal_interface = Combobox(self, state="readonly")
        self.label_interface_info = Label(self)
        self.label_region = Label(self, text="Region")
        self.dropdown_region = Combobox(self, state="readonly")
        # Events
        self.button_start.bind("<Button-1>", self.start_server)
        self.button_stop.bind("<Button-1>", self.stop_server)
        # Position widgets
        self.label_wpa.grid(column=0, row=0, sticky="e")
        self.label_backend.grid(column=0, row=1, sticky="e")
        self.label_wpa_status.grid(column=1, row=0, sticky="w")
        self.label_backend_status.grid(column=1, row=1, sticky="w")
        self.label_wiiu_interface.grid(column=0, row=2)
        self.label_normal_interface.grid(column=0, row=3)
        self.dropdown_wiiu_interface.grid(column=1, row=2, columnspan=2)
        self.dropdown_normal_interface.grid(column=1, row=3, columnspan=2)
        self.label_region.grid(column=0, row=4)
        self.dropdown_region.grid(column=1, row=4, columnspan=2)
        self.button_start.grid(column=1, row=5)
        self.button_stop.grid(column=2, row=5)
        self.label_interface_info.grid(column=0, row=6, columnspan=3)
        LoggerGui.extra("Initialized FrameRunServer")

    def start_server(self, event=None):
        """
        Try to start wpa_supplicant and connect to a Wii U.
        :param event: Determines if this was a user initiated start.
        :return: None
        """
        if event:
            LoggerGui.debug("User clicked start server button")
        LoggerGui.debug("Start server called")
        if self.label_backend_status["text"] != DrcSimC.STOPPED and \
                (self.label_wpa_status["text"] not in (WpaSupplicant.DISCONNECTED, WpaSupplicant.TERMINATED)):
            messagebox.showerror("Running", "Server is already running")
            return
        if not os.path.exists(constants.PATH_CONF_CONNECT):
            messagebox.showerror(
                "Auth Error",
                "No auth details found. Use the \"Get Key\" tab to pair with a Wii U."
            )
            self.activate()
            return
        self.normal_interface = self.dropdown_normal_interface.get()
        self.wii_u_interface = self.dropdown_wiiu_interface.get()
        if not self.normal_interface or not self.wii_u_interface:
            messagebox.showerror("Interface Error",
                                 "Two interfaces need to be selected.")
            self.activate()
            return
        if self.normal_interface == self.wii_u_interface:
            messagebox.showerror(
                "Interface Error",
                "The selected normal and Wii U interfaces must be different.")
            self.activate()
            return
        try:
            InterfaceUtil.get_mac(self.normal_interface)
            InterfaceUtil.get_mac(self.wii_u_interface)
        except ValueError:
            messagebox.showerror(
                "Interface Error",
                "The selected Interface is no longer available.")
            self.activate()
            return
        if InterfaceUtil.is_managed_by_network_manager(self.wii_u_interface):
            set_unmanaged = messagebox.askokcancel(
                "Managed Interface",
                "This interface is managed by Network Manager. To use it with DRC Sim it needs "
                "to be set to unmanaged. Network Manager will not be able to control the interface"
                " after this.\nSet %s to unmanaged?" % self.wii_u_interface)
            if set_unmanaged:
                InterfaceUtil.set_unmanaged_by_network_manager(
                    self.wii_u_interface)
            else:
                messagebox.showerror(
                    "Managed Interface",
                    "Selected Wii U interface is managed by Network Manager.")
                self.activate()
                return
        LoggerGui.debug("Starting wpa supplicant")
        self.wpa_supplicant = WpaSupplicant()
        self.wpa_supplicant.add_status_change_listener(self.wpa_status_changed)
        self.wpa_supplicant.connect(constants.PATH_CONF_CONNECT,
                                    self.wii_u_interface)
        self.label_backend_status.config(text="WAITING")

    def wpa_status_changed(self, status):
        """
        Handles wpa status changes. Initializes backend server if a connection is made.
        :param status: status message
        :return: None
        """
        LoggerGui.debug("Wpa changed status to %s", status)
        self.label_wpa_status.config(text=status)
        if status == WpaSupplicant.CONNECTED:
            LoggerGui.debug("Routing")
            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")
            self.drc_sim_c = DrcSimC()
            self.drc_sim_c.add_status_change_listener(
                self.backend_status_changed)
            self.drc_sim_c.set_region(self.dropdown_region.get())
            self.drc_sim_c.start()
            self.label_interface_info.config(
                text="Server IP: " +
                InterfaceUtil.get_ip(self.normal_interface) + "\n" +
                os.uname()[1])
        elif status in (WpaSupplicant.DISCONNECTED, WpaSupplicant.TERMINATED):
            self.stop_server()
        elif status == WpaSupplicant.NOT_FOUND:
            self.stop_server()
            messagebox.showerror("Scan Error", "No Wii U found.")
        elif status == WpaSupplicant.FAILED_START:
            self.stop_server()
            messagebox.showerror(
                "Cannot Connect",
                "Failed to start wpa_supplicant_drc. This could mean there is a "
                "configuration error or wpa_supplicant_drc is not installed. "
                "Check %s for details." % constants.PATH_LOG_WPA)

    def backend_status_changed(self, status):
        """
        Handles backend status changes.
        :param status: status message
        :return: None
        """
        LoggerGui.debug("Backend status changed to %s", status)
        self.label_backend_status.config(text=status)
        if status == DrcSimC.STOPPED:
            self.stop_server()

    def stop_server(self, event=None):
        """
        Stops active threads.
        :param event: Determines if this is a user initiated stop
        :return: None
        """
        if event:
            LoggerGui.debug("User clicked stop server button")
        LoggerGui.debug("Stop server called")
        if event and (self.label_wpa_status["text"]
                      in (WpaSupplicant.DISCONNECTED, WpaSupplicant.TERMINATED)
                      and self.label_backend_status["text"]
                      == DrcSimC.STOPPED):
            messagebox.showerror("Stop", "Server is not running.")
            return
        if self.drc_sim_c:
            self.drc_sim_c.stop()
            self.drc_sim_c = None
        if self.wpa_supplicant:
            self.wpa_supplicant.stop()
            self.wpa_supplicant = None
        self.activate()

    def activate(self):
        """
        Initializes the frame.
        :return: None
        """
        LoggerGui.debug("FrameRunServer activated")
        self.dropdown_wiiu_interface[
            "values"] = InterfaceUtil.get_wiiu_compatible_interfaces()
        self.dropdown_normal_interface[
            "values"] = InterfaceUtil.get_all_interfaces()
        self.dropdown_region["values"] = ["NONE", "NA"]
        self.label_wpa_status["text"] = self.wpa_supplicant.get_status() \
            if self.wpa_supplicant and self.wpa_supplicant.get_status() else WpaSupplicant.DISCONNECTED
        self.label_backend_status["text"] = self.drc_sim_c.get_status() \
            if self.drc_sim_c and self.drc_sim_c.get_status() else DrcSimC.STOPPED
        self.button_start.config(state="normal")
        self.button_stop.config(state="normal")
        self.label_interface_info.config(text="")

    def deactivate(self):
        """
        De-initializes the frame.
        :return: None
        """
        LoggerGui.debug("FrameRunServer deactivated")
        self.stop_server()

    def kill_other_tabs(self):
        return True
예제 #2
0
class FrameGetKey(FrameTab):
    def __init__(self, master=None, **kw):
        FrameTab.__init__(self, master, **kw)
        self.wpa_supplicant = None
        self.getting_psk = False
        # Widgets
        button_size = 50
        # Spade
        self.button_spade = Button(self, width=button_size, height=button_size)
        self.button_spade.image = self.get_image("image/spade.gif",
                                                 button_size, button_size)
        self.button_spade.config(image=self.button_spade.image)
        self.button_spade.number = 0
        # Heart
        self.button_heart = Button(self, width=button_size, height=button_size)
        self.button_heart.image = self.get_image("image/heart.gif",
                                                 button_size, button_size)
        self.button_heart.config(image=self.button_heart.image)
        self.button_heart.number = 1
        # Diamond
        self.button_diamond = Button(self,
                                     width=button_size,
                                     height=button_size)
        self.button_diamond.image = self.get_image("image/diamond.gif",
                                                   button_size, button_size)
        self.button_diamond.config(image=self.button_diamond.image)
        self.button_diamond.number = 2
        # Clover
        self.button_clover = Button(self,
                                    width=button_size,
                                    height=button_size)
        self.button_clover.image = self.get_image("image/clover.gif",
                                                  button_size, button_size)
        self.button_clover.config(image=self.button_clover.image)
        self.button_clover.number = 3
        # Delete
        self.button_delete = Button(self, text="Delete")
        # Code
        self.entry_pair_code = Entry(self, state="readonly")
        # Status Message
        self.status_message = Label(self, state="readonly")
        # interface dropdown
        self.dropdown_wii_u = Combobox(self, state="readonly")
        # Events
        self.button_spade.bind("<Button-1>", self.button_clicked)
        self.button_heart.bind("<Button-1>", self.button_clicked)
        self.button_diamond.bind("<Button-1>", self.button_clicked)
        self.button_clover.bind("<Button-1>", self.button_clicked)
        self.button_delete.bind("<Button-1>", self.button_delete_clicked)
        # Grid
        self.button_spade.grid(column=0, row=0)
        self.button_heart.grid(column=1, row=0)
        self.button_diamond.grid(column=2, row=0)
        self.button_clover.grid(column=3, row=0)
        self.button_delete.grid(column=4, row=0)
        self.entry_pair_code.grid(column=0, row=1, columnspan=5)
        self.status_message.grid(column=0, row=3, columnspan=5)
        self.dropdown_wii_u.grid(column=0, row=2, columnspan=5)

    # noinspection PyUnusedLocal
    def button_delete_clicked(self, event):
        self.set_code_text(
            self.entry_pair_code.get()[:len(self.entry_pair_code.get()) - 1])

    def button_clicked(self, event):
        if self.getting_psk:
            messagebox.showerror("Running",
                                 "A pairing attempt is already im progress.")
            return
        number = str(event.widget.number)
        LoggerGui.debug(
            "A suit button was clicked"
        )  # Don't log numbers as the code can be derived from that
        code = self.entry_pair_code.get()
        code += number
        self.set_code_text(code)
        wii_u_interface = self.dropdown_wii_u.get()
        if not wii_u_interface:
            messagebox.showerror("No Interface",
                                 "An interface must be selected.")
            self.activate()
            return
        try:
            InterfaceUtil.get_mac(wii_u_interface)
        except ValueError:
            messagebox.showerror(
                "Interface Error",
                "The selected Interface is no longer available.")
            self.activate()
            return
        if InterfaceUtil.is_managed_by_network_manager(wii_u_interface):
            set_unmanaged = messagebox.askokcancel(
                "Managed Interface",
                "This interface is managed by Network Manager. To use it with DRC Sim it needs "
                "to be set to unmanaged. Network Manager will not be able to control the interface"
                " after this.\nSet %s to unmanaged?" % wii_u_interface)
            if set_unmanaged:
                InterfaceUtil.set_unmanaged_by_network_manager(wii_u_interface)
            else:
                messagebox.showerror(
                    "Managed Interface",
                    "Selected Wii U interface is managed by Network Manager.")
                self.activate()
                return
        if len(code) == 4:
            self.getting_psk = True
            self.set_code_text("")
            self.get_psk(code, wii_u_interface)

    def get_psk(self, code, interface):
        LoggerGui.debug("Attempting to get PSK")  # Don't log code
        CliMain.create_temp_config_file()
        self.wpa_supplicant = WpaSupplicant()
        self.wpa_supplicant.add_status_change_listener(self.wpa_status_changed)
        self.wpa_supplicant.get_psk(constants.PATH_CONF_CONNECT_TMP, interface,
                                    code)

    def wpa_status_changed(self, status):
        LoggerGui.debug("Wpa status changed to %s", status)
        if status == WpaSupplicant.NOT_FOUND:
            self.deactivate()
            self.activate()
            messagebox.showerror("Scan", "No Wii U found.")
        elif status == WpaSupplicant.TERMINATED:
            self.deactivate()
            self.activate()
            messagebox.showerror(
                "Auth Fail", "Could not authenticate. Check the entered PIN.")
        elif status == WpaSupplicant.FAILED_START:
            self.deactivate()
            self.activate()
            messagebox.showerror("Error", "An unexpected error occurred.")
        elif status == WpaSupplicant.DISCONNECTED:
            self.deactivate()
            self.activate()
            messagebox.showerror("Auth Saved",
                                 "Successfully paired with Wii U.")
        elif status == WpaSupplicant.SCANNING:
            self.status_message["text"] = "Scanning"
        elif status == WpaSupplicant.CONNECTING:
            self.status_message["text"] = "Connecting"

    def activate(self):
        LoggerGui.debug("FrameTab activate called")
        self.getting_psk = False
        self.set_code_text("")
        if not self.wpa_supplicant or not self.wpa_supplicant.get_status():
            self.status_message["text"] = ""
        self.dropdown_wii_u[
            "values"] = InterfaceUtil.get_wiiu_compatible_interfaces()

    def deactivate(self):
        LoggerGui.debug("FrameTab deactivate called")
        self.status_message["text"] = ""
        self.getting_psk = False
        if self.wpa_supplicant:
            self.wpa_supplicant.stop()
            self.wpa_supplicant = None

    @staticmethod
    def get_image(location, width, height):
        image = PhotoImage(data=Resource(location).resource)
        orig_width = image.width()
        orig_height = image.height()
        image = image.zoom(width, height)
        image = image.subsample(orig_width, orig_height)
        return image

    def set_code_text(self, text):
        self.entry_pair_code.config(state="normal")
        self.entry_pair_code.delete(0, END)
        self.entry_pair_code.insert(0, text)
        self.entry_pair_code.config(state="readonly")

    def kill_other_tabs(self):
        return True