Exemplo n.º 1
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 as e:
            log.error("Bad device XML %s" % e.message)
            self.callback(self.cargo, None)
            return

        DeviceBuilder(self.device, self.location, tree).cleanup()
        if brisa.__skip_service_xml__:
            self.callback(self.cargo, self.device)
        else:
            log.debug("Fetching device services")
            log.debug("embedded devices: %s" % str(self.device.devices))
            embedded_services = []
            for d in list(self.device.devices.values()):
                embedded_services.extend(list(d.services.items()))

            log.debug("Embedded devices services are %s" % str(embedded_services))
            self.pending_services = len(self.device.services) + \
                                    len(embedded_services)
            for service_name, service_object in \
                     list(self.device.services.items()):
                service_object._build_async(self.service_has_been_built)
            for s_name, s_obj in embedded_services:
                s_obj._build_async(self.service_has_been_built)
Exemplo n.º 2
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
Exemplo n.º 3
0
    def run(self):
        """ Implementation of the call procedure.
        """
        if self.delay:
            # This runs in a thread. We can sleep here instead using time
            safe_sleep(self.delay)
            log.debug('sleeping for %d' % self.delay)

        if self.is_cancelled():
            self.cleanup()
            return

        try:
            log.debug('calling function')
            # Performing the call
            self.result = self.function(*self.args, **self.kwargs)
            log.debug('got result %s' % self.result)
            if self.success_callback:
                log.debug('forwarding to success_callback')
                self.success_callback(self.result, self.success_callback_cargo)

            self.set_completed()

        except Exception, e:
            log.error('exception happened (%s), forwarding...' % str(e))
            # Storing exception for handling
            self.result = e

            if self.error_callback:
                self.error_callback(self.error_callback_cargo, e)

            self.set_completed()
Exemplo n.º 4
0
    def application(self, environ, start_response):
        """ WSGI application callback. May not be called directly by the
        user.
        """
        path = wsgiref.util.shift_path_info(environ)

        if path in self._tree:
            # Path directly available
            return self._tree[path].application(environ, start_response)
        else:
            # End point or needs redirect. In case get_render is overriden,
            # then a request should be handled by returned get_render()
            # object.
            req = Request(environ)
            resp = Response(200, start_response)

            render = self.get_render(req.uri, req.params)

            if not render:
                log.error('Could not find resource at %s' % req.uri)
                return simple_response(404, start_response)

            resp.body = render.render(req.uri, req, resp)

            if not resp.body and not req.headers:
                log.error('Body and headers were empty.')
                return simple_response(404, start_response)
            else:
                resp._respond()
                return resp.body

        return simple_response(404, start_response)
Exemplo n.º 5
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
Exemplo n.º 6
0
    def run(self):
        """ Implementation of the call procedure.
        """
        if self.delay:
            # This runs in a thread. We can sleep here instead using time
            safe_sleep(self.delay)
            log.debug('sleeping for %d' % self.delay)

        if self.is_cancelled():
            self.cleanup()
            return

        try:
            log.debug('calling function')
            # Performing the call
            self.result = self.function(*self.args, **self.kwargs)
            log.debug('got result %s' % self.result)
            if self.success_callback:
                log.debug('forwarding to success_callback')
                self.success_callback(self.result, self.success_callback_cargo)

            self.set_completed()

        except Exception as e:
            log.error('exception happened (%s), forwarding...'
                      % str(e))
            # Storing exception for handling
            self.result = e

            if self.error_callback:
                self.error_callback(self.error_callback_cargo, e)

            self.set_completed()
Exemplo n.º 7
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)
Exemplo n.º 8
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
Exemplo n.º 9
0
    def application(self, environ, start_response):
        """ WSGI application callback. May not be called directly by the
        user.
        """
        path = wsgiref.util.shift_path_info(environ)

        if path in self._tree:
            # Path directly available
            return self._tree[path].application(environ, start_response)
        else:
            # End point or needs redirect. In case get_render is overriden,
            # then a request should be handled by returned get_render()
            # object.
            req = Request(environ)
            resp = Response(200, start_response)

            render = self.get_render(req.uri, req.params)

            if not render:
                log.error('Could not find resource at %s' % req.uri)
                return simple_response(404, start_response)

            resp.body = render.render(req.uri, req, resp)

            if not resp.body and not req.headers:
                log.error('Body and headers were empty.')
                return simple_response(404, start_response)
            else:
                resp._respond()
                return resp.body

        return simple_response(404, start_response)
Exemplo n.º 10
0
    def _soap_Browse(self, *args):
        """ Real implementation of the soap browse.

        @param args: list of arguments
        @type args: list

        @return: the results of browsing
        @rtype: dict
        """
        (object_id, browse_flag, filter, starting_index, requested_count,
         sort_criteria) = args
        try:
            starting_index = int(starting_index)
            requested_count = int(requested_count)
            last_index = None
            plugin = self.plugin_manager.root_plugin

            if browse_flag == 'BrowseDirectChildren' and \
            requested_count != 0:
                last_index = requested_count + starting_index

            if ':' in object_id:
                namespace = object_id.split(':')[0]
                plugin = self.plugin_manager.plugins_instances[namespace]

                if not plugin:
                    log.error('Could not get plugin associated with this'\
                              'browse action on id %s' % object_id)

            elements = plugin.browse(object_id, browse_flag, filter,
                                     starting_index, requested_count,
                                     sort_criteria)

            elements.sort(cmp=compare_objects)
            didl = Element()
            total = 0

            if plugin.has_browse_filter:
                for item in elements:
                    didl.add_item(item)
                    total = total + 1
            else:
                for item in elements[starting_index: last_index]:
                    didl.add_item(item)
                    total = total + 1

            didl_xml = didl.to_string()
            soap_result = {'Result': didl_xml,
                           'TotalMatches': len(elements),
                           'NumberReturned': total,
                           'UpdateID': self.updateID}
        except Exception as e:
            soap_result = {'Result': '',
                           'TotalMatches': 0,
                           'NumberReturned': 0,
                           'UpdateID': self.updateID}
            log.error('ContentDirectory.Browse internal problem: %s', e)

        return soap_result
Exemplo n.º 11
0
def daemonize(stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
    try:
        pid = os.fork()
        if pid > 0:
            sys.exit(0) # Exit first parent.
    except OSError, e:
        log.error("fork #1 failed: (%d) %s\n", e.errno, e.strerror)
        sys.exit(1)
Exemplo n.º 12
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
Exemplo n.º 13
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
Exemplo n.º 14
0
def daemonize(stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
    try:
        pid = os.fork()
        if pid > 0:
            sys.exit(0)  # Exit first parent.
    except OSError, e:
        log.error("fork #1 failed: (%d) %s\n", e.errno, e.strerror)
        sys.exit(1)
Exemplo n.º 15
0
    def stop(self):
        self.player.set_state(gst.STATE_NULL)
        if self.player.set_state(gst.STATE_READY) == gst.STATE_CHANGE_FAILURE:
            log.error("error stopping")
            return
        self.player_state = 0

        self.av_uri = self.__av_uri
Exemplo n.º 16
0
 def play(self):
     if self.av_uri is not None:
         if (self.player.set_state(gst.STATE_PLAYING) ==
             gst.STATE_CHANGE_FAILURE):
             log.error("error trying to play %s.", self.av_uri)
         self.player_state = 1
     else:
         log.info("av_uri is None, unable to play.")
Exemplo n.º 17
0
 def play(self):
     if self.av_uri is not None:
         if (self.player.set_state(
                 gst.STATE_PLAYING) == gst.STATE_CHANGE_FAILURE):
             log.error("error trying to play %s.", self.av_uri)
         self.player_state = 1
     else:
         log.info("av_uri is None, unable to play.")
Exemplo n.º 18
0
    def stop(self):
        self.player.set_state(gst.STATE_NULL)
        if self.player.set_state(gst.STATE_READY) == gst.STATE_CHANGE_FAILURE:
            log.error("error stopping")
            return
        self.player_state = 0

        self.av_uri = self.__av_uri
Exemplo n.º 19
0
 def _load_plugins(self):
     """ Loads all plugins selected using _load_plugin() method.
     """
     try:
         plugins = self.plugins_instances.values()
         for plugin in plugins:
             self._load_plugin(plugin)
     except Exception, e:
         log.error("Error loading plugin %s: %s", plugin.name, e)
Exemplo n.º 20
0
 def play(self):
     if self.av_uri is not None:
         if self.player.set_state(gst.STATE_PLAYING) == \
              gst.STATE_CHANGE_FAILURE:
             log.error("gst_renderer error while trying to play")
             return
         self.player_state = 1
     else:
         log.info("av_uri is None, unable to play.")
Exemplo n.º 21
0
 def _load_plugins(self):
     """ Loads all plugins selected using _load_plugin() method.
     """
     try:
         plugins = self.plugins_instances.values()
         for plugin in plugins:
             self._load_plugin(plugin)
     except Exception, e:
         log.error("Error loading plugin %s: %s", plugin.name, e)
Exemplo n.º 22
0
    def _datagram_received(self, data, address):
        """ Callback for the UDPListener when messages arrive.

        @param data: raw data received
        @param host: host where data came from
        @param port: port where data came from

        @type data: string
        @type host: string
        @type port: integer
        """
        (host, port) = address
        try:
            cmd, headers = parse_http_response(data)
            body = data[data.find("<"):data.rfind(">")+1]
        except Exception as err:
            log.error('Error while receiving datagram packet: %s', str(err))
            return

        # Render notify message
        if not (cmd[0] == 'NOTIFY' and cmd[1] == '*' and cmd[2] == 'HTTP/1.0' and \
           'content-type' in headers and \
           headers['content-type'] == 'text/xml; charset="utf-8"' and \
           'nt' in headers and headers['nt'] == 'upnp:event' and \
           'nts' in headers and headers['nts'] == 'upnp:propchange' and \
           'host' in headers and 'usn' in headers and \
           'svcid' in headers and 'seq' in headers and \
           'lvl' in headers and 'bootid.upnp.org' in headers and \
           'content-length' in headers):

            log.warning('Invalid message')
            return

        addr = headers['host'].split(':')[0]
        port = int(headers['host'].split(':')[1])
        udn = headers['usn'].split('::')[0]
        service_type = headers['usn'].split('::')[1]
        svcid = headers['svcid']
        seq = int(headers['seq'])
        lvl = headers['lvl']
        content_length = int(headers['content-length'])
        bootid = int(headers['bootid.upnp.org'])

        if addr != UPnPDefaults.MULTICAST_EVENT_ADDR or \
           port != UPnPDefaults.MULTICAST_EVENT_PORT:
            log.warning('Invalid address %s:%d' % (addr, port))
            return

        changed_vars = read_notify_message_body(body)

        self.control_point._on_event('', changed_vars)

        for id, dev in list(self.control_point._known_devices.items()):
            service = self._find_service(dev, udn, service_type, svcid)
            if service != None:
                service._on_event(changed_vars)
                log.debug('Multicast event. Event changed vars: %s', changed_vars)
Exemplo n.º 23
0
 def play(self):
     if self.av_uri is not None:
         if self.player.set_state(gst.STATE_PLAYING) == \
              gst.STATE_CHANGE_FAILURE:
             log.error("gst_renderer error while trying to play")
             return
         self.player_state = 1
     else:
         log.info("av_uri is None, unable to play.")
Exemplo n.º 24
0
 def _instantiate_plugins(self):
     """ Instantiates all plugin classes into the plugin manager.
     """
     plugins = self.plugins_classes.values()
     for plugin in plugins:
         if plugin.usage:
             try:
                 self.plugins_instances[plugin.name] = plugin()
             except Exception, e:
                 log.error("Error while instantiating %s: %s" % (plugin.name, str(e)))
Exemplo n.º 25
0
    def application(self, environ, start_response):
        """ WSGI application callback. May not be called directly by the
        user.
        """

#        if  environ['HTTP_USER_AGENT'] != 'TeraStation-IMHTTP/1.8.225':
#        print "@ Resource.application @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
#        print environ
#        print start_response
        
        path = wsgiref.util.shift_path_info(environ)
#        print path
#        print self._tree
        # circuits
#        print environ['wsgi.input'].getvalue()
        # cherrypy
#        print environ['wsgi.input'].read()
    
        if path in self._tree:
#            print "PATH"
#            print self._tree[path]
#            print self._tree[path].application
            # Path directly available
            return self._tree[path].application(environ, start_response)
        else:
            # End point or needs redirect. In case get_render is overriden,
            # then a request should be handled by returned get_render()
            # object.
#            print "NO PATH"
            req = Request(environ)
            resp = Response(200, start_response)
#            print "resp: " + str(resp)

            render = self.get_render(req.uri, req.params)

#            print "RENDER: " + str(render)

            if not render:
                log.error('Could not find resource at %s' % req.uri)
                return simple_response(404, start_response)

#            print "~~~~~ before >>>>>>>>>>>>>>>>>>>>"
            resp.body = render.render(req.uri, req, resp)
#            print "~~~~~ after >>>>>>>>>>>>>>>>>>>>>"
#            print "resp.body: " + str(resp.body)

            if not resp.body and not req.headers:
                log.error('Body and headers were empty.')
                return simple_response(404, start_response)
            else:
                resp._respond()
#                print "resp.body2: " + str(resp.body)
                return resp.body

        return simple_response(404, start_response)
Exemplo n.º 26
0
 def _instantiate_plugins(self):
     """ Instantiates all plugin classes into the plugin manager.
     """
     plugins = self.plugins_classes.values()
     for plugin in plugins:
         if plugin.usage:
             try:
                 self.plugins_instances[plugin.name] = plugin()
             except Exception, e:
                 log.error("Error while instantiating %s: %s" % \
                           (plugin.name, str(e)))
Exemplo n.º 27
0
 def start(self):
     """ Starts the device.
     """
     log.info('Starting device %s' % self.friendly_name)
     log.info('Starting device\'s services')
     for k, v in self.services.items():
         try:
             log.info('Starting service %s' % k)
             v.start()
         except Exception, e:
             log.error('Error starting service %s: %s' % (k, e))
Exemplo n.º 28
0
    def on_message(self, bus, message):
        t = message.type
        if t == gst.MESSAGE_EOS:
            self.player.set_state(gst.STATE_NULL)
            self.player_state = 0
            self.player.set_state(gst.STATE_READY)

        elif t == gst.MESSAGE_ERROR:
            self.player.set_state(gst.STATE_NULL)
            log.error(str(message))
            self.player_state = 0
            self.player.set_state(gst.STATE_READY)
Exemplo n.º 29
0
    def on_message(self, bus, message):
        t = message.type
        if t == gst.MESSAGE_EOS:
            self.player.set_state(gst.STATE_NULL)
            self.player_state = 0
            self.player.set_state(gst.STATE_READY)

        elif t == gst.MESSAGE_ERROR:
            self.player.set_state(gst.STATE_NULL)
            log.error(str(message))
            self.player_state = 0
            self.player.set_state(gst.STATE_READY)
Exemplo n.º 30
0
    def _validate_renew_request(self, request, compressed_headers):
        if 'callback' in compressed_headers or 'nt' in compressed_headers:
            log.error('Missing callback or nt')
            return 400, None

        subs = self._find_subscriber(compressed_headers['sid'])
        if not subs:
            log.error('Subscriber does not exist')
            return 412, None

        #TODO: Put the verification of error 5xx

        # No errors
        return 200, subs
Exemplo n.º 31
0
    def _build_error(self, request, response_obj, status):
        log.error('Building error response')
        response = soap.build_soap_error(status)

        response_obj.status = 500

        if self.encoding is not None:
            mime_type = 'text/xml; charset="%s"' % self.encoding
        else:
            mime_type = "text/xml"
        response_obj.headers["Content-type"] = mime_type
        response_obj.headers["Content-length"] = str(len(response))
        response_obj.headers["EXT"] = ''
        response_obj.body = response
        return response
Exemplo n.º 32
0
    def _find_and_import_plugins(self, plugins_folder, plugins_modules_path):
        for root, dirs, files in os.walk(plugins_folder):
            if root != plugins_folder:
                break

            for dir in dirs:
                if not dir.startswith("."):
                    try:
                        module_path = '%s.%s' % (plugins_modules_path, dir)
                        __import__(module_path)
                    except Exception, e:
                        msg = 'Error while importing %s plugin. The module '\
                              'path used to load was: %s. Error: %s' % \
                              (dir, module_path, e)
                        log.error(msg)
Exemplo n.º 33
0
    def _validate_subscribe_request(self, request, compressed_headers):
        log.debug('Validating subscribe request')
        #TODO: verify if the callback url is a valid one
        if not 'callback' in compressed_headers:
            log.error('There is not a callback at the request')
            return 412

        if (not 'nt' in compressed_headers) or \
           (compressed_headers['nt'] != "upnp:event"):
            return 412

        #TODO: Put the verification of error 5xx

        # No errors
        return 200
Exemplo n.º 34
0
 def _main_trigger_timers(self):
     """ Triggers the timers that are ready.
     """
     for callback in self._timers.values():
         if callback.timeout_abs - callback.threshold < time.time():
             log.debug('Callback ready: %s' % str(callback))
             if self.is_running():
                 try:
                     callback()
                 except KeyboardInterrupt, k:
                     # Ctrl-C would be ignored
                     return False
                 except:
                     log.error('Error while processing timer %s' %
                               str(callback))
Exemplo n.º 35
0
 def _main_trigger_timers(self):
     """ Triggers the timers that are ready.
     """
     for callback in self._timers.values():
         if callback.timeout_abs - callback.threshold < time.time():
             log.debug('Callback ready: %s' % str(callback))
             if self.is_running():
                 try:
                     callback()
                 except KeyboardInterrupt, k:
                     # Ctrl-C would be ignored
                     return False
                 except:
                     log.error('Error while processing timer %s' %
                               str(callback))
Exemplo n.º 36
0
    def _find_and_import_plugins(self, plugins_folder, plugins_modules_path):
        for root, dirs, files in os.walk(plugins_folder):
            if root != plugins_folder:
                break

            for dir in dirs:
                if not dir.startswith("."):
                    try:
                        module_path = '%s.%s' % (plugins_modules_path, dir)
                        __import__(module_path)
                    except Exception, e:
                        msg = 'Error while importing %s plugin. The module '\
                              'path used to load was: %s. Error: %s' % \
                              (dir, module_path, e)
                        log.error(msg)
Exemplo n.º 37
0
 def start(self):
     """ Starts the device.
     """
     log.info('Starting device %s' % self.friendly_name)
     log.info('Starting device\'s services')
     for k, v in self.services.items():
         try:
             if self._force_event_reload:
                 v._set_force_event_reload(self._force_event_reload)
             else:
                 if self._event_reload_time:
                     v._set_event_reload_time(self._event_reload_time)
             log.info('Starting service %s' % k)
             v.start()
         except Exception, e:
             log.error('Error starting service %s: %s' % (k, str(e)))
Exemplo n.º 38
0
 def start(self):
     """ Starts the device.
     """
     log.info('Starting device %s' % self.friendly_name)
     log.info('Starting device\'s services')
     for k, v in self.services.items():
         try:
             if self._force_event_reload:
                 v._set_force_event_reload(self._force_event_reload)
             else:
                 if self._event_reload_time:
                     v._set_event_reload_time(self._event_reload_time)
             log.info('Starting service %s' % k)
             v.start()
         except Exception, e:
             log.error('Error starting service %s: %s' % (k, e))
Exemplo n.º 39
0
    def __init__(self, subscriber, variables, event_delay, cargo):
        """ Constructor for the EventMessage class.

        @param subscriber: subscriber that will receive the message
        @param variables: variables of the event
        @param event_delay: delay to wait before sending the event
        @param cargo: callback parameters

        @type subscriber: Subscriber
        @type variables: dict
        @type event_delay: float
        """
        log.debug("event message")

        if not variables:
            log.error("There are no variables to send")
            return

        self.cargo = cargo

        headers = {}
        headers["HOST"] = subscriber.delivery_url
        headers["CONTENT-TYPE"] = 'text/xml'
        headers["NT"] = 'upnp:event'
        headers["NTS"] = 'upnp:propchange'
        headers["SID"] = "uuid:" + str(subscriber.subscription_id)
        headers["SEQ"] = str(subscriber.event_key)
        subscriber.event_key_increment()

        event_body = self._build_message_body(variables)

        headers["CONTENT-LENGTH"] = str(len(event_body))

        log.debug("Running http call")
        run_async_call(http_call,
                       success_callback=self.response,
                       error_callback=self.error,
                       delay=event_delay,
                       method='NOTIFY',
                       url=subscriber.delivery_url,
                       body=event_body,
                       headers=headers)
Exemplo n.º 40
0
    def update(self, value):
        """ Updates the state variable value. The new value must
        has the same type as specified at data type.

        @param value: new value.
        @type value: data_type
        """
#        log.debug("Updating state variable")
        if self._value == value:
            log.debug("Don't update")
            return

        self._value = value
        if self.send_events:
            for callback in self._callbacks:
                try:
                    callback(self.name, self._value)
                except Exception, e:
                    log.error('Error at callback %s' % str(callback))
                    raise e
Exemplo n.º 41
0
class MulticastEventController:

    msg_already_started = 'tried to start() MulticastEventController when already started'
    msg_already_stopped = 'tried to stop() MulticastEventController when already stopped'

    def __init__(self, parent_udn, service, event_reload_time, force_event_reload):
        self.service = service
        self.parent_udn = parent_udn
        self.udp_transport = UDPTransport()
        


        self.listen_udp = UDPListener(UPnPDefaults.MULTICAST_EVENT_ADDR,
                                      UPnPDefaults.MULTICAST_EVENT_PORT,
                                      data_callback=self._datagram_received,
                                      shared_socket=self.udp_transport.socket)
        
        
        
        self.eventing_variables = {}
        self.event_key = 0
        self.event_reload_time = event_reload_time
        self.force_event_reload = force_event_reload

        if not self.force_event_reload:
            self.l_call = LoopingCall(self.send_variables)
            reactor.add_after_stop_func(self.stop)
        self._is_running = False







    def _datagram_received(self, data, (host, port)):
        """ Callback for the UDPListener when messages arrive.

        @param data: raw data received
        @param host: host where data came from
        @param port: port where data came from

        @type data: string
        @type host: string
        @type port: integer
        """
        log.debug("device.MEC._datagram_received host: %s, port: %s\ndata: %s", host, port, data)
        try:
            cmd, headers = parse_http_response(data)
            body = data[data.find("<"):data.rfind(">")+1]
        except Exception, err:
            log.error('Error while receiving datagram packet: %s', str(err))
            return
Exemplo n.º 42
0
 def start(self):
     """ Starts the device.
     """
     log.info('Starting device %s' % self.friendly_name)
     log.info('Starting device\'s services')
     for k, v in list(self.services.items()):
         try:
             if self._force_event_reload:
                 v._set_force_event_reload(self._force_event_reload)
             else:
                 if self._event_reload_time:
                     v._set_event_reload_time(self._event_reload_time)
             log.info('Starting service %s' % k)
             v.start()
         except Exception as e:
             log.error('Error starting service %s: %s' % (k, str(e)))
     self._publish()
     self.SSDP.register_device(self)
     self.webserver.start()
     self.SSDP.start()
     self.SSDP.announce_device()
     log.info('Finished starting device %s' % self.friendly_name)
Exemplo n.º 43
0
    def update(self, value):
        """ Updates the state variable value. The new value must
        has the same type as specified at data type.

        @param value: new value.
        @type value: data_type
        """
        log.debug("Updating state variable %s: %s" % (self.name, str(value)))
        if self._value == value:
            log.debug("Don't update. Same value.")
            return

        self._value = value
        if self.send_events:
            cbs = self._callbacks[:]
            log.debug("Calling callbacks")
            for callback in cbs:
                try:
                    callback(self.name, self._value)
                except Exception, e:
                    log.error('Error at callback %s' % str(callback))
                    self._callbacks.remove(callback)
Exemplo n.º 44
0
    def update(self, value):
        """ Updates the state variable value. The new value must
        has the same type as specified at data type.

        @param value: new value.
        @type value: data_type
        """
        # unicode issue        log.debug("Updating state variable %s: %s" % (self.name, str(value)))
        if self._value == value:
            log.debug("Don't update. Same value.")
            return

        self._value = value
        if self.send_events:
            cbs = self._callbacks[:]
            log.debug("Calling callbacks")
            for callback in cbs:
                try:
                    callback(self.name, self._value)
                except Exception, e:
                    log.error('Error at callback %s' % str(callback))
                    raise e
Exemplo n.º 45
0
def build_notify_message_body(variables):
    log.debug("Building event message body")
    property_set = ElementTree.Element("e:propertyset")
    property_set.attrib.update({'xmlns:e': "urn:schemas-upnp-org:event-1-0"})

    for var_name, var_value in variables.items():
        property = ElementTree.SubElement(property_set, "e:property")

        try:
            var_val = map_upnp_value(var_value)
        except:
            #TODO - raise an error?
            log.error("Unknown state variable type")
            pass

        if var_val == None:
            var_val = ''

        e = ElementTree.SubElement(property, var_name)
        e.text = var_val

    return ElementTree.tostring(property_set, 'utf-8')
Exemplo n.º 46
0
    def __init__(self, subscriber, variables, event_delay, cargo):
        """ Constructor for the EventMessage class.

        @param subscriber: subscriber that will receive the message
        @param variables: variables of the event
        @param event_delay: delay to wait before sending the event
        @param cargo: callback parameters

        @type subscriber: Subscriber
        @type variables: dict
        @type event_delay: float
        """
        log.debug("event message")

        if not variables:
            log.error("There are no variables to send")
            return

        self.cargo = cargo

        headers = {}
#        headers["HOST"] = subscriber.delivery_url
        headers["HOST"] = subscriber.host
        headers["CONTENT-TYPE"] = 'text/xml'
        headers["NT"] = 'upnp:event'
        headers["NTS"] = 'upnp:propchange'
        headers["SID"] = "uuid:" + str(subscriber.subscription_id)
        headers["SEQ"] = str(subscriber.event_key)
        subscriber.event_key_increment()

        event_body = self._build_message_body(variables)

        headers["CONTENT-LENGTH"] = str(len(event_body))

        log.debug("Running http call")
        run_async_call(http_call, success_callback=self.response,
                       error_callback=self.error, delay=event_delay,
                       method='NOTIFY', url=subscriber.delivery_url,
                       body=event_body, headers=headers)
Exemplo n.º 47
0
class MulticastEventListener:
    """ Represents a multicast event listener. Contains some control 
    functions for starting and stopping the listener.
    """

    msg_already_started = 'tried to start() MulticastEventListener when already started'
    msg_already_stopped = 'tried to stop() MulticastEventListener when already stopped'

    def __init__(self, control_point, start=True):
        """ Constructor for the MulticastEventListener class.

        @param ssdp: ssdp server instance that will receive new device events
        and subscriptions
        @param start: if True starts the search when constructed
        @param ssdp_addr: ssdp address for listening (UDP)
        @param ssdp_port: ssdp port for listening (UDP)

        @type ssdp: SSDPServer
        @type start: boolean
        @type ssdp_addr: string
        @type ssdp_port integer
        """
        self.udp_transport = UDPTransport()
        self.listen_udp = UDPListener(UPnPDefaults.MULTICAST_EVENT_ADDR,
                                      UPnPDefaults.MULTICAST_EVENT_PORT,
                                      data_callback=self._datagram_received,
                                      shared_socket=self.udp_transport.socket)
        self.control_point = control_point
        if start:
            self.start()

    def _datagram_received(self, data, (host, port)):
        """ Callback for the UDPListener when messages arrive.

        @param data: raw data received
        @param host: host where data came from
        @param port: port where data came from

        @type data: string
        @type host: string
        @type port: integer
        """
        log.debug("cp.event._datagram_received host: %s, port: %s\ndata: %s",
                  host, port, data)
        try:
            cmd, headers = parse_http_response(data)
            body = data[data.find("<"):data.rfind(">") + 1]
        except Exception, err:
            log.error('Error while receiving datagram packet: %s', str(err))
            return
Exemplo n.º 48
0
def build_notify_message_body(variables):
    log.debug("Building event message body")
    property_set = ElementTree.Element("e:propertyset")
    property_set.attrib.update({'xmlns:e':
                                "urn:schemas-upnp-org:event-1-0"})

    for var_name, var_value in variables.items():
        property = ElementTree.SubElement(property_set, "e:property")

        try:
            var_val = map_upnp_value(var_value)
        except:
            #TODO - raise an error?
            log.error("Unknown state variable type")
            pass
                
        if var_val == None:
            var_val = ''

        e = ElementTree.SubElement(property, var_name)
        e.text = var_val

    return ElementTree.tostring(property_set, 'utf-8')
Exemplo n.º 49
0
    def __call__(self, *args, **kwargs):
        log.debug('Entering at action %s __call__' % self.name)
        # Update in arguments
        in_kwargs = {}

        log.debug('Updating IN variables')
        for arg_name, arg_value in kwargs.iteritems():
	    if arg_name != '__header__':
                arg = self.get_in_argument(arg_name)
                if not arg:
                    log.error('Input argument "%s" not' \
                              ' present on action definition.' \
                              % arg_name)
                    raise InvalidActionInput('Input argument "%s" not' \
                                             ' present on action definition.' \
                                             % arg_name)
	        if arg.state_var:
	            arg.state_var.update(arg_value)
            in_kwargs[arg_name] = arg_value

        log.debug('Calling run function')
        returned_kwargs = self.run_function(*(), **in_kwargs)

        if not isinstance(returned_kwargs, dict):
	    msg = 'returned value from service function is not a dict.'
            log.error(msg)
            raise InvalidActionOutput(msg)

        # Update out arguments
        out_kwargs = {}

        log.debug('Updating OUT variables')
        for arg_name, arg_value in returned_kwargs.iteritems():
	    if arg_name != '__header__':
                arg = self.get_out_argument(arg_name)
                if not arg:
                    log.error('output contains argument "%s" not'\
                              ' present on action definition' % \
                              arg_name)
                    raise InvalidActionOutput('output contains argument "%s" not'\
                                              ' present on action definition' % \
                                              arg_name)

	        if arg.state_var:
            	    arg.state_var.update(arg_value)
            out_kwargs[arg_name] = arg_value

        log.debug('Returning from action %s __call__' % self.name)
	if "__header__" in out_kwargs:
            header = out_kwargs.pop('__header__', {})
            return {self.name + "Response": out_kwargs,
	            "__header__": header}
        else:
            return {self.name + "Response": out_kwargs}
Exemplo n.º 50
0
    def __call__(self, *args, **kwargs):
        log.debug('Entering at action %s __call__' % self.name)
        # Update in arguments
        in_kwargs = {}

        log.debug('Updating IN variables')
        for arg_name, arg_value in kwargs.iteritems():
            if arg_name != '__header__':
                arg = self.get_in_argument(arg_name)
                if not arg:
                    log.error('Input argument "%s" not' \
                              ' present on action definition.' \
                              % arg_name)
                    raise InvalidActionInput('Input argument "%s" not' \
                                             ' present on action definition.' \
                                             % arg_name)
                if arg.state_var:
                    arg.state_var.update(arg_value)
            in_kwargs[arg_name] = arg_value

        log.debug('Calling run function')
        returned_kwargs = self.run_function(*(), **in_kwargs)

        if not isinstance(returned_kwargs, dict):
            msg = 'returned value from service function is not a dict.'
            log.error(msg)
            raise InvalidActionOutput(msg)

        # Update out arguments
        out_kwargs = {}

        log.debug('Updating OUT variables')
        for arg_name, arg_value in returned_kwargs.iteritems():
            if arg_name != '__header__':
                arg = self.get_out_argument(arg_name)
                if not arg:
                    log.error('output contains argument "%s" not'\
                              ' present on action definition' % \
                              arg_name)
                    raise InvalidActionOutput('output contains argument "%s" not'\
                                              ' present on action definition' % \
                                              arg_name)

                if arg.state_var:
                    arg.state_var.update(arg_value)
            out_kwargs[arg_name] = arg_value

        log.debug('Returning from action %s __call__' % self.name)
        if "__header__" in out_kwargs:
            header = out_kwargs.pop('__header__', {})
            return {self.name + "Response": out_kwargs, "__header__": header}
        else:
            return {self.name + "Response": out_kwargs}
Exemplo n.º 51
0
    def _validate_unsubscribe_request(self, request, compressed_headers):

        if not 'sid' in compressed_headers:
            log.error('Missing sid')
            return 412, None

        if 'callback' in compressed_headers or 'nt' in compressed_headers:
            log.error('Missing callback or nt')
            return 400, None

        subs = self._find_subscriber(compressed_headers['sid'])
        if not subs:
            log.error('Subscriber does not exist')
            return 412, None

        # No errors
        return 200, subs
Exemplo n.º 52
0
    def __call__(self, *args, **kwargs):
        log.debug('Entering at action %s __call__' % self.name)
        # Update in arguments
        in_kwargs = {}

        log.debug('Updating IN variables')
        for arg_name, arg_value in kwargs.iteritems():
            arg = self.get_in_argument(arg_name)
            if not arg:
                log.error('Input argument "%s" not' \
                          ' present on action definition.' \
                          % arg_name)
                raise InvalidActionInput('Input argument "%s" not' \
                                         ' present on action definition.' \
                                         % arg_name)
            arg.state_var.update(arg_value)
            in_kwargs[arg_name] = arg_value

        log.debug('Calling run function')
        out_args = self.run_function(*(), **in_kwargs)

        if not isinstance(out_args, dict):
            log.error('output is not a dict.')
            raise InvalidActionOutput('output is not a dict.')

        # Update out arguments
        return_args = {}

        log.debug('Updating OUT variables')
        for arg_name, arg_value in out_args.iteritems():
            arg = self.get_out_argument(arg_name)
            if not arg:
                log.error('output contains argument "%s" not'\
                          ' present on action definition' % \
                          arg_name)
                raise InvalidActionOutput('output contains argument "%s" not'\
                                          ' present on action definition' % \
                                          arg_name)

            arg.state_var.update(arg_value)
            return_args[arg_name] = arg_value

        log.debug('Returning from action %s __call__' % self.name)
        return {self.name + "Response": return_args}
Exemplo n.º 53
0
 def mount_device_async_error(self, cargo, error):
     log.error("Error fetching %s - Error: %s" %
               (self.location, str(error)))
     self.callback(self.cargo, None)
     return True
Exemplo n.º 54
0
                hcopy = dict(headers.iteritems())
                hcopy['st'] = self.known_device[i]['ST']
                self._discovery_request(hcopy, (host, port))
            return

        for key in self.known_device.keys():
            if self.known_device[key]['ST'].split()[0] == (
                    headers['st']).split()[0]:
                right_key = key
                break
        else:
            log.debug('Discovery request ST %s not found', headers['st'])
            return

        if right_key == 0:
            log.error('Unknown error in DiscoveryRequest for %s',
                      headers['st'])
            return

        # Generate a response
        response = []
        response.append('HTTP/1.1 200 OK')
        append = response.append

        [
            append('%s: %s' % (k, v))
            for k, v in self.known_device[right_key].items()
        ]
        response.extend(('', ''))
        delay = random.randint(0, int(headers['mx']))
        # Avoid using a timer with delay 0 :)
        if delay:
Exemplo n.º 55
0
class SSDPServer(object):
    """ Implementation of a SSDP server.

    The notify_received and search_received methods are called when the
    appropriate type of datagram is received by the server.
    """

    msg_already_started = 'tried to start() SSDPServer when already started'
    msg_already_stopped = 'tried to stop() SSDPServer when already stopped'

    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)

    def is_running(self):
        """ Returns True if the SSDPServer is running, False otherwise.
        """
        return self.running

    def start(self):
        """ Starts the SSDPServer.
        """
        if not self.is_running():
            if self.udp_listener != None:
                self.udp_listener.start()
            self.running = True
        else:
            log.warning(self.msg_already_started)

    def stop(self):
        """ Sends bye bye notifications and stops the SSDPServer.
        """
        if self.is_running():
            # Avoid racing conditions
            own_temp = self.advertised.copy()
            for usn in own_temp:
                self._do_byebye(usn)

            self.renew_loop.stop()
            if self.udp_listener != None:
                self.udp_listener.stop()
            self.running = False
        else:
            log.warning(self.msg_already_stopped)

    def destroy(self):
        """ Destroys the SSDPServer.
        """
        if self.is_running():
            self.stop()
        self.renew_loop.destroy()
        if self.udp_listener != None:
            self.udp_listener.destroy()
        self._cleanup()

    def clear_device_list(self):
        """ Clears the device list.
        """
        self.known_device.clear()

    def discovered_device_failed(self, dev):
        """ Device could not be fully built, so forget it.
        """
        usn = dev['USN']
        if usn in self.known_device:
            self.known_device.pop(usn)

    def is_known_device(self, usn):
        """ Returns if the device with the passed usn is already known.

        @param usn: device's usn
        @type usn: string

        @return: True if it is known
        @rtype: boolean
        """
        return usn in self.known_device

    def subscribe(self, name, callback):
        """ Subscribes a callback for an event.

        @param name: name of the event. May be "new_device_event" or
                     "removed_device_event"
        @param callback: callback

        @type name: string
        @type callback: callable
        """
        self._callbacks.setdefault(name, []).append(callback)

    def unsubscribe(self, name, callback):
        """ Unsubscribes a callback for an event.

        @param name: name of the event
        @param callback: callback

        @type name: string
        @type callback: callable
        """
        callbacks = self._callbacks.get(name, [])
        [callbacks.remove(c) for c in callbacks]
        self._callbacks[name] = callbacks

    def announce_device(self):
        """ Announces the device.
        """
        log.debug("announce_device")
        [self._do_notify(usn) for usn in self.advertised]

    def register_device(self, device):
        """ Registers a device on the SSDP server.

        @param device: device to be registered
        @type device: Device
        """
        self._register_device(device)
        if device.is_root_device():
            [self._register_device(d) for d in device.devices.values()]

    # Messaging

    def _datagram_received(self, data, (host, port)):
        """ Handles a received multicast datagram.

        @param data: raw data
        @param host: datagram source host
        @param port: datagram source port

        @type data: string
        @type host: string
        @type port: integer
        """
        log.debug("SSDP._datagram_received host: %s, port: %s\ndata: %s", host,
                  port, data)
        try:
            header, payload = data.split('\r\n\r\n')
        except ValueError, err:
            log.error('Error while receiving datagram packet: %s', str(err))
            return