Example #1
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
Example #2
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")
Example #3
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
Example #4
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
Example #5
0
 def serviceAnnouncement( cls, info, ttl=dns._DNS_TTL ):
     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)
     return out
Example #6
0
    def handleQuery(self, msg, addr, port):
        """Deal with incoming query packets.  Provides a response if
        possible."""
        out = None

        # Support unicast client responses
        #
        if port != dns._MDNS_PORT:
            out = dns.DNSOutgoing(dns._FLAGS_QR_RESPONSE | dns._FLAGS_AA, 0)
            for question in msg.questions:
                out.addQuestion(question)
        log.debug( 'Questions...')
        for question in msg.questions:
            log.debug( 'Question: %s', question )
            if question.type == dns._TYPE_PTR:
                for service in list(self.services.values()):
                    if question.name == service.type:
                        log.info( 'Service query found %s', service.name )
                        if out is None:
                            out = dns.DNSOutgoing(dns._FLAGS_QR_RESPONSE | dns._FLAGS_AA)
                        out.addAnswer(msg, dns.DNSPointer(service.type, dns._TYPE_PTR, dns._CLASS_IN, dns._DNS_TTL, service.name))
                        # devices such as AAstra phones will not re-query to
                        # resolve the pointer, they expect the final IP to show up
                        # in the response
                        out.addAdditionalAnswer(dns.DNSText(service.name, dns._TYPE_TXT, dns._CLASS_IN | dns._CLASS_UNIQUE, dns._DNS_TTL, service.text))
                        out.addAdditionalAnswer(dns.DNSService(service.name, dns._TYPE_SRV, dns._CLASS_IN | dns._CLASS_UNIQUE, dns._DNS_TTL, service.priority, service.weight, service.port, service.server))
                        out.addAdditionalAnswer(dns.DNSAddress(service.server, dns._TYPE_A, dns._CLASS_IN | dns._CLASS_UNIQUE, dns._DNS_TTL, service.address))
            else:
                try:
                    if out is None:
                        out = dns.DNSOutgoing(dns._FLAGS_QR_RESPONSE | dns._FLAGS_AA)

                    # Answer A record queries for any service addresses we know
                    if question.type == dns._TYPE_A or question.type == dns._TYPE_ANY:
                        for service in list(self.services.values()):
                            if service.server == question.name.lower():
                                out.addAnswer(msg, DNSAddress(question.name, dns._TYPE_A, dns._CLASS_IN | dns._CLASS_UNIQUE, dns._DNS_TTL, service.address))


                    service = self.services.get(question.name.lower(), None)
                    if not service: continue

                    if question.type == dns._TYPE_SRV or question.type == dns._TYPE_ANY:
                        out.addAnswer(msg, dns.DNSService(question.name, dns._TYPE_SRV, dns._CLASS_IN | dns._CLASS_UNIQUE, dns._DNS_TTL, service.priority, service.weight, service.port, service.server))
                    if question.type == dns._TYPE_TXT or question.type == dns._TYPE_ANY:
                        out.addAnswer(msg, dns.DNSText(question.name, dns._TYPE_TXT, dns._CLASS_IN | dns._CLASS_UNIQUE, dns._DNS_TTL, service.text))
                    if question.type == dns._TYPE_SRV:
                        out.addAdditionalAnswer(dns.DNSAddress(service.server, dns._TYPE_A, dns._CLASS_IN | dns._CLASS_UNIQUE, dns._DNS_TTL, service.address))
                except Exception as err:
                    log.error(
                        'Error handling query: %s',traceback.format_exc()
                    )

        if out is not None and out.answers:
            out.id = msg.id
            self.send(out, addr, port)
        else:
            log.debug( 'No answer for %s', [q for q in msg.questions] )
Example #7
0
 def responses(self, question, msg, out):
     """Adds all responses to out which match the given question
     
     Note that the incoming query may suppress our responses 
     by having cache times higher than our records.  That is,
     out.answers may be null even if we have the records that 
     match the query.
     """
     log.debug('Question: %s', question)
     for service in self.services.values():
         if question.type == dns._TYPE_PTR:
             if question.name.lower() in (service.type.lower(),
                                          service.name.lower()):
                 log.debug('Service query found %s', service.name)
                 out.addAnswer(
                     msg,
                     dns.DNSPointer(question.name, dns._TYPE_PTR,
                                    dns._CLASS_IN, dns._DNS_TTL,
                                    service.name))
                 # devices such as AAstra phones will not re-query to
                 # resolve the pointer, they expect the final IP to show up
                 # in the response
                 out.addAdditionalAnswer(
                     dns.DNSText(service.name, dns._TYPE_TXT,
                                 dns._CLASS_IN | dns._CLASS_UNIQUE,
                                 dns._DNS_TTL, service.text))
                 out.addAdditionalAnswer(
                     dns.DNSService(service.name, dns._TYPE_SRV,
                                    dns._CLASS_IN | dns._CLASS_UNIQUE,
                                    dns._DNS_TTL, service.priority,
                                    service.weight, service.port,
                                    service.server))
                 out.addAdditionalAnswer(
                     dns.DNSAddress(service.server, dns._TYPE_A,
                                    dns._CLASS_IN | dns._CLASS_UNIQUE,
                                    dns._DNS_TTL, service.address))
         else:
             if question.type in (dns._TYPE_A, ):
                 if service.server.lower() == question.name.lower():
                     out.addAnswer(
                         msg,
                         dns.DNSAddress(question.name, dns._TYPE_A,
                                        dns._CLASS_IN | dns._CLASS_UNIQUE,
                                        dns._DNS_TTL, service.address))
             if question.type in (dns._TYPE_SRV, dns._TYPE_ANY):
                 if question.name.lower() in (service.name.lower(),
                                              service.server.lower(),
                                              service.type.lower()):
                     out.addAnswer(
                         msg,
                         dns.DNSService(question.name, dns._TYPE_SRV,
                                        dns._CLASS_IN | dns._CLASS_UNIQUE,
                                        dns._DNS_TTL, service.priority,
                                        service.weight, service.port,
                                        service.server))
             if question.type in (dns._TYPE_TXT, dns._TYPE_ANY):
                 if question.name.lower() in (service.name.lower(),
                                              service.server.lower(),
                                              service.type.lower()):
                     out.addAnswer(
                         msg,
                         dns.DNSText(question.name, dns._TYPE_TXT,
                                     dns._CLASS_IN | dns._CLASS_UNIQUE,
                                     dns._DNS_TTL, service.text))
             if question.type in (dns._TYPE_SRV, dns._TYPE_ANY):
                 # srv queries need the address for aastra-style single query
                 if question.name.lower() in (service.name.lower(),
                                              service.server.lower(),
                                              service.type.lower()):
                     out.addAdditionalAnswer(
                         dns.DNSAddress(service.server, dns._TYPE_A,
                                        dns._CLASS_IN | dns._CLASS_UNIQUE,
                                        dns._DNS_TTL, service.address))