def _serve_metadata(self, parsed_url, parsed_query, user, password): try: mount = parsed_query['mount'][0] except (KeyError, IndexError): mount = '' for path in manager.lookup_destination(mount): client = MetadataTuple( user, path.source, path.host, path.port, path.mount ) logger.debug("Serving metadata for %s", client) song = parsed_query.get('song', None) artist = parsed_query.get('artist', None) title = parsed_query.get('title', None) encoding = parsed_query.get('charset', ['latin1']) if not song is None: metadata = fix_encoding(song[0], encoding[0]) manager.send_metadata( metadata=metadata, client=client) elif title and artist: metadata = fix_encoding( "%s - %s" % (artist[0], title[0]), encoding[0]) manager.send_metadata( metadata=metadata, client=client) # Send a response... although most clients just ignore this. try: self.send_response(200) self.send_header("Content-Type", "text/xml") self.send_header("Content-Length", "113") self.end_headers() self.wfile.write( '<?xml version="1.0"?>\n<iceresponse>' '<message>Metadata update successful</message>' '<return>1</return></iceresponse>') except IOError as err: if hasattr(err, 'errno') and err.errno == 32: #logger.warning("Broken pipe exception, ignoring") pass else: logger.exception("Error in request handler")
def do_SOURCE(self): global manager, sockets self.useragent = self.headers.get('User-Agent', None) self.mount = self.path # oh so simple self.stream_name = self.headers.get('ice-name', '<Unknown>') self.source_content = self.headers.get('Content-type', None) fmt = re.search("(mpeg|ogg|flac)", self.source_content).groups()[0] ice_audio_info = urlparse.parse_qs( self.headers.get('ice-audio-info', '') ) self.source_bitrate = self.headers.get( 'ice-bitrate', "".join(ice_audio_info.get('bitrate', ['128']))) user, password = self._get_login() if user == 'source' and "|" in password: user, password = password.split('|') auth = self.login(user=user, password=password) if auth: logger.info("source: User '%s' logged in correctly.", user) self.send_response(200) self.end_headers() else: logger.info("source: User '%s' failed to login from %s.", user, str(self.client_address)) self.send_response(401) self.end_headers() return icy_client = [] logger.debug('lookup for source mountpoint %s' % self.mount) for path in manager.lookup_destination(self.mount): icy_client.append( IcyClient( path.host, path.port, path.source, path.mount, user=auth, password=path.password, useragent=self.useragent, stream_name=self.stream_name, informat=fmt, outformat=path.format, protocol=path.protocol, name=path.name, inbitrate=self.source_bitrate, outbitrate=path.bitrate or self.source_bitrate ) ) try: manager.register_source(icy_client[-1]) except Exception as err: logger.error(err) icy_client.pop() continue logger.debug( 'registered %d mountpoints destinations' % len(icy_client)) sockets.add(self.rfile) try: retries = 0 while self.rfile and retries < 10: rlist, wlist, xlist = select([self.rfile], [], [], 1) if not len(rlist): retries = retries + 1 continue retries = 0 data = self.rfile.read(8192) if data == b'': break for client in icy_client: if client.is_active: client.write(data) else: icy_client.remove(client) if not len(icy_client): logger.debug("Thread exiting since no more clients are active") break except: logger.exception("Timeout occured (most likely)") logger.info("source: User '%s' logged off.", user) if self.rfile: self.rfile.close() sockets.remove(self.rfile) while len(icy_client): client = icy_client.pop() manager.remove_source(client)