def __init__(self, transport, user=None, password=None, cur_player_id=None, debug=False): self.transport = transport self._debug = debug self.user = user self.password = password if user and password: self.log_in() print_d("Authenticated with %s!" % self) self.players = {} self.refresh_status() players = list(self.players.values()) if not players: raise SqueezeboxException("Uh-oh. No players found.") if not cur_player_id: self.cur_player_id = players[0].id elif cur_player_id not in self.players: print_w("Couldn't find player {id} (found: {all}). " "Check your DEFAULT_PLAYER config.", id=cur_player_id, all=", ".join(list(self.players.keys()))) self.cur_player_id = players[0].id else: self.cur_player_id = cur_player_id print_d("Current player is now: {}", self.players[self.cur_player_id]) self.__genres = [] self.__playlists = [] self.__favorites = []
def _request(self, lines, raw=False, wait=True) -> List[str]: """ Send multiple pipelined requests to the server, if connected, and return their responses, assuming order is maintained (which seems safe). """ if not (lines and len(lines)): return [] lines = [l.rstrip() for l in lines] match = RESPONSE_CMD_REGEX.match(lines[0]) # If we can't match, then take the first two words (for debugging) first_word = (match.group(2) if match else ' '.join(lines[0].split()[:2])) if not (self.transport.is_connected or first_word == 'login'): try: print_w("Transport wasn't connected - trying to restart") self.transport.start() except Exception: raise SqueezeboxException( "Can't do '{cmd}', {transport} is not connected".format( cmd=first_word, transport=self.transport)) if self._debug: print_d("<<<< " + "\n..<< ".join(lines)) request = "\n".join(lines) raw_response = self.transport.communicate(request, wait=wait) if not wait: return [] if not raw_response: raise SqueezeboxException( "No further response from %s. Login problem?" % self) raw_response = raw_response.rstrip("\n") response = raw_response if raw else self._unquote(raw_response) if self._debug: print_d(">>>> " + "\n..>> ".join(response.splitlines())) def start_point(text): if first_word == 'login': return 6 delta = -1 if text.endswith('?') else 1 return len(self._unquote(text) if raw else text) + delta resp_lines = response.splitlines() if len(lines) != len(resp_lines): print_d("Got mismatched response: {lines} vs {resp_lines}", lines=lines, resp_lines=resp_lines) raise Error("Transport response problem: got %d lines, not %d" % (len(resp_lines), len(lines))) return [ resp_line[start_point(line):] for line, resp_line in zip(lines, resp_lines) ]
def lambda_handler(event, context): """ Route the incoming request based on type (LaunchRequest, IntentRequest, etc.) The JSON body of the request is provided in the event parameter. """ sqa = SqueezeAlexa(app_id=APPLICATION_ID) try: return sqa.handle(event, context) except Exception as e: if not settings.USE_SPOKEN_ERRORS: raise e # Work with AWS stack-trace log magic print_w(format_exc().replace('\n', '\r')) error = str(e.msg if hasattr(e, "msg") else e) return speech_response(title=_("All went wrong"), text=_("Oh dear: {type}. {message}").format( type=type(e).__name__, message=error))
def communicate(self, data, wait=True): eof = False response = '' num_lines = data.count("\n") try: self._ssl_sock.sendall(data.encode('utf-8')) if not wait: return None while not eof: response += self._ssl_sock.recv().decode('utf-8') eof = response.count("\n") == num_lines or not response return response except socket.error as e: print_d("Couldn't communicate with Squeezebox ({!r})", e) self.failures += 1 if self.failures >= self._MAX_FAILURES: print_w("Too many Squeezebox failures. Disconnecting") self.is_connected = False return None
def handle(self, event, context=None): """The main entry point for Alexa requests""" request = event['request'] req_type = request['type'] session = self._verified_app_session(event) if session and session['new']: self.on_session_started(request, session) if req_type == Request.LAUNCH: return self.on_launch(request, session) elif req_type == Request.INTENT: return self.on_intent(request, session) elif req_type == Request.SESSION_ENDED: return self.on_session_ended(request, session) elif req_type == Request.EXCEPTION: print_w("ERROR callback received (\"%s\"). Full event: %s" % (request['error'].get('message', "?"), event)) else: raise ValueError("Unknown request type %s" % req_type)
def test_print_w(self): assert "Exception" in print_w("{!r}", Exception("bar"))
def __init__(self, hostname, port=9090, ca_file=None, cert_file=None, verify_hostname=False, timeout=5): super().__init__() self.hostname = hostname self.port = port self.timeout = timeout self.failures = 0 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) self.__harden_context(context) try: if ca_file: context.load_verify_locations(ca_file) if cert_file: context.verify_mode = ssl.CERT_REQUIRED context.check_hostname = verify_hostname context.load_cert_chain(cert_file) except ssl.SSLError as e: raise Error( "Problem with Cert / CA (+key) files ({} / {}). " "Does it include the private key?".format(cert_file, ca_file), e) except IOError as e: if 'No such file or directory' in e.strerror: self._die("Can't find cert '{cert_file}' or CA '{ca_file}'. " "Check CERT_FILE / CA_FILE_PATH in settings".format( ca_file=ca_file, cert_file=cert_file)) self._die( "could be mismatched certificate files, " "or wrong hostname in cert." "Check CERT_FILE and certs on server too.", e) sock = socket.socket() sock.settimeout(self.timeout) self._ssl_sock = context.wrap_socket(sock, server_hostname=hostname) print_d("Connecting to port {port} on {hostname}", port=port, hostname=hostname or '(localhost)') try: self._ssl_sock.connect((hostname, port)) except socket.gaierror as e: if "Name or service not know" in e.strerror: self._die( "unknown host ({}) - check SERVER_HOSTNAME".format( hostname), e) self._die("Couldn't connect to %s with TLS" % (self, ), e) except IOError as e: err_str = e.strerror or str(e) if 'Connection refused' in err_str: self._die("nothing listening on {}. " "Check settings, or (re)start server.".format(self)) elif 'WRONG_VERSION_NUMBER' in err_str: self._die( 'probably not TLS on port {} - ' 'wrong SERVER_PORT maybe?'.format(port), e) elif 'Connection reset by peer' in err_str: self._die("server killed the connection - handshake error? " "Check the SSL tunnel logs") elif 'CERTIFICATE_VERIFY_FAILED' in err_str: self._die( "Cert not trusted by / from server. " "Is your CA correct? Is the cert expired? " "Is the cert for the right hostname ({})?".format( hostname), e) elif 'timed out' in err_str: msg = ("Couldn't connect to port {port} on {host} - " "check the server setup and the firewall.").format( host=self.hostname, port=self.port) self._die(msg) self._die("Connection problem ({}: {})".format( type(e).__name__, err_str)) peer_cert = self._ssl_sock.getpeercert() if peer_cert is None: self._die("No certificate configured at {}".format(self)) elif not peer_cert: print_w("Unvalidated server cert at {}", self) else: subject_data = peer_cert['subject'] try: data = {k: v for d in subject_data for k, v in d} except Exception: data = subject_data print_d("Validated cert for {}", data) self.is_connected = True
def connect_cli(): global telnet telnet = telnetlib.Telnet(host=MQTT_SETTINGS.internal_server_hostname, port=LMS_SETTINGS.cli_port, timeout=5) print_d("Connected to Squeezeserver CLI") return telnet if __name__ == "__main__": try: telnet = connect_cli() except socket.timeout as e: print_w("Couldn't connect to Squeeze CLI using {} ({})", MQTT_SETTINGS, e) exit(3) else: client = CustomClient(MQTT_SETTINGS) client.on_connect = on_connect client.on_subscribe = on_subscribe client.on_message = on_message client.connect() # Continue the network loop client.loop_forever(retry_first_connection=True) finally: if telnet: telnet.close()
def __init__(self, hostname, port=9090, ca_file=None, cert_file=None, verify_hostname=False): self.hostname = hostname self.port = port self.failures = 0 context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) self.__harden_context(context) try: if ca_file: context.load_verify_locations(ca_file) if cert_file: context.verify_mode = ssl.CERT_REQUIRED context.check_hostname = verify_hostname context.load_cert_chain(cert_file) except ssl.SSLError as e: raise Error( "Problem with Cert / CA (+key) files (%s / %s). " "Does it include the private key?" % (cert_file, ca_file), e) except IOError as e: if 'No such file or directory' in e.strerror: self._die("Can't find '%s'. " "Check CERT_NAME / CERT_PATH in settings" % ca_file) self._die( "could be mismatched certificate files, " "or wrong hostname in cert." "Check CERT_FILE and certs on server too.", e) self._ssl_sock = context.wrap_socket(socket.socket(), server_hostname=hostname) try: self._ssl_sock.connect((hostname, port)) except socket.gaierror as e: if "Name or service not know" in e.strerror: self._die( "unknown host (%s) - check SERVER_HOSTNAME" % hostname, e) self._die("Couldn't connect to %s with TLS" % (self, ), e) except IOError as e: if 'Connection refused' in e.strerror: self._die("nothing listening on %s" "Check settings, or (re)start server." % self) elif 'WRONG_VERSION_NUMBER' in e.strerror: self._die( 'probably not TLS on port %d - ' 'wrong SERVER_PORT maybe?' % port, e) elif 'Connection reset by peer' in e.strerror: self._die("server killed the connection - handshake error? " "Check the SSL tunnel logs") elif 'CERTIFICATE_VERIFY_FAILED' in e.strerror: self._die( "Cert not trusted by / from server. " "Is your CA correct? Is the cert expired? " "Is the cert for the right hostname (%s)?" % hostname, e) self._die("Connection problem (%s)" % e.strerror) peer_cert = self._ssl_sock.getpeercert() if peer_cert is None: self._die("No certificate configured at %s" % self) elif not peer_cert: print_w("Unvalidated server cert at %s" % self) else: subject_data = peer_cert['subject'] try: data = {k: v for d in subject_data for k, v in d} except Exception: data = subject_data print_d("Validated cert for %s" % (data, )) self.is_connected = True
global telnet telnet = telnetlib.Telnet(host=MQTT_SETTINGS.internal_server_hostname, port=LMS_SETTINGS.cli_port, timeout=5) print_d("Connected to Squeezeserver CLI") return telnet if __name__ == "__main__": if not MQTT_SETTINGS.configured: print("MQTT transport not configured. Check your settings") exit(1) try: telnet = connect_cli() except socket.timeout as e: print_w("Couldn't connect to Squeeze CLI using {settings} ({err})", settings=MQTT_SETTINGS, err=e) exit(3) else: client = CustomClient(MQTT_SETTINGS) client.on_connect = on_connect client.on_subscribe = on_subscribe client.on_message = on_message client.connect() # Continue the network loop client.loop_forever(retry_first_connection=True) finally: if telnet: telnet.close()