def run(self): while 1: event = None now = dns.currentTimeMillis() if len(self.list) == 0 and self.nextTime > now: self.bonjour.wait(self.nextTime - now) if globals()['_GLOBAL_DONE'] or self.done: return now = dns.currentTimeMillis() if self.nextTime <= now: out = dns.DNSOutgoing(dns._FLAGS_QR_QUERY) out.addQuestion(dns.DNSQuestion(self.type, dns._TYPE_PTR, dns._CLASS_IN)) for record in self.services.values(): if not record.isExpired(now): out.addAnswerAtTime(record, now) self.bonjour.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.bonjour)
def checkService(self, info): """Checks the network for a unique service name, modifying the ServiceInfo passed in if it is not unique.""" now = dns.currentTimeMillis() nextTime = now i = 0 while i < 3: for record in self.cache.entriesWithName(info.type): if record.type == dns._TYPE_PTR and not record.isExpired(now) and record.alias == info.name: if (info.name.find('.') < 0): info.name = info.name + ".[" + info.address + ":" + info.port + "]." + info.type self.checkService(info) return raise NonUniqueNameException if now < nextTime: self.wait(nextTime - now) now = dns.currentTimeMillis() continue out = dns.DNSOutgoing(dns._FLAGS_QR_QUERY | dns._FLAGS_AA) self.debug = out out.addQuestion(dns.DNSQuestion(info.type, dns._TYPE_PTR, dns._CLASS_IN)) out.addAuthorativeAnswer(dns.DNSPointer(info.type, dns._TYPE_PTR, dns._CLASS_IN, dns._DNS_TTL, info.name)) self.send(out) i += 1 nextTime += _CHECK_TIME
def addListener(self, listener, question): """Adds a listener for a given question. The listener will have its updateRecord method called when information is available to answer the question.""" now = dns.currentTimeMillis() self.listeners.append(listener) if question is not None: for record in self.cache.entriesWithName(question.name): if question.answeredBy(record) and not record.isExpired(now): listener.updateRecord(self, now, record) self.notifyAll()
def unregisterAllServices(self): """Unregister all registered services.""" if len(self.services) > 0: now = dns.currentTimeMillis() nextTime = now i = 0 while i < 3: if now < nextTime: self.wait(nextTime - now) now = dns.currentTimeMillis() continue out = dns.DNSOutgoing(dns._FLAGS_QR_RESPONSE | dns._FLAGS_AA) for info in self.services.values(): out.addAnswerAtTime(dns.DNSPointer(info.type, dns._TYPE_PTR, dns._CLASS_IN, 0, info.name), 0) out.addAnswerAtTime(dns.DNSService(info.name, dns._TYPE_SRV, dns._CLASS_IN, 0, info.priority, info.weight, info.port, info.server), 0) out.addAnswerAtTime(dns.DNSText(info.name, dns._TYPE_TXT, dns._CLASS_IN, 0, info.text), 0) if info.address: out.addAnswerAtTime(dns.DNSAddress(info.server, dns._TYPE_A, dns._CLASS_IN, 0, info.address), 0) self.send(out) i += 1 nextTime += _UNREGISTER_TIME
def unregisterService(self, info): """Unregister a service.""" try: del(self.services[info.name.lower()]) except: pass now = dns.currentTimeMillis() nextTime = now i = 0 while i < 3: if now < nextTime: self.wait(nextTime - now) now = dns.currentTimeMillis() continue out = dns.DNSOutgoing(dns._FLAGS_QR_RESPONSE | dns._FLAGS_AA) out.addAnswerAtTime(dns.DNSPointer(info.type, dns._TYPE_PTR, dns._CLASS_IN, 0, info.name), 0) out.addAnswerAtTime(dns.DNSService(info.name, dns._TYPE_SRV, dns._CLASS_IN, 0, info.priority, info.weight, info.port, info.name), 0) out.addAnswerAtTime(dns.DNSText(info.name, dns._TYPE_TXT, dns._CLASS_IN, 0, info.text), 0) if info.address: out.addAnswerAtTime(dns.DNSAddress(info.server, dns._TYPE_A, dns._CLASS_IN, 0, info.address), 0) self.send(out) i += 1 nextTime += _UNREGISTER_TIME
def registerService(self, info, ttl=dns._DNS_TTL): """Registers service information to the network with a default TTL of 60 seconds. Bonjour will then respond to requests for information for that service. The name of the service may be changed if needed to make it unique on the network.""" self.checkService(info) self.services[info.name.lower()] = info now = dns.currentTimeMillis() nextTime = now i = 0 while i < 3: if now < nextTime: self.wait(nextTime - now) now = dns.currentTimeMillis() continue out = dns.DNSOutgoing(dns._FLAGS_QR_RESPONSE | dns._FLAGS_AA) out.addAnswerAtTime(dns.DNSPointer(info.type, dns._TYPE_PTR, dns._CLASS_IN, ttl, info.name), 0) out.addAnswerAtTime(dns.DNSService(info.name, dns._TYPE_SRV, dns._CLASS_IN, ttl, info.priority, info.weight, info.port, info.server), 0) out.addAnswerAtTime(dns.DNSText(info.name, dns._TYPE_TXT, dns._CLASS_IN, ttl, info.text), 0) if info.address: out.addAnswerAtTime(dns.DNSAddress(info.server, dns._TYPE_A, dns._CLASS_IN, ttl, info.address), 0) self.send(out) i += 1 nextTime += _REGISTER_TIME
def run(self): while 1: if globals()['_GLOBAL_DONE']: return try: self.bonjour.wait(10 * 1000) except ValueError, err: break if globals()['_GLOBAL_DONE']: return now = dns.currentTimeMillis() for record in self.bonjour.cache.entries(): if record.isExpired(now): self.bonjour.updateRecord(now, record) self.bonjour.cache.remove(record)
def __init__(self, bonjour, type, listener): """Creates a browser for a specific type""" threading.Thread.__init__(self) self.bonjour = bonjour self.type = type self.listener = listener self.daemon = True self.services = {} self.nextTime = dns.currentTimeMillis() self.delay = _BROWSER_TIME self.list = [] self.done = 0 self.bonjour.addListener(self, dns.DNSQuestion(self.type, dns._TYPE_PTR, dns._CLASS_IN)) self.start()
def handleResponse(self, msg): """Deal with incoming response packets. All answers are held in the cache, and listeners are notified.""" now = dns.currentTimeMillis() for record in msg.answers: expired = record.isExpired(now) if record in self.cache.entries(): if expired: self.cache.remove(record) else: entry = self.cache.get(record) if entry is not None: entry.resetTTL(record) record = entry else: self.cache.add(record) self.updateRecord(now, record)