⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zeroconf.py

📁 bittorrent source by python. please enjoy
💻 PY
📖 第 1 页 / 共 4 页
字号:
            list = self.cache[entry.key] = []        list.append(entry)    def remove(self, entry):        """Removes an entry"""        try:            list = self.cache[entry.key]            list.remove(entry)        except:            pass    def get(self, entry):        """Gets an entry by key.  Will return None if there is no        matching entry."""        try:            list = self.cache[entry.key]            return list[list.index(entry)]        except:            return None    def getByDetails(self, name, type, clazz):        """Gets an entry by details.  Will return None if there is        no matching entry."""        entry = DNSEntry(name, type, clazz)        return self.get(entry)    def entriesWithName(self, name):        """Returns a list of entries whose key matches the name."""        try:            return self.cache[name]        except:            return []    def entries(self):        """Returns a list of all entries"""        def add(x, y): return x+y        try:            return reduce(add, self.cache.values())        except:            return []class Engine(threading.Thread):    """An engine wraps read access to sockets, allowing objects that    need to receive data from sockets to be called back when the    sockets are ready.    A reader needs a handle_read() method, which is called when the socket    it is interested in is ready for reading.    Writers are not implemented here, because we only send short    packets.    """    def __init__(self, zeroconf):        threading.Thread.__init__(self)        self.setDaemon(True)   # Added by David Harrison        self.zeroconf = zeroconf        self.readers = {} # maps socket to reader        self.timeout = 5        self.condition = threading.Condition()        self.start()    def run(self):        while not globals()['_GLOBAL_DONE']:            rs = self.getReaders()            if len(rs) == 0:                # No sockets to manage, but we wait for the timeout                # or addition of a socket                #                self.condition.acquire()                self.condition.wait(self.timeout)                self.condition.release()            else:                try:                    rr, wr, er = select.select(rs, [], [], self.timeout)                    for socket in rr:                        try:                            self.readers[socket].handle_read()                        except socket.error, e:                            if e == socket.EBADF:                                ## what should I do here?                                # data, (addr, port) = self.zeroconf.socket.recvfrom(_MAX_MSG_ABSOLUTE)                                # File "C:\Python24\lib\socket.py", line 144, in _dummy                                # raise error(EBADF, 'Bad file descriptor')                                # error: (9, 'Bad file descriptor')                                pass                            else:                                traceback.print_exc()                        except:                            traceback.print_exc()                except:                    pass    def getReaders(self):        result = []        self.condition.acquire()        result = self.readers.keys()        self.condition.release()        return result        def addReader(self, reader, socket):        self.condition.acquire()        self.readers[socket] = reader        self.condition.notify()        self.condition.release()    def delReader(self, socket):        self.condition.acquire()        del(self.readers[socket])        self.condition.notify()        self.condition.release()    def notify(self):        self.condition.acquire()        self.condition.notify()        self.condition.release()class Listener(object):    """A Listener is used by this module to listen on the multicast    group to which DNS messages are sent, allowing the implementation    to cache information as it arrives.    It requires registration with an Engine object in order to have    the read() method called when a socket is availble for reading."""        def __init__(self, zeroconf):        self.zeroconf = zeroconf        self.zeroconf.engine.addReader(self, self.zeroconf.socket)    def handle_read(self):        data, (addr, port) = self.zeroconf.socket.recvfrom(_MAX_MSG_ABSOLUTE)        self.data = data        msg = DNSIncoming(data)        if msg.isQuery():            # Always multicast responses            #            if port == _MDNS_PORT:                self.zeroconf.handleQuery(msg, _MDNS_ADDR, _MDNS_PORT)            # If it's not a multicast query, reply via unicast            # and multicast            #            elif port == _DNS_PORT:                self.zeroconf.handleQuery(msg, addr, port)                self.zeroconf.handleQuery(msg, _MDNS_ADDR, _MDNS_PORT)        else:            self.zeroconf.handleResponse(msg)class Reaper(threading.Thread):    """A Reaper is used by this module to remove cache entries that    have expired."""        def __init__(self, zeroconf):        threading.Thread.__init__(self)        self.setDaemon(True)   # Added by David Harrison        self.zeroconf = zeroconf        self.start()    def run(self):        while 1:            self.zeroconf.wait(10 * 1000)            if globals()['_GLOBAL_DONE']:                return            now = currentTimeMillis()            for record in self.zeroconf.cache.entries():                if record.isExpired(now):                    self.zeroconf.updateRecord(now, record)                    self.zeroconf.cache.remove(record)class ServiceBrowser(threading.Thread):    """Used to browse for a service of a specific type.    The listener object will have its addService() and    removeService() methods called when this browser    discovers changes in the services availability."""        def __init__(self, zeroconf, type, listener):        """Creates a browser for a specific type"""        threading.Thread.__init__(self)        self.setDaemon(True)  # Added by David Harrison        self.zeroconf = zeroconf        self.type = type        self.listener = listener        self.services = {}        self.nextTime = currentTimeMillis()        self.delay = _BROWSER_TIME        self.list = []                self.done = 0        self.zeroconf.addListener(self, DNSQuestion(self.type, _TYPE_PTR, _CLASS_IN))        self.start()    def updateRecord(self, zeroconf, now, record):        """Callback invoked by Zeroconf when new information arrives.        Updates information required by browser in the Zeroconf cache."""        if record.type == _TYPE_PTR and record.name == self.type:            expired = record.isExpired(now)            try:                oldrecord = self.services[record.alias.lower()]                if not expired:                    oldrecord.resetTTL(record)                else:                    del(self.services[record.alias.lower()])                    callback = lambda x: self.listener.removeService(x, self.type, record.alias)                    self.list.append(callback)                    return            except:                if not expired:                    self.services[record.alias.lower()] = record                    callback = lambda x: self.listener.addService(x, self.type, record.alias)                    self.list.append(callback)            expires = record.getExpirationTime(75)            if expires < self.nextTime:                self.nextTime = expires    def cancel(self):        self.done = 1        self.zeroconf.notifyAll()    def run(self):        while 1:            event = None            now = currentTimeMillis()            if len(self.list) == 0 and self.nextTime > now:                self.zeroconf.wait(self.nextTime - now)            if globals()['_GLOBAL_DONE'] or self.done:                return            now = currentTimeMillis()            if self.nextTime <= now:                out = DNSOutgoing(_FLAGS_QR_QUERY)                out.addQuestion(DNSQuestion(self.type, _TYPE_PTR, _CLASS_IN))                for record in self.services.values():                    if not record.isExpired(now):                        out.addAnswerAtTime(record, now)                self.zeroconf.send(out)                self.nextTime = now + self.delay                self.delay = min(20 * 1000, self.delay * 2)            if len(self.list) > 0:                event = self.list.pop(0)            if event is not None:                event(self.zeroconf)                class ServiceInfo(object):    """Service information"""        def __init__(self, type, name, address=None, port=None, weight=0, priority=0, properties=None, server=None):        """Create a service description.        type: fully qualified service type name        name: fully qualified service name        address: IP address as unsigned short, network byte order        port: port that the service runs on        weight: weight of the service        priority: priority of the service        properties: dictionary of properties (or a string holding the bytes for the text field)        server: fully qualified name for service host (defaults to name)"""        if not name.endswith(type):            raise BadTypeInNameException        self.type = type        self.name = name        self.address = address        self.port = port        self.weight = weight        self.priority = priority        if server:            self.server = server        else:            self.server = name        self.setProperties(properties)    def setProperties(self, properties):        """Sets properties and text of this info from a dictionary"""        if isinstance(properties, dict):            self.properties = properties            list = []            result = ''            for key in properties:                value = properties[key]                if value is None:                    suffix = ''.encode('utf-8')                elif isinstance(value, str):                    suffix = value.encode('utf-8')                elif isinstance(value, int):                    if value:                        suffix = 'true'                    else:                        suffix = 'false'                else:                    suffix = ''.encode('utf-8')                list.append('='.join((key, suffix)))            for item in list:                result = ''.join((result, struct.pack('!c', chr(len(item))), item))            self.text = result        else:            self.text = properties    def setText(self, text):        """Sets properties and text given a text field"""        self.text = text        try:            result = {}            end = len(text)            index = 0            strs = []            while index < end:                length = ord(text[index])                index += 1                strs.append(text[index:index+length])                index += length                        for s in strs:                eindex = s.find('=')                if eindex == -1:                    # No equals sign at all                    key = s                    value = 0                else:                    key = s[:eindex]                    value = s[eindex+1:]                    if value == 'true':                        value = 1                    elif value == 'false' or not value:                        value = 0                # Only update non-existent properties                if key and result.get(key) == None:                    result[key] = value            self.properties = result        except:            traceback.print_exc()            self.properties = None                def getType(self):        """Type accessor"""        return self.type    def getName(self):        """Name accessor"""        if self.type is not None and self.name.endswith("." + self.type):            return self.name[:len(self.name) - len(self.type) - 1]        return self.name    def getAddress(self):        """Address accessor"""        return self.address    def getPort(self):        """Port accessor"""        return self.port    def getPriority(self):        """Pirority accessor"""        return self.priority    def getWeight(self):        """Weight accessor"""        return self.weight    def getProperties(self):        """Properties accessor"""        return self.properties    def getText(self):        """Text accessor"""        return self.text    def getServer(self):        """Server accessor"""        return self.server    def updateRecord(self, zeroconf, now, record):        """Updates service information from a DNS record"""        if record is not None and not record.isExpired(now):            if record.type == _TYPE_A:                if record.name == self.name:                    self.address = record.address            elif record.type == _TYPE_SRV:                if record.name == self.name:                    self.server = record.server                    self.port = record.port                    self.weight = record.weight                    self.priority = record.priority                    self.address = None

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -