def connect(self, conf_path, interface, status_check=True):
     """
     Starts a thread that connects to the Wii U.
     Status:
       FAILED_START: wpa_supplicant_drc did not initialize
       SCANNING: wpa_supplicant_drc is scanning
       CONNECTED: wpa_supplicant_drc is connected to an AP
       CONNECTING: wpa_supplicant_drc is authenticating
       TERMINATED: wpa_supplicant_drc was found by the T-1000 Cyberdyne Systems Model 101
       NOT_FOUND: wpa_supplicant_drc could not find a Wii U AP
       UNKNOWN: wpa_supplicant_drc is in a state that is unhandled - it will be logged
     :return: None
     """
     LoggerWpa.debug("Connect called")
     self.running = True
     self.unblock_wlan()
     self.kill_wpa()
     command = [
         "wpa_supplicant_drc", "-Dnl80211", "-i", interface, "-c", conf_path
     ]
     if LoggerWpa.get_level() == LoggerWpa.FINER:
         command.append("-d")
     elif LoggerWpa.get_level() == LoggerWpa.VERBOSE:
         command.append("-dd")
     LoggerWpa.debug("Starting wpa supplicant")
     self.wpa_supplicant_process = subprocess.Popen(
         command,
         stdout=open(constants.PATH_LOG_WPA, "w"),
         stderr=subprocess.STDOUT)
     LoggerWpa.debug("Started wpa supplicant")
     if status_check:
         LoggerWpa.debug("Starting status check thread")
         self.status_check_thread = Thread(target=self.check_status,
                                           name="WPA Status Check Thread")
         self.status_check_thread.start()
 def save_connect_conf(bssid):
     """
     Modify the temp get_psk configuration to be a connect configurraton and save it to
      ~/.drc-sim/connect_to_wii_u.conf.
     :param bssid: Wii U BSSID
     :return: None
     """
     LoggerWpa.debug("Saving connection config")
     # add additional connect information to config
     conf = open(constants.PATH_CONF_CONNECT_TMP, "r")
     lines = conf.readlines()
     conf.close()
     for line in lines:
         if "update_config=1" in line:
             lines.insert(lines.index(line) + 1, "ap_scan=1\n")
             break
     for line in lines:
         if "network={" in line:
             lines.insert(lines.index(line) + 1, "\tscan_ssid=1\n")
             lines.insert(lines.index(line) + 2, "\tbssid=" + bssid + "\n")
             break
     save_conf = open(constants.PATH_CONF_CONNECT, "w")
     save_conf.writelines(lines)
     save_conf.close()
     LoggerWpa.info("Authenticated with the Wii U")
 def check_status(self):
     """
     Thread that checks WPA status every second
     Updates
     :return: None
     """
     while self.running:
         wpa_status = self.wpa_cli("status")
         scan_results = self.wpa_cli("scan_results")
         not_started_message = "Failed to connect to non-global ctrl_ifname"
         LoggerWpa.finer("Scan Results: %s", scan_results)
         LoggerWpa.finer("Status: %s", wpa_status)
         # process is dead or wpa_supplicant has not started
         if self.wpa_supplicant_process.poll(
         ) or not_started_message in scan_results:
             LoggerWpa.finer("%d seconds until start timeout",
                             30 - self.time_start)
             # wait for wpa_supplicant to initialize
             if self.time_start >= 5:
                 status = self.FAILED_START
             else:
                 status = self.status
                 self.time_start += 1
         # scanning
         elif not self.scan_contains_wii_u(
                 scan_results) or "wpa_state=SCANNING" in wpa_status:
             LoggerWpa.finer("%d seconds until scan timeout",
                             ConfigGeneral.scan_timeout - self.time_scan)
             # disconnect
             if self.time_scan == -1:
                 status = self.DISCONNECTED
             # timeout scan
             elif self.time_scan >= ConfigGeneral.scan_timeout:
                 status = self.NOT_FOUND
             else:
                 status = self.SCANNING
                 self.time_scan += 1
         elif "wpa_state=COMPLETED" in wpa_status:
             status = self.CONNECTED
             self.time_scan = -1  # forces a disconnect - might need to be handled better
         elif "wpa_state=AUTHENTICATING" in wpa_status or "wpa_state=ASSOCIATING" in wpa_status:
             status = self.CONNECTING
         elif "wpa_state=DISCONNECTED" in wpa_status:
             status = self.DISCONNECTED
             if self.time_scan != -1:
                 status = self.FAILED_START
         else:
             LoggerWpa.extra("WPA status: %s", wpa_status)
             status = self.UNKNOWN
         self.set_status(status)
         time.sleep(1)
 def stop(self):
     """
     Stops any background thread that is running
     :return: None
     """
     if not self.running:
         LoggerWpa.debug("Ignored stop request: already stopped")
         return
     self.running = False
     if self.psk_thread_cli and self.psk_thread_cli.isalive():
         LoggerWpa.debug("Stopping psk pexpect spawn")
         self.psk_thread_cli.sendline("quit")
         self.psk_thread_cli.close(True)
     LoggerWpa.debug("Stopping wpa process")
     if self.wpa_supplicant_process and self.wpa_supplicant_process.poll(
     ) is None:
         self.wpa_supplicant_process.terminate()
         self.kill_wpa()
     # reset
     self.clear_status_change_listeners()
     self.time_start = 0
     self.time_scan = 0
     LoggerWpa.debug("Wpa stopped")
 def get_psk_thread(self, code):
     """
     Thread that attempts to authenticate with a Wii U. Updates status
     :param code: WPS PIN
     :return: None
     """
     try:
         LoggerWpa.debug("CLI expect starting")
         self.psk_thread_cli = pexpect.spawn(
             "wpa_cli_drc -p /var/run/wpa_supplicant_drc")
         LoggerWpa.debug("CLI expect Waiting for init")
         self.psk_thread_cli.expect("Interactive mode")
         # Scan for Wii U SSIDs
         scan_tries = 5
         wii_u_bssids = []
         self.set_status(self.SCANNING)
         while self.running and scan_tries > 0:
             self.psk_thread_cli.sendline("scan")
             LoggerWpa.debug(
                 "CLI expect waiting for scan results available event")
             scan_wait_tries = 60
             while self.running:
                 try:
                     self.psk_thread_cli.expect(
                         "<3>CTRL-EVENT-SCAN-RESULTS", timeout=1)
                     break
                 except pexpect.TIMEOUT:
                     scan_wait_tries -= 1
                     if scan_wait_tries <= 0:
                         raise pexpect.TIMEOUT("Scan timeout")
             self.psk_thread_cli.sendline("scan_results")
             LoggerWpa.debug("CLI expect waiting for scan results")
             self.psk_thread_cli.expect(
                 "bssid / frequency / signal level / flags / ssid")
             for line in range(0, 100):  # up to 100 APs
                 try:
                     self.psk_thread_cli.expect(self.mac_addr_regex.pattern,
                                                timeout=1)
                 except pexpect.TIMEOUT:
                     break
             scan_results = self.psk_thread_cli.before.decode()
             LoggerWpa.finer("CLI expect - scan results: %s", scan_results)
             for line in scan_results.splitlines():
                 if self.wiiu_ap_regex.match(line):
                     wii_u_bssids.append(line.split()[0])
             if len(wii_u_bssids) == 0:
                 scan_tries -= 1
             else:
                 scan_tries = 0
         # Check for found Wii U ssids
         if len(wii_u_bssids) == 0:
             LoggerWpa.debug("No Wii U SSIDs found")
             self.set_status(self.NOT_FOUND)
             return
         # attempt to pair with any wii u bssid
         self.set_status(self.CONNECTING)
         for bssid in wii_u_bssids:
             self.psk_thread_cli.sendline("wps_pin %s %s" %
                                          (bssid, code + "5678"))
             LoggerWpa.debug(
                 "CLI expect waiting for wps_pin input confirmation")
             self.psk_thread_cli.expect(code + "5678")
             LoggerWpa.debug("CLI expect waiting for authentication")
             try:
                 connect_wait_tries = 60
                 while self.running:
                     try:
                         self.psk_thread_cli.expect("<3>WPS-CRED-RECEIVED",
                                                    timeout=1)
                         break
                     except pexpect.TIMEOUT:
                         connect_wait_tries -= 1
                         if connect_wait_tries <= 0:
                             raise pexpect.TIMEOUT("Connect Timeout")
                 # save conf
                 LoggerWpa.debug("PSK obtained")
                 # Save to temp config before reading from it
                 self.psk_thread_cli.sendline("save_config")
                 self.psk_thread_cli.expect("OK", timeout=5)
                 self.save_connect_conf(bssid)
                 self.set_status(self.DISCONNECTED)
                 return
             except pexpect.TIMEOUT:
                 LoggerWpa.debug("CLI expect BSSID auth failed")
                 self.psk_thread_cli.sendline("reconnect")
                 self.psk_thread_cli.expect("OK")
     # Timed out
     except pexpect.TIMEOUT as e:
         LoggerWpa.debug("PSK get attempt ended with an error.")
         LoggerWpa.exception(e)
         self.set_status(self.FAILED_START)
     # Unexpected EOF
     except pexpect.EOF as e:
         if self.running:  # Thread was not killed
             LoggerWpa.exception(e)
         return
     # Failed to authenticate
     LoggerWpa.debug("Could not authenticate with any SSIDs")
     self.set_status(self.TERMINATED)