Beispiel #1
0
    def _receive_datagram(self, sock, cond):
        """ Implements the UDPListener listening actions.
        """
#        print "@@@@@@@@ UDP datagram: " + str(sock)
        
        if not self.is_listening():
            return

        try:
            (data, addr) = self.socket.recvfrom(self.BUFFER_SIZE)

#            if 'Coherence' in data:
   #         print "@@@@@@@@ addr: " + str(addr)
   #         print "@@@@@@@@ data before: " + str(data)
            
            # HACK: WMP sometimes returns 0.0.0.0 as the IP in its location field - fix it here            
            if 'http://0.0.0.0:2869' in data:
#                print "@@@@@@@@ addr: " + str(addr)
#                print "@@@@@@@@ data before: " + str(data)
                ip, port = addr
                newaddr = 'http://' + ip + ':2869'
                data = data.replace('http://0.0.0.0:2869', newaddr)
#                print "@@@@@@@@ data after: " + str(data)

            self.forward_data(data, addr)

        except Exception, e:
            log.debug('Error when reading on UDP socket: %s', e)
Beispiel #2
0
 def _event_subscribe_callback(self, cargo, subscription_id, timeout):
     log.debug('Event subscribe done cargo=%s sid=%s timeout=%s', cargo, subscription_id, timeout)
     udn, servicetype, service, name = cargo
     uuid = udn[5:]
     if servicetype == 'AVTransport':
         self.at_lookup[uuid] = subscription_id
         self.at_subscription_ids[subscription_id] = udn
         self.at_service[subscription_id] = service
         self.current_track_scrobbled[subscription_id] = False
         self.current_play_state[subscription_id] = None
         self.current_position_info[subscription_id] = None
         self.current_track_duration[subscription_id] = None
         self.current_track_relative_time_position[subscription_id] = None
         self.current_track_absolute_time_position[subscription_id] = None
         self.current_track_URI[subscription_id] = None
         self.current_track_start[subscription_id] = None
         self.previous_track_URI[subscription_id] = None
         self.previous_play_state[subscription_id] = None
         self.zone_grouped[subscription_id] = False
         self.current_track_metadata[subscription_id] = None
         self.current_transport_metadata[subscription_id] = None
         self.avt_track_URI[subscription_id] = None
         self.transport_error[subscription_id] = False
         self.zone_groups[subscription_id] = None
         self.zone_group_coordinators_lookup[subscription_id] = None
     if servicetype == 'ContentDirectory':
         self.cd_subscription_ids[subscription_id] = udn
         self.cd_service[subscription_id] = service
     if servicetype == 'ZoneGroupTopology':
         self.zt_lookup[uuid] = subscription_id
         self.zt_subscription_ids[subscription_id] = udn
         self.zt_service[subscription_id] = service
     self.subscription_ids[subscription_id] = '%s, %s' % (servicetype, name)
     self.process_event_queue(subscription_id)
Beispiel #3
0
    def __init__(self, server_name, xml_description_filename, max_age=1800, receive_notify=True, udp_listener=""):
        """ Constructor for the SSDPServer class.

        @param server_name: server name
        @param xml_description_filename: XML description filename
        @param max_age: max age parameter, default 1800.
        @param receive_notify: if False, ignores notify messages

        @type server_name: string
        @type xml_description_filename:
        @type max_age: integer
        @type receive_notify: boolean
        """
        self.server_name = server_name
        self.xml_description_filename = xml_description_filename
        self.max_age = max_age
        log.debug("max_age: %s", max_age)
        self.receive_notify = receive_notify
        self.running = False
        self.known_device = {}
        self.advertised = {}
        self._callbacks = {}
        self.udp_transport = UDPTransport()
        if udp_listener == "":
            self.udp_listener = UDPListener(SSDP_ADDR, SSDP_PORT, data_callback=self._datagram_received)
        else:
            self.udp_listener = None
            udp_listener.subscribe(self)
        self.renew_loop = LoopingCall(self._renew_notifications)
        self.renew_loop.start(0.8 * self.max_age, now=True)
Beispiel #4
0
    def response(self, http_response, cargo):
        """ Callback for receiving the HTTP response on a successful HTTP call.

        @param http_response: response object
        @param cargo: callback parameters passed at construction

        @type http_response: HTTPResponse

        @rtype: boolean
        """
        log.debug("response")
        compressed_headers = {}
        for k, v in dict(http_response.getheaders()).items():
            if not v:
                v = ""
            compressed_headers[k.lower()] = v.strip()
        if 'sid' in compressed_headers:
            sid = compressed_headers['sid']
            timeout = 300
            if 'timeout' in compressed_headers:
                stimeout = compressed_headers['timeout']
                if stimeout[0:7] == "Second-":
                    try:
                        timeout = int(stimeout[7:])
                    except ValueError:
                        log.error(
                            "value convert of timeout failed using default 300 seconds"
                        )
            self.service.event_sid = sid
            self.service.event_timeout = timeout
        if self.callback and sid:
            self.callback(self.cargo, sid, timeout)

        return True
Beispiel #5
0
    def _main_select(self):
        """ Selects and process events.

        @return: True if no exception was raised. False if an exception was
                 raised, meaning that we recommend another _main_select()
        @rtype: boolean
        """
        try:
            revt, wevt, eevt = select.select(list(self._read_fds.keys()),
                                             list(self._write_fds.keys()),
                                             list(self._excpt_fds.keys()),
                                             self._get_min_timeout())
            if not self._main_process_events(revt, wevt, eevt):
                return False
        # Fix problems with problematic file descriptors
        except ValueError as v:
            log.debug('Main loop ValueError: %s' % str(v))
            self._main_cleanup_fds()
        except TypeError as t:
            log.debug('Main loop TypeError %s' % str(t))
            self._main_cleanup_fds()
        except (select.error, IOError) as s:
            if s.args[0] in (0, 2):
                if not ((not self._read_fds) and (not self._write_fds)):
                    raise
            elif s.args[0] == EINTR:
                pass
            elif s.args[0] == EBADF:
                self._main_cleanup_fds()
        except socket.error as s:
            if s.args[0] == EBADF:
                self._main_cleanup_fds()
        except KeyboardInterrupt:
            return False
        return True
Beispiel #6
0
 def soap_SelectPreset(self, *args, **kwargs):
     """ Select Present state variables. This action restores (a subset) of
     the state variables to the values associated with the specified
     preset.
     """
     log.debug('Action on RenderingControlController: SelectPreset()')
     return {}
Beispiel #7
0
    def __init__(self, service, event_host, callback, cargo):
        """ Constructor for the SubscribeRequest class.

        @param service: service that is subscribing
        @param event_host: 2-tuple (host, port) of the event listener server
        @param callback: callback
        @param cargo: callback parameters

        @type service: Service
        @type event_host: tuple
        @type callback: callable
        """
        log.debug("subscribe")
        self.callback = callback
        self.cargo = cargo
        self.service = service

        addr = "%s%s" % (service.url_base, service.event_sub_url)
        Paddr = parse_url(addr)

        headers = {}
        headers["User-agent"] = 'BRisa UPnP Framework'
        headers["TIMEOUT"] = 'Second-300'
        headers["NT"] = 'upnp:event'
        headers["CALLBACK"] = "<http://%s:%d/eventSub>" % event_host
        headers["HOST"] = '%s:%d' % (Paddr.hostname, Paddr.port)

        run_async_call(http_call, success_callback=self.response,
                       error_callback=self.error, delay=0,
                       method='SUBSCRIBE', url=addr,
                       headers=headers)
Beispiel #8
0
    def _do_notify(self, usn):
        """ Do a notification for the usn specified.

        @param usn: st
        @type usn: string
        """
        log.debug('Sending alive notification for %s', usn)
        response = [
            'NOTIFY * HTTP/%s' % self.http_version,
            'HOST: %s:%d' % (SSDP_ADDR, SSDP_PORT),
            'NTS: ssdp:alive',
        ]
        stcpy = dict(self.advertised[usn].iteritems())
        stcpy['NT'] = stcpy['ST']
        del stcpy['EXT']
        del stcpy['ST']
        response.extend(map(lambda x: ': '.join(x), stcpy.iteritems()))
        append = response.append
        [append('%s: %s' % (k, v)) for k, v in self.additional_headers.items()]
        response.extend(('', ''))
        log.debug('Sending notify message with content %s' % response)
        try:
            self.udp_transport.send_data('\r\n'.join(response), SSDP_ADDR,
                                         SSDP_PORT)
            self.udp_transport.send_data('\r\n'.join(response), SSDP_ADDR,
                                         SSDP_PORT)
        except Exception, e:
            log.info("Failure sending notify with message %s" % str(e))
Beispiel #9
0
    def response(self, http_response, cargo):
        """ Callback for receiving the HTTP response on a successful HTTP call.

        @param http_response: response object
        @param cargo: callback parameters passed at construction

        @type http_response: HTTPResponse

        @rtype: boolean
        """
        log.debug("response")
        compressed_headers = {}
        for k, v in dict(http_response.getheaders()).items():
            if not v:
                v = ""
            #            compressed_headers[k.lower()] = v.lower().strip()
            compressed_headers[k.lower()] = v.strip()
            if "sid" in compressed_headers:
                sid = compressed_headers["sid"]
                timeout = 1800
                if "timeout" in compressed_headers:
                    stimeout = compressed_headers["timeout"]
                    if stimeout[0:7] == "second-":
                        try:
                            timeout = int(stimeout[7:])
                        except ValueError:
                            pass
                self.service.event_sid = sid
                self.service.event_timeout = timeout
        if self.callback and sid:
            self.callback(self.cargo, sid, timeout)

        return True
Beispiel #10
0
def getAlbumArt(service, AlbumArtURI):

#TODO: display a "getting album art" graphic until art is updated

#    log.debug('#### GETALBUMART service: %s' % service)
#    log.debug('#### GETALBUMART AlbumArtURI: %s' % AlbumArtURI)

    if AlbumArtURI == '' or AlbumArtURI == None:
        return (None, "No albumart to display")
    else:
        url_info = parse_url(service.url_base)
#        log.debug('#### GETALBUMART url_info: %s' % str(url_info))
        aa_url = "%s://%s%s" % (url_info[0], url_info[1], AlbumArtURI)
#        log.debug('#### GETALBUMART control_url: %s' % aa_url)
        try:
            fd = url_fetch(aa_url)
#        except HTTPError as detail:
        except HTTPError:
            return (None, HTTPError)

        try:
            data = fd.read()
        except:
            log.debug("#### GETALBUMART fd is invalid")
            return (None, "Error getting albumArt")

        pbl = gtk.gdk.PixbufLoader()
        pbl.write(data)
        pbuf = pbl.get_pixbuf()
#        print "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
#        print pbl.get_format()
#        print "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
        pbl.close()

        return (pbuf, '')
Beispiel #11
0
 def _renew_notifications(self):
     """ Renew notifications (sends a notify
     """
     own_temp = self.advertised.copy()
     for usn in own_temp:
         log.debug('Renew notification for %s ', own_temp[usn]['USN'])
         self._do_notify(own_temp[usn]['USN'])
Beispiel #12
0
    def _parse_description(self, fd):
        """ Parses the actions and state variables of a service given a file
        descriptor containing the SCPD XML. File descriptor must be open.

        @param fd: file descriptor
        @type fd: file

        @return: True if service parser succeeded, otherwise False.
        @rtype: bool
        """
        #        print ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
        #        print ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>BaseServiceBuilder._parse_description"
        try:
            data = fd.read()
            #            print "data: " + str(data)
            data = data[data.find("<"):data.rfind(">") + 1]
            tree = ElementTree.XML(data)
            #            print "tree: " + str(tree)
            if tree:
                self._parse_actions(tree)
                self._parse_variables(tree)
                #                print ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>BaseServiceBuilder._parse_description success"
                return True
        except Exception, e:
            log.debug('Could not build service SCPD XML. %s' % str(e))
Beispiel #13
0
def read_notify_message_body(body_data):
    changed_vars = {}

    try:
        tree = ElementTree.XML(body_data)
    except:
        log.debug("Event XML invalid: %s", body_data)
        tree = None

    if tree:
        for prop1 in tree.findall("{%s}property" % "urn:schemas-upnp-org:event-1-0"):
            # prop1 = <e:property> <Ble> cont </Ble> </e:property>
            for prop2 in prop1:
                # <Ble>cont</Ble>
                # PS: IMERGE do not adhere to UPnP standard
                # the following is a get out of jail card
                if "}" in prop2.tag:
                    # Then you have something that is not UPnP compliant
                    log.debug("Imerge do not adhere to UPnP and they ought to be shot!")
                    crudly_madeup_tag = prop2.tag.split("}")[1]
                    changed_vars[crudly_madeup_tag] = prop2.text
                else:
                    changed_vars[prop2.tag] = prop2.text
                # Never to be submitted to Brisa, since non UPnP fix

    return changed_vars
Beispiel #14
0
    def start(self, interval=DEFAULT_SEARCH_TIME,
              search_type=DEFAULT_SEARCH_TYPE, http_version="1.1",
	      man='"ssdp:discover"', mx=1, additionals={}):
        """ Starts the search.

        @param interval: interval between searchs. Default is 600.0 seconds
        @param search_type: type of the search, default is "ssdp:all"
        @param http_version: http version for m-search (default is 1.1)
        @param man: man field for m-search (default is ssdp:discover)
        @param mx: mx field for m-search (default is 1)
        @param additionals: dict containing additional field to be appended
			    in the end of the m-search message (default is
			    a empty dictionary)

        @type interval: float
        @type search_type: string
        @type http_version: string
        @type man: string
        @type mx: int
        @type additionals: dict
        """
        if not self.is_running():
	    self.ssdp.search_type = search_type
            self.listen_udp.start()
            self.loopcall._args = (search_type, http_version, man, mx,
	    			   additionals, )
            self.loopcall.start(interval, now=True)
            log.debug('MSearch started')
        else:
            log.warning(self.msg_already_started)
Beispiel #15
0
    def make_third_party_mediaserver_service(self, mediaserver):
        """
        Mmanually create Sonos Third Party Media Server service
        """
        '''
        mediaserver['CURL'] = "http://192.168.0.10:56043/ContentDirectory/50565062-8a5b-7f33-c3de-168e9401eaee/control.xml" 
        mediaserver['EURL'] = "http://192.168.0.10:56043/ContentDirectory/50565062-8a5b-7f33-c3de-168e9401eaee/event.xml" 
        mediaserver['T'] = "1" 
        mediaserver['EXT'] = ""
        mediaserver['Name'] = "Sonos: Asset UPnP: HENKELIS" 
        mediaserver['UDN'] = "50565062-8a5b-7f33-c3de-168e9401eaee" 
        mediaserver['Location'] = "http://192.168.0.10:56043/DeviceDescription.xml"
        '''
        
        # For Third Party Media Servers in Sonos, the event and control urls are absolute and may be at different ip's
        # Sonos doesn't provide the Media Server SCPD address - so we get it from the location
        # As the urls can be at different ip's, when we build the service we send absolute ip's and a null base url

        log.debug("make_third_party_mediaserver_service: %s", mediaserver)
        scpd_url = self.getscpdurl(mediaserver['Location'])
        if scpd_url != None:    # Sonos may hold out of date info, especially for proxies
            log.debug("create tpms_service: %s", mediaserver['Name'])
            self.tpms_service[unicode(mediaserver['Name'])] = Service('Browse', 'urn:schemas-upnp-org:service:ContentDirectory:1',  #'http://www.sonos.com/Services/1.1', 
                                                               url_base = '',
                                                               control_url = mediaserver['CURL'],
                                                               event_url = mediaserver['EURL'],
                                                               scpd_url = scpd_url,
                                                               build = True)
Beispiel #16
0
 def soap_GetProtocolInfo(self, *args, **kwargs):
     """Required: Returns the protocol-related info that this \
        ConnectionManager supports in its current state
     """
     log.debug('Action on ConnectionManager: GetProtocolInfo()')
     return {'Source': 'http-get:*:*:*',
             'Sink': ''}
Beispiel #17
0
    def forward_notification(self, received_headers, data):
        """ Forwards notifications to the observer registered.

        @param received_headers: headers received on the event notify
        @param data: XML data for the event

        @type received_headers: dictionary
        @type data: string
        """
        log.debug('forward notification')
        headers = {}
        for k, v in received_headers.items():
            headers[k.lower()] = v

        changed_vars = read_notify_message_body(data)

        log.debug('Event changed vars: %s', changed_vars)

        if self.observer and 'sid' in headers:
            self.observer._on_event(headers['sid'], changed_vars)

            for id, dev in self.observer._known_devices.items():
                service = self._find_service(dev, headers['sid'])
                if service != None:
                    service._on_event(changed_vars)
                    return
Beispiel #18
0
    def response(self, http_response, cargo):
        """ Callback for receiving the HTTP response on a successful HTTP call.

        @param http_response: response object
        @param cargo: callback parameters passed at construction

        @type http_response: HTTPResponse

        @rtype: boolean
        """
        log.debug("response")
        compressed_headers = {}
        for k, v in dict(http_response.getheaders()).items():
            if not v:
                v = ""
            compressed_headers[k.lower()] = v.strip()
        if 'sid' in compressed_headers:
            sid = compressed_headers['sid']
            timeout = 300
            if 'timeout' in compressed_headers:
                stimeout = compressed_headers['timeout']
                if stimeout[0:7] == "Second-":
                    try:
                        timeout = int(stimeout[7:])
                    except ValueError:
                        log.error("value convert of timeout failed using default 300 seconds")
            self.service.event_sid = sid
            self.service.event_timeout = timeout
        if self.callback and sid:
            self.callback(self.cargo, sid, timeout)

        return True
Beispiel #19
0
    def add_device(self, device):
        """ Adds a device embedded inside this device.

        @param device: device to be added
        @type device: Device
        """
        if device in self.devices.values():
            log.debug('Device %s already contained by %s' % (device, self))
            return False
        if device.friendly_name not in self.devices:
            self.devices[device.friendly_name] = device
        else:
            d = 0
            name = None
            while not name:
                name = '%s%d' % (device.friendly_name, d)
                if name not in [d.friendly_name for d in self.devices if \
                                device.friendly_name in d.friendly_name]:
                    break
                else:
                    d += 1
                    name = None
                    continue
            self.devices[name] = device
        return True
Beispiel #20
0
 def soap_GetCurrentConnectionIDs(self, *args, **kwargs):
     """Required: Returns a comma-separated list of ConnectionIDs of
     currently ongoing Connections."""
     log.debug('Action on ConnectionManager: GetCurrentConnectionIDs()')
     #If optional action PrepareForConnection is not implemented
     #this state variable should be set to 0.
     return {'ConnectionIDs': '0'}
Beispiel #21
0
    def __init__(self, service, event_host, callback, cargo):
        """ Constructor for the RenewSubscribeRequest class.

        @param service: service that is renewing the subscribe
        @param event_host: 2-tuple (host, port) of the event listener server
        @param callback: callback
        @param cargo: callback parameters

        @type service: Service
        @type event_host: tuple
        @type callback: callable
        """
        log.debug("renew subscribe")

        if not service.event_sid or service.event_sid == "":
            return

        self.callback = callback
        self.cargo = cargo
        self.service = service

        addr = "%s%s" % (service.url_base, service.event_sub_url)
        Paddr = parse_url(addr)

        headers = {}
        headers["HOST"] = '%s:%d' % (Paddr.hostname, Paddr.port)
        headers["SID"] = self.service.event_sid
        headers["TIMEOUT"] = 'Second-300'

        run_async_call(http_call, success_callback=self.response,
                       error_callback=self.error, delay=0,
                       method='SUBSCRIBE', url=addr,
                       headers=headers)
Beispiel #22
0
    def __init__(self, service, event_host, callback, cargo):
        """ Constructor for the SubscribeRequest class.

        @param service: service that is subscribing
        @param event_host: 2-tuple (host, port) of the event listener server
        @param callback: callback
        @param cargo: callback parameters

        @type service: Service
        @type event_host: tuple
        @type callback: callable
        """
        log.debug("subscribe")
        self.callback = callback
        self.cargo = cargo
        self.service = service

        addr = "%s%s" % (service.url_base, service.event_sub_url)
        Paddr = parse_url(addr)

        headers = {}
        #        headers["Host"] = Paddr.hostname
        headers["User-agent"] = 'BRisa UPnP Framework'
        headers["TIMEOUT"] = 'Second-1800'
        headers["NT"] = 'upnp:event'
        headers["CALLBACK"] = "<http://%s:%d/eventSub>" % event_host
        headers["HOST"] = '%s:%d' % (Paddr.hostname, Paddr.port)

        run_async_call(http_call,
                       success_callback=self.response,
                       error_callback=self.error,
                       delay=0,
                       method='SUBSCRIBE',
                       url=addr,
                       headers=headers)
Beispiel #23
0
    def _parse_description(self, fd):
        """ Parses the actions and state variables of a service given a file
        descriptor containing the SCPD XML. File descriptor must be open.

        @param fd: file descriptor
        @type fd: file

        @return: True if service parser succeeded, otherwise False.
        @rtype: bool
        """
#        print ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
#        print ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
#        print ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>BaseServiceBuilder._parse_description"
        try:
            data = fd.read()
#            print "data: " + str(data)
            data = data[data.find("<"):data.rfind(">")+1]
            tree = ElementTree.XML(data)
#            print "tree: " + str(tree)
            if tree:
                self._parse_actions(tree)
                self._parse_variables(tree)
                return True
        except Exception, e:
            log.debug('Could not build service SCPD XML. %s' % str(e))
Beispiel #24
0
    def __init__(self, service, subscription_duration, delivery_url, http_version,
                 event_reload_time, force_event_reload):

        self.service = service
        self.subscription_id = uuid.uuid4()
        self.delivery_url = delivery_url
        url = parse_url(delivery_url)
        self.host = '%s:%d' % (url.hostname, url.port)
        self.event_key = 0
        self.subscription_duration = subscription_duration
        self.http_version = http_version
        self.timestamp = datetime.now()

        self.eventing_variables = {}
        for name, state_var in self.service.get_variables().items():
            state_var.subscribe_for_update(self._update_variable)

        self.force_event_reload = force_event_reload
        if not force_event_reload:
            self.looping_call = LoopingCall(self._send_variables)
            reactor.add_after_stop_func(self.looping_call.stop)
            self.looping_call.start(event_reload_time, False)

        sid = str(self.subscription_id)
        log.debug('Creating subscriber with subscription id: %s' % sid)
Beispiel #25
0
 def soap_GetCurrentConnectionIDs(self, *args, **kwargs):
     """Required: Returns a comma-separated list of ConnectionIDs of
     currently ongoing Connections."""
     log.debug('Action on ConnectionManager: GetCurrentConnectionIDs()')
     #If optional action PrepareForConnection is not implemented
     #this state variable should be set to 0.
     return {'ConnectionIDs': '0'}
    def soap_Browse(self, *args, **kwargs):
        """ Implements the Browse action for the ContentDirectory.

        @param args: list of arguments for the Browse UPnP\
        function
        @param kwargs: dict of arguments for the Browse UPnP\
        function

        @type args: list
        @type kwargs: dict

        @return: the results of the browsing
        @rtype: dict
        """
        log.debug('Action on ContentDirectory: Browse%s', args)
        # Formats the parameters for the real soap browse
        args = (kwargs['ObjectID'], kwargs['BrowseFlag'], kwargs['Filter'],
                kwargs['StartingIndex'], kwargs['RequestedCount'],
                kwargs['SortCriteria'])
        l = {}
        l['query'] = 'Browse(ObjectID=%s, BrowseFlags=%s, Filter=%s, ' \
            'StartingIndex=%s RequestedCount=%s SortCriteria=%s)' % \
            tuple(map(repr, args))
        try:
            ret = self._soap_Browse(*args)
        except Exception as e:
            log.error('Action Browse on ContentDirectory: %s', e.message)

        l['response'] = ret

        return ret
Beispiel #27
0
    def render_unsubscribe(self, request, response, compressed_headers):
        """ Renders the unsubscribe message for an event.

        @param request: request object (Cherrypy)
        @param response: response object (Cherrypy)

        @note: see Cherrypy documentation for further info about request and
        response attributes and methods.
        """

#        print "EventController.render_unsubscribe"
#        print "request: " + str(request)
#        print "compressed_headers: " + str(compressed_headers)
        
        log.debug('Receiving unsubscribe request')
        request_status, subs = self._validate_unsubscribe_request(request,
                                                            compressed_headers)

        if request_status == 200:
            self._remove_subscriber(subs)

            response.status = 200
            response.body = [""]
            return response.body
        else:
            return self._build_error(request_status, request, response)
Beispiel #28
0
 def _parse_services(self):
     for xml_service_element in self.tree.\
                                 findall('.//{%s}service' % self.ns):
         service_type = xml_service_element.\
                                 findtext('{%s}serviceType' % self.ns)
         service_id = xml_service_element.\
                                 findtext('{%s}serviceId' % self.ns)
         control_url = xml_service_element.\
                                 findtext('{%s}controlURL' % self.ns)
         if control_url and not control_url.startswith('/'):
             control_url = '/' + control_url
         event_sub_url = xml_service_element.\
                                 findtext('{%s}eventSubURL' % self.ns)
         if event_sub_url and not event_sub_url.startswith('/'):
             event_sub_url = '/' + event_sub_url
         presentation_url = xml_service_element.\
                                 findtext('{%s}presentationURL' % self.ns)
         if presentation_url and not presentation_url.startswith('/'):
             presentation_url = '/' + presentation_url
         scpd_url = xml_service_element.\
                                 findtext('{%s}SCPDURL' % self.ns)
         if scpd_url and not scpd_url.startswith('/'):
             scpd_url = '/' + scpd_url
         log.debug('control_url: %s, event_sub_url: %s, presentation_url: %s, scpd_url: %s', control_url, event_sub_url, presentation_url, scpd_url)
         service = Service(service_id, service_type, self.location,
                           scpd_url, control_url, event_sub_url,
                           presentation_url)
         self.device.add_service(service)
Beispiel #29
0
 def _renew_notifications(self):
     """ Renew notifications (sends a notify
     """
     own_temp = self.advertised.copy()
     for usn in own_temp:
         log.debug('Renew notification for %s ', own_temp[usn]['USN'])
         self._do_notify(own_temp[usn]['USN'])
Beispiel #30
0
    def soap_GetProtocolInfo(self, *args, **kwargs):
        """Required: Returns the protocol-related info that this
        ConnectionManager supports in its current state - Specific
        for MediaRenderer Devices"""

        log.debug('Action on ConnectionManager: GetProtocolInfo()')
        return {'Source': '', 'Sink': 'http-get:*:audio/mpeg:*'}
Beispiel #31
0
    def _get_call_response(self, request, response_obj, method_name,
                         function, *args, **kwargs):
        """ Performs the soap call, builds and returns a response.
        """
        try:
            result = function(*args, **kwargs)
            force_use_header = False
            if "__header__" in result:
                header_args = result.pop("__header__", {})
                force_use_header = True
        except Exception as e:
            # TODO: Create a soap exception to return to the remote requester
            log.debug(str(e))
            print((str(e)))

        ns = self.service_type
        try:
            method = list(result.keys())[0]
            result = result[method]
        except AttributeError as IndexError:
            result = {}
            method = ''

        if not force_use_header:
            header_args = self.service.call_headers

        response = soap.build_soap_call("{%s}%s" % (ns, method),
                                        result, encoding=None,
                                        header_args=header_args)
        return self._build_response(request, response, response_obj)
Beispiel #32
0
 def _parse_services(self):
     for xml_service_element in self.tree.\
                                 findall('.//{%s}service' % self.ns):
         service_type = xml_service_element.\
                                 findtext('{%s}serviceType' % self.ns)
         service_id = xml_service_element.\
                                 findtext('{%s}serviceId' % self.ns)
         control_url = xml_service_element.\
                                 findtext('{%s}controlURL' % self.ns)
         if control_url and not control_url.startswith('/'):
             control_url = '/' + control_url
         event_sub_url = xml_service_element.\
                                 findtext('{%s}eventSubURL' % self.ns)
         if event_sub_url and not event_sub_url.startswith('/'):
             event_sub_url = '/' + event_sub_url
         presentation_url = xml_service_element.\
                                 findtext('{%s}presentationURL' % self.ns)
         if presentation_url and not presentation_url.startswith('/'):
             presentation_url = '/' + presentation_url
         scpd_url = xml_service_element.\
                                 findtext('{%s}SCPDURL' % self.ns)
         if scpd_url and not scpd_url.startswith('/'):
             scpd_url = '/' + scpd_url
         log.debug(
             'control_url: %s, event_sub_url: %s, presentation_url: %s, scpd_url: %s',
             control_url, event_sub_url, presentation_url, scpd_url)
         service = Service(service_id, service_type, self.location,
                           scpd_url, control_url, event_sub_url,
                           presentation_url)
         self.device.add_service(service)
Beispiel #33
0
    def forward_notification(self, received_headers, data):
        """ Forwards notifications to the observer registered.

        @param received_headers: headers received on the event notify
        @param data: XML data for the event

        @type received_headers: dictionary
        @type data: string
        """
        log.debug('forward notification')
        headers = {}
        for k, v in list(received_headers.items()):
            headers[k.lower()] = v

        changed_vars = read_notify_message_body(data)

        log.debug('Event changed vars: %s', changed_vars)

        if self.observer and 'sid' in headers:
            self.observer._on_event(headers['sid'], changed_vars)

            for id, dev in list(self.observer._known_devices.items()):
                service = self._find_service(dev, headers['sid'])
                if service != None:
                    service._on_event(changed_vars)
                    return
Beispiel #34
0
    def soap_Browse(self, *args, **kwargs):
        """ Implements the Browse action for the ContentDirectory.

        @param args: list of arguments for the Browse UPnP\
        function
        @param kwargs: dict of arguments for the Browse UPnP\
        function

        @type args: list
        @type kwargs: dict

        @return: the results of the browsing
        @rtype: dict
        """
        log.debug('Action on ContentDirectory: Browse%s', args)
        # Formats the parameters for the real soap browse
        args = (kwargs['ObjectID'], kwargs['BrowseFlag'], kwargs['Filter'],
                kwargs['StartingIndex'], kwargs['RequestedCount'],
                kwargs['SortCriteria'])
        l = {}
        l['query'] = 'Browse(ObjectID=%s, BrowseFlags=%s, Filter=%s, ' \
            'StartingIndex=%s RequestedCount=%s SortCriteria=%s)' % \
            tuple(map(repr, args))
        try:
            ret = self._soap_Browse(*args)
        except Exception, e:
            log.error('Action Browse on ContentDirectory: %s', e.message)
Beispiel #35
0
 def listener_start(self):
     """ Starts the listener.
     """
     if not self.listener_is_running():
         self.listen_udp.start()
         log.debug('Multicast event listener started')
     else:
         log.warning(self.msg_already_started)
Beispiel #36
0
    def soap_GetProtocolInfo(self, *args, **kwargs):
        """Required: Returns the protocol-related info that this
        ConnectionManager supports in its current state - Specific
        for MediaRenderer Devices"""

        log.debug('Action on ConnectionManager: GetProtocolInfo()')
        return {'Source': '', 'Sink':
                'http-get:*:audio/mpeg:*'}
Beispiel #37
0
 def listener_stop(self):
     """ Stops the search.
     """
     if self.listener_is_running():
         log.debug('Multicast event listener stopped')
         self.listen_udp.stop()
     else:
         log.warning(self.msg_already_stopped)
Beispiel #38
0
    def _call(self):
        if not self.running:
            log.debug('LoopingCall on function %s cancelled' %
                      str(self._function))
            return False

        self._function(*self._args, **self._kwargs)
        return True
Beispiel #39
0
 def mount_device_async_gotdata(self, fd, cargo=None):
     try:
         log.debug('to object async got data getting tree')
         tree = ElementTree(file=fd).getroot()
     except Exception, e:
         log.error("Bad device XML %s" % e.message)
         self.callback(self.cargo, None)
         return
Beispiel #40
0
    def _guess_content_type(self):
        """ Guesses content type for this file based on the filename.

        Copyright (c) 2002-2008, CherryPy Team ([email protected])
        """
        self._content_type = mimetypes.types_map.get(
            '.%s' % self.path.split('.')[-1], 'text/plain')
        log.debug('File %s type %s' % (self.path, self._content_type))
Beispiel #41
0
 def mount_device_async_gotdata(self, fd, cargo=None):
     try:
         log.debug('to object async got data getting tree')
         tree = ElementTree(file=fd).getroot()
     except Exception, e:
         log.error("Bad device XML %s" % e.message)
         self.callback(self.cargo, None)
         return
Beispiel #42
0
 def seek(self, unit, target):
     '''
     <InstanceID>0</InstanceID>
     <Unit>TRACK_NR</Unit>
     <Target>57</Target>
     '''
     ssresult = self.get_at_service().Seek(InstanceID=0, Unit=unit, Target=target)
     log.debug('seek result: %s', ssresult)
Beispiel #43
0
 def soap_GetVolume(self, *args, **kwargs):
     """ Return the current volume state. This action retrieves the current
     value of the Volume state variable of the specified channel for the
     specified instance of this service
     """
     log.debug('Action on RenderingControlController: GetVolume()')
     (instance_id, channel) = args
     volume = int(self.gst_player.get_volume())
     return {'CurrentVolume': volume}
Beispiel #44
0
    def soap_SetVolume(self, *args, **kwargs):
        """Set volume of instance and chanel.

        This action sets the Volume state variable of the specified
        instance and channel to the specified value."""
        log.debug('Action on RenderingControlController: SetVolume%s', args)
        (instance_id, channel, desired_volume) = args
        self.gst_player.set_volume(int(desired_volume))
        return {}
Beispiel #45
0
 def stop(self):
     """ Stops the search.
     """
     if self.is_running():
         log.debug('MSearch stopped')
         self.listen_udp.stop()
         self.loopcall.stop()
     else:
         log.warning(self.msg_already_stopped)
Beispiel #46
0
    def _guess_content_type(self):
        """ Guesses content type for this file based on the filename.

        Copyright (c) 2002-2008, CherryPy Team ([email protected])
        """
        self._content_type = mimetypes.types_map.get('.%s' %
                                                     self.path.split('.')[-1],
                                                     'text/plain')
        log.debug('File %s type %s' % (self.path, self._content_type))
Beispiel #47
0
    def render(self, uri, request, response):
        """ Event renderer method.

        @param uri: URI of the request
        @param request: request object (Cherrypy)
        @param response: response object (Cherrypy)

        @type uri: string

        @note: see Cherrypy documentation for further info about request and
        response attributes and methods.
        """
        '''
        print "EventController.render"
        print "uri: " + str(uri)
        print "request: " + str(request)
        if request.env:
            print " request.env: " + str(request.env)
        if request.body:
            print " request.body: " + str(request.body)
        if request.headers:
            print " request.headers: " + str(request.headers)
        if request.method:
            print " request.method: " + str(request.method)
        if request.server_protocol:
            print " request.server_protocol: " + str(request.server_protocol)
        if request.query:
            print " request.query: " + str(request.query)
        if request.uri:
            print " request.uri: " + str(request.uri)
        if request.params:
            print " request.params: " + str(request.params)
        '''

        compressed_headers = {}
        for k, v in request.headers.items():
            if not v:
                v = ""
            compressed_headers[k.lower()] = v.strip()

        if request.method.lower() == "subscribe":

        
            log.debug("uri: %s, headers: %s", uri, compressed_headers)
            log.debug("subscribers: %s", self.subscribers)
        
        
            if not 'sid' in compressed_headers:
                return self.render_subscriber(request,
                            response, compressed_headers)
            else:
                return self.render_renew(request, response, compressed_headers)
        elif request.method.lower() == "unsubscribe":
            return self.render_unsubscribe(request,
                            response, compressed_headers)

        return response.body
Beispiel #48
0
    def _unregister(self, usn):
        log.debug("Unregistering %s", usn)

        try:
            self._callback("removed_device_event", self.known_device[usn])
            if usn in self.known_device:
                del self.known_device[usn]
        except:
            pass
Beispiel #49
0
 def __add__(self, obj):
     if issubclass(obj.__class__, Device):
         log.debug("Adding device %s as embedded for %s", obj, self)
         self.add_device(obj)
     elif issubclass(obj.__class__, BaseService):
         log.debug("Adding service %s as service for %s", obj, self)
         self.add_service(obj)
     else:
         log.warning("Ignored invalid addition: %s + %s", self, obj)
     return self
Beispiel #50
0
 def on_new_zone_player(self, device_object):
     self.known_zone_players[device_object.udn] = device_object
     self.zoneattributes[device_object.udn] = self.get_zone_details(device_object)
     self.musicservices[device_object.udn] = self.get_music_services(device_object)
     log.debug('new zone player - %s' % self.zoneattributes[device_object.udn]['CurrentZoneName'])
     self.known_zone_names[device_object.udn] = self.zoneattributes[device_object.udn]['CurrentZoneName']
     self.subscribe_to_device(self.control_point.get_zt_service(device_object), device_object.udn, "ZoneGroupTopology", self.known_zone_names[device_object.udn])
     self.subscribe_to_device(self.control_point.get_ms_service(device_object), device_object.udn, "MusicServices", self.known_zone_names[device_object.udn])
     self.subscribe_to_device(self.control_point.get_dp_service(device_object), device_object.udn, "DeviceProperties", self.known_zone_names[device_object.udn])
     self.subscribe_to_device(self.control_point.get_sp_service(device_object), device_object.udn, "SystemProperties", self.known_zone_names[device_object.udn])
     self.subscribe_to_device(self.control_point.get_gm_service(device_object), device_object.udn, "GroupManagement", self.known_zone_names[device_object.udn])
    def _receive_datagram(self, sock, cond):
        """ Implements the UDPListener listening actions.
        """
        if not self.is_listening():
            return

        try:
            (data, addr) = self.socket.recvfrom(self.BUFFER_SIZE)
            self.forward_data(data, addr)
        except Exception, e:
            log.debug('Error when reading on UDP socket: %s', e)
Beispiel #52
0
    def force_discovery(self, search_type="ssdp:all"):
        """ Forces a multicast MSearch bypassing the time interval. This method
        force msearch to send discovery message, bypassing the initial time
        interval passed to start_search function. Note this method doesn't
        cause any effect if the start_search call was never called.

        @param search_type: UPnP type search
        @type search_type: string
        """
        log.debug('force_discovery, search_type: %s', search_type)
        self._msearch.double_discover(search_type)
Beispiel #53
0
    def service_has_been_built(self, built_ok):
        log.debug("Service fetched, %d left, result %s", \
                self.pending_services - 1, built_ok)
        if not built_ok and not brisa.__tolerate_service_parse_failure__:
            log.warning("Device killed")
            self.device = None
        self.pending_services -= 1

        if self.pending_services <= 0:
            log.debug("All services fetched, sending device forward")
            self.callback(self.cargo, self.device)