python-zeroconf

changeset 1:ed4f4e7ad09b

convert tabs to spaces
author Alexander Solovyov <piranha@piranha.org.ua>
date Mon Mar 23 15:55:51 2009 +0200
parents 72b67d13900b
children d9eeb67de097
files Zeroconf.py
diffstat 1 files changed, 1204 insertions(+), 1204 deletions(-) [+]
line diff
     1.1 --- a/Zeroconf.py	Mon Mar 23 15:02:44 2009 +0200
     1.2 +++ b/Zeroconf.py	Mon Mar 23 15:55:51 2009 +0200
     1.3 @@ -23,29 +23,29 @@
     1.4  """
     1.5  
     1.6  """0.12 update - allow selection of binding interface
     1.7 -		 typo fix - Thanks A. M. Kuchlingi
     1.8 -		 removed all use of word 'Rendezvous' - this is an API change"""
     1.9 +         typo fix - Thanks A. M. Kuchlingi
    1.10 +         removed all use of word 'Rendezvous' - this is an API change"""
    1.11  
    1.12  """0.11 update - correction to comments for addListener method
    1.13                   support for new record types seen from OS X
    1.14 -				  - IPv6 address
    1.15 -				  - hostinfo
    1.16 -				 ignore unknown DNS record types
    1.17 -				 fixes to name decoding
    1.18 -				 works alongside other processes using port 5353 (e.g. on Mac OS X)
    1.19 -				 tested against Mac OS X 10.3.2's mDNSResponder
    1.20 -				 corrections to removal of list entries for service browser"""
    1.21 +                  - IPv6 address
    1.22 +                  - hostinfo
    1.23 +                 ignore unknown DNS record types
    1.24 +                 fixes to name decoding
    1.25 +                 works alongside other processes using port 5353 (e.g. on Mac OS X)
    1.26 +                 tested against Mac OS X 10.3.2's mDNSResponder
    1.27 +                 corrections to removal of list entries for service browser"""
    1.28  
    1.29  """0.10 update - Jonathon Paisley contributed these corrections:
    1.30                   always multicast replies, even when query is unicast
    1.31 -				 correct a pointer encoding problem
    1.32 -				 can now write records in any order
    1.33 -				 traceback shown on failure
    1.34 -				 better TXT record parsing
    1.35 -				 server is now separate from name
    1.36 -				 can cancel a service browser
    1.37 +                 correct a pointer encoding problem
    1.38 +                 can now write records in any order
    1.39 +                 traceback shown on failure
    1.40 +                 better TXT record parsing
    1.41 +                 server is now separate from name
    1.42 +                 can cancel a service browser
    1.43  
    1.44 -				 modified some unit tests to accommodate these changes"""
    1.45 +                 modified some unit tests to accommodate these changes"""
    1.46  
    1.47  """0.09 update - remove all records on service unregistration
    1.48                   fix DOS security problem with readName"""
    1.49 @@ -54,25 +54,25 @@
    1.50  
    1.51  """0.07 update - faster shutdown on engine
    1.52                   pointer encoding of outgoing names
    1.53 -				 ServiceBrowser now works
    1.54 -				 new unit tests"""
    1.55 +                 ServiceBrowser now works
    1.56 +                 new unit tests"""
    1.57  
    1.58  """0.06 update - small improvements with unit tests
    1.59                   added defined exception types
    1.60 -				 new style objects
    1.61 -				 fixed hostname/interface problem
    1.62 -				 fixed socket timeout problem
    1.63 -				 fixed addServiceListener() typo bug
    1.64 -				 using select() for socket reads
    1.65 -				 tested on Debian unstable with Python 2.2.2"""
    1.66 +                 new style objects
    1.67 +                 fixed hostname/interface problem
    1.68 +                 fixed socket timeout problem
    1.69 +                 fixed addServiceListener() typo bug
    1.70 +                 using select() for socket reads
    1.71 +                 tested on Debian unstable with Python 2.2.2"""
    1.72  
    1.73  """0.05 update - ensure case insensitivty on domain names
    1.74                   support for unicast DNS queries"""
    1.75  
    1.76  """0.04 update - added some unit tests
    1.77                   added __ne__ adjuncts where required
    1.78 -				 ensure names end in '.local.'
    1.79 -				 timeout on receiving socket for clean shutdown"""
    1.80 +                 ensure names end in '.local.'
    1.81 +                 timeout on receiving socket for clean shutdown"""
    1.82  
    1.83  __author__ = "Paul Scott-Murphy"
    1.84  __email__ = "paul at scott dash murphy dot com"
    1.85 @@ -155,1416 +155,1416 @@
    1.86  # Mapping constants to names
    1.87  
    1.88  _CLASSES = { _CLASS_IN : "in",
    1.89 -			 _CLASS_CS : "cs",
    1.90 -			 _CLASS_CH : "ch",
    1.91 -			 _CLASS_HS : "hs",
    1.92 -			 _CLASS_NONE : "none",
    1.93 -			 _CLASS_ANY : "any" }
    1.94 +             _CLASS_CS : "cs",
    1.95 +             _CLASS_CH : "ch",
    1.96 +             _CLASS_HS : "hs",
    1.97 +             _CLASS_NONE : "none",
    1.98 +             _CLASS_ANY : "any" }
    1.99  
   1.100  _TYPES = { _TYPE_A : "a",
   1.101 -		   _TYPE_NS : "ns",
   1.102 -		   _TYPE_MD : "md",
   1.103 -		   _TYPE_MF : "mf",
   1.104 -		   _TYPE_CNAME : "cname",
   1.105 -		   _TYPE_SOA : "soa",
   1.106 -		   _TYPE_MB : "mb",
   1.107 -		   _TYPE_MG : "mg",
   1.108 -		   _TYPE_MR : "mr",
   1.109 -		   _TYPE_NULL : "null",
   1.110 -		   _TYPE_WKS : "wks",
   1.111 -		   _TYPE_PTR : "ptr",
   1.112 -		   _TYPE_HINFO : "hinfo",
   1.113 -		   _TYPE_MINFO : "minfo",
   1.114 -		   _TYPE_MX : "mx",
   1.115 -		   _TYPE_TXT : "txt",
   1.116 -		   _TYPE_AAAA : "quada",
   1.117 -		   _TYPE_SRV : "srv",
   1.118 -		   _TYPE_ANY : "any" }
   1.119 +           _TYPE_NS : "ns",
   1.120 +           _TYPE_MD : "md",
   1.121 +           _TYPE_MF : "mf",
   1.122 +           _TYPE_CNAME : "cname",
   1.123 +           _TYPE_SOA : "soa",
   1.124 +           _TYPE_MB : "mb",
   1.125 +           _TYPE_MG : "mg",
   1.126 +           _TYPE_MR : "mr",
   1.127 +           _TYPE_NULL : "null",
   1.128 +           _TYPE_WKS : "wks",
   1.129 +           _TYPE_PTR : "ptr",
   1.130 +           _TYPE_HINFO : "hinfo",
   1.131 +           _TYPE_MINFO : "minfo",
   1.132 +           _TYPE_MX : "mx",
   1.133 +           _TYPE_TXT : "txt",
   1.134 +           _TYPE_AAAA : "quada",
   1.135 +           _TYPE_SRV : "srv",
   1.136 +           _TYPE_ANY : "any" }
   1.137  
   1.138  # utility functions
   1.139  
   1.140  def currentTimeMillis():
   1.141 -	"""Current system time in milliseconds"""
   1.142 -	return time.time() * 1000
   1.143 +    """Current system time in milliseconds"""
   1.144 +    return time.time() * 1000
   1.145  
   1.146  # Exceptions
   1.147  
   1.148  class NonLocalNameException(Exception):
   1.149 -	pass
   1.150 +    pass
   1.151  
   1.152  class NonUniqueNameException(Exception):
   1.153 -	pass
   1.154 +    pass
   1.155  
   1.156  class NamePartTooLongException(Exception):
   1.157 -	pass
   1.158 +    pass
   1.159  
   1.160  class AbstractMethodException(Exception):
   1.161 -	pass
   1.162 +    pass
   1.163  
   1.164  class BadTypeInNameException(Exception):
   1.165 -	pass
   1.166 +    pass
   1.167  
   1.168  # implementation classes
   1.169  
   1.170  class DNSEntry(object):
   1.171 -	"""A DNS entry"""
   1.172 +    """A DNS entry"""
   1.173  
   1.174 -	def __init__(self, name, type, clazz):
   1.175 -		self.key = string.lower(name)
   1.176 -		self.name = name
   1.177 -		self.type = type
   1.178 -		self.clazz = clazz & _CLASS_MASK
   1.179 -		self.unique = (clazz & _CLASS_UNIQUE) != 0
   1.180 +    def __init__(self, name, type, clazz):
   1.181 +        self.key = string.lower(name)
   1.182 +        self.name = name
   1.183 +        self.type = type
   1.184 +        self.clazz = clazz & _CLASS_MASK
   1.185 +        self.unique = (clazz & _CLASS_UNIQUE) != 0
   1.186  
   1.187 -	def __eq__(self, other):
   1.188 -		"""Equality test on name, type, and class"""
   1.189 -		if isinstance(other, DNSEntry):
   1.190 -			return self.name == other.name and self.type == other.type and self.clazz == other.clazz
   1.191 -		return 0
   1.192 +    def __eq__(self, other):
   1.193 +        """Equality test on name, type, and class"""
   1.194 +        if isinstance(other, DNSEntry):
   1.195 +            return self.name == other.name and self.type == other.type and self.clazz == other.clazz
   1.196 +        return 0
   1.197  
   1.198 -	def __ne__(self, other):
   1.199 -		"""Non-equality test"""
   1.200 -		return not self.__eq__(other)
   1.201 +    def __ne__(self, other):
   1.202 +        """Non-equality test"""
   1.203 +        return not self.__eq__(other)
   1.204  
   1.205 -	def getClazz(self, clazz):
   1.206 -		"""Class accessor"""
   1.207 -		try:
   1.208 -			return _CLASSES[clazz]
   1.209 -		except:
   1.210 -			return "?(%s)" % (clazz)
   1.211 +    def getClazz(self, clazz):
   1.212 +        """Class accessor"""
   1.213 +        try:
   1.214 +            return _CLASSES[clazz]
   1.215 +        except:
   1.216 +            return "?(%s)" % (clazz)
   1.217  
   1.218 -	def getType(self, type):
   1.219 -		"""Type accessor"""
   1.220 -		try:
   1.221 -			return _TYPES[type]
   1.222 -		except:
   1.223 -			return "?(%s)" % (type)
   1.224 +    def getType(self, type):
   1.225 +        """Type accessor"""
   1.226 +        try:
   1.227 +            return _TYPES[type]
   1.228 +        except:
   1.229 +            return "?(%s)" % (type)
   1.230  
   1.231 -	def toString(self, hdr, other):
   1.232 -		"""String representation with additional information"""
   1.233 -		result = "%s[%s,%s" % (hdr, self.getType(self.type), self.getClazz(self.clazz))
   1.234 -		if self.unique:
   1.235 -			result += "-unique,"
   1.236 -		else:
   1.237 -			result += ","
   1.238 -		result += self.name
   1.239 -		if other is not None:
   1.240 -			result += ",%s]" % (other)
   1.241 -		else:
   1.242 -			result += "]"
   1.243 -		return result
   1.244 +    def toString(self, hdr, other):
   1.245 +        """String representation with additional information"""
   1.246 +        result = "%s[%s,%s" % (hdr, self.getType(self.type), self.getClazz(self.clazz))
   1.247 +        if self.unique:
   1.248 +            result += "-unique,"
   1.249 +        else:
   1.250 +            result += ","
   1.251 +        result += self.name
   1.252 +        if other is not None:
   1.253 +            result += ",%s]" % (other)
   1.254 +        else:
   1.255 +            result += "]"
   1.256 +        return result
   1.257  
   1.258  class DNSQuestion(DNSEntry):
   1.259 -	"""A DNS question entry"""
   1.260 +    """A DNS question entry"""
   1.261  
   1.262 -	def __init__(self, name, type, clazz):
   1.263 -		if not name.endswith(".local."):
   1.264 -			raise NonLocalNameException
   1.265 -		DNSEntry.__init__(self, name, type, clazz)
   1.266 +    def __init__(self, name, type, clazz):
   1.267 +        if not name.endswith(".local."):
   1.268 +            raise NonLocalNameException
   1.269 +        DNSEntry.__init__(self, name, type, clazz)
   1.270  
   1.271 -	def answeredBy(self, rec):
   1.272 -		"""Returns true if the question is answered by the record"""
   1.273 -		return self.clazz == rec.clazz and (self.type == rec.type or self.type == _TYPE_ANY) and self.name == rec.name
   1.274 +    def answeredBy(self, rec):
   1.275 +        """Returns true if the question is answered by the record"""
   1.276 +        return self.clazz == rec.clazz and (self.type == rec.type or self.type == _TYPE_ANY) and self.name == rec.name
   1.277  
   1.278 -	def __repr__(self):
   1.279 -		"""String representation"""
   1.280 -		return DNSEntry.toString(self, "question", None)
   1.281 +    def __repr__(self):
   1.282 +        """String representation"""
   1.283 +        return DNSEntry.toString(self, "question", None)
   1.284  
   1.285  
   1.286  class DNSRecord(DNSEntry):
   1.287 -	"""A DNS record - like a DNS entry, but has a TTL"""
   1.288 +    """A DNS record - like a DNS entry, but has a TTL"""
   1.289  
   1.290 -	def __init__(self, name, type, clazz, ttl):
   1.291 -		DNSEntry.__init__(self, name, type, clazz)
   1.292 -		self.ttl = ttl
   1.293 -		self.created = currentTimeMillis()
   1.294 +    def __init__(self, name, type, clazz, ttl):
   1.295 +        DNSEntry.__init__(self, name, type, clazz)
   1.296 +        self.ttl = ttl
   1.297 +        self.created = currentTimeMillis()
   1.298  
   1.299 -	def __eq__(self, other):
   1.300 -		"""Tests equality as per DNSRecord"""
   1.301 -		if isinstance(other, DNSRecord):
   1.302 -			return DNSEntry.__eq__(self, other)
   1.303 -		return 0
   1.304 +    def __eq__(self, other):
   1.305 +        """Tests equality as per DNSRecord"""
   1.306 +        if isinstance(other, DNSRecord):
   1.307 +            return DNSEntry.__eq__(self, other)
   1.308 +        return 0
   1.309  
   1.310 -	def suppressedBy(self, msg):
   1.311 -		"""Returns true if any answer in a message can suffice for the
   1.312 -		information held in this record."""
   1.313 -		for record in msg.answers:
   1.314 -			if self.suppressedByAnswer(record):
   1.315 -				return 1
   1.316 -		return 0
   1.317 +    def suppressedBy(self, msg):
   1.318 +        """Returns true if any answer in a message can suffice for the
   1.319 +        information held in this record."""
   1.320 +        for record in msg.answers:
   1.321 +            if self.suppressedByAnswer(record):
   1.322 +                return 1
   1.323 +        return 0
   1.324  
   1.325 -	def suppressedByAnswer(self, other):
   1.326 -		"""Returns true if another record has same name, type and class,
   1.327 -		and if its TTL is at least half of this record's."""
   1.328 -		if self == other and other.ttl > (self.ttl / 2):
   1.329 -			return 1
   1.330 -		return 0
   1.331 +    def suppressedByAnswer(self, other):
   1.332 +        """Returns true if another record has same name, type and class,
   1.333 +        and if its TTL is at least half of this record's."""
   1.334 +        if self == other and other.ttl > (self.ttl / 2):
   1.335 +            return 1
   1.336 +        return 0
   1.337  
   1.338 -	def getExpirationTime(self, percent):
   1.339 -		"""Returns the time at which this record will have expired
   1.340 -		by a certain percentage."""
   1.341 -		return self.created + (percent * self.ttl * 10)
   1.342 +    def getExpirationTime(self, percent):
   1.343 +        """Returns the time at which this record will have expired
   1.344 +        by a certain percentage."""
   1.345 +        return self.created + (percent * self.ttl * 10)
   1.346  
   1.347 -	def getRemainingTTL(self, now):
   1.348 -		"""Returns the remaining TTL in seconds."""
   1.349 -		return max(0, (self.getExpirationTime(100) - now) / 1000)
   1.350 +    def getRemainingTTL(self, now):
   1.351 +        """Returns the remaining TTL in seconds."""
   1.352 +        return max(0, (self.getExpirationTime(100) - now) / 1000)
   1.353  
   1.354 -	def isExpired(self, now):
   1.355 -		"""Returns true if this record has expired."""
   1.356 -		return self.getExpirationTime(100) <= now
   1.357 +    def isExpired(self, now):
   1.358 +        """Returns true if this record has expired."""
   1.359 +        return self.getExpirationTime(100) <= now
   1.360  
   1.361 -	def isStale(self, now):
   1.362 -		"""Returns true if this record is at least half way expired."""
   1.363 -		return self.getExpirationTime(50) <= now
   1.364 +    def isStale(self, now):
   1.365 +        """Returns true if this record is at least half way expired."""
   1.366 +        return self.getExpirationTime(50) <= now
   1.367  
   1.368 -	def resetTTL(self, other):
   1.369 -		"""Sets this record's TTL and created time to that of
   1.370 -		another record."""
   1.371 -		self.created = other.created
   1.372 -		self.ttl = other.ttl
   1.373 +    def resetTTL(self, other):
   1.374 +        """Sets this record's TTL and created time to that of
   1.375 +        another record."""
   1.376 +        self.created = other.created
   1.377 +        self.ttl = other.ttl
   1.378  
   1.379 -	def write(self, out):
   1.380 -		"""Abstract method"""
   1.381 -		raise AbstractMethodException
   1.382 +    def write(self, out):
   1.383 +        """Abstract method"""
   1.384 +        raise AbstractMethodException
   1.385  
   1.386 -	def toString(self, other):
   1.387 -		"""String representation with addtional information"""
   1.388 -		arg = "%s/%s,%s" % (self.ttl, self.getRemainingTTL(currentTimeMillis()), other)
   1.389 -		return DNSEntry.toString(self, "record", arg)
   1.390 +    def toString(self, other):
   1.391 +        """String representation with addtional information"""
   1.392 +        arg = "%s/%s,%s" % (self.ttl, self.getRemainingTTL(currentTimeMillis()), other)
   1.393 +        return DNSEntry.toString(self, "record", arg)
   1.394  
   1.395  class DNSAddress(DNSRecord):
   1.396 -	"""A DNS address record"""
   1.397 +    """A DNS address record"""
   1.398  
   1.399 -	def __init__(self, name, type, clazz, ttl, address):
   1.400 -		DNSRecord.__init__(self, name, type, clazz, ttl)
   1.401 -		self.address = address
   1.402 +    def __init__(self, name, type, clazz, ttl, address):
   1.403 +        DNSRecord.__init__(self, name, type, clazz, ttl)
   1.404 +        self.address = address
   1.405  
   1.406 -	def write(self, out):
   1.407 -		"""Used in constructing an outgoing packet"""
   1.408 -		out.writeString(self.address, len(self.address))
   1.409 +    def write(self, out):
   1.410 +        """Used in constructing an outgoing packet"""
   1.411 +        out.writeString(self.address, len(self.address))
   1.412  
   1.413 -	def __eq__(self, other):
   1.414 -		"""Tests equality on address"""
   1.415 -		if isinstance(other, DNSAddress):
   1.416 -			return self.address == other.address
   1.417 -		return 0
   1.418 +    def __eq__(self, other):
   1.419 +        """Tests equality on address"""
   1.420 +        if isinstance(other, DNSAddress):
   1.421 +            return self.address == other.address
   1.422 +        return 0
   1.423  
   1.424 -	def __repr__(self):
   1.425 -		"""String representation"""
   1.426 -		try:
   1.427 -			return socket.inet_ntoa(self.address)
   1.428 -		except:
   1.429 -			return self.address
   1.430 +    def __repr__(self):
   1.431 +        """String representation"""
   1.432 +        try:
   1.433 +            return socket.inet_ntoa(self.address)
   1.434 +        except:
   1.435 +            return self.address
   1.436  
   1.437  class DNSHinfo(DNSRecord):
   1.438 -	"""A DNS host information record"""
   1.439 +    """A DNS host information record"""
   1.440  
   1.441 -	def __init__(self, name, type, clazz, ttl, cpu, os):
   1.442 -		DNSRecord.__init__(self, name, type, clazz, ttl)
   1.443 -		self.cpu = cpu
   1.444 -		self.os = os
   1.445 +    def __init__(self, name, type, clazz, ttl, cpu, os):
   1.446 +        DNSRecord.__init__(self, name, type, clazz, ttl)
   1.447 +        self.cpu = cpu
   1.448 +        self.os = os
   1.449  
   1.450 -	def write(self, out):
   1.451 -		"""Used in constructing an outgoing packet"""
   1.452 -		out.writeString(self.cpu, len(self.cpu))
   1.453 -		out.writeString(self.os, len(self.os))
   1.454 +    def write(self, out):
   1.455 +        """Used in constructing an outgoing packet"""
   1.456 +        out.writeString(self.cpu, len(self.cpu))
   1.457 +        out.writeString(self.os, len(self.os))
   1.458  
   1.459 -	def __eq__(self, other):
   1.460 -		"""Tests equality on cpu and os"""
   1.461 -		if isinstance(other, DNSHinfo):
   1.462 -			return self.cpu == other.cpu and self.os == other.os
   1.463 -		return 0
   1.464 +    def __eq__(self, other):
   1.465 +        """Tests equality on cpu and os"""
   1.466 +        if isinstance(other, DNSHinfo):
   1.467 +            return self.cpu == other.cpu and self.os == other.os
   1.468 +        return 0
   1.469  
   1.470 -	def __repr__(self):
   1.471 -		"""String representation"""
   1.472 -		return self.cpu + " " + self.os
   1.473 +    def __repr__(self):
   1.474 +        """String representation"""
   1.475 +        return self.cpu + " " + self.os
   1.476  
   1.477  class DNSPointer(DNSRecord):
   1.478 -	"""A DNS pointer record"""
   1.479 +    """A DNS pointer record"""
   1.480  
   1.481 -	def __init__(self, name, type, clazz, ttl, alias):
   1.482 -		DNSRecord.__init__(self, name, type, clazz, ttl)
   1.483 -		self.alias = alias
   1.484 +    def __init__(self, name, type, clazz, ttl, alias):
   1.485 +        DNSRecord.__init__(self, name, type, clazz, ttl)
   1.486 +        self.alias = alias
   1.487  
   1.488 -	def write(self, out):
   1.489 -		"""Used in constructing an outgoing packet"""
   1.490 -		out.writeName(self.alias)
   1.491 +    def write(self, out):
   1.492 +        """Used in constructing an outgoing packet"""
   1.493 +        out.writeName(self.alias)
   1.494  
   1.495 -	def __eq__(self, other):
   1.496 -		"""Tests equality on alias"""
   1.497 -		if isinstance(other, DNSPointer):
   1.498 -			return self.alias == other.alias
   1.499 -		return 0
   1.500 +    def __eq__(self, other):
   1.501 +        """Tests equality on alias"""
   1.502 +        if isinstance(other, DNSPointer):
   1.503 +            return self.alias == other.alias
   1.504 +        return 0
   1.505  
   1.506 -	def __repr__(self):
   1.507 -		"""String representation"""
   1.508 -		return self.toString(self.alias)
   1.509 +    def __repr__(self):
   1.510 +        """String representation"""
   1.511 +        return self.toString(self.alias)
   1.512  
   1.513  class DNSText(DNSRecord):
   1.514 -	"""A DNS text record"""
   1.515 +    """A DNS text record"""
   1.516  
   1.517 -	def __init__(self, name, type, clazz, ttl, text):
   1.518 -		DNSRecord.__init__(self, name, type, clazz, ttl)
   1.519 -		self.text = text
   1.520 +    def __init__(self, name, type, clazz, ttl, text):
   1.521 +        DNSRecord.__init__(self, name, type, clazz, ttl)
   1.522 +        self.text = text
   1.523  
   1.524 -	def write(self, out):
   1.525 -		"""Used in constructing an outgoing packet"""
   1.526 -		out.writeString(self.text, len(self.text))
   1.527 +    def write(self, out):
   1.528 +        """Used in constructing an outgoing packet"""
   1.529 +        out.writeString(self.text, len(self.text))
   1.530  
   1.531 -	def __eq__(self, other):
   1.532 -		"""Tests equality on text"""
   1.533 -		if isinstance(other, DNSText):
   1.534 -			return self.text == other.text
   1.535 -		return 0
   1.536 +    def __eq__(self, other):
   1.537 +        """Tests equality on text"""
   1.538 +        if isinstance(other, DNSText):
   1.539 +            return self.text == other.text
   1.540 +        return 0
   1.541  
   1.542 -	def __repr__(self):
   1.543 -		"""String representation"""
   1.544 -		if len(self.text) > 10:
   1.545 -			return self.toString(self.text[:7] + "...")
   1.546 -		else:
   1.547 -			return self.toString(self.text)
   1.548 +    def __repr__(self):
   1.549 +        """String representation"""
   1.550 +        if len(self.text) > 10:
   1.551 +            return self.toString(self.text[:7] + "...")
   1.552 +        else:
   1.553 +            return self.toString(self.text)
   1.554  
   1.555  class DNSService(DNSRecord):
   1.556 -	"""A DNS service record"""
   1.557 +    """A DNS service record"""
   1.558  
   1.559 -	def __init__(self, name, type, clazz, ttl, priority, weight, port, server):
   1.560 -		DNSRecord.__init__(self, name, type, clazz, ttl)
   1.561 -		self.priority = priority
   1.562 -		self.weight = weight
   1.563 -		self.port = port
   1.564 -		self.server = server
   1.565 +    def __init__(self, name, type, clazz, ttl, priority, weight, port, server):
   1.566 +        DNSRecord.__init__(self, name, type, clazz, ttl)
   1.567 +        self.priority = priority
   1.568 +        self.weight = weight
   1.569 +        self.port = port
   1.570 +        self.server = server
   1.571  
   1.572 -	def write(self, out):
   1.573 -		"""Used in constructing an outgoing packet"""
   1.574 -		out.writeShort(self.priority)
   1.575 -		out.writeShort(self.weight)
   1.576 -		out.writeShort(self.port)
   1.577 -		out.writeName(self.server)
   1.578 +    def write(self, out):
   1.579 +        """Used in constructing an outgoing packet"""
   1.580 +        out.writeShort(self.priority)
   1.581 +        out.writeShort(self.weight)
   1.582 +        out.writeShort(self.port)
   1.583 +        out.writeName(self.server)
   1.584  
   1.585 -	def __eq__(self, other):
   1.586 -		"""Tests equality on priority, weight, port and server"""
   1.587 -		if isinstance(other, DNSService):
   1.588 -			return self.priority == other.priority and self.weight == other.weight and self.port == other.port and self.server == other.server
   1.589 -		return 0
   1.590 +    def __eq__(self, other):
   1.591 +        """Tests equality on priority, weight, port and server"""
   1.592 +        if isinstance(other, DNSService):
   1.593 +            return self.priority == other.priority and self.weight == other.weight and self.port == other.port and self.server == other.server
   1.594 +        return 0
   1.595  
   1.596 -	def __repr__(self):
   1.597 -		"""String representation"""
   1.598 -		return self.toString("%s:%s" % (self.server, self.port))
   1.599 +    def __repr__(self):
   1.600 +        """String representation"""
   1.601 +        return self.toString("%s:%s" % (self.server, self.port))
   1.602  
   1.603  class DNSIncoming(object):
   1.604 -	"""Object representation of an incoming DNS packet"""
   1.605 +    """Object representation of an incoming DNS packet"""
   1.606  
   1.607 -	def __init__(self, data):
   1.608 -		"""Constructor from string holding bytes of packet"""
   1.609 -		self.offset = 0
   1.610 -		self.data = data
   1.611 -		self.questions = []
   1.612 -		self.answers = []
   1.613 -		self.numQuestions = 0
   1.614 -		self.numAnswers = 0
   1.615 -		self.numAuthorities = 0
   1.616 -		self.numAdditionals = 0
   1.617 +    def __init__(self, data):
   1.618 +        """Constructor from string holding bytes of packet"""
   1.619 +        self.offset = 0
   1.620 +        self.data = data
   1.621 +        self.questions = []
   1.622 +        self.answers = []
   1.623 +        self.numQuestions = 0
   1.624 +        self.numAnswers = 0
   1.625 +        self.numAuthorities = 0
   1.626 +        self.numAdditionals = 0
   1.627  
   1.628 -		self.readHeader()
   1.629 -		self.readQuestions()
   1.630 -		self.readOthers()
   1.631 +        self.readHeader()
   1.632 +        self.readQuestions()
   1.633 +        self.readOthers()
   1.634  
   1.635 -	def readHeader(self):
   1.636 -		"""Reads header portion of packet"""
   1.637 -		format = '!HHHHHH'
   1.638 -		length = struct.calcsize(format)
   1.639 -		info = struct.unpack(format, self.data[self.offset:self.offset+length])
   1.640 -		self.offset += length
   1.641 +    def readHeader(self):
   1.642 +        """Reads header portion of packet"""
   1.643 +        format = '!HHHHHH'
   1.644 +        length = struct.calcsize(format)
   1.645 +        info = struct.unpack(format, self.data[self.offset:self.offset+length])
   1.646 +        self.offset += length
   1.647  
   1.648 -		self.id = info[0]
   1.649 -		self.flags = info[1]
   1.650 -		self.numQuestions = info[2]
   1.651 -		self.numAnswers = info[3]
   1.652 -		self.numAuthorities = info[4]
   1.653 -		self.numAdditionals = info[5]
   1.654 +        self.id = info[0]
   1.655 +        self.flags = info[1]
   1.656 +        self.numQuestions = info[2]
   1.657 +        self.numAnswers = info[3]
   1.658 +        self.numAuthorities = info[4]
   1.659 +        self.numAdditionals = info[5]
   1.660  
   1.661 -	def readQuestions(self):
   1.662 -		"""Reads questions section of packet"""
   1.663 -		format = '!HH'
   1.664 -		length = struct.calcsize(format)
   1.665 -		for i in range(0, self.numQuestions):
   1.666 -			name = self.readName()
   1.667 -			info = struct.unpack(format, self.data[self.offset:self.offset+length])
   1.668 -			self.offset += length
   1.669 +    def readQuestions(self):
   1.670 +        """Reads questions section of packet"""
   1.671 +        format = '!HH'
   1.672 +        length = struct.calcsize(format)
   1.673 +        for i in range(0, self.numQuestions):
   1.674 +            name = self.readName()
   1.675 +            info = struct.unpack(format, self.data[self.offset:self.offset+length])
   1.676 +            self.offset += length
   1.677  
   1.678 -			question = DNSQuestion(name, info[0], info[1])
   1.679 -			self.questions.append(question)
   1.680 +            question = DNSQuestion(name, info[0], info[1])
   1.681 +            self.questions.append(question)
   1.682  
   1.683 -	def readInt(self):
   1.684 -		"""Reads an integer from the packet"""
   1.685 -		format = '!I'
   1.686 -		length = struct.calcsize(format)
   1.687 -		info = struct.unpack(format, self.data[self.offset:self.offset+length])
   1.688 -		self.offset += length
   1.689 -		return info[0]
   1.690 +    def readInt(self):
   1.691 +        """Reads an integer from the packet"""
   1.692 +        format = '!I'
   1.693 +        length = struct.calcsize(format)
   1.694 +        info = struct.unpack(format, self.data[self.offset:self.offset+length])
   1.695 +        self.offset += length
   1.696 +        return info[0]
   1.697  
   1.698 -	def readCharacterString(self):
   1.699 -		"""Reads a character string from the packet"""
   1.700 -		length = ord(self.data[self.offset])
   1.701 -		self.offset += 1
   1.702 -		return self.readString(length)
   1.703 +    def readCharacterString(self):
   1.704 +        """Reads a character string from the packet"""
   1.705 +        length = ord(self.data[self.offset])
   1.706 +        self.offset += 1
   1.707 +        return self.readString(length)
   1.708  
   1.709 -	def readString(self, len):
   1.710 -		"""Reads a string of a given length from the packet"""
   1.711 -		format = '!' + str(len) + 's'
   1.712 -		length =  struct.calcsize(format)
   1.713 -		info = struct.unpack(format, self.data[self.offset:self.offset+length])
   1.714 -		self.offset += length
   1.715 -		return info[0]
   1.716 +    def readString(self, len):
   1.717 +        """Reads a string of a given length from the packet"""
   1.718 +        format = '!' + str(len) + 's'
   1.719 +        length =  struct.calcsize(format)
   1.720 +        info = struct.unpack(format, self.data[self.offset:self.offset+length])
   1.721 +        self.offset += length
   1.722 +        return info[0]
   1.723  
   1.724 -	def readUnsignedShort(self):
   1.725 -		"""Reads an unsigned short from the packet"""
   1.726 -		format = '!H'
   1.727 -		length = struct.calcsize(format)
   1.728 -		info = struct.unpack(format, self.data[self.offset:self.offset+length])
   1.729 -		self.offset += length
   1.730 -		return info[0]
   1.731 +    def readUnsignedShort(self):
   1.732 +        """Reads an unsigned short from the packet"""
   1.733 +        format = '!H'
   1.734 +        length = struct.calcsize(format)
   1.735 +        info = struct.unpack(format, self.data[self.offset:self.offset+length])
   1.736 +        self.offset += length
   1.737 +        return info[0]
   1.738  
   1.739 -	def readOthers(self):
   1.740 -		"""Reads the answers, authorities and additionals section of the packet"""
   1.741 -		format = '!HHiH'
   1.742 -		length = struct.calcsize(format)
   1.743 -		n = self.numAnswers + self.numAuthorities + self.numAdditionals
   1.744 -		for i in range(0, n):
   1.745 -			domain = self.readName()
   1.746 -			info = struct.unpack(format, self.data[self.offset:self.offset+length])
   1.747 -			self.offset += length
   1.748 +    def readOthers(self):
   1.749 +        """Reads the answers, authorities and additionals section of the packet"""
   1.750 +        format = '!HHiH'
   1.751 +        length = struct.calcsize(format)
   1.752 +        n = self.numAnswers + self.numAuthorities + self.numAdditionals
   1.753 +        for i in range(0, n):
   1.754 +            domain = self.readName()
   1.755 +            info = struct.unpack(format, self.data[self.offset:self.offset+length])
   1.756 +            self.offset += length
   1.757  
   1.758 -			rec = None
   1.759 -			if info[0] == _TYPE_A:
   1.760 -				rec = DNSAddress(domain, info[0], info[1], info[2], self.readString(4))
   1.761 -			elif info[0] == _TYPE_CNAME or info[0] == _TYPE_PTR:
   1.762 -				rec = DNSPointer(domain, info[0], info[1], info[2], self.readName())
   1.763 -			elif info[0] == _TYPE_TXT:
   1.764 -				rec = DNSText(domain, info[0], info[1], info[2], self.readString(info[3]))
   1.765 -			elif info[0] == _TYPE_SRV:
   1.766 -				rec = DNSService(domain, info[0], info[1], info[2], self.readUnsignedShort(), self.readUnsignedShort(), self.readUnsignedShort(), self.readName())
   1.767 -			elif info[0] == _TYPE_HINFO:
   1.768 -				rec = DNSHinfo(domain, info[0], info[1], info[2], self.readCharacterString(), self.readCharacterString())
   1.769 -			elif info[0] == _TYPE_AAAA:
   1.770 -				rec = DNSAddress(domain, info[0], info[1], info[2], self.readString(16))
   1.771 -			else:
   1.772 -				# Try to ignore types we don't know about
   1.773 -				# this may mean the rest of the name is
   1.774 -				# unable to be parsed, and may show errors
   1.775 -				# so this is left for debugging.  New types
   1.776 -				# encountered need to be parsed properly.
   1.777 -				#
   1.778 -				#print "UNKNOWN TYPE = " + str(info[0])
   1.779 -				#raise BadTypeInNameException
   1.780 -				pass
   1.781 +            rec = None
   1.782 +            if info[0] == _TYPE_A:
   1.783 +                rec = DNSAddress(domain, info[0], info[1], info[2], self.readString(4))
   1.784 +            elif info[0] == _TYPE_CNAME or info[0] == _TYPE_PTR:
   1.785 +                rec = DNSPointer(domain, info[0], info[1], info[2], self.readName())
   1.786 +            elif info[0] == _TYPE_TXT:
   1.787 +                rec = DNSText(domain, info[0], info[1], info[2], self.readString(info[3]))
   1.788 +            elif info[0] == _TYPE_SRV:
   1.789 +                rec = DNSService(domain, info[0], info[1], info[2], self.readUnsignedShort(), self.readUnsignedShort(), self.readUnsignedShort(), self.readName())
   1.790 +            elif info[0] == _TYPE_HINFO:
   1.791 +                rec = DNSHinfo(domain, info[0], info[1], info[2], self.readCharacterString(), self.readCharacterString())
   1.792 +            elif info[0] == _TYPE_AAAA:
   1.793 +                rec = DNSAddress(domain, info[0], info[1], info[2], self.readString(16))
   1.794 +            else:
   1.795 +                # Try to ignore types we don't know about
   1.796 +                # this may mean the rest of the name is
   1.797 +                # unable to be parsed, and may show errors
   1.798 +                # so this is left for debugging.  New types
   1.799 +                # encountered need to be parsed properly.
   1.800 +                #
   1.801 +                #print "UNKNOWN TYPE = " + str(info[0])
   1.802 +                #raise BadTypeInNameException
   1.803 +                pass
   1.804  
   1.805 -			if rec is not None:
   1.806 -				self.answers.append(rec)
   1.807 +            if rec is not None:
   1.808 +                self.answers.append(rec)
   1.809  
   1.810 -	def isQuery(self):
   1.811 -		"""Returns true if this is a query"""
   1.812 -		return (self.flags & _FLAGS_QR_MASK) == _FLAGS_QR_QUERY
   1.813 +    def isQuery(self):
   1.814 +        """Returns true if this is a query"""
   1.815 +        return (self.flags & _FLAGS_QR_MASK) == _FLAGS_QR_QUERY
   1.816  
   1.817 -	def isResponse(self):
   1.818 -		"""Returns true if this is a response"""
   1.819 -		return (self.flags & _FLAGS_QR_MASK) == _FLAGS_QR_RESPONSE
   1.820 +    def isResponse(self):
   1.821 +        """Returns true if this is a response"""
   1.822 +        return (self.flags & _FLAGS_QR_MASK) == _FLAGS_QR_RESPONSE
   1.823  
   1.824 -	def readUTF(self, offset, len):
   1.825 -		"""Reads a UTF-8 string of a given length from the packet"""
   1.826 -		result = self.data[offset:offset+len].decode('utf-8')
   1.827 -		return result
   1.828 +    def readUTF(self, offset, len):
   1.829 +        """Reads a UTF-8 string of a given length from the packet"""
   1.830 +        result = self.data[offset:offset+len].decode('utf-8')
   1.831 +        return result
   1.832  
   1.833 -	def readName(self):
   1.834 -		"""Reads a domain name from the packet"""
   1.835 -		result = ''
   1.836 -		off = self.offset
   1.837 -		next = -1
   1.838 -		first = off
   1.839 +    def readName(self):
   1.840 +        """Reads a domain name from the packet"""
   1.841 +        result = ''
   1.842 +        off = self.offset
   1.843 +        next = -1
   1.844 +        first = off
   1.845  
   1.846 -		while 1:
   1.847 -			len = ord(self.data[off])
   1.848 -			off += 1
   1.849 -			if len == 0:
   1.850 -				break
   1.851 -			t = len & 0xC0
   1.852 -			if t == 0x00:
   1.853 -				result = ''.join((result, self.readUTF(off, len) + '.'))
   1.854 -				off += len
   1.855 -			elif t == 0xC0:
   1.856 -				if next < 0:
   1.857 -					next = off + 1
   1.858 -				off = ((len & 0x3F) << 8) | ord(self.data[off])
   1.859 -				if off >= first:
   1.860 -					raise "Bad domain name (circular) at " + str(off)
   1.861 -				first = off
   1.862 -			else:
   1.863 -				raise "Bad domain name at " + str(off)
   1.864 +        while 1:
   1.865 +            len = ord(self.data[off])
   1.866 +            off += 1
   1.867 +            if len == 0:
   1.868 +                break
   1.869 +            t = len & 0xC0
   1.870 +            if t == 0x00:
   1.871 +                result = ''.join((result, self.readUTF(off, len) + '.'))
   1.872 +                off += len
   1.873 +            elif t == 0xC0:
   1.874 +                if next < 0:
   1.875 +                    next = off + 1
   1.876 +                off = ((len & 0x3F) << 8) | ord(self.data[off])
   1.877 +                if off >= first:
   1.878 +                    raise "Bad domain name (circular) at " + str(off)
   1.879 +                first = off
   1.880 +            else:
   1.881 +                raise "Bad domain name at " + str(off)
   1.882  
   1.883 -		if next >= 0:
   1.884 -			self.offset = next
   1.885 -		else:
   1.886 -			self.offset = off
   1.887 +        if next >= 0:
   1.888 +            self.offset = next
   1.889 +        else:
   1.890 +            self.offset = off
   1.891  
   1.892 -		return result
   1.893 +        return result
   1.894  
   1.895  
   1.896  class DNSOutgoing(object):
   1.897 -	"""Object representation of an outgoing packet"""
   1.898 +    """Object representation of an outgoing packet"""
   1.899  
   1.900 -	def __init__(self, flags, multicast = 1):
   1.901 -		self.finished = 0
   1.902 -		self.id = 0
   1.903 -		self.multicast = multicast
   1.904 -		self.flags = flags
   1.905 -		self.names = {}
   1.906 -		self.data = []
   1.907 -		self.size = 12
   1.908 +    def __init__(self, flags, multicast = 1):
   1.909 +        self.finished = 0
   1.910 +        self.id = 0
   1.911 +        self.multicast = multicast
   1.912 +        self.flags = flags
   1.913 +        self.names = {}
   1.914 +        self.data = []
   1.915 +        self.size = 12
   1.916  
   1.917 -		self.questions = []
   1.918 -		self.answers = []
   1.919 -		self.authorities = []
   1.920 -		self.additionals = []
   1.921 +        self.questions = []
   1.922 +        self.answers = []
   1.923 +        self.authorities = []
   1.924 +        self.additionals = []
   1.925  
   1.926 -	def addQuestion(self, record):
   1.927 -		"""Adds a question"""
   1.928 -		self.questions.append(record)
   1.929 +    def addQuestion(self, record):
   1.930 +        """Adds a question"""
   1.931 +        self.questions.append(record)
   1.932  
   1.933 -	def addAnswer(self, inp, record):
   1.934 -		"""Adds an answer"""
   1.935 -		if not record.suppressedBy(inp):
   1.936 -			self.addAnswerAtTime(record, 0)
   1.937 +    def addAnswer(self, inp, record):
   1.938 +        """Adds an answer"""
   1.939 +        if not record.suppressedBy(inp):
   1.940 +            self.addAnswerAtTime(record, 0)
   1.941  
   1.942 -	def addAnswerAtTime(self, record, now):
   1.943 -		"""Adds an answer if if does not expire by a certain time"""
   1.944 -		if record is not None:
   1.945 -			if now == 0 or not record.isExpired(now):
   1.946 -				self.answers.append((record, now))
   1.947 +    def addAnswerAtTime(self, record, now):
   1.948 +        """Adds an answer if if does not expire by a certain time"""
   1.949 +        if record is not None:
   1.950 +            if now == 0 or not record.isExpired(now):
   1.951 +                self.answers.append((record, now))
   1.952  
   1.953 -	def addAuthorativeAnswer(self, record):
   1.954 -		"""Adds an authoritative answer"""
   1.955 -		self.authorities.append(record)
   1.956 +    def addAuthorativeAnswer(self, record):
   1.957 +        """Adds an authoritative answer"""
   1.958 +        self.authorities.append(record)
   1.959  
   1.960 -	def addAdditionalAnswer(self, record):
   1.961 -		"""Adds an additional answer"""
   1.962 -		self.additionals.append(record)
   1.963 +    def addAdditionalAnswer(self, record):
   1.964 +        """Adds an additional answer"""
   1.965 +        self.additionals.append(record)
   1.966  
   1.967 -	def writeByte(self, value):
   1.968 -		"""Writes a single byte to the packet"""
   1.969 -		format = '!c'
   1.970 -		self.data.append(struct.pack(format, chr(value)))
   1.971 -		self.size += 1
   1.972 +    def writeByte(self, value):
   1.973 +        """Writes a single byte to the packet"""
   1.974 +        format = '!c'
   1.975 +        self.data.append(struct.pack(format, chr(value)))
   1.976 +        self.size += 1
   1.977  
   1.978 -	def insertShort(self, index, value):
   1.979 -		"""Inserts an unsigned short in a certain position in the packet"""
   1.980 -		format = '!H'
   1.981 -		self.data.insert(index, struct.pack(format, value))
   1.982 -		self.size += 2
   1.983 +    def insertShort(self, index, value):
   1.984 +        """Inserts an unsigned short in a certain position in the packet"""
   1.985 +        format = '!H'
   1.986 +        self.data.insert(index, struct.pack(format, value))
   1.987 +        self.size += 2
   1.988  
   1.989 -	def writeShort(self, value):
   1.990 -		"""Writes an unsigned short to the packet"""
   1.991 -		format = '!H'
   1.992 -		self.data.append(struct.pack(format, value))
   1.993 -		self.size += 2
   1.994 +    def writeShort(self, value):
   1.995 +        """Writes an unsigned short to the packet"""
   1.996 +        format = '!H'
   1.997 +        self.data.append(struct.pack(format, value))
   1.998 +        self.size += 2
   1.999  
  1.1000 -	def writeInt(self, value):
  1.1001 -		"""Writes an unsigned integer to the packet"""
  1.1002 -		format = '!I'
  1.1003 -		self.data.append(struct.pack(format, int(value)))
  1.1004 -		self.size += 4
  1.1005 +    def writeInt(self, value):
  1.1006 +        """Writes an unsigned integer to the packet"""
  1.1007 +        format = '!I'
  1.1008 +        self.data.append(struct.pack(format, int(value)))
  1.1009 +        self.size += 4
  1.1010  
  1.1011 -	def writeString(self, value, length):
  1.1012 -		"""Writes a string to the packet"""
  1.1013 -		format = '!' + str(length) + 's'
  1.1014 -		self.data.append(struct.pack(format, value))
  1.1015 -		self.size += length
  1.1016 +    def writeString(self, value, length):
  1.1017 +        """Writes a string to the packet"""
  1.1018 +        format = '!' + str(length) + 's'
  1.1019 +        self.data.append(struct.pack(format, value))
  1.1020 +        self.size += length
  1.1021  
  1.1022 -	def writeUTF(self, s):
  1.1023 -		"""Writes a UTF-8 string of a given length to the packet"""
  1.1024 -		utfstr = s.encode('utf-8')
  1.1025 -		length = len(utfstr)
  1.1026 -		if length > 64:
  1.1027 -			raise NamePartTooLongException
  1.1028 -		self.writeByte(length)
  1.1029 -		self.writeString(utfstr, length)
  1.1030 +    def writeUTF(self, s):
  1.1031 +        """Writes a UTF-8 string of a given length to the packet"""
  1.1032 +        utfstr = s.encode('utf-8')
  1.1033 +        length = len(utfstr)
  1.1034 +        if length > 64:
  1.1035 +            raise NamePartTooLongException
  1.1036 +        self.writeByte(length)
  1.1037 +        self.writeString(utfstr, length)
  1.1038  
  1.1039 -	def writeName(self, name):
  1.1040 -		"""Writes a domain name to the packet"""
  1.1041 +    def writeName(self, name):
  1.1042 +        """Writes a domain name to the packet"""
  1.1043  
  1.1044 -		try:
  1.1045 -			# Find existing instance of this name in packet
  1.1046 -			#
  1.1047 -			index = self.names[name]
  1.1048 -		except KeyError:
  1.1049 -			# No record of this name already, so write it
  1.1050 -			# out as normal, recording the location of the name
  1.1051 -			# for future pointers to it.
  1.1052 -			#
  1.1053 -			self.names[name] = self.size
  1.1054 -			parts = name.split('.')
  1.1055 -			if parts[-1] == '':
  1.1056 -				parts = parts[:-1]
  1.1057 -			for part in parts:
  1.1058 -				self.writeUTF(part)
  1.1059 -			self.writeByte(0)
  1.1060 -			return
  1.1061 +        try:
  1.1062 +            # Find existing instance of this name in packet
  1.1063 +            #
  1.1064 +            index = self.names[name]
  1.1065 +        except KeyError:
  1.1066 +            # No record of this name already, so write it
  1.1067 +            # out as normal, recording the location of the name
  1.1068 +            # for future pointers to it.
  1.1069 +            #
  1.1070 +            self.names[name] = self.size
  1.1071 +            parts = name.split('.')
  1.1072 +            if parts[-1] == '':
  1.1073 +                parts = parts[:-1]
  1.1074 +            for part in parts:
  1.1075 +                self.writeUTF(part)
  1.1076 +            self.writeByte(0)
  1.1077 +            return
  1.1078  
  1.1079 -		# An index was found, so write a pointer to it
  1.1080 -		#
  1.1081 -		self.writeByte((index >> 8) | 0xC0)
  1.1082 -		self.writeByte(index)
  1.1083 +        # An index was found, so write a pointer to it
  1.1084 +        #
  1.1085 +        self.writeByte((index >> 8) | 0xC0)
  1.1086 +        self.writeByte(index)
  1.1087  
  1.1088 -	def writeQuestion(self, question):
  1.1089 -		"""Writes a question to the packet"""
  1.1090 -		self.writeName(question.name)
  1.1091 -		self.writeShort(question.type)
  1.1092 -		self.writeShort(question.clazz)
  1.1093 +    def writeQuestion(self, question):
  1.1094 +        """Writes a question to the packet"""
  1.1095 +        self.writeName(question.name)
  1.1096 +        self.writeShort(question.type)
  1.1097 +        self.writeShort(question.clazz)
  1.1098  
  1.1099 -	def writeRecord(self, record, now):
  1.1100 -		"""Writes a record (answer, authoritative answer, additional) to
  1.1101 -		the packet"""
  1.1102 -		self.writeName(record.name)
  1.1103 -		self.writeShort(record.type)
  1.1104 -		if record.unique and self.multicast:
  1.1105 -			self.writeShort(record.clazz | _CLASS_UNIQUE)
  1.1106 -		else:
  1.1107 -			self.writeShort(record.clazz)
  1.1108 -		if now == 0:
  1.1109 -			self.writeInt(record.ttl)
  1.1110 -		else:
  1.1111 -			self.writeInt(record.getRemainingTTL(now))
  1.1112 -		index = len(self.data)
  1.1113 -		# Adjust size for the short we will write before this record
  1.1114 -		#
  1.1115 -		self.size += 2
  1.1116 -		record.write(self)
  1.1117 -		self.size -= 2
  1.1118 +    def writeRecord(self, record, now):
  1.1119 +        """Writes a record (answer, authoritative answer, additional) to
  1.1120 +        the packet"""
  1.1121 +        self.writeName(record.name)
  1.1122 +        self.writeShort(record.type)
  1.1123 +        if record.unique and self.multicast:
  1.1124 +            self.writeShort(record.clazz | _CLASS_UNIQUE)
  1.1125 +        else:
  1.1126 +            self.writeShort(record.clazz)
  1.1127 +        if now == 0:
  1.1128 +            self.writeInt(record.ttl)
  1.1129 +        else:
  1.1130 +            self.writeInt(record.getRemainingTTL(now))
  1.1131 +        index = len(self.data)
  1.1132 +        # Adjust size for the short we will write before this record
  1.1133 +        #
  1.1134 +        self.size += 2
  1.1135 +        record.write(self)
  1.1136 +        self.size -= 2
  1.1137  
  1.1138 -		length = len(''.join(self.data[index:]))
  1.1139 -		self.insertShort(index, length) # Here is the short we adjusted for
  1.1140 +        length = len(''.join(self.data[index:]))
  1.1141 +        self.insertShort(index, length) # Here is the short we adjusted for
  1.1142  
  1.1143 -	def packet(self):
  1.1144 -		"""Returns a string containing the packet's bytes
  1.1145 +    def packet(self):
  1.1146 +        """Returns a string containing the packet's bytes
  1.1147  
  1.1148 -		No further parts should be added to the packet once this
  1.1149 -		is done."""
  1.1150 -		if not self.finished:
  1.1151 -			self.finished = 1
  1.1152 -			for question in self.questions:
  1.1153 -				self.writeQuestion(question)
  1.1154 -			for answer, time in self.answers:
  1.1155 -				self.writeRecord(answer, time)
  1.1156 -			for authority in self.authorities:
  1.1157 -				self.writeRecord(authority, 0)
  1.1158 -			for additional in self.additionals:
  1.1159 -				self.writeRecord(additional, 0)
  1.1160 +        No further parts should be added to the packet once this
  1.1161 +        is done."""
  1.1162 +        if not self.finished:
  1.1163 +            self.finished = 1
  1.1164 +            for question in self.questions:
  1.1165 +                self.writeQuestion(question)
  1.1166 +            for answer, time in self.answers:
  1.1167 +                self.writeRecord(answer, time)
  1.1168 +            for authority in self.authorities:
  1.1169 +                self.writeRecord(authority, 0)
  1.1170 +            for additional in self.additionals:
  1.1171 +                self.writeRecord(additional, 0)
  1.1172  
  1.1173 -			self.insertShort(0, len(self.additionals))
  1.1174 -			self.insertShort(0, len(self.authorities))
  1.1175 -			self.insertShort(0, len(self.answers))
  1.1176 -			self.insertShort(0, len(self.questions))
  1.1177 -			self.insertShort(0, self.flags)
  1.1178 -			if self.multicast:
  1.1179 -				self.insertShort(0, 0)
  1.1180 -			else:
  1.1181 -				self.insertShort(0, self.id)
  1.1182 -		return ''.join(self.data)
  1.1183 +            self.insertShort(0, len(self.additionals))
  1.1184 +            self.insertShort(0, len(self.authorities))
  1.1185 +            self.insertShort(0, len(self.answers))
  1.1186 +            self.insertShort(0, len(self.questions))
  1.1187 +            self.insertShort(0, self.flags)
  1.1188 +            if self.multicast:
  1.1189 +                self.insertShort(0, 0)
  1.1190 +            else:
  1.1191 +                self.insertShort(0, self.id)
  1.1192 +        return ''.join(self.data)
  1.1193  
  1.1194  
  1.1195  class DNSCache(object):
  1.1196 -	"""A cache of DNS entries"""
  1.1197 +    """A cache of DNS entries"""
  1.1198  
  1.1199 -	def __init__(self):
  1.1200 -		self.cache = {}
  1.1201 +    def __init__(self):
  1.1202 +        self.cache = {}
  1.1203  
  1.1204 -	def add(self, entry):
  1.1205 -		"""Adds an entry"""
  1.1206 -		try:
  1.1207 -			list = self.cache[entry.key]
  1.1208 -		except:
  1.1209 -			list = self.cache[entry.key] = []
  1.1210 -		list.append(entry)
  1.1211 +    def add(self, entry):
  1.1212 +        """Adds an entry"""
  1.1213 +        try:
  1.1214 +            list = self.cache[entry.key]
  1.1215 +        except:
  1.1216 +            list = self.cache[entry.key] = []
  1.1217 +        list.append(entry)
  1.1218  
  1.1219 -	def remove(self, entry):
  1.1220 -		"""Removes an entry"""
  1.1221 -		try:
  1.1222 -			list = self.cache[entry.key]
  1.1223 -			list.remove(entry)
  1.1224 -		except:
  1.1225 -			pass
  1.1226 +    def remove(self, entry):
  1.1227 +        """Removes an entry"""
  1.1228 +        try:
  1.1229 +            list = self.cache[entry.key]
  1.1230 +            list.remove(entry)
  1.1231 +        except:
  1.1232 +            pass
  1.1233  
  1.1234 -	def get(self, entry):
  1.1235 -		"""Gets an entry by key.  Will return None if there is no
  1.1236 -		matching entry."""
  1.1237 -		try:
  1.1238 -			list = self.cache[entry.key]
  1.1239 -			return list[list.index(entry)]
  1.1240 -		except:
  1.1241 -			return None
  1.1242 +    def get(self, entry):
  1.1243 +        """Gets an entry by key.  Will return None if there is no
  1.1244 +        matching entry."""
  1.1245 +        try:
  1.1246 +            list = self.cache[entry.key]
  1.1247 +            return list[list.index(entry)]
  1.1248 +        except:
  1.1249 +            return None
  1.1250  
  1.1251 -	def getByDetails(self, name, type, clazz):
  1.1252 -		"""Gets an entry by details.  Will return None if there is
  1.1253 -		no matching entry."""
  1.1254 -		entry = DNSEntry(name, type, clazz)
  1.1255 -		return self.get(entry)
  1.1256 +    def getByDetails(self, name, type, clazz):
  1.1257 +        """Gets an entry by details.  Will return None if there is
  1.1258 +        no matching entry."""
  1.1259 +        entry = DNSEntry(name, type, clazz)
  1.1260 +        return self.get(entry)
  1.1261  
  1.1262 -	def entriesWithName(self, name):
  1.1263 -		"""Returns a list of entries whose key matches the name."""
  1.1264 -		try:
  1.1265 -			return self.cache[name]
  1.1266 -		except:
  1.1267 -			return []
  1.1268 +    def entriesWithName(self, name):
  1.1269 +        """Returns a list of entries whose key matches the name."""
  1.1270 +        try:
  1.1271 +            return self.cache[name]
  1.1272 +        except:
  1.1273 +            return []
  1.1274  
  1.1275 -	def entries(self):
  1.1276 -		"""Returns a list of all entries"""
  1.1277 -		def add(x, y): return x+y
  1.1278 -		try:
  1.1279 -			return reduce(add, self.cache.values())
  1.1280 -		except:
  1.1281 -			return []
  1.1282 +    def entries(self):
  1.1283 +        """Returns a list of all entries"""
  1.1284 +        def add(x, y): return x+y
  1.1285 +        try:
  1.1286 +            return reduce(add, self.cache.values())
  1.1287 +        except:
  1.1288 +            return []
  1.1289  
  1.1290  
  1.1291  class Engine(threading.Thread):
  1.1292 -	"""An engine wraps read access to sockets, allowing objects that
  1.1293 -	need to receive data from sockets to be called back when the
  1.1294 -	sockets are ready.
  1.1295 +    """An engine wraps read access to sockets, allowing objects that
  1.1296 +    need to receive data from sockets to be called back when the
  1.1297 +    sockets are ready.
  1.1298  
  1.1299 -	A reader needs a handle_read() method, which is called when the socket
  1.1300 -	it is interested in is ready for reading.
  1.1301 +    A reader needs a handle_read() method, which is called when the socket
  1.1302 +    it is interested in is ready for reading.
  1.1303  
  1.1304 -	Writers are not implemented here, because we only send short
  1.1305 -	packets.
  1.1306 -	"""
  1.1307 +    Writers are not implemented here, because we only send short
  1.1308 +    packets.
  1.1309 +    """
  1.1310  
  1.1311 -	def __init__(self, zeroconf):
  1.1312 -		threading.Thread.__init__(self)
  1.1313 -		self.zeroconf = zeroconf
  1.1314 -		self.readers = {} # maps socket to reader
  1.1315 -		self.timeout = 5
  1.1316 -		self.condition = threading.Condition()
  1.1317 -		self.start()
  1.1318 +    def __init__(self, zeroconf):
  1.1319 +        threading.Thread.__init__(self)
  1.1320 +        self.zeroconf = zeroconf
  1.1321 +        self.readers = {} # maps socket to reader
  1.1322 +        self.timeout = 5
  1.1323 +        self.condition = threading.Condition()
  1.1324 +        self.start()
  1.1325  
  1.1326 -	def run(self):
  1.1327 -		while not globals()['_GLOBAL_DONE']:
  1.1328 -			rs = self.getReaders()
  1.1329 -			if len(rs) == 0:
  1.1330 -				# No sockets to manage, but we wait for the timeout
  1.1331 -				# or addition of a socket
  1.1332 -				#
  1.1333 -				self.condition.acquire()
  1.1334 -				self.condition.wait(self.timeout)
  1.1335 -				self.condition.release()
  1.1336 -			else:
  1.1337 -				try:
  1.1338 -					rr, wr, er = select.select(rs, [], [], self.timeout)
  1.1339 -					for socket in rr:
  1.1340 -						try:
  1.1341 -							self.readers[socket].handle_read()
  1.1342 -						except:
  1.1343 -							traceback.print_exc()
  1.1344 -				except:
  1.1345 -					pass
  1.1346 +    def run(self):
  1.1347 +        while not globals()['_GLOBAL_DONE']:
  1.1348 +            rs = self.getReaders()
  1.1349 +            if len(rs) == 0:
  1.1350 +                # No sockets to manage, but we wait for the timeout
  1.1351 +                # or addition of a socket
  1.1352 +                #
  1.1353 +                self.condition.acquire()
  1.1354 +                self.condition.wait(self.timeout)
  1.1355 +                self.condition.release()
  1.1356 +            else:
  1.1357 +                try:
  1.1358 +                    rr, wr, er = select.select(rs, [], [], self.timeout)
  1.1359 +                    for socket in rr:
  1.1360 +                        try:
  1.1361 +                            self.readers[socket].handle_read()
  1.1362 +                        except:
  1.1363 +                            traceback.print_exc()
  1.1364 +                except:
  1.1365 +                    pass
  1.1366  
  1.1367 -	def getReaders(self):
  1.1368 -		self.condition.acquire()
  1.1369 -		result = self.readers.keys()
  1.1370 -		self.condition.release()
  1.1371 -		return result
  1.1372 +    def getReaders(self):
  1.1373 +        self.condition.acquire()
  1.1374 +        result = self.readers.keys()
  1.1375 +        self.condition.release()
  1.1376 +        return result
  1.1377  
  1.1378 -	def addReader(self, reader, socket):
  1.1379 -		self.condition.acquire()
  1.1380 -		self.readers[socket] = reader
  1.1381 -		self.condition.notify()
  1.1382 -		self.condition.release()
  1.1383 +    def addReader(self, reader, socket):
  1.1384 +        self.condition.acquire()
  1.1385 +        self.readers[socket] = reader
  1.1386 +        self.condition.notify()
  1.1387 +        self.condition.release()
  1.1388  
  1.1389 -	def delReader(self, socket):
  1.1390 -		self.condition.acquire()
  1.1391 -		del(self.readers[socket])
  1.1392 -		self.condition.notify()
  1.1393 -		self.condition.release()
  1.1394 +    def delReader(self, socket):
  1.1395 +        self.condition.acquire()
  1.1396 +        del(self.readers[socket])
  1.1397 +        self.condition.notify()
  1.1398 +        self.condition.release()
  1.1399  
  1.1400 -	def notify(self):
  1.1401 -		self.condition.acquire()
  1.1402 -		self.condition.notify()
  1.1403 -		self.condition.release()
  1.1404 +    def notify(self):
  1.1405 +        self.condition.acquire()
  1.1406 +        self.condition.notify()
  1.1407 +        self.condition.release()
  1.1408  
  1.1409  class Listener(object):
  1.1410 -	"""A Listener is used by this module to listen on the multicast
  1.1411 -	group to which DNS messages are sent, allowing the implementation
  1.1412 -	to cache information as it arrives.
  1.1413 +    """A Listener is used by this module to listen on the multicast
  1.1414 +    group to which DNS messages are sent, allowing the implementation
  1.1415 +    to cache information as it arrives.
  1.1416  
  1.1417 -	It requires registration with an Engine object in order to have
  1.1418 -	the read() method called when a socket is availble for reading."""
  1.1419 +    It requires registration with an Engine object in order to have
  1.1420 +    the read() method called when a socket is availble for reading."""
  1.1421  
  1.1422 -	def __init__(self, zeroconf):
  1.1423 -		self.zeroconf = zeroconf
  1.1424 -		self.zeroconf.engine.addReader(self, self.zeroconf.socket)
  1.1425 +    def __init__(self, zeroconf):
  1.1426 +        self.zeroconf = zeroconf
  1.1427 +        self.zeroconf.engine.addReader(self, self.zeroconf.socket)
  1.1428  
  1.1429 -	def handle_read(self):
  1.1430 -		data, (addr, port) = self.zeroconf.socket.recvfrom(_MAX_MSG_ABSOLUTE)
  1.1431 -		self.data = data
  1.1432 -		msg = DNSIncoming(data)
  1.1433 -		if msg.isQuery():
  1.1434 -			# Always multicast responses
  1.1435 -			#
  1.1436 -			if port == _MDNS_PORT:
  1.1437 -				self.zeroconf.handleQuery(msg, _MDNS_ADDR, _MDNS_PORT)
  1.1438 -			# If it's not a multicast query, reply via unicast
  1.1439 -			# and multicast
  1.1440 -			#
  1.1441 -			elif port == _DNS_PORT:
  1.1442 -				self.zeroconf.handleQuery(msg, addr, port)
  1.1443 -				self.zeroconf.handleQuery(msg, _MDNS_ADDR, _MDNS_PORT)
  1.1444 -		else:
  1.1445 -			self.zeroconf.handleResponse(msg)
  1.1446 +    def handle_read(self):
  1.1447 +        data, (addr, port) = self.zeroconf.socket.recvfrom(_MAX_MSG_ABSOLUTE)
  1.1448 +        self.data = data
  1.1449 +        msg = DNSIncoming(data)
  1.1450 +        if msg.isQuery():
  1.1451 +            # Always multicast responses
  1.1452 +            #
  1.1453 +            if port == _MDNS_PORT:
  1.1454 +                self.zeroconf.handleQuery(msg, _MDNS_ADDR, _MDNS_PORT)
  1.1455 +            # If it's not a multicast query, reply via unicast
  1.1456 +            # and multicast
  1.1457 +            #
  1.1458 +            elif port == _DNS_PORT:
  1.1459 +                self.zeroconf.handleQuery(msg, addr, port)
  1.1460 +                self.zeroconf.handleQuery(msg, _MDNS_ADDR, _MDNS_PORT)
  1.1461 +        else:
  1.1462 +            self.zeroconf.handleResponse(msg)
  1.1463  
  1.1464  
  1.1465  class Reaper(threading.Thread):
  1.1466 -	"""A Reaper is used by this module to remove cache entries that
  1.1467 -	have expired."""
  1.1468 +    """A Reaper is used by this module to remove cache entries that
  1.1469 +    have expired."""
  1.1470  
  1.1471 -	def __init__(self, zeroconf):
  1.1472 -		threading.Thread.__init__(self)
  1.1473 -		self.zeroconf = zeroconf
  1.1474 -		self.start()
  1.1475 +    def __init__(self, zeroconf):
  1.1476 +        threading.Thread.__init__(self)
  1.1477 +        self.zeroconf = zeroconf
  1.1478 +        self.start()
  1.1479  
  1.1480 -	def run(self):
  1.1481 -		while 1:
  1.1482 -			self.zeroconf.wait(10 * 1000)
  1.1483 -			if globals()['_GLOBAL_DONE']:
  1.1484 -				return
  1.1485 -			now = currentTimeMillis()
  1.1486 -			for record in self.zeroconf.cache.entries():
  1.1487 -				if record.isExpired(now):
  1.1488 -					self.zeroconf.updateRecord(now, record)
  1.1489 -					self.zeroconf.cache.remove(record)
  1.1490 +    def run(self):
  1.1491 +        while 1:
  1.1492 +            self.zeroconf.wait(10 * 1000)
  1.1493 +            if globals()['_GLOBAL_DONE']:
  1.1494 +                return
  1.1495 +            now = currentTimeMillis()
  1.1496 +            for record in self.zeroconf.cache.entries():
  1.1497 +                if record.isExpired(now):
  1.1498 +                    self.zeroconf.updateRecord(now, record)
  1.1499 +                    self.zeroconf.cache.remove(record)
  1.1500  
  1.1501  
  1.1502  class ServiceBrowser(threading.Thread):
  1.1503 -	"""Used to browse for a service of a specific type.
  1.1504 +    """Used to browse for a service of a specific type.
  1.1505  
  1.1506 -	The listener object will have its addService() and
  1.1507 -	removeService() methods called when this browser
  1.1508 -	discovers changes in the services availability."""
  1.1509 +    The listener object will have its addService() and
  1.1510 +    removeService() methods called when this browser
  1.1511 +    discovers changes in the services availability."""
  1.1512  
  1.1513 -	def __init__(self, zeroconf, type, listener):
  1.1514 -		"""Creates a browser for a specific type"""
  1.1515 -		threading.Thread.__init__(self)
  1.1516 -		self.zeroconf = zeroconf
  1.1517 -		self.type = type
  1.1518 -		self.listener = listener
  1.1519 -		self.services = {}
  1.1520 -		self.nextTime = currentTimeMillis()
  1.1521 -		self.delay = _BROWSER_TIME
  1.1522 -		self.list = []
  1.1523 +    def __init__(self, zeroconf, type, listener):
  1.1524 +        """Creates a browser for a specific type"""
  1.1525 +        threading.Thread.__init__(self)
  1.1526 +        self.zeroconf = zeroconf
  1.1527 +        self.type = type
  1.1528 +        self.listener = listener
  1.1529 +        self.services = {}
  1.1530 +        self.nextTime = currentTimeMillis()
  1.1531 +        self.delay = _BROWSER_TIME
  1.1532 +        self.list = []
  1.1533  
  1.1534 -		self.done = 0
  1.1535 +        self.done = 0
  1.1536  
  1.1537 -		self.zeroconf.addListener(self, DNSQuestion(self.type, _TYPE_PTR, _CLASS_IN))
  1.1538 -		self.start()
  1.1539 +        self.zeroconf.addListener(self, DNSQuestion(self.type, _TYPE_PTR, _CLASS_IN))
  1.1540 +        self.start()
  1.1541  
  1.1542 -	def updateRecord(self, zeroconf, now, record):
  1.1543 -		"""Callback invoked by Zeroconf when new information arrives.
  1.1544 +    def updateRecord(self, zeroconf, now, record):
  1.1545 +        """Callback invoked by Zeroconf when new information arrives.
  1.1546  
  1.1547 -		Updates information required by browser in the Zeroconf cache."""
  1.1548 -		if record.type == _TYPE_PTR and record.name == self.type:
  1.1549 -			expired = record.isExpired(now)
  1.1550 -			try:
  1.1551 -				oldrecord = self.services[record.alias.lower()]
  1.1552 -				if not expired:
  1.1553 -					oldrecord.resetTTL(record)
  1.1554 -				else:
  1.1555 -					del(self.services[record.alias.lower()])
  1.1556 -					callback = lambda x: self.listener.removeService(x, self.type, record.alias)
  1.1557 -					self.list.append(callback)
  1.1558 -					return
  1.1559 -			except:
  1.1560 -				if not expired:
  1.1561 -					self.services[record.alias.lower()] = record
  1.1562 -					callback = lambda x: self.listener.addService(x, self.type, record.alias)
  1.1563 -					self.list.append(callback)
  1.1564 +        Updates information required by browser in the Zeroconf cache."""
  1.1565 +        if record.type == _TYPE_PTR and record.name == self.type:
  1.1566 +            expired = record.isExpired(now)
  1.1567 +            try:
  1.1568 +                oldrecord = self.services[record.alias.lower()]
  1.1569 +                if not expired:
  1.1570 +                    oldrecord.resetTTL(record)
  1.1571 +                else:
  1.1572 +                    del(self.services[record.alias.lower()])
  1.1573 +                    callback = lambda x: self.listener.removeService(x, self.type, record.alias)
  1.1574 +                    self.list.append(callback)
  1.1575 +                    return
  1.1576 +            except:
  1.1577 +                if not expired:
  1.1578 +                    self.services[record.alias.lower()] = record
  1.1579 +                    callback = lambda x: self.listener.addService(x, self.type, record.alias)
  1.1580 +                    self.list.append(callback)
  1.1581  
  1.1582 -			expires = record.getExpirationTime(75)
  1.1583 -			if expires < self.nextTime:
  1.1584 -				self.nextTime = expires
  1.1585 +            expires = record.getExpirationTime(75)
  1.1586 +            if expires < self.nextTime:
  1.1587 +                self.nextTime = expires
  1.1588  
  1.1589 -	def cancel(self):
  1.1590 -		self.done = 1
  1.1591 -		self.zeroconf.notifyAll()
  1.1592 +    def cancel(self):
  1.1593 +        self.done = 1
  1.1594 +        self.zeroconf.notifyAll()
  1.1595  
  1.1596 -	def run(self):
  1.1597 -		while 1:
  1.1598 -			event = None
  1.1599 -			now = currentTimeMillis()
  1.1600 -			if len(self.list) == 0 and self.nextTime > now:
  1.1601 -				self.zeroconf.wait(self.nextTime - now)
  1.1602 -			if globals()['_GLOBAL_DONE'] or self.done:
  1.1603 -				return
  1.1604 -			now = currentTimeMillis()
  1.1605 +    def run(self):
  1.1606 +        while 1:
  1.1607 +            event = None
  1.1608 +            now = currentTimeMillis()
  1.1609 +            if len(self.list) == 0 and self.nextTime > now:
  1.1610 +                self.zeroconf.wait(self.nextTime - now)
  1.1611 +            if globals()['_GLOBAL_DONE'] or self.done:
  1.1612 +                return
  1.1613 +            now = currentTimeMillis()
  1.1614  
  1.1615 -			if self.nextTime <= now:
  1.1616 -				out = DNSOutgoing(_FLAGS_QR_QUERY)
  1.1617 -				out.addQuestion(DNSQuestion(self.type, _TYPE_PTR, _CLASS_IN))
  1.1618 -				for record in self.services.values():
  1.1619 -					if not record.isExpired(now):
  1.1620 -						out.addAnswerAtTime(record, now)
  1.1621 -				self.zeroconf.send(out)
  1.1622 -				self.nextTime = now + self.delay
  1.1623 -				self.delay = min(20 * 1000, self.delay * 2)
  1.1624 +            if self.nextTime <= now:
  1.1625 +                out = DNSOutgoing(_FLAGS_QR_QUERY)
  1.1626 +                out.addQuestion(DNSQuestion(self.type, _TYPE_PTR, _CLASS_IN))
  1.1627 +                for record in self.services.values():
  1.1628 +                    if not record.isExpired(now):
  1.1629 +                        out.addAnswerAtTime(record, now)
  1.1630 +                self.zeroconf.send(out)
  1.1631 +                self.nextTime = now + self.delay
  1.1632 +                self.delay = min(20 * 1000, self.delay * 2)
  1.1633  
  1.1634 -			if len(self.list) > 0:
  1.1635 -				event = self.list.pop(0)
  1.1636 +            if len(self.list) > 0:
  1.1637 +                event = self.list.pop(0)
  1.1638  
  1.1639 -			if event is not None:
  1.1640 -				event(self.zeroconf)
  1.1641 +            if event is not None:
  1.1642 +                event(self.zeroconf)
  1.1643  
  1.1644  
  1.1645  class ServiceInfo(object):
  1.1646 -	"""Service information"""
  1.1647 +    """Service information"""
  1.1648  
  1.1649 -	def __init__(self, type, name, address=None, port=None, weight=0, priority=0, properties=None, server=None):
  1.1650 -		"""Create a service description.
  1.1651 +    def __init__(self, type, name, address=None, port=None, weight=0, priority=0, properties=None, server=None):
  1.1652 +        """Create a service description.
  1.1653  
  1.1654 -		type: fully qualified service type name
  1.1655 -		name: fully qualified service name
  1.1656 -		address: IP address as unsigned short, network byte order
  1.1657 -		port: port that the service runs on
  1.1658 -		weight: weight of the service
  1.1659 -		priority: priority of the service
  1.1660 -		properties: dictionary of properties (or a string holding the bytes for the text field)
  1.1661 -		server: fully qualified name for service host (defaults to name)"""
  1.1662 +        type: fully qualified service type name
  1.1663 +        name: fully qualified service name
  1.1664 +        address: IP address as unsigned short, network byte order
  1.1665 +        port: port that the service runs on
  1.1666 +        weight: weight of the service
  1.1667 +        priority: priority of the service
  1.1668 +        properties: dictionary of properties (or a string holding the bytes for the text field)
  1.1669 +        server: fully qualified name for service host (defaults to name)"""
  1.1670  
  1.1671 -		if not name.endswith(type):
  1.1672 -			raise BadTypeInNameException
  1.1673 -		self.type = type
  1.1674 -		self.name = name
  1.1675 -		self.address = address
  1.1676 -		self.port = port
  1.1677 -		self.weight = weight
  1.1678 -		self.priority = priority
  1.1679 -		if server:
  1.1680 -			self.server = server
  1.1681 -		else:
  1.1682 -			self.server = name
  1.1683 -		self.setProperties(properties)
  1.1684 +        if not name.endswith(type):
  1.1685 +            raise BadTypeInNameException
  1.1686 +        self.type = type
  1.1687 +        self.name = name
  1.1688 +        self.address = address
  1.1689 +        self.port = port
  1.1690 +        self.weight = weight
  1.1691 +        self.priority = priority
  1.1692 +        if server:
  1.1693 +            self.server = server
  1.1694 +        else:
  1.1695 +            self.server = name
  1.1696 +        self.setProperties(properties)
  1.1697  
  1.1698 -	def setProperties(self, properties):
  1.1699 -		"""Sets properties and text of this info from a dictionary"""
  1.1700 -		if isinstance(properties, dict):
  1.1701 -			self.properties = properties
  1.1702 -			list = []
  1.1703 -			result = ''
  1.1704 -			for key in properties:
  1.1705 -				value = properties[key]
  1.1706 -				if value is None:
  1.1707 -					suffix = ''.encode('utf-8')
  1.1708 -				elif isinstance(value, str):
  1.1709 -					suffix = value.encode('utf-8')
  1.1710 -				elif isinstance(value, int):
  1.1711 -					if value:
  1.1712 -						suffix = 'true'
  1.1713 -					else:
  1.1714 -						suffix = 'false'
  1.1715 -				else:
  1.1716 -					suffix = ''.encode('utf-8')
  1.1717 -				list.append('='.join((key, suffix)))
  1.1718 -			for item in list:
  1.1719 -				result = ''.join((result, struct.pack('!c', chr(len(item))), item))
  1.1720 -			self.text = result
  1.1721 -		else:
  1.1722 -			self.text = properties
  1.1723 +    def setProperties(self, properties):
  1.1724 +        """Sets properties and text of this info from a dictionary"""
  1.1725 +        if isinstance(properties, dict):
  1.1726 +            self.properties = properties
  1.1727 +            list = []
  1.1728 +            result = ''
  1.1729 +            for key in properties:
  1.1730 +                value = properties[key]
  1.1731 +                if value is None:
  1.1732 +                    suffix = ''.encode('utf-8')
  1.1733 +                elif isinstance(value, str):
  1.1734 +                    suffix = value.encode('utf-8')
  1.1735 +                elif isinstance(value, int):
  1.1736 +                    if value:
  1.1737 +                        suffix = 'true'
  1.1738 +                    else:
  1.1739 +                        suffix = 'false'
  1.1740 +                else:
  1.1741 +                    suffix = ''.encode('utf-8')
  1.1742 +                list.append('='.join((key, suffix)))
  1.1743 +            for item in list:
  1.1744 +                result = ''.join((result, struct.pack('!c', chr(len(item))), item))
  1.1745 +            self.text = result
  1.1746 +        else:
  1.1747 +            self.text = properties
  1.1748  
  1.1749 -	def setText(self, text):
  1.1750 -		"""Sets properties and text given a text field"""
  1.1751 -		self.text = text
  1.1752 -		try:
  1.1753 -			result = {}
  1.1754 -			end = len(text)
  1.1755 -			index = 0
  1.1756 -			strs = []
  1.1757 -			while index < end:
  1.1758 -				length = ord(text[index])
  1.1759 -				index += 1
  1.1760 -				strs.append(text[index:index+length])
  1.1761 -				index += length
  1.1762 +    def setText(self, text):
  1.1763 +        """Sets properties and text given a text field"""
  1.1764 +        self.text = text
  1.1765 +        try:
  1.1766 +            result = {}
  1.1767 +            end = len(text)
  1.1768 +            index = 0
  1.1769 +            strs = []
  1.1770 +            while index < end:
  1.1771 +                length = ord(text[index])
  1.1772 +                index += 1
  1.1773 +                strs.append(text[index:index+length])
  1.1774 +                index += length
  1.1775  
  1.1776 -			for s in strs:
  1.1777 -				eindex = s.find('=')
  1.1778 -				if eindex == -1:
  1.1779 -					# No equals sign at all
  1.1780 -					key = s
  1.1781 -					value = 0
  1.1782 -				else:
  1.1783 -					key = s[:eindex]
  1.1784 -					value = s[eindex+1:]
  1.1785 -					if value == 'true':
  1.1786 -						value = 1
  1.1787 -					elif value == 'false' or not value:
  1.1788 -						value = 0
  1.1789 +            for s in strs:
  1.1790 +                eindex = s.find('=')
  1.1791 +                if eindex == -1:
  1.1792 +                    # No equals sign at all
  1.1793 +                    key = s
  1.1794 +                    value = 0
  1.1795 +                else:
  1.1796 +                    key = s[:eindex]
  1.1797 +                    value = s[eindex+1:]
  1.1798 +                    if value == 'true':
  1.1799 +                        value = 1
  1.1800 +                    elif value == 'false' or not value:
  1.1801 +                        value = 0
  1.1802  
  1.1803 -				# Only update non-existent properties
  1.1804 -				if key and result.get(key) == None:
  1.1805 -					result[key] = value
  1.1806 +                # Only update non-existent properties
  1.1807 +                if key and result.get(key) == None:
  1.1808 +                    result[key] = value
  1.1809  
  1.1810 -			self.properties = result
  1.1811 -		except:
  1.1812 -			traceback.print_exc()
  1.1813 -			self.properties = None
  1.1814 +            self.properties = result
  1.1815 +        except:
  1.1816 +            traceback.print_exc()
  1.1817 +            self.properties = None
  1.1818  
  1.1819 -	def getType(self):
  1.1820 -		"""Type accessor"""
  1.1821 -		return self.type
  1.1822 +    def getType(self):
  1.1823 +        """Type accessor"""
  1.1824 +        return self.type
  1.1825  
  1.1826 -	def getName(self):
  1.1827 -		"""Name accessor"""
  1.1828 -		if self.type is not None and self.name.endswith("." + self.type):
  1.1829 -			return self.name[:len(self.name) - len(self.type) - 1]
  1.1830 -		return self.name
  1.1831 +    def getName(self):
  1.1832 +        """Name accessor"""
  1.1833 +        if self.type is not None and self.name.endswith("." + self.type):
  1.1834 +            return self.name[:len(self.name) - len(self.type) - 1]
  1.1835 +        return self.name
  1.1836  
  1.1837 -	def getAddress(self):
  1.1838 -		"""Address accessor"""
  1.1839 -		return self.address
  1.1840 +    def getAddress(self):
  1.1841 +        """Address accessor"""
  1.1842 +        return self.address
  1.1843  
  1.1844 -	def getPort(self):
  1.1845 -		"""Port accessor"""
  1.1846 -		return self.port
  1.1847 +    def getPort(self):
  1.1848 +        """Port accessor"""
  1.1849 +        return self.port
  1.1850  
  1.1851 -	def getPriority(self):
  1.1852 -		"""Pirority accessor"""
  1.1853 -		return self.priority
  1.1854 +    def getPriority(self):
  1.1855 +        """Pirority accessor"""
  1.1856 +        return self.priority
  1.1857  
  1.1858 -	def getWeight(self):
  1.1859 -		"""Weight accessor"""
  1.1860 -		return self.weight
  1.1861 +    def getWeight(self):
  1.1862 +        """Weight accessor"""
  1.1863 +        return self.weight
  1.1864  
  1.1865 -	def getProperties(self):
  1.1866 -		"""Properties accessor"""
  1.1867 -		return self.properties
  1.1868 +    def getProperties(self):
  1.1869 +        """Properties accessor"""
  1.1870 +        return self.properties
  1.1871  
  1.1872 -	def getText(self):
  1.1873 -		"""Text accessor"""
  1.1874 -		return self.text
  1.1875 +    def getText(self):
  1.1876 +        """Text accessor"""
  1.1877 +        return self.text
  1.1878  
  1.1879 -	def getServer(self):
  1.1880 -		"""Server accessor"""
  1.1881 -		return self.server
  1.1882 +    def getServer(self):
  1.1883 +        """Server accessor"""
  1.1884 +        return self.server
  1.1885  
  1.1886 -	def updateRecord(self, zeroconf, now, record):
  1.1887 -		"""Updates service information from a DNS record"""
  1.1888 -		if record is not None and not record.isExpired(now):
  1.1889 -			if record.type == _TYPE_A:
  1.1890 -				#if record.name == self.name:
  1.1891 -				if record.name == self.server:
  1.1892 -					self.address = record.address
  1.1893 -			elif record.type == _TYPE_SRV:
  1.1894 -				if record.name == self.name:
  1.1895 -					self.server = record.server
  1.1896 -					self.port = record.port
  1.1897 -					self.weight = record.weight
  1.1898 -					self.priority = record.priority
  1.1899 -					#self.address = None
  1.1900 -					self.updateRecord(zeroconf, now, zeroconf.cache.getByDetails(self.server, _TYPE_A, _CLASS_IN))
  1.1901 -			elif record.type == _TYPE_TXT:
  1.1902 -				if record.name == self.name:
  1.1903 -					self.setText(record.text)
  1.1904 +    def updateRecord(self, zeroconf, now, record):
  1.1905 +        """Updates service information from a DNS record"""
  1.1906 +        if record is not None and not record.isExpired(now):
  1.1907 +            if record.type == _TYPE_A:
  1.1908 +                #if record.name == self.name:
  1.1909 +                if record.name == self.server:
  1.1910 +                    self.address = record.address
  1.1911 +            elif record.type == _TYPE_SRV:
  1.1912 +                if record.name == self.name:
  1.1913 +                    self.server = record.server
  1.1914 +                    self.port = record.port
  1.1915 +                    self.weight = record.weight
  1.1916 +                    self.priority = record.priority
  1.1917 +                    #self.address = None
  1.1918 +                    self.updateRecord(zeroconf, now, zeroconf.cache.getByDetails(self.server, _TYPE_A, _CLASS_IN))
  1.1919 +            elif record.type == _TYPE_TXT:
  1.1920 +                if record.name == self.name:
  1.1921 +                    self.setText(record.text)
  1.1922  
  1.1923 -	def request(self, zeroconf, timeout):
  1.1924 -		"""Returns true if the service could be discovered on the
  1.1925 -		network, and updates this object with details discovered.
  1.1926 -		"""
  1.1927 -		now = currentTimeMillis()
  1.1928 -		delay = _LISTENER_TIME
  1.1929 -		next = now + delay
  1.1930 -		last = now + timeout
  1.1931 -		result = 0
  1.1932 -		try:
  1.1933 -			zeroconf.addListener(self, DNSQuestion(self.name, _TYPE_ANY, _CLASS_IN))
  1.1934 -			while self.server is None or self.address is None or self.text is None:
  1.1935 -				if last <= now:
  1.1936 -					return 0
  1.1937 -				if next <= now:
  1.1938 -					out = DNSOutgoing(_FLAGS_QR_QUERY)
  1.1939 -					out.addQuestion(DNSQuestion(self.name, _TYPE_SRV, _CLASS_IN))
  1.1940 -					out.addAnswerAtTime(zeroconf.cache.getByDetails(self.name, _TYPE_SRV, _CLASS_IN), now)
  1.1941 -					out.addQuestion(DNSQuestion(self.name, _TYPE_TXT, _CLASS_IN))
  1.1942 -					out.addAnswerAtTime(zeroconf.cache.getByDetails(self.name, _TYPE_TXT, _CLASS_IN), now)
  1.1943 -					if self.server is not None:
  1.1944 -						out.addQuestion(DNSQuestion(self.server, _TYPE_A, _CLASS_IN))
  1.1945 -						out.addAnswerAtTime(zeroconf.cache.getByDetails(self.server, _TYPE_A, _CLASS_IN), now)
  1.1946 -					zeroconf.send(out)
  1.1947 -					next = now + delay
  1.1948 -					delay = delay * 2
  1.1949 +    def request(self, zeroconf, timeout):
  1.1950 +        """Returns true if the service could be discovered on the
  1.1951 +        network, and updates this object with details discovered.
  1.1952 +        """
  1.1953 +        now = currentTimeMillis()
  1.1954 +        delay = _LISTENER_TIME
  1.1955 +        next = now + delay
  1.1956 +        last = now + timeout
  1.1957 +        result = 0
  1.1958 +        try:
  1.1959 +            zeroconf.addListener(self, DNSQuestion(self.name, _TYPE_ANY, _CLASS_IN))
  1.1960 +            while self.server is None or self.address is None or self.text is None:
  1.1961 +                if last <= now:
  1.1962 +                    return 0
  1.1963 +                if next <= now:
  1.1964 +                    out = DNSOutgoing(_FLAGS_QR_QUERY)
  1.1965 +                    out.addQuestion(DNSQuestion(self.name, _TYPE_SRV, _CLASS_IN))
  1.1966 +                    out.addAnswerAtTime(zeroconf.cache.getByDetails(self.name, _TYPE_SRV, _CLASS_IN), now)
  1.1967 +                    out.addQuestion(DNSQuestion(self.name, _TYPE_TXT, _CLASS_IN))
  1.1968 +                    out.addAnswerAtTime(zeroconf.cache.getByDetails(self.name, _TYPE_TXT, _CLASS_IN), now)
  1.1969 +                    if self.server is not None:
  1.1970 +                        out.addQuestion(DNSQuestion(self.server, _TYPE_A, _CLASS_IN))
  1.1971 +                        out.addAnswerAtTime(zeroconf.cache.getByDetails(self.server, _TYPE_A, _CLASS_IN), now)
  1.1972 +                    zeroconf.send(out)
  1.1973 +                    next = now + delay
  1.1974 +                    delay = delay * 2
  1.1975  
  1.1976 -				zeroconf.wait(min(next, last) - now)
  1.1977 -				now = currentTimeMillis()
  1.1978 -			result = 1
  1.1979 -		finally:
  1.1980 -			zeroconf.removeListener(self)
  1.1981 +                zeroconf.wait(min(next, last) - now)
  1.1982 +                now = currentTimeMillis()
  1.1983 +            result = 1
  1.1984 +        finally:
  1.1985 +            zeroconf.removeListener(self)
  1.1986  
  1.1987 -		return result
  1.1988 +        return result
  1.1989  
  1.1990 -	def __eq__(self, other):
  1.1991 -		"""Tests equality of service name"""
  1.1992 -		if isinstance(other, ServiceInfo):
  1.1993 -			return other.name == self.name
  1.1994 -		return 0
  1.1995 +    def __eq__(self, other):
  1.1996 +        """Tests equality of service name"""
  1.1997 +        if isinstance(other, ServiceInfo):
  1.1998 +            return other.name == self.name
  1.1999 +        return 0
  1.2000  
  1.2001 -	def __ne__(self, other):
  1.2002 -		"""Non-equality test"""
  1.2003 -		return not self.__eq__(other)
  1.2004 +    def __ne__(self, other):
  1.2005 +        """Non-equality test"""
  1.2006 +        return not self.__eq__(other)
  1.2007  
  1.2008 -	def __repr__(self):
  1.2009 -		"""String representation"""
  1.2010 -		result = "service[%s,%s:%s," % (self.name, socket.inet_ntoa(self.getAddress()), self.port)
  1.2011 -		if self.text is None:
  1.2012 -			result += "None"
  1.2013 -		else:
  1.2014 -			if len(self.text) < 20:
  1.2015 -				result += self.text
  1.2016 -			else:
  1.2017 -				result += self.text[:17] + "..."
  1.2018 -		result += "]"
  1.2019 -		return result
  1.2020 +    def __repr__(self):
  1.2021 +        """String representation"""
  1.2022 +        result = "service[%s,%s:%s," % (self.name, socket.inet_ntoa(self.getAddress()), self.port)
  1.2023 +        if self.text is None:
  1.2024 +            result += "None"
  1.2025 +        else:
  1.2026 +            if len(self.text) < 20:
  1.2027 +                result += self.text
  1.2028 +            else:
  1.2029 +                result += self.text[:17] + "..."
  1.2030 +        result += "]"
  1.2031 +        return result
  1.2032  
  1.2033  
  1.2034  class Zeroconf(object):
  1.2035 -	"""Implementation of Zeroconf Multicast DNS Service Discovery
  1.2036 +    """Implementation of Zeroconf Multicast DNS Service Discovery
  1.2037  
  1.2038 -	Supports registration, unregistration, queries and browsing.
  1.2039 -	"""
  1.2040 -	def __init__(self, bindaddress=None):
  1.2041 -		"""Creates an instance of the Zeroconf class, establishing
  1.2042 -		multicast communications, listening and reaping threads."""
  1.2043 -		globals()['_GLOBAL_DONE'] = 0
  1.2044 -		if bindaddress is None:
  1.2045 -			self.intf = socket.gethostbyname(socket.gethostname())
  1.2046 -		else:
  1.2047 -			self.intf = bindaddress
  1.2048 -		self.group = ('', _MDNS_PORT)
  1.2049 -		self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  1.2050 -		try:
  1.2051 -			self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  1.2052 -			self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
  1.2053 -		except:
  1.2054 -			# SO_REUSEADDR should be equivalent to SO_REUSEPORT for
  1.2055 -			# multicast UDP sockets (p 731, "TCP/IP Illustrated,
  1.2056 -			# Volume 2"), but some BSD-derived systems require
  1.2057 -			# SO_REUSEPORT to be specified explicity.  Also, not all
  1.2058 -			# versions of Python have SO_REUSEPORT available.  So
  1.2059 -			# if you're on a BSD-based system, and haven't upgraded
  1.2060 -			# to Python 2.3 yet, you may find this library doesn't
  1.2061 -			# work as expected.
  1.2062 -			#
  1.2063 -			pass
  1.2064 -		self.socket.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_TTL, 255)
  1.2065 -		self.socket.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_LOOP, 1)
  1.2066 -		try:
  1.2067 -			self.socket.bind(self.group)
  1.2068 -		except:
  1.2069 -			# Some versions of linux raise an exception even though
  1.2070 -			# the SO_REUSE* options have been set, so ignore it
  1.2071 -			#
  1.2072 -			pass
  1.2073 -		#self.socket.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_IF, socket.inet_aton(self.intf) + socket.inet_aton('0.0.0.0'))
  1.2074 -		self.socket.setsockopt(socket.SOL_IP, socket.IP_ADD_MEMBERSHIP, socket.inet_aton(_MDNS_ADDR) + socket.inet_aton('0.0.0.0'))
  1.2075 +    Supports registration, unregistration, queries and browsing.
  1.2076 +    """
  1.2077 +    def __init__(self, bindaddress=None):
  1.2078 +        """Creates an instance of the Zeroconf class, establishing
  1.2079 +        multicast communications, listening and reaping threads."""
  1.2080 +        globals()['_GLOBAL_DONE'] = 0
  1.2081 +        if bindaddress is None:
  1.2082 +            self.intf = socket.gethostbyname(socket.gethostname())
  1.2083 +        else:
  1.2084 +            self.intf = bindaddress
  1.2085 +        self.group = ('', _MDNS_PORT)
  1.2086 +        self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  1.2087 +        try:
  1.2088 +            self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  1.2089 +            self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
  1.2090 +        except:
  1.2091 +            # SO_REUSEADDR should be equivalent to SO_REUSEPORT for
  1.2092 +            # multicast UDP sockets (p 731, "TCP/IP Illustrated,
  1.2093 +            # Volume 2"), but some BSD-derived systems require
  1.2094 +            # SO_REUSEPORT to be specified explicity.  Also, not all
  1.2095 +            # versions of Python have SO_REUSEPORT available.  So
  1.2096 +            # if you're on a BSD-based system, and haven't upgraded
  1.2097 +            # to Python 2.3 yet, you may find this library doesn't
  1.2098 +            # work as expected.
  1.2099 +            #
  1.2100 +            pass
  1.2101 +        self.socket.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_TTL, 255)
  1.2102 +        self.socket.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_LOOP, 1)
  1.2103 +        try:
  1.2104 +            self.socket.bind(self.group)
  1.2105 +        except:
  1.2106 +            # Some versions of linux raise an exception even though
  1.2107 +            # the SO_REUSE* options have been set, so ignore it
  1.2108 +            #
  1.2109 +            pass
  1.2110 +        #self.socket.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_IF, socket.inet_aton(self.intf) + socket.inet_aton('0.0.0.0'))
  1.2111 +        self.socket.setsockopt(socket.SOL_IP, socket.IP_ADD_MEMBERSHIP, socket.inet_aton(_MDNS_ADDR) + socket.inet_aton('0.0.0.0'))
  1.2112  
  1.2113 -		self.listeners = []
  1.2114 -		self.browsers = []
  1.2115 -		self.services = {}
  1.2116 -		self.servicetypes = {}
  1.2117 +        self.listeners = []
  1.2118 +        self.browsers = []
  1.2119 +        self.services = {}
  1.2120 +        self.servicetypes = {}
  1.2121  
  1.2122 -		self.cache = DNSCache()
  1.2123 +        self.cache = DNSCache()
  1.2124  
  1.2125 -		self.condition = threading.Condition()
  1.2126 +        self.condition = threading.Condition()
  1.2127  
  1.2128 -		self.engine = Engine(self)
  1.2129 -		self.listener = Listener(self)
  1.2130 -		self.reaper = Reaper(self)
  1.2131 +        self.engine = Engine(self)
  1.2132 +        self.listener = Listener(self)
  1.2133 +        self.reaper = Reaper(self)
  1.2134  
  1.2135 -	def isLoopback(self):
  1.2136 -		return self.intf.startswith("127.0.0.1")
  1.2137 +    def isLoopback(self):
  1.2138 +        return self.intf.startswith("127.0.0.1")
  1.2139  
  1.2140 -	def isLinklocal(self):
  1.2141 -		return self.intf.startswith("169.254.")
  1.2142 +    def isLinklocal(self):
  1.2143 +        return self.intf.startswith("169.254.")
  1.2144  
  1.2145 -	def wait(self, timeout):
  1.2146 -		"""Calling thread waits for a given number of milliseconds or
  1.2147 -		until notified."""
  1.2148 -		self.condition.acquire()
  1.2149 -		self.condition.wait(timeout/1000)
  1.2150 -		self.condition.release()
  1.2151 +    def wait(self, timeout):
  1.2152 +        """Calling thread waits for a given number of milliseconds or
  1.2153 +        until notified."""
  1.2154 +        self.condition.acquire()
  1.2155 +        self.condition.wait(timeout/1000)
  1.2156 +        self.condition.release()
  1.2157  
  1.2158 -	def notifyAll(self):
  1.2159 -		"""Notifies all waiting threads"""
  1.2160 -		self.condition.acquire()
  1.2161 -		self.condition.notifyAll()
  1.2162 -		self.condition.release()
  1.2163 +    def notifyAll(self):
  1.2164 +        """Notifies all waiting threads"""
  1.2165 +        self.condition.acquire()
  1.2166 +        self.condition.notifyAll()
  1.2167 +        self.condition.release()
  1.2168  
  1.2169 -	def getServiceInfo(self, type, name, timeout=3000):
  1.2170 -		"""Returns network's service information for a particular
  1.2171 -		name and type, or None if no service matches by the timeout,
  1.2172 -		which defaults to 3 seconds."""
  1.2173 -		info = ServiceInfo(type, name)
  1.2174 -		if info.request(self, timeout):
  1.2175 -			return info
  1.2176 -		return None
  1.2177 +    def getServiceInfo(self, type, name, timeout=3000):
  1.2178 +        """Returns network's service information for a particular
  1.2179 +        name and type, or None if no service matches by the timeout,
  1.2180 +        which defaults to 3 seconds."""
  1.2181 +        info = ServiceInfo(type, name)
  1.2182 +        if info.request(self, timeout):
  1.2183 +            return info
  1.2184 +        return None
  1.2185  
  1.2186 -	def addServiceListener(self, type, listener):
  1.2187 -		"""Adds a listener for a particular service type.  This object
  1.2188 -		will then have its updateRecord method called when information
  1.2189 -		arrives for that type."""
  1.2190 -		self.removeServiceListener(listener)
  1.2191 -		self.browsers.append(ServiceBrowser(self, type, listener))
  1.2192 +    def addServiceListener(self, type, listener):
  1.2193 +        """Adds a listener for a particular service type.  This object
  1.2194 +        will then have its updateRecord method called when information
  1.2195 +        arrives for that type."""
  1.2196 +        self.removeServiceListener(listener)
  1.2197 +        self.browsers.append(ServiceBrowser(self, type, listener))
  1.2198  
  1.2199 -	def removeServiceListener(self, listener):
  1.2200 -		"""Removes a listener from the set that is currently listening."""
  1.2201 -		for browser in self.browsers:
  1.2202 -			if browser.listener == listener:
  1.2203 -				browser.cancel()
  1.2204 -				del(browser)
  1.2205 +    def removeServiceListener(self, listener):
  1.2206 +        """Removes a listener from the set that is currently listening."""
  1.2207 +        for browser in self.browsers:
  1.2208 +            if browser.listener == listener:
  1.2209 +                browser.cancel()
  1.2210 +                del(browser)
  1.2211  
  1.2212 -	def registerService(self, info, ttl=_DNS_TTL):
  1.2213 -		"""Registers service information to the network with a default TTL
  1.2214 -		of 60 seconds.  Zeroconf will then respond to requests for
  1.2215 -		information for that service.  The name of the service may be
  1.2216 -		changed if needed to make it unique on the network."""
  1.2217 -		self.checkService(info)
  1.2218 -		self.services[info.name.lower()] = info
  1.2219 -		if self.servicetypes.has_key(info.type):
  1.2220 -			self.servicetypes[info.type]+=1
  1.2221 -		else:
  1.2222 -			self.servicetypes[info.type]=1
  1.2223 -		now = currentTimeMillis()
  1.2224 -		nextTime = now
  1.2225 -		i = 0
  1.2226 -		while i < 3:
  1.2227 -			if now < nextTime:
  1.2228 -				self.wait(nextTime - now)
  1.2229 -				now = currentTimeMillis()
  1.2230 -				continue
  1.2231 -			out = DNSOutgoing(_FLAGS_QR_RESPONSE | _FLAGS_AA)
  1.2232 -			out.addAnswerAtTime(DNSPointer(info.type, _TYPE_PTR, _CLASS_IN, ttl, info.name), 0)
  1.2233 -			out.addAnswerAtTime(DNSService(info.name, _TYPE_SRV, _CLASS_IN, ttl, info.priority, info.weight, info.port, info.server), 0)
  1.2234 -			out.addAnswerAtTime(DNSText(info.name, _TYPE_TXT, _CLASS_IN, ttl, info.text), 0)
  1.2235 -			if info.address:
  1.2236 -				out.addAnswerAtTime(DNSAddress(info.server, _TYPE_A, _CLASS_IN, ttl, info.address), 0)
  1.2237 -			self.send(out)
  1.2238 -			i += 1
  1.2239 -			nextTime += _REGISTER_TIME
  1.2240 +    def registerService(self, info, ttl=_DNS_TTL):
  1.2241 +        """Registers service information to the network with a default TTL
  1.2242 +        of 60 seconds.  Zeroconf will then respond to requests for
  1.2243 +        information for that service.  The name of the service may be
  1.2244 +        changed if needed to make it unique on the network."""
  1.2245 +        self.checkService(info)
  1.2246 +        self.services[info.name.lower()] = info
  1.2247 +        if self.servicetypes.has_key(info.type):
  1.2248 +            self.servicetypes[info.type]+=1
  1.2249 +        else:
  1.2250 +            self.servicetypes[info.type]=1
  1.2251 +        now = currentTimeMillis()
  1.2252 +        nextTime = now
  1.2253 +        i = 0
  1.2254 +        while i < 3:
  1.2255 +            if now < nextTime:
  1.2256 +                self.wait(nextTime - now)
  1.2257 +                now = currentTimeMillis()
  1.2258 +                continue
  1.2259 +            out = DNSOutgoing(_FLAGS_QR_RESPONSE | _FLAGS_AA)
  1.2260 +            out.addAnswerAtTime(DNSPointer(info.type, _TYPE_PTR, _CLASS_IN, ttl, info.name), 0)
  1.2261 +            out.addAnswerAtTime(DNSService(info.name, _TYPE_SRV, _CLASS_IN, ttl, info.priority, info.weight, info.port, info.server), 0)
  1.2262 +            out.addAnswerAtTime(DNSText(info.name, _TYPE_TXT, _CLASS_IN, ttl, info.text), 0)
  1.2263 +            if info.address:
  1.2264 +                out.addAnswerAtTime(DNSAddress(info.server, _TYPE_A, _CLASS_IN, ttl, info.address), 0)
  1.2265 +            self.send(out)
  1.2266 +            i += 1
  1.2267 +            nextTime += _REGISTER_TIME
  1.2268  
  1.2269 -	def unregisterService(self, info):
  1.2270 -		"""Unregister a service."""
  1.2271 -		try:
  1.2272 -			del(self.services[info.name.lower()])
  1.2273 -			if self.servicetypes[info.type]>1:
  1.2274 -				self.servicetypes[info.type]-=1
  1.2275 -			else:
  1.2276 -				del self.servicetypes[info.type]
  1.2277 -		except:
  1.2278 -			pass
  1.2279 -		now = currentTimeMillis()
  1.2280 -		nextTime = now
  1.2281 -		i = 0
  1.2282 -		while i < 3:
  1.2283 -			if now < nextTime:
  1.2284 -				self.wait(nextTime - now)
  1.2285 -				now = currentTimeMillis()
  1.2286 -				continue
  1.2287 -			out = DNSOutgoing(_FLAGS_QR_RESPONSE | _FLAGS_AA)
  1.2288 -			out.addAnswerAtTime(DNSPointer(info.type, _TYPE_PTR, _CLASS_IN, 0, info.name), 0)
  1.2289 -			out.addAnswerAtTime(DNSService(info.name, _TYPE_SRV, _CLASS_IN, 0, info.priority, info.weight, info.port, info.name), 0)
  1.2290 -			out.addAnswerAtTime(DNSText(info.name, _TYPE_TXT, _CLASS_IN, 0, info.text), 0)
  1.2291 -			if info.address:
  1.2292 -				out.addAnswerAtTime(DNSAddress(info.server, _TYPE_A, _CLASS_IN, 0, info.address), 0)
  1.2293 -			self.send(out)
  1.2294 -			i += 1
  1.2295 -			nextTime += _UNREGISTER_TIME
  1.2296 +    def unregisterService(self, info):
  1.2297 +        """Unregister a service."""
  1.2298 +        try:
  1.2299 +            del(self.services[info.name.lower()])
  1.2300 +            if self.servicetypes[info.type]>1:
  1.2301 +                self.servicetypes[info.type]-=1
  1.2302 +            else:
  1.2303 +                del self.servicetypes[info.type]
  1.2304 +        except:
  1.2305 +            pass
  1.2306 +        now = currentTimeMillis()
  1.2307 +        nextTime = now
  1.2308 +        i = 0
  1.2309 +        while i < 3:
  1.2310 +            if now < nextTime:
  1.2311 +                self.wait(nextTime - now)
  1.2312 +                now = currentTimeMillis()
  1.2313 +                continue
  1.2314 +            out = DNSOutgoing(_FLAGS_QR_RESPONSE | _FLAGS_AA)
  1.2315 +            out.addAnswerAtTime(DNSPointer(info.type, _TYPE_PTR, _CLASS_IN, 0, info.name), 0)
  1.2316 +            out.addAnswerAtTime(DNSService(info.name, _TYPE_SRV, _CLASS_IN, 0, info.priority, info.weight, info.port, info.name), 0)
  1.2317 +            out.addAnswerAtTime(DNSText(info.name, _TYPE_TXT, _CLASS_IN, 0, info.text), 0)
  1.2318 +            if info.address:
  1.2319 +                out.addAnswerAtTime(DNSAddress(info.server, _TYPE_A, _CLASS_IN, 0, info.address), 0)
  1.2320 +            self.send(out)
  1.2321 +            i += 1
  1.2322 +            nextTime += _UNREGISTER_TIME
  1.2323  
  1.2324 -	def unregisterAllServices(self):
  1.2325 -		"""Unregister all registered services."""
  1.2326 -		if len(self.services) > 0:
  1.2327 -			now = currentTimeMillis()
  1.2328 -			nextTime = now
  1.2329 -			i = 0
  1.2330 -			while i < 3:
  1.2331 -				if now < nextTime:
  1.2332 -					self.wait(nextTime - now)
  1.2333 -					now = currentTimeMillis()
  1.2334 -					continue
  1.2335 -				out = DNSOutgoing(_FLAGS_QR_RESPONSE | _FLAGS_AA)
  1.2336 -				for info in self.services.values():
  1.2337 -					out.addAnswerAtTime(DNSPointer(info.type, _TYPE_PTR, _CLASS_IN, 0, info.name), 0)
  1.2338 -					out.addAnswerAtTime(DNSService(info.name, _TYPE_SRV, _CLASS_IN, 0, info.priority, info.weight, info.port, info.server), 0)
  1.2339 -					out.addAnswerAtTime(DNSText(info.name, _TYPE_TXT, _CLASS_IN, 0, info.text), 0)
  1.2340 -					if info.address:
  1.2341 -						out.addAnswerAtTime(DNSAddress(info.server, _TYPE_A, _CLASS_IN, 0, info.address), 0)
  1.2342 -				self.send(out)
  1.2343 -				i += 1
  1.2344 -				nextTime += _UNREGISTER_TIME
  1.2345 +    def unregisterAllServices(self):
  1.2346 +        """Unregister all registered services."""
  1.2347 +        if len(self.services) > 0:
  1.2348 +            now = currentTimeMillis()
  1.2349 +            nextTime = now
  1.2350 +            i = 0
  1.2351 +            while i < 3:
  1.2352 +                if now < nextTime:
  1.2353 +                    self.wait(nextTime - now)
  1.2354 +                    now = currentTimeMillis()
  1.2355 +                    continue
  1.2356 +                out = DNSOutgoing(_FLAGS_QR_RESPONSE | _FLAGS_AA)
  1.2357 +                for info in self.services.values():
  1.2358 +                    out.addAnswerAtTime(DNSPointer(info.type, _TYPE_PTR, _CLASS_IN, 0, info.name), 0)
  1.2359 +                    out.addAnswerAtTime(DNSService(info.name, _TYPE_SRV, _CLASS_IN, 0, info.priority, info.weight, info.port, info.server), 0)
  1.2360 +                    out.addAnswerAtTime(DNSText(info.name, _TYPE_TXT, _CLASS_IN, 0, info.text), 0)
  1.2361 +                    if info.address:
  1.2362 +                        out.addAnswerAtTime(DNSAddress(info.server, _TYPE_A, _CLASS_IN, 0, info.address), 0)
  1.2363 +                self.send(out)
  1.2364 +                i += 1
  1.2365 +                nextTime += _UNREGISTER_TIME
  1.2366  
  1.2367 -	def checkService(self, info):
  1.2368 -		"""Checks the network for a unique service name, modifying the
  1.2369 -		ServiceInfo passed in if it is not unique."""
  1.2370 -		now = currentTimeMillis()
  1.2371 -		nextTime = now
  1.2372 -		i = 0
  1.2373 -		while i < 3:
  1.2374 -			for record in self.cache.entriesWithName(info.type):
  1.2375 -				if record.type == _TYPE_PTR and not record.isExpired(now) and record.alias == info.name:
  1.2376 -					if (info.name.find('.') < 0):
  1.2377 -						info.name = info.name + ".[" + info.address + ":" + info.port + "]." + info.type
  1.2378 -						self.checkService(info)
  1.2379 -						return
  1.2380 -					raise NonUniqueNameException
  1.2381 -			if now < nextTime:
  1.2382 -				self.wait(nextTime - now)
  1.2383 -				now = currentTimeMillis()
  1.2384 -				continue
  1.2385 -			out = DNSOutgoing(_FLAGS_QR_QUERY | _FLAGS_AA)
  1.2386 -			self.debug = out
  1.2387 -			out.addQuestion(DNSQuestion(info.type, _TYPE_PTR, _CLASS_IN))
  1.2388 -			out.addAuthorativeAnswer(DNSPointer(info.type, _TYPE_PTR, _CLASS_IN, _DNS_TTL, info.name))
  1.2389 -			self.send(out)
  1.2390 -			i += 1
  1.2391 -			nextTime += _CHECK_TIME
  1.2392 +    def checkService(self, info):
  1.2393 +        """Checks the network for a unique service name, modifying the
  1.2394 +        ServiceInfo passed in if it is not unique."""
  1.2395 +        now = currentTimeMillis()
  1.2396 +        nextTime = now
  1.2397 +        i = 0
  1.2398 +        while i < 3:
  1.2399 +            for record in self.cache.entriesWithName(info.type):
  1.2400 +                if record.type == _TYPE_PTR and not record.isExpired(now) and record.alias == info.name:
  1.2401 +                    if (info.name.find('.') < 0):
  1.2402 +                        info.name = info.name + ".[" + info.address + ":" + info.port + "]." + info.type
  1.2403 +                        self.checkService(info)
  1.2404 +                        return
  1.2405 +                    raise NonUniqueNameException
  1.2406 +            if now < nextTime:
  1.2407 +                self.wait(nextTime - now)
  1.2408 +                now = currentTimeMillis()
  1.2409 +                continue
  1.2410 +            out = DNSOutgoing(_FLAGS_QR_QUERY | _FLAGS_AA)
  1.2411 +            self.debug = out
  1.2412 +            out.addQuestion(DNSQuestion(info.type, _TYPE_PTR, _CLASS_IN))
  1.2413 +            out.addAuthorativeAnswer(DNSPointer(info.type, _TYPE_PTR, _CLASS_IN, _DNS_TTL, info.name))
  1.2414 +            self.send(out)
  1.2415 +            i += 1
  1.2416 +            nextTime += _CHECK_TIME
  1.2417  
  1.2418 -	def addListener(self, listener, question):
  1.2419 -		"""Adds a listener for a given question.  The listener will have
  1.2420 -		its updateRecord method called when information is available to
  1.2421 -		answer the question."""
  1.2422 -		now = currentTimeMillis()
  1.2423 -		self.listeners.append(listener)
  1.2424 -		if question is not None:
  1.2425 -			for record in self.cache.entriesWithName(question.name):
  1.2426 -				if question.answeredBy(record) and not record.isExpired(now):
  1.2427 -					listener.updateRecord(self, now, record)
  1.2428 -		self.notifyAll()
  1.2429 +    def addListener(self, listener, question):
  1.2430 +        """Adds a listener for a given question.  The listener will have
  1.2431 +        its updateRecord method called when information is available to
  1.2432 +        answer the question."""
  1.2433 +        now = currentTimeMillis()
  1.2434 +        self.listeners.append(listener)
  1.2435 +        if question is not None:
  1.2436 +            for record in self.cache.entriesWithName(question.name):
  1.2437 +                if question.answeredBy(record) and not record.isExpired(now):
  1.2438 +                    listener.updateRecord(self, now, record)
  1.2439 +        self.notifyAll()
  1.2440  
  1.2441 -	def removeListener(self, listener):
  1.2442 -		"""Removes a listener."""
  1.2443 -		try:
  1.2444 -			self.listeners.remove(listener)
  1.2445 -			self.notifyAll()
  1.2446 -		except:
  1.2447 -			pass
  1.2448 +    def removeListener(self, listener):
  1.2449 +        """Removes a listener."""
  1.2450 +        try:
  1.2451 +            self.listeners.remove(listener)
  1.2452 +            self.notifyAll()
  1.2453 +        except:
  1.2454 +            pass
  1.2455  
  1.2456 -	def updateRecord(self, now, rec):
  1.2457 -		"""Used to notify listeners of new information that has updated
  1.2458 -		a record."""
  1.2459 -		for listener in self.listeners:
  1.2460 -			listener.updateRecord(self, now, rec)
  1.2461 -		self.notifyAll()
  1.2462 +    def updateRecord(self, now, rec):
  1.2463 +        """Used to notify listeners of new information that has updated
  1.2464 +        a record."""
  1.2465 +        for listener in self.listeners:
  1.2466 +            listener.updateRecord(self, now, rec)
  1.2467 +        self.notifyAll()
  1.2468  
  1.2469 -	def handleResponse(self, msg):
  1.2470 -		"""Deal with incoming response packets.  All answers
  1.2471 -		are held in the cache, and listeners are notified."""
  1.2472 -		now = currentTimeMillis()
  1.2473 -		for record in msg.answers:
  1.2474 -			expired = record.isExpired(now)
  1.2475 -			if record in self.cache.entries():
  1.2476 -				if expired:
  1.2477 -					self.cache.remove(record)
  1.2478 -				else:
  1.2479 -					entry = self.cache.get(record)
  1.2480 -					if entry is not None:
  1.2481 -						entry.resetTTL(record)
  1.2482 -						record = entry
  1.2483 -			else:
  1.2484 -				self.cache.add(record)
  1.2485 +    def handleResponse(self, msg):
  1.2486 +        """Deal with incoming response packets.  All answers
  1.2487 +        are held in the cache, and listeners are notified."""
  1.2488 +        now = currentTimeMillis()
  1.2489 +        for record in msg.answers:
  1.2490 +            expired = record.isExpired(now)
  1.2491 +            if record in self.cache.entries():
  1.2492 +                if expired:
  1.2493 +                    self.cache.remove(record)
  1.2494 +                else:
  1.2495 +                    entry = self.cache.get(record)
  1.2496 +                    if entry is not None:
  1.2497 +                        entry.resetTTL(record)
  1.2498 +                        record = entry
  1.2499 +            else:
  1.2500 +                self.cache.add(record)
  1.2501  
  1.2502 -			self.updateRecord(now, record)
  1.2503 +            self.updateRecord(now, record)
  1.2504  
  1.2505 -	def handleQuery(self, msg, addr, port):
  1.2506 -		"""Deal with incoming query packets.  Provides a response if
  1.2507 -		possible."""
  1.2508 -		out = None
  1.2509 +    def handleQuery(self, msg, addr, port):
  1.2510 +        """Deal with incoming query packets.  Provides a response if
  1.2511 +        possible."""
  1.2512 +        out = None
  1.2513  
  1.2514 -		# Support unicast client responses
  1.2515 -		#
  1.2516 -		if port != _MDNS_PORT:
  1.2517 -			out = DNSOutgoing(_FLAGS_QR_RESPONSE | _FLAGS_AA, 0)
  1.2518 -			for question in msg.questions:
  1.2519 -				out.addQuestion(question)
  1.2520 +        # Support unicast client responses
  1.2521 +        #
  1.2522 +        if port != _MDNS_PORT:
  1.2523 +            out = DNSOutgoing(_FLAGS_QR_RESPONSE | _FLAGS_AA, 0)
  1.2524 +            for question in msg.questions:
  1.2525 +                out.addQuestion(question)
  1.2526  
  1.2527 -		for question in msg.questions:
  1.2528 -			if question.type == _TYPE_PTR:
  1.2529 -				if question.name == "_services._dns-sd._udp.local.":
  1.2530 -					for stype in self.servicetypes.keys():
  1.2531 -						if out is None:
  1.2532 -							out = DNSOutgoing(_FLAGS_QR_RESPONSE | _FLAGS_AA)
  1.2533 -						out.addAnswer(msg, DNSPointer("_services._dns-sd._udp.local.", _TYPE_PTR, _CLASS_IN, _DNS_TTL, stype))
  1.2534 -				for service in self.services.values():
  1.2535 -					if question.name == service.type:
  1.2536 -						if out is None:
  1.2537 -							out = DNSOutgoing(_FLAGS_QR_RESPONSE | _FLAGS_AA)
  1.2538 -						out.addAnswer(msg, DNSPointer(service.type, _TYPE_PTR, _CLASS_IN, _DNS_TTL, service.name))
  1.2539 -			else:
  1.2540 -				try:
  1.2541 -					if out is None:
  1.2542 -						out = DNSOutgoing(_FLAGS_QR_RESPONSE | _FLAGS_AA)
  1.2543 +        for question in msg.questions:
  1.2544 +            if question.type == _TYPE_PTR:
  1.2545 +                if question.name == "_services._dns-sd._udp.local.":
  1.2546 +                    for stype in self.servicetypes.keys():
  1.2547 +                        if out is None:
  1.2548 +                            out = DNSOutgoing(_FLAGS_QR_RESPONSE | _FLAGS_AA)
  1.2549 +                        out.addAnswer(msg, DNSPointer("_services._dns-sd._udp.local.", _TYPE_PTR, _CLASS_IN, _DNS_TTL, stype))
  1.2550 +                for service in self.services.values():
  1.2551 +                    if question.name == service.type:
  1.2552 +                        if out is None:
  1.2553 +                            out = DNSOutgoing(_FLAGS_QR_RESPONSE | _FLAGS_AA)
  1.2554 +                        out.addAnswer(msg, DNSPointer(service.type, _TYPE_PTR, _CLASS_IN, _DNS_TTL, service.name))
  1.2555 +            else:
  1.2556 +                try:
  1.2557 +                    if out is None:
  1.2558 +                        out = DNSOutgoing(_FLAGS_QR_RESPONSE | _FLAGS_AA)
  1.2559  
  1.2560 -					# Answer A record queries for any service addresses we know
  1.2561 -					if question.type == _TYPE_A or question.type == _TYPE_ANY:
  1.2562 -						for service in self.services.values():
  1.2563 -							if service.server == question.name.lower():
  1.2564 -								out.addAnswer(msg, DNSAddress(question.name, _TYPE_A, _CLASS_IN | _CLASS_UNIQUE, _DNS_TTL, service.address))
  1.2565 +                    # Answer A record queries for any service addresses we know
  1.2566 +                    if question.type == _TYPE_A or question.type == _TYPE_ANY:
  1.2567 +                        for service in self.services.values():
  1.2568 +                            if service.server == question.name.lower():
  1.2569 +                                out.addAnswer(msg, DNSAddress(question.name, _TYPE_A, _CLASS_IN | _CLASS_UNIQUE, _DNS_TTL, service.address))
  1.2570  
  1.2571 -					service = self.services.get(question.name.lower(), None)
  1.2572 -					if not service: continue
  1.2573 +                    service = self.services.get(question.name.lower(), None)
  1.2574 +                    if not service: continue
  1.2575  
  1.2576 -					if question.type == _TYPE_SRV or question.type == _TYPE_ANY:
  1.2577 -						out.addAnswer(msg, DNSService(question.name, _TYPE_SRV, _CLASS_IN | _CLASS_UNIQUE, _DNS_TTL, service.priority, service.weight, service.port, service.server))
  1.2578 -					if question.type == _TYPE_TXT or question.type == _TYPE_ANY:
  1.2579 -						out.addAnswer(msg, DNSText(question.name, _TYPE_TXT, _CLASS_IN | _CLASS_UNIQUE, _DNS_TTL, service.text))
  1.2580 -					if question.type == _TYPE_SRV:
  1.2581 -						out.addAdditionalAnswer(DNSAddress(service.server, _TYPE_A, _CLASS_IN | _CLASS_UNIQUE, _DNS_TTL, service.address))
  1.2582 -				except:
  1.2583 -					traceback.print_exc()
  1.2584 +                    if question.type == _TYPE_SRV or question.type == _TYPE_ANY:
  1.2585 +                        out.addAnswer(msg, DNSService(question.name, _TYPE_SRV, _CLASS_IN | _CLASS_UNIQUE, _DNS_TTL, service.priority, service.weight, service.port, service.server))
  1.2586 +                    if question.type == _TYPE_TXT or question.type == _TYPE_ANY:
  1.2587 +                        out.addAnswer(msg, DNSText(question.name, _TYPE_TXT, _CLASS_IN | _CLASS_UNIQUE, _DNS_TTL, service.text))
  1.2588 +                    if question.type == _TYPE_SRV:
  1.2589 +                        out.addAdditionalAnswer(DNSAddress(service.server, _TYPE_A, _CLASS_IN | _CLASS_UNIQUE, _DNS_TTL, service.address))
  1.2590 +                except:
  1.2591 +                    traceback.print_exc()
  1.2592  
  1.2593 -		if out is not None and out.answers:
  1.2594 -			out.id = msg.id
  1.2595 -			self.send(out, addr, port)
  1.2596 +        if out is not None and out.answers:
  1.2597 +            out.id = msg.id
  1.2598 +            self.send(out, addr, port)
  1.2599  
  1.2600 -	def send(self, out, addr = _MDNS_ADDR, port = _MDNS_PORT):
  1.2601 -		"""Sends an outgoing packet."""
  1.2602 -		# This is a quick test to see if we can parse the packets we generate
  1.2603 -		#temp = DNSIncoming(out.packet())
  1.2604 -		try:
  1.2605 -			self.socket.sendto(out.packet(), 0, (addr, port))
  1.2606 -		except:
  1.2607 -			# Ignore this, it may be a temporary loss of network connection
  1.2608 -			pass
  1.2609 +    def send(self, out, addr = _MDNS_ADDR, port = _MDNS_PORT):
  1.2610 +        """Sends an outgoing packet."""
  1.2611 +        # This is a quick test to see if we can parse the packets we generate
  1.2612 +        #temp = DNSIncoming(out.packet())
  1.2613 +        try:
  1.2614 +            self.socket.sendto(out.packet(), 0, (addr, port))
  1.2615 +        except:
  1.2616 +            # Ignore this, it may be a temporary loss of network connection
  1.2617 +            pass
  1.2618  
  1.2619 -	def close(self):
  1.2620 -		"""Ends the background threads, and prevent this instance from
  1.2621 -		servicing further queries."""
  1.2622 -		if globals()['_GLOBAL_DONE'] == 0:
  1.2623 -			globals()['_GLOBAL_DONE'] = 1
  1.2624 -			self.notifyAll()
  1.2625 -			self.engine.notify()
  1.2626 -			self.unregisterAllServices()
  1.2627 -			self.socket.setsockopt(socket.SOL_IP, socket.IP_DROP_MEMBERSHIP, socket.inet_aton(_MDNS_ADDR) + socket.inet_aton('0.0.0.0'))
  1.2628 -			self.socket.close()
  1.2629 +    def close(self):
  1.2630 +        """Ends the background threads, and prevent this instance from
  1.2631 +        servicing further queries."""
  1.2632 +        if globals()['_GLOBAL_DONE'] == 0:
  1.2633 +            globals()['_GLOBAL_DONE'] = 1
  1.2634 +            self.notifyAll()
  1.2635 +            self.engine.notify()
  1.2636 +            self.unregisterAllServices()
  1.2637 +            self.socket.setsockopt(socket.SOL_IP, socket.IP_DROP_MEMBERSHIP, socket.inet_aton(_MDNS_ADDR) + socket.inet_aton('0.0.0.0'))
  1.2638 +            self.socket.close()
  1.2639  
  1.2640  # Test a few module features, including service registration, service
  1.2641  # query (for Zoe), and service unregistration.
  1.2642  
  1.2643  if __name__ == '__main__':
  1.2644 -	print "Multicast DNS Service Discovery for Python, version", __version__
  1.2645 -	r = Zeroconf()
  1.2646 -	print "1. Testing registration of a service..."
  1.2647 -	desc = {'version':'0.10','a':'test value', 'b':'another value'}
  1.2648 -	info = ServiceInfo("_http._tcp.local.", "My Service Name._http._tcp.local.", socket.inet_aton("127.0.0.1"), 1234, 0, 0, desc)
  1.2649 -	print "   Registering service..."
  1.2650 -	r.registerService(info)
  1.2651 -	print "   Registration done."
  1.2652 -	print "2. Testing query of service information..."
  1.2653 -	print "   Getting ZOE service:", str(r.getServiceInfo("_http._tcp.local.", "ZOE._http._tcp.local."))
  1.2654 -	print "   Query done."
  1.2655 -	print "3. Testing query of own service..."
  1.2656 -	print "   Getting self:", str(r.getServiceInfo("_http._tcp.local.", "My Service Name._http._tcp.local."))
  1.2657 -	print "   Query done."
  1.2658 -	print "4. Testing unregister of service information..."
  1.2659 -	r.unregisterService(info)
  1.2660 -	print "   Unregister done."
  1.2661 -	r.close()
  1.2662 +    print "Multicast DNS Service Discovery for Python, version", __version__
  1.2663 +    r = Zeroconf()
  1.2664 +    print "1. Testing registration of a service..."
  1.2665 +    desc = {'version':'0.10','a':'test value', 'b':'another value'}
  1.2666 +    info = ServiceInfo("_http._tcp.local.", "My Service Name._http._tcp.local.", socket.inet_aton("127.0.0.1"), 1234, 0, 0, desc)
  1.2667 +    print "   Registering service..."
  1.2668 +    r.registerService(info)
  1.2669 +    print "   Registration done."
  1.2670 +    print "2. Testing query of service information..."
  1.2671 +    print "   Getting ZOE service:", str(r.getServiceInfo("_http._tcp.local.", "ZOE._http._tcp.local."))
  1.2672 +    print "   Query done."
  1.2673 +    print "3. Testing query of own service..."
  1.2674 +    print "   Getting self:", str(r.getServiceInfo("_http._tcp.local.", "My Service Name._http._tcp.local."))
  1.2675 +    print "   Query done."
  1.2676 +    print "4. Testing unregister of service information..."
  1.2677 +    r.unregisterService(info)
  1.2678 +    print "   Unregister done."
  1.2679 +    r.close()
Repositories maintained by Alexander Solovyov