Beispiel #1
0
    def run(self):
        while 1:
            event = None
            now = dns.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 = 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 list(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)
Beispiel #2
0
 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
Beispiel #3
0
    def registerService(self, info, ttl=dns._DNS_TTL):
        """Registers service information to the network with a default TTL
        of 60 seconds.  Zeroconf 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."""
        #print "REGISTERING SERVICE!"
        #log.debug(">>",self.services[info.name.lower()])
    
        #import pdb
        #pdb.set_trace()
        
        self.checkService(info)
        self.services[info.name.lower()] = info
        log.debug(">>",self.services[info.name.lower()])
        
        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
            print("registerService end")
Beispiel #4
0
 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
Beispiel #5
0
 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
Beispiel #6
0
    def unregisterService(self, info):
        """Unregister a service."""
        try:
            del(self.services[info.name.lower()])

            self.servicetypes[info.type] -= 1
            if self.servicetypes[info.type] <= 0:
                del self.servicetypes[info.type]
        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
Beispiel #7
0
 def send(self, out, addr=dns._MDNS_ADDR, port=dns._MDNS_PORT):
     """Sends an outgoing packet.
     
     Note: this method is instrumented to provide low-level 
     prevention of packet floods by throttling same-message 
     sending to once per _MINIMUM_REPEAT_TIME ms.  That will 
     fail for a "regular" DNS server, which should also use 
     the addr/port combo...
     """
     current = dns.currentTimeMillis()
     log.info('%s messages in suppression_queue',
              len(self.suppression_queue))
     while self.suppression_queue and self.suppression_queue[0][0] < current:
         log.debug('Removing...')
         self.suppression_queue.pop(0)
     packet = out.packet()
     sent = False
     for i, (expire, old_packet) in enumerate(self.suppression_queue[:]):
         if old_packet == packet:
             log.debug('Dropping to prevent flood')
             sent = True
     if not sent:
         try:
             sent = self.socket.sendto(packet, 0, (addr, port))
         except:
             # Ignore this, it may be a temporary loss of network connection
             pass
     self.suppression_queue.append((current + _MINIMUM_REPEAT_TIME, packet))
     return sent
Beispiel #8
0
 def send(self, out, addr = dns._MDNS_ADDR, port = dns._MDNS_PORT):
     """Sends an outgoing packet.
     
     Note: this method is instrumented to provide low-level 
     prevention of packet floods by throttling same-message 
     sending to once per _MINIMUM_REPEAT_TIME ms.  That will 
     fail for a "regular" DNS server, which should also use 
     the addr/port combo...
     """
     current = dns.currentTimeMillis()
     log.info( '%s messages in suppression_queue', len(self.suppression_queue))
     while self.suppression_queue and self.suppression_queue[0][0] < current:
         log.debug( 'Removing...' )
         self.suppression_queue.pop(0)
     packet = out.packet()
     sent = False
     for i,(expire,old_packet) in enumerate(self.suppression_queue[:]):
         if old_packet == packet:
             log.debug( 'Dropping to prevent flood' )
             sent = True
     if not sent:
         try:
             sent = self.socket.sendto(packet, 0, (addr, port))
         except:
             # Ignore this, it may be a temporary loss of network connection
             pass
     self.suppression_queue.append(
         (current + _MINIMUM_REPEAT_TIME, packet )
     )
     return sent
Beispiel #9
0
 def registerService(self, info, ttl=dns._DNS_TTL):
     """Registers service information to the network with a default TTL
     of 60 seconds.  Zeroconf 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 = self.serviceAnnouncement(info, ttl)
         self.send(out)
         i += 1
         nextTime += _REGISTER_TIME
Beispiel #10
0
 def registerService(self, info, ttl=dns._DNS_TTL):
     """Registers service information to the network with a default TTL
     of 60 seconds.  Zeroconf 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 = self.serviceAnnouncement( info, ttl )
         self.send(out)
         i += 1
         nextTime += _REGISTER_TIME
Beispiel #11
0
 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()
Beispiel #12
0
 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 list(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
Beispiel #13
0
 def run(self):
     while 1:
         if globals()['_GLOBAL_DONE']:
             return
         try:
             self.zeroconf.wait(10 * 1000)
         except ValueError as err:
             break
         if globals()['_GLOBAL_DONE']:
             return
         now = dns.currentTimeMillis()
         for record in self.zeroconf.cache.entries():
             if record.isExpired(now):
                 self.zeroconf.updateRecord(now, record)
                 self.zeroconf.cache.remove(record)
Beispiel #14
0
    def __init__(self, zeroconf, type, listener):
        """Creates a browser for a specific type"""
        threading.Thread.__init__(self)
        self.zeroconf = zeroconf
        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.zeroconf.addListener(self, dns.DNSQuestion(self.type, dns._TYPE_PTR, dns._CLASS_IN))
        self.start()
Beispiel #15
0
    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)