Package brisa :: Package upnp :: Package control_point :: Module msearch
[hide private]
[frames] | no frames]

Source Code for Module brisa.upnp.control_point.msearch

  1  # Licensed under the MIT license 
  2  # http://opensource.org/licenses/mit-license.php or see LICENSE file. 
  3  # 
  4  # Copyright (C) 2006 Fluendo, S.A. (www.fluendo.com). 
  5  # Copyright 2006, Frank Scholz <coherence@beebits.net> 
  6  # Copyright 2007-2008 Brisa Team <brisa-develop@garage.maemo.org> 
  7   
  8  """ Contains the MSearch class which can search for devices. 
  9  """ 
 10   
 11  from brisa.core import log 
 12  from brisa.core.network import parse_http_response 
 13  from brisa.core.network_senders import UDPTransport 
 14  from brisa.core.network_listeners import UDPListener 
 15  from brisa.utils.looping_call import LoopingCall 
 16  from brisa.upnp.upnp_defaults import UPnPDefaults 
 17   
 18   
 19  DEFAULT_SEARCH_TIME = UPnPDefaults.MSEARCH_DEFAULT_SEARCH_TIME 
 20  DEFAULT_SEARCH_TYPE = UPnPDefaults.MSEARCH_DEFAULT_SEARCH_TYPE 
 21   
 22   
23 -class MSearch(object):
24 """ Represents a MSearch. Contains some control functions for starting and 25 stopping the search. While running, search will be repeated in regular 26 intervals specified at construction or passed to the start() method. 27 """ 28 29 msg_already_started = 'tried to start() MSearch when already started' 30 msg_already_stopped = 'tried to stop() MSearch when already stopped' 31
32 - def __init__(self, ssdp, start=True, interval=DEFAULT_SEARCH_TIME, 33 ssdp_addr='239.255.255.250', ssdp_port=1900):
34 """ Constructor for the MSearch class. 35 36 @param ssdp: ssdp server instance that will receive new device events 37 and subscriptions 38 @param start: if True starts the search when constructed 39 @param interval: interval between searchs 40 @param ssdp_addr: ssdp address for listening (UDP) 41 @param ssdp_port: ssdp port for listening (UDP) 42 43 @type ssdp: SSDPServer 44 @type start: boolean 45 @type interval: float 46 @type ssdp_addr: string 47 @type ssdp_port integer 48 """ 49 self.ssdp = ssdp 50 self.ssdp_addr = ssdp_addr 51 self.ssdp_port = ssdp_port 52 self.search_type = DEFAULT_SEARCH_TYPE 53 self.udp_transport = UDPTransport() 54 self.listen_udp = UDPListener(ssdp_addr, ssdp_port, 55 data_callback=self._datagram_received, 56 shared_socket=self.udp_transport.socket) 57 self.loopcall = LoopingCall(self.double_discover) 58 if start: 59 self.start(interval)
60
61 - def is_running(self):
62 """ Returns True if the search is running (it's being repeated in the 63 interval given). 64 65 @rtype: boolean 66 """ 67 return self.loopcall.is_running()
68
69 - def start(self, interval=DEFAULT_SEARCH_TIME, 70 search_type=DEFAULT_SEARCH_TYPE):
71 """ Starts the search. 72 73 @param interval: interval between searchs. Default is 600.0 seconds 74 @param search_type: type of the search, default is "ssdp:all" 75 76 @type interval: float 77 @type search_type: string 78 """ 79 if not self.is_running(): 80 self.search_type = search_type 81 self.listen_udp.start() 82 self.loopcall.start(interval, now=True) 83 log.debug('MSearch started') 84 else: 85 log.warning(self.msg_already_started)
86
87 - def stop(self):
88 """ Stops the search. 89 """ 90 if self.is_running(): 91 log.debug('MSearch stopped') 92 self.listen_udp.stop() 93 self.loopcall.stop() 94 else: 95 log.warning(self.msg_already_stopped)
96
97 - def destroy(self):
98 """ Destroys and quits MSearch. 99 """ 100 if self.is_running(): 101 self.stop() 102 self.listen_udp.destroy() 103 self.loopcall.destroy() 104 self._cleanup()
105
106 - def double_discover(self, search_type=DEFAULT_SEARCH_TYPE):
107 """ Sends a MSearch imediatelly. Each call to this method will yield a 108 MSearch message, that is, it won't repeat automatically. 109 """ 110 self.discover(search_type) 111 self.discover(search_type)
112
113 - def discover(self, type="ssdp:all"):
114 """ Mounts and sends the discover message (MSearch). 115 116 @param type: search type 117 @type type: string 118 """ 119 req = ['M-SEARCH * HTTP/1.1', 120 'HOST: %s:%d' % (self.ssdp_addr, self.ssdp_port), 121 'MAN: "ssdp:discover"', 122 'MX: 5', 123 'ST: ' + type, '', ''] 124 req = '\r\n'.join(req) 125 self.udp_transport.send_data(req, self.ssdp_addr, self.ssdp_port)
126
127 - def _datagram_received(self, data, (host, port)):
128 """ Callback for the UDPListener when messages arrive. 129 130 @param data: raw data received 131 @param host: host where data came from 132 @param port: port where data came from 133 134 @type data: string 135 @type host: string 136 @type port: integer 137 """ 138 cmd, headers = parse_http_response(data) 139 if cmd[0] == 'HTTP/1.1' and cmd[1] == '200': 140 if self.ssdp != None: 141 if not self.ssdp.is_known_device(headers['usn']): 142 log.debug('Received MSearch answer %s,%s from %s:%s', 143 headers['usn'], headers['st'], host, port) 144 self.ssdp._register(headers['usn'], 145 headers['st'], 146 headers['location'], 147 headers['server'], 148 headers['cache-control'])
149
150 - def _cleanup(self):
151 """ Clean up references. 152 """ 153 self.ssdp = None 154 self.listen_udp = None 155 self.loopcall = None
156