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)
def start(self, interval, now=True): """ Starts the function calls in the interval specified. If now is False, it waits the interval before starting doing calls. @param interval: interval between calls @param now: whether it will start calling now or not @type interval: float @type now: boolean """ # print "@@@@@@@@ LoopingCall start: " + str(self) # print "@@@@@@@@ LoopingCall start interval: " + str(interval) # print "@@@@@@@@ LoopingCall start now: " + str(now) if not self.is_running(): self.interval = interval self.running = True assert interval != 0, ('(warning) starting LoopingCall with \ interval %f' % self.interval) if now: self._register() else: Timer(interval, self._register).start() else: log.warning(self.msg_already_started)
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)
def stop(self): """ Stops the LoopingCall. """ if self.running: self.running = False self._unregister() else: log.warning(self.msg_already_stopped)
def start(self): """ Starts the SSDPServer. """ if not self.is_running(): self.udp_listener.start() self.running = True else: log.warning(self.msg_already_started)
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)
def get_byte_ranges(r, clen): """ Based on a Range header and on the content length of a file, returns a list of byte ranges requested. Returns None if the header was invalid and an empty list in case of invalid range. Based on Cherrypy 3.1 implementation. @param r: range header @param clen: content length """ # Byte unit supported by us (HTTP1.1) is "bytes". Get the ranges string. log.debug('Range: %s, %d' % (r, clen)) if not r: return None bunit, branges = r.split('=', 1) log.debug('Bunit, branges: %s %s' % (bunit, branges)) if bunit != 'bytes': # Ignore any other kind of units log.warning('Received a request with wrong Range header (unit is not'\ 'bytes') return None ranges = [] for br in branges.split(','): start, stop = [b.strip() for b in br.split('-', 1)] log.debug('%s %s' % (start, stop)) if not start: # If the first number is missing, should return the last n bytes # and stop must be present, or else return the whole body. if not stop: # Invalid! Return None and indicate the whole body return None # Last n bytes ranges.append((clen - int(stop), clen)) log.debug('Ranges: %s' % ranges) else: # Start is present if not stop: # Whole body stop = clen - 1 if int(start) >= clen: # If start is equal to or larger than the size of the document # minus one, return the whole body continue if int(stop) < int(start): return None ranges.append((int(start), int(stop) + 1)) log.debug('Ranges: %s' % ranges) log.debug('Ranges: %s' % ranges) return ranges
def start(self): """ Starts the control point. """ if not self.is_running(): self._ssdp_server.start() self._event_listener.start(self.event_host) self._multicast_event_listener.start() else: log.warning(self.msg_already_started)
def stop(self): """ Stops the webserver. """ if self.is_running(): if not self.adapter: raise RuntimeError('Adapter not set') self.adapter.stop() else: log.warning(self.msg_already_stopped)
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)
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)
def start(self): """ Starts the webserver. """ if not self.is_running(): if not self.adapter: raise RuntimeError('Adapter not set.') threaded_call.run_async_function(self.adapter.start) self.running = True else: log.warning(self.msg_already_started)
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
def __init__(self): import brisa.core import sys if 'brisa.core.reactor' in sys.modules: from brisa.core import log log.warning('reactor already installed') brisa.core.reactor = self sys.modules['brisa.core.reactor'] = self
def stop_control_point(self): """ Stops the control point. """ if self.is_running(): if self.is_msearch_running(): self.stop_search() self._ssdp_server.stop() self._event_listener.stop() else: log.warning(self.msg_already_stopped)
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)
def start(self): """ Starts the control point. """ print "ControlPoint.start" if not self.is_running(): print "ControlPoint.start _ssdp_server" self._ssdp_server.start() print "ControlPoint.start _event_listener" self._event_listener.start(self.event_host) else: log.warning(self.msg_already_started)
def stop_control_point(self): """ Stops the control point. """ if self.is_running(): if self.is_msearch_running(): self.stop_search() self._ssdp_server.stop() self._event_listener.stop() self._multicast_event_listener.stop() else: log.warning(self.msg_already_stopped)
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)
def url_fetch(url, filename='', attempts=0, interval=0): """ Fetches an URL into a file or returns a file descriptor. If attempts and interval are not specified, they get their values from brisa.url_fetch_attempts and brisa.url_fetch_attempts_interval. @param url: URL to be fetched @param filename: if specified fetch result gets written on this path @param attempts: number of attempts @param interval: interval between attempts in seconds @type url: string @type filename: string @type attempts: integer @type interval: float """ if not attempts: attempts = brisa.url_fetch_attempts if not interval: interval = brisa.url_fetch_attempts_interval handle = None last_exception = None for k in range(attempts): log.debug('Fetching %r (attempt %d)' % (url, k)) req = urllib.request.Request(url) try: handle = urllib.request.urlopen(req) except IOError as e: if hasattr(e, 'reason'): log.warning('Attempt %d: failed to reach a server. Reason: %s'% (k, e.reason)) elif hasattr(e, 'code'): log.warning('Attempt %d: the server couldn\'t fulfill the '\ 'request. Error code: %s' % (k, e.code)) handle = None last_exception = e finally: if handle != None: if not filename: # Return mode log.debug('url %r fetched successfully' % url) return handle else: log.debug('writing data to filename %s' % filename) # Writing mode shutil.copyfile(handle, open(filename, 'w')) return None sleep(interval) if last_exception: raise last_exception else: return None
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() self.udp_listener.stop() self.running = False else: log.warning(self.msg_already_stopped)
def start(self): """ Starts the listener. """ if not self.is_running(): for name, state_var in list(self.service.get_variables().items()): if state_var.send_events and state_var.multicast: state_var.subscribe_for_update(self._update_variable) if not self.force_event_reload: self.l_call.start(self.event_reload_time) self._is_running = True log.debug('Multicast event controller started with event reload time: %d' % self.event_reload_time) else: log.warning(self.msg_already_started)
def stop(self): """ Stops the search. """ if self.is_running(): log.debug('Multicast event controller stopped') for name, state_var in list(self.service.get_variables().items()): if state_var.send_events and state_var.multicast: state_var.unsubscribe_for_update(self._update_variable) if not self.force_event_reload: self.l_call.stop() reactor.rem_after_stop_func(self.stop) self._is_running = False else: log.warning(self.msg_already_stopped)
def stop(self): """ Stops the search. """ if self.is_running(): log.debug('Multicast event controller stopped') for name, state_var in self.service.get_variables().items(): if state_var.send_events and state_var.multicast: state_var.unsubscribe_for_update(self._update_variable) if not self.force_event_reload: self.l_call.stop() reactor.rem_after_stop_func(self.stop) self._is_running = False else: log.warning(self.msg_already_stopped)
def start(self): """ Starts the listener. """ self.listener_start() if not self.is_running(): for name, state_var in self.service.get_variables().items(): if state_var.send_events and state_var.multicast: state_var.subscribe_for_update(self._update_variable) if not self.force_event_reload: self.l_call.start(self.event_reload_time) self._is_running = True log.debug('Multicast event controller started with event reload time: %d' % self.event_reload_time) else: log.warning(self.msg_already_started)
def start(self, interval=DEFAULT_SEARCH_TIME, search_type=DEFAULT_SEARCH_TYPE): """ Starts the search. @param interval: interval between searchs. Default is 600.0 seconds @param search_type: type of the search, default is "ssdp:all" @type interval: float @type search_type: string """ if not self.is_running(): self.listen_udp.start() self.loopcall._args = (search_type, ) self.loopcall.start(interval, now=True) log.debug('MSearch started') else: log.warning(self.msg_already_started)
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)
def url_fetch(url, filename='', attempts=0, interval=0, silent=False): """ Fetches an URL into a file or returns a file descriptor. If attempts and interval are not specified, they get their values from brisa.url_fetch_attempts and brisa.url_fetch_attempts_interval. @param url: URL to be fetched @param filename: if specified fetch result gets written on this path @param attempts: number of attempts @param interval: interval between attempts in seconds# @param silent: silently ignore exception and return none @type url: string @type filename: string @type attempts: integer @type interval: float """ if not attempts: attempts = brisa.url_fetch_attempts if not interval: interval = brisa.url_fetch_attempts_interval handle = None last_exception = None for k in range(attempts): log.debug('Fetching %r (attempt %d)' % (url, k)) req = urllib2.Request(url) try: handle = urllib2.urlopen(req) except IOError, e: if hasattr(e, 'reason'): log.warning('Attempt %d: failed to reach a server. Reason: %s'% (k, e.reason)) elif hasattr(e, 'code'): log.warning('Attempt %d: the server couldn\'t fulfill the '\ 'request. Error code: %s' % (k, e.code)) handle = None last_exception = e finally:
def url_fetch(url, filename='', attempts=0, interval=0): """ Fetches an URL into a file or returns a file descriptor. If attempts and interval are not specified, they get their values from brisa.url_fetch_attempts and brisa.url_fetch_attempts_interval. @param url: URL to be fetched @param filename: if specified fetch result gets written on this path @param attempts: number of attempts @param interval: interval between attempts in seconds @type url: string @type filename: string @type attempts: integer @type interval: float """ if not attempts: attempts = brisa.url_fetch_attempts if not interval: interval = brisa.url_fetch_attempts_interval handle = None last_exception = None for k in range(attempts): log.debug('Fetching %r (attempt %d)' % (url, k)) req = urllib2.Request(url) try: handle = urllib2.urlopen(req) except IOError, e: if hasattr(e, 'reason'): log.warning( 'Attempt %d: failed to reach a server. Reason: %s' % (k, e.reason)) elif hasattr(e, 'code'): log.warning('Attempt %d: the server couldn\'t fulfill the '\ 'request. Error code: %s' % (k, e.code)) handle = None last_exception = e finally:
def start(self, interval=DEFAULT_SEARCH_TIME, search_type=DEFAULT_SEARCH_TYPE): """ Starts the search. @param interval: interval between searchs. Default is 600.0 seconds @param search_type: type of the search, default is "ssdp:all" @type interval: float @type search_type: string """ # interval = 30.0 if not self.is_running(): self.search_type = search_type self.listen_udp.start() # print ">>>>>>>>> interval: " + str(interval) self.loopcall.start(interval, now=True) log.debug('MSearch started') else: log.warning(self.msg_already_started)
except Exception, 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 \ headers.has_key('content-type') and \ headers['content-type'] == 'text/xml; charset="utf-8"' and \ headers.has_key('nt') and headers['nt'] == 'upnp:event' and \ headers.has_key('nts') and headers['nts'] == 'upnp:propchange' and \ headers.has_key('host') and headers.has_key('usn') and \ headers.has_key('svcid') and headers.has_key('seq') and \ headers.has_key('lvl') and headers.has_key('bootid.upnp.org') and \ headers.has_key('content-length')): 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))
'because of SSDPServer.receive_notify is False)', host, port) return if self.search_type != "upnp:rootdevice" and \ self.search_type != "sspd:all" and \ self.search_type != headers['nt']: # Ignore notify log.debug('Received NOTIFY command from %s:%s (ignored '\ 'because of SSDPServer.search_type is different'\ 'than headers["nt"])', host, port) return # SSDP presence self._notify_received(headers, (host, port)) else: log.warning('Received unknown SSDP command %s with headers %s '\ 'from %s:%s', cmd, str(headers), host, port) def _discovery_request(self, headers, (host, port)): """ Processes discovery requests and responds accordingly. @param headers: discovery headers @param host: discovery source host @param port: discovery source port @type headers: dictionary @type host: string @type port integer """ for dev_info in self.known_device.values(): if (headers['st'] == 'ssdp:all' or dev_info['ST'] == headers['st']): response = []
def application(self, environ, start_response, response=None): """ Application wsgi callback that processes a request. Must not be called by the user. @param response: used when the request was redirected to this file. If not present, then this file was accessed directly (no redirections) and in this case environ and start_response must be passed accordingly. """ req = Request(environ) if response: # Redirect mode, see method doc and comments at the end r = response else: # Normal request r = Response(200, start_response) if not os.path.exists(self.path): log.warning('Received request on missing file: %s' % self.path) return simple_response(500, r.start_response, 'File not available.') try: st = os.stat(self.path) except OSError: return simple_response(404, r.start_response) r.body = open(self.path, 'rb') content_length = st.st_size h = r.headers h['Last-modified'] = rfc822.formatdate(st.st_mtime) h['Content-type'] = self._content_type if self._disposition: h['Content-disposition'] = '%s; filename="%s"' % \ (self._disposition, self.name) if req.protocol >= (1, 1): h['Accept-ranges'] = 'bytes' if 'range' not in req.headers: # Send the whole response body h['Content-length'] = str(content_length) else: ranges = get_byte_ranges(req.headers['Range'], content_length) if ranges == []: # Request range not satisfiable r.status = 416 r.headers['Content-range'] = 'bytes */%s' % content_length r.headers['Content-length'] = 0 r.body = [''] elif ranges: # Partial content status r.status = 206 if len(ranges) == 1: # Single part setup_single_part_response(r, ranges[0], content_length) else: # Multipart setup_multi_part_response(r, ranges, content_length, self._content_type) # Recalculate content length s = 0 for ra in ranges: s += ra[1] - ra[0] + 1 h['Content-length'] = str(s) else: # Lower protocols do not support ranges, whole body h['Content-length'] = str(content_length) if not response: # Normal request, not redirected. When redirected, who respond()s is # the caller. r._respond() return r.body
log.debug("Received M-Search command from %s:%s", host, port) self._discovery_request(headers, (host, port)) elif cmd[0] == "NOTIFY" and cmd[1] == "*": log.debug("NOTIFY receive_notify: %s", self.receive_notify) if not self.receive_notify: # Ignore notify log.debug( "Received NOTIFY command from %s:%s (ignored " "because of SSDPServer.receive_notify is False)", host, port, ) return # SSDP presence self._notify_received(headers, (host, port)) else: log.warning("Received unknown SSDP command %s with headers %s " "from %s:%s", cmd, str(headers), host, port) def _discovery_request(self, headers, (host, port)): """ Processes discovery requests and responds accordingly. @param headers: discovery headers @param host: discovery source host @param port: discovery source port @type headers: dictionary @type host: string @type port integer """ right_key = 0 # Do we know about this service?
and headers.has_key("content-type") and headers["content-type"] == 'text/xml; charset="utf-8"' and headers.has_key("nt") and headers["nt"] == "upnp:event" and headers.has_key("nts") and headers["nts"] == "upnp:propchange" and headers.has_key("host") and headers.has_key("usn") and headers.has_key("svcid") and headers.has_key("seq") and headers.has_key("lvl") and headers.has_key("bootid.upnp.org") and headers.has_key("content-length") ): 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
# and headers['man'] == '"ssdp:discover"': # SSDP discovery log.debug('Received M-Search command from %s:%s', host, port) self._discovery_request(headers, (host, port)) elif cmd[0] == 'NOTIFY' and cmd[1] == '*': log.debug("NOTIFY receive_notify: %s", self.receive_notify) if not self.receive_notify: # Ignore notify log.debug('Received NOTIFY command from %s:%s (ignored '\ 'because of SSDPServer.receive_notify is False)', host, port) return # SSDP presence self._notify_received(headers, (host, port)) else: log.warning('Received unknown SSDP command %s with headers %s '\ 'from %s:%s', cmd, str(headers), host, port) def _discovery_request(self, headers, (host, port)): """ Processes discovery requests and responds accordingly. @param headers: discovery headers @param host: discovery source host @param port: discovery source port @type headers: dictionary @type host: string @type port integer """ right_key = 0 # Do we know about this service?