Пример #1
0
	def __init__(self, remote_url, desc_url=None, device=None):
		if len(remote_url) > 0 and remote_url[-1] != '/':
			remote_url = remote_url + '/'
		self.remote_url = remote_url
		self.router = ClientRouter('/')
		self.router.postprocess(ST.ContentDirectory, URL.controlURL)(self.hack_mediaserver_response)
		if desc_url:
			if len(desc_url) and desc_url[0] == '/':
				desc_url = desc_url[1:]
			self.router.postprocessors[desc_url] = self.hack_description_response
		if device:
			self.set_device(device)
Пример #2
0
class UpnpClientResource(Resource):
	""" Smarter proxy, with mild routing """
	isLeaf = True

	def __init__(self, remote_url, desc_url=None, device=None):
		if len(remote_url) > 0 and remote_url[-1] != '/':
			remote_url = remote_url + '/'
		self.remote_url = remote_url
		self.router = ClientRouter('/')
		self.router.postprocess(ST.ContentDirectory, URL.controlURL)(self.hack_mediaserver_response)
		if desc_url:
			if len(desc_url) and desc_url[0] == '/':
				desc_url = desc_url[1:]
			self.router.postprocessors[desc_url] = self.hack_description_response
		if device:
			self.set_device(device)

	def set_device(self, device):
		self.device = device
		self.router.add_device(device)

	@ensure_utf8
	def render(self, request):
		return self.router.dispatch_device_request(request, self.get_proxied_url(request.uri))

	def get_proxied_url(self, url):
		# convert a local device url to a proxied url
		if len(url)>1 and url[0] == '/':
			url = url[1:]
		return self.remote_url + url

	def get_altport_url(self, url):
		""" Convert a response's relative url to absolute """
		# url is uuid:74hjasncv:4040/streamid...
		if '/' in url:
			uuidport,rest = url.split('/', 1)
		else:
			uuidport,rest = url, ''

		if uuidport.count(':') != 2:
			# suburl on current device
			return self.localbase + rest
		else:
			# needs an alt device
			base = urljoin(self.remote_url, '..')
			proxy = altDeviceManager.get_device(base, uuidport)
			return proxy.url + rest

	def hack_description_response(self, request, response_data):
		request.setResponseCode(response_data['code'])
		request.responseHeaders = response_data['headers']
		if 'xml' not in response_data['headers'].getRawHeaders('Content-Type', [''])[0]:
			request.responseHeaders.setRawHeaders('Content-Length', [len(response_data['content'])])
			request.write(response_data['content'])
			request.finish()
			return
		request.responseHeaders.removeHeader('Content-Length')
		request.responseHeaders.removeHeader('Content-Encoding')
		# get the device that we're talking to, and its ip
		# load up response
		upnp = 'urn:schemas-upnp-org:device-1-0'
		root = ElementTree.fromstring(response_data['content'])
		for urlbase in root.findall("./{%s}URLBase"%(upnp,)):
			urlbase.text = self.get_altport_url(urlbase.text)
		# write out
		doc = ElementTree.ElementTree(root)
		docout = StringIO.StringIO()
		doc.write(docout, encoding='utf-8', xml_declaration=True)
		docoutstr = docout.getvalue()
		request.responseHeaders.setRawHeaders('Content-Length', [len(docoutstr)])
		request.write(docoutstr)
		request.finish()

	def hack_mediaserver_response(self, request, response_data):
		request.setResponseCode(response_data['code'])
		request.responseHeaders = response_data['headers']
		if 'xml' not in response_data['headers'].getRawHeaders('Content-Type', [''])[0]:
			request.responseHeaders.setRawHeaders('Content-Length', [len(response_data['content'])])
			request.write(response_data['content'])
			request.finish()
			return
		request.responseHeaders.removeHeader('Content-Length')
		request.responseHeaders.removeHeader('Content-Encoding')
		# get the device that we're talking to, and its ip
		# load up response
		didl = 'urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/'
		upnp = 'urn:schemas-upnp-org:metadata-1-0/upnp/'
		root = ElementTree.fromstring(response_data['content'])
		for result in root.iter('Result'):
			resultdoc = ElementTree.fromstring(result.text.encode('utf-8'))
			for uritag in resultdoc.iter('{%s}albumArtURI'%(upnp,)):
				uritag.text = self.get_altport_url(uritag.text).decode('utf-8')
			for uritag in resultdoc.iter('{%s}res'%(didl,)):
				uritag.text = self.get_altport_url(uritag.text).decode('utf-8')
			result.text = ElementTree.tostring(resultdoc, encoding='utf-8').decode('utf-8')
		# write out
		doc = ElementTree.ElementTree(root)
		docout = StringIO.StringIO()
		doc.write(docout, encoding='utf-8', xml_declaration=True)
		docoutstr = docout.getvalue()
		request.responseHeaders.setRawHeaders('Content-Length', [len(docoutstr)])
		request.write(docoutstr)
		request.finish()