Show More
@@ -34,7 +34,7 b' from __future__ import absolute_import, ' | |||||
34 | - hostinfo |
|
34 | - hostinfo | |
35 | ignore unknown DNS record types |
|
35 | ignore unknown DNS record types | |
36 | fixes to name decoding |
|
36 | fixes to name decoding | |
37 |
works alongside other processes using port 5353 (e.g. |
|
37 | works alongside other processes using port 5353 (e.g. Mac OS X) | |
38 | tested against Mac OS X 10.3.2's mDNSResponder |
|
38 | tested against Mac OS X 10.3.2's mDNSResponder | |
39 | corrections to removal of list entries for service browser""" |
|
39 | corrections to removal of list entries for service browser""" | |
40 |
|
40 | |||
@@ -228,7 +228,8 b' class DNSEntry(object):' | |||||
228 | def __eq__(self, other): |
|
228 | def __eq__(self, other): | |
229 | """Equality test on name, type, and class""" |
|
229 | """Equality test on name, type, and class""" | |
230 | if isinstance(other, DNSEntry): |
|
230 | if isinstance(other, DNSEntry): | |
231 |
return self.name == other.name and self.type == other.type and |
|
231 | return (self.name == other.name and self.type == other.type and | |
|
232 | self.clazz == other.clazz) | |||
232 | return 0 |
|
233 | return 0 | |
233 |
|
234 | |||
234 | def __ne__(self, other): |
|
235 | def __ne__(self, other): | |
@@ -251,7 +252,8 b' class DNSEntry(object):' | |||||
251 |
|
252 | |||
252 | def toString(self, hdr, other): |
|
253 | def toString(self, hdr, other): | |
253 | """String representation with additional information""" |
|
254 | """String representation with additional information""" | |
254 | result = "%s[%s,%s" % (hdr, self.getType(self.type), self.getClazz(self.clazz)) |
|
255 | result = ("%s[%s,%s" % | |
|
256 | (hdr, self.getType(self.type), self.getClazz(self.clazz))) | |||
255 | if self.unique: |
|
257 | if self.unique: | |
256 | result += "-unique," |
|
258 | result += "-unique," | |
257 | else: |
|
259 | else: | |
@@ -273,7 +275,9 b' class DNSQuestion(DNSEntry):' | |||||
273 |
|
275 | |||
274 | def answeredBy(self, rec): |
|
276 | def answeredBy(self, rec): | |
275 | """Returns true if the question is answered by the record""" |
|
277 | """Returns true if the question is answered by the record""" | |
276 | return self.clazz == rec.clazz and (self.type == rec.type or self.type == _TYPE_ANY) and self.name == rec.name |
|
278 | return (self.clazz == rec.clazz and | |
|
279 | (self.type == rec.type or self.type == _TYPE_ANY) and | |||
|
280 | self.name == rec.name) | |||
277 |
|
281 | |||
278 | def __repr__(self): |
|
282 | def __repr__(self): | |
279 | """String representation""" |
|
283 | """String representation""" | |
@@ -338,7 +342,8 b' class DNSRecord(DNSEntry):' | |||||
338 |
|
342 | |||
339 | def toString(self, other): |
|
343 | def toString(self, other): | |
340 | """String representation with additional information""" |
|
344 | """String representation with additional information""" | |
341 | arg = "%s/%s,%s" % (self.ttl, self.getRemainingTTL(currentTimeMillis()), other) |
|
345 | arg = ("%s/%s,%s" % | |
|
346 | (self.ttl, self.getRemainingTTL(currentTimeMillis()), other)) | |||
342 | return DNSEntry.toString(self, "record", arg) |
|
347 | return DNSEntry.toString(self, "record", arg) | |
343 |
|
348 | |||
344 | class DNSAddress(DNSRecord): |
|
349 | class DNSAddress(DNSRecord): | |
@@ -453,7 +458,10 b' class DNSService(DNSRecord):' | |||||
453 | def __eq__(self, other): |
|
458 | def __eq__(self, other): | |
454 | """Tests equality on priority, weight, port and server""" |
|
459 | """Tests equality on priority, weight, port and server""" | |
455 | if isinstance(other, DNSService): |
|
460 | if isinstance(other, DNSService): | |
456 | return self.priority == other.priority and self.weight == other.weight and self.port == other.port and self.server == other.server |
|
461 | return (self.priority == other.priority and | |
|
462 | self.weight == other.weight and | |||
|
463 | self.port == other.port and | |||
|
464 | self.server == other.server) | |||
457 | return 0 |
|
465 | return 0 | |
458 |
|
466 | |||
459 | def __repr__(self): |
|
467 | def __repr__(self): | |
@@ -498,7 +506,8 b' class DNSIncoming(object):' | |||||
498 | length = struct.calcsize(format) |
|
506 | length = struct.calcsize(format) | |
499 | for i in range(0, self.numQuestions): |
|
507 | for i in range(0, self.numQuestions): | |
500 | name = self.readName() |
|
508 | name = self.readName() | |
501 |
info = struct.unpack(format, |
|
509 | info = struct.unpack(format, | |
|
510 | self.data[self.offset:self.offset+length]) | |||
502 | self.offset += length |
|
511 | self.offset += length | |
503 |
|
512 | |||
504 | try: |
|
513 | try: | |
@@ -538,28 +547,39 b' class DNSIncoming(object):' | |||||
538 | return info[0] |
|
547 | return info[0] | |
539 |
|
548 | |||
540 | def readOthers(self): |
|
549 | def readOthers(self): | |
541 |
"""Reads |
|
550 | """Reads answers, authorities and additionals section of the packet""" | |
542 | format = '!HHiH' |
|
551 | format = '!HHiH' | |
543 | length = struct.calcsize(format) |
|
552 | length = struct.calcsize(format) | |
544 | n = self.numAnswers + self.numAuthorities + self.numAdditionals |
|
553 | n = self.numAnswers + self.numAuthorities + self.numAdditionals | |
545 | for i in range(0, n): |
|
554 | for i in range(0, n): | |
546 | domain = self.readName() |
|
555 | domain = self.readName() | |
547 |
info = struct.unpack(format, |
|
556 | info = struct.unpack(format, | |
|
557 | self.data[self.offset:self.offset+length]) | |||
548 | self.offset += length |
|
558 | self.offset += length | |
549 |
|
559 | |||
550 | rec = None |
|
560 | rec = None | |
551 | if info[0] == _TYPE_A: |
|
561 | if info[0] == _TYPE_A: | |
552 |
rec = DNSAddress(domain, info[0], info[1], info[2], |
|
562 | rec = DNSAddress(domain, info[0], info[1], info[2], | |
|
563 | self.readString(4)) | |||
553 | elif info[0] == _TYPE_CNAME or info[0] == _TYPE_PTR: |
|
564 | elif info[0] == _TYPE_CNAME or info[0] == _TYPE_PTR: | |
554 |
rec = DNSPointer(domain, info[0], info[1], info[2], |
|
565 | rec = DNSPointer(domain, info[0], info[1], info[2], | |
|
566 | self.readName()) | |||
555 | elif info[0] == _TYPE_TXT: |
|
567 | elif info[0] == _TYPE_TXT: | |
556 |
rec = DNSText(domain, info[0], info[1], info[2], |
|
568 | rec = DNSText(domain, info[0], info[1], info[2], | |
|
569 | self.readString(info[3])) | |||
557 | elif info[0] == _TYPE_SRV: |
|
570 | elif info[0] == _TYPE_SRV: | |
558 | rec = DNSService(domain, info[0], info[1], info[2], self.readUnsignedShort(), self.readUnsignedShort(), self.readUnsignedShort(), self.readName()) |
|
571 | rec = DNSService(domain, info[0], info[1], info[2], | |
|
572 | self.readUnsignedShort(), | |||
|
573 | self.readUnsignedShort(), | |||
|
574 | self.readUnsignedShort(), | |||
|
575 | self.readName()) | |||
559 | elif info[0] == _TYPE_HINFO: |
|
576 | elif info[0] == _TYPE_HINFO: | |
560 |
rec = DNSHinfo(domain, info[0], info[1], info[2], |
|
577 | rec = DNSHinfo(domain, info[0], info[1], info[2], | |
|
578 | self.readCharacterString(), | |||
|
579 | self.readCharacterString()) | |||
561 | elif info[0] == _TYPE_AAAA: |
|
580 | elif info[0] == _TYPE_AAAA: | |
562 |
rec = DNSAddress(domain, info[0], info[1], info[2], |
|
581 | rec = DNSAddress(domain, info[0], info[1], info[2], | |
|
582 | self.readString(16)) | |||
563 | else: |
|
583 | else: | |
564 | # Try to ignore types we don't know about |
|
584 | # Try to ignore types we don't know about | |
565 | # this may mean the rest of the name is |
|
585 | # this may mean the rest of the name is | |
@@ -972,7 +992,8 b' class ServiceBrowser(threading.Thread):' | |||||
972 |
|
992 | |||
973 | self.done = 0 |
|
993 | self.done = 0 | |
974 |
|
994 | |||
975 |
self.zeroconf.addListener(self, DNSQuestion(self.type, _TYPE_PTR, |
|
995 | self.zeroconf.addListener(self, DNSQuestion(self.type, _TYPE_PTR, | |
|
996 | _CLASS_IN)) | |||
976 | self.start() |
|
997 | self.start() | |
977 |
|
998 | |||
978 | def updateRecord(self, zeroconf, now, record): |
|
999 | def updateRecord(self, zeroconf, now, record): | |
@@ -987,13 +1008,15 b' class ServiceBrowser(threading.Thread):' | |||||
987 | oldrecord.resetTTL(record) |
|
1008 | oldrecord.resetTTL(record) | |
988 | else: |
|
1009 | else: | |
989 | del(self.services[record.alias.lower()]) |
|
1010 | del(self.services[record.alias.lower()]) | |
990 | callback = lambda x: self.listener.removeService(x, self.type, record.alias) |
|
1011 | callback = (lambda x: | |
|
1012 | self.listener.removeService(x, self.type, record.alias)) | |||
991 | self.list.append(callback) |
|
1013 | self.list.append(callback) | |
992 | return |
|
1014 | return | |
993 | except Exception: |
|
1015 | except Exception: | |
994 | if not expired: |
|
1016 | if not expired: | |
995 | self.services[record.alias.lower()] = record |
|
1017 | self.services[record.alias.lower()] = record | |
996 | callback = lambda x: self.listener.addService(x, self.type, record.alias) |
|
1018 | callback = (lambda x: | |
|
1019 | self.listener.addService(x, self.type, record.alias)) | |||
997 | self.list.append(callback) |
|
1020 | self.list.append(callback) | |
998 |
|
1021 | |||
999 | expires = record.getExpirationTime(75) |
|
1022 | expires = record.getExpirationTime(75) | |
@@ -1034,7 +1057,8 b' class ServiceBrowser(threading.Thread):' | |||||
1034 | class ServiceInfo(object): |
|
1057 | class ServiceInfo(object): | |
1035 | """Service information""" |
|
1058 | """Service information""" | |
1036 |
|
1059 | |||
1037 |
def __init__(self, type, name, address=None, port=None, weight=0, |
|
1060 | def __init__(self, type, name, address=None, port=None, weight=0, | |
|
1061 | priority=0, properties=None, server=None): | |||
1038 | """Create a service description. |
|
1062 | """Create a service description. | |
1039 |
|
1063 | |||
1040 | type: fully qualified service type name |
|
1064 | type: fully qualified service type name | |
@@ -1043,7 +1067,8 b' class ServiceInfo(object):' | |||||
1043 | port: port that the service runs on |
|
1067 | port: port that the service runs on | |
1044 | weight: weight of the service |
|
1068 | weight: weight of the service | |
1045 | priority: priority of the service |
|
1069 | priority: priority of the service | |
1046 |
properties: dictionary of properties (or a string holding the bytes for |
|
1070 | properties: dictionary of properties (or a string holding the bytes for | |
|
1071 | the text field) | |||
1047 | server: fully qualified name for service host (defaults to name)""" |
|
1072 | server: fully qualified name for service host (defaults to name)""" | |
1048 |
|
1073 | |||
1049 | if not name.endswith(type): |
|
1074 | if not name.endswith(type): | |
@@ -1081,7 +1106,8 b' class ServiceInfo(object):' | |||||
1081 | suffix = '' |
|
1106 | suffix = '' | |
1082 | list.append('='.join((key, suffix))) |
|
1107 | list.append('='.join((key, suffix))) | |
1083 | for item in list: |
|
1108 | for item in list: | |
1084 |
result = ''.join((result, struct.pack('!c', chr(len(item))), |
|
1109 | result = ''.join((result, struct.pack('!c', chr(len(item))), | |
|
1110 | item)) | |||
1085 | self.text = result |
|
1111 | self.text = result | |
1086 | else: |
|
1112 | else: | |
1087 | self.text = properties |
|
1113 | self.text = properties | |
@@ -1175,7 +1201,9 b' class ServiceInfo(object):' | |||||
1175 | self.weight = record.weight |
|
1201 | self.weight = record.weight | |
1176 | self.priority = record.priority |
|
1202 | self.priority = record.priority | |
1177 | #self.address = None |
|
1203 | #self.address = None | |
1178 |
self.updateRecord(zeroconf, now, |
|
1204 | self.updateRecord(zeroconf, now, | |
|
1205 | zeroconf.cache.getByDetails(self.server, | |||
|
1206 | _TYPE_A, _CLASS_IN)) | |||
1179 | elif record.type == _TYPE_TXT: |
|
1207 | elif record.type == _TYPE_TXT: | |
1180 | if record.name == self.name: |
|
1208 | if record.name == self.name: | |
1181 | self.setText(record.text) |
|
1209 | self.setText(record.text) | |
@@ -1190,19 +1218,34 b' class ServiceInfo(object):' | |||||
1190 | last = now + timeout |
|
1218 | last = now + timeout | |
1191 | result = 0 |
|
1219 | result = 0 | |
1192 | try: |
|
1220 | try: | |
1193 |
zeroconf.addListener(self, DNSQuestion(self.name, _TYPE_ANY, |
|
1221 | zeroconf.addListener(self, DNSQuestion(self.name, _TYPE_ANY, | |
1194 | while self.server is None or self.address is None or self.text is None: |
|
1222 | _CLASS_IN)) | |
|
1223 | while (self.server is None or self.address is None or | |||
|
1224 | self.text is None): | |||
1195 | if last <= now: |
|
1225 | if last <= now: | |
1196 | return 0 |
|
1226 | return 0 | |
1197 | if next <= now: |
|
1227 | if next <= now: | |
1198 | out = DNSOutgoing(_FLAGS_QR_QUERY) |
|
1228 | out = DNSOutgoing(_FLAGS_QR_QUERY) | |
1199 |
out.addQuestion(DNSQuestion(self.name, _TYPE_SRV, |
|
1229 | out.addQuestion(DNSQuestion(self.name, _TYPE_SRV, | |
1200 | out.addAnswerAtTime(zeroconf.cache.getByDetails(self.name, _TYPE_SRV, _CLASS_IN), now) |
|
1230 | _CLASS_IN)) | |
1201 | out.addQuestion(DNSQuestion(self.name, _TYPE_TXT, _CLASS_IN)) |
|
1231 | out.addAnswerAtTime( | |
1202 |
|
|
1232 | zeroconf.cache.getByDetails(self.name, | |
|
1233 | _TYPE_SRV, | |||
|
1234 | _CLASS_IN), | |||
|
1235 | now) | |||
|
1236 | out.addQuestion(DNSQuestion(self.name, _TYPE_TXT, | |||
|
1237 | _CLASS_IN)) | |||
|
1238 | out.addAnswerAtTime( | |||
|
1239 | zeroconf.cache.getByDetails(self.name, _TYPE_TXT, | |||
|
1240 | _CLASS_IN), | |||
|
1241 | now) | |||
1203 | if self.server is not None: |
|
1242 | if self.server is not None: | |
1204 |
out.addQuestion( |
|
1243 | out.addQuestion( | |
1205 |
|
|
1244 | DNSQuestion(self.server, _TYPE_A, _CLASS_IN)) | |
|
1245 | out.addAnswerAtTime( | |||
|
1246 | zeroconf.cache.getByDetails(self.server, _TYPE_A, | |||
|
1247 | _CLASS_IN), | |||
|
1248 | now) | |||
1206 | zeroconf.send(out) |
|
1249 | zeroconf.send(out) | |
1207 | next = now + delay |
|
1250 | next = now + delay | |
1208 | delay = delay * 2 |
|
1251 | delay = delay * 2 | |
@@ -1227,7 +1270,8 b' class ServiceInfo(object):' | |||||
1227 |
|
1270 | |||
1228 | def __repr__(self): |
|
1271 | def __repr__(self): | |
1229 | """String representation""" |
|
1272 | """String representation""" | |
1230 | result = "service[%s,%s:%s," % (self.name, socket.inet_ntoa(self.getAddress()), self.port) |
|
1273 | result = ("service[%s,%s:%s," % | |
|
1274 | (self.name, socket.inet_ntoa(self.getAddress()), self.port)) | |||
1231 | if self.text is None: |
|
1275 | if self.text is None: | |
1232 | result += "None" |
|
1276 | result += "None" | |
1233 | else: |
|
1277 | else: | |
@@ -1276,7 +1320,8 b' class Zeroconf(object):' | |||||
1276 | # Some versions of linux raise an exception even though |
|
1320 | # Some versions of linux raise an exception even though | |
1277 | # SO_REUSEADDR and SO_REUSEPORT have been set, so ignore it |
|
1321 | # SO_REUSEADDR and SO_REUSEPORT have been set, so ignore it | |
1278 | pass |
|
1322 | pass | |
1279 |
self.socket.setsockopt(socket.SOL_IP, socket.IP_ADD_MEMBERSHIP, |
|
1323 | self.socket.setsockopt(socket.SOL_IP, socket.IP_ADD_MEMBERSHIP, | |
|
1324 | socket.inet_aton(_MDNS_ADDR) + socket.inet_aton('0.0.0.0')) | |||
1280 |
|
1325 | |||
1281 | self.listeners = [] |
|
1326 | self.listeners = [] | |
1282 | self.browsers = [] |
|
1327 | self.browsers = [] | |
@@ -1353,11 +1398,20 b' class Zeroconf(object):' | |||||
1353 | now = currentTimeMillis() |
|
1398 | now = currentTimeMillis() | |
1354 | continue |
|
1399 | continue | |
1355 | out = DNSOutgoing(_FLAGS_QR_RESPONSE | _FLAGS_AA) |
|
1400 | out = DNSOutgoing(_FLAGS_QR_RESPONSE | _FLAGS_AA) | |
1356 |
out.addAnswerAtTime(DNSPointer(info.type, _TYPE_PTR, |
|
1401 | out.addAnswerAtTime(DNSPointer(info.type, _TYPE_PTR, | |
1357 | out.addAnswerAtTime(DNSService(info.name, _TYPE_SRV, _CLASS_IN, ttl, info.priority, info.weight, info.port, info.server), 0) |
|
1402 | _CLASS_IN, ttl, info.name), 0) | |
1358 | out.addAnswerAtTime(DNSText(info.name, _TYPE_TXT, _CLASS_IN, ttl, info.text), 0) |
|
1403 | out.addAnswerAtTime( | |
|
1404 | DNSService( | |||
|
1405 | info.name, _TYPE_SRV, | |||
|
1406 | _CLASS_IN, ttl, info.priority, info.weight, info.port, | |||
|
1407 | info.server), | |||
|
1408 | 0) | |||
|
1409 | out.addAnswerAtTime( | |||
|
1410 | DNSText(info.name, _TYPE_TXT, _CLASS_IN, ttl, info.text), | |||
|
1411 | 0) | |||
1359 | if info.address: |
|
1412 | if info.address: | |
1360 |
out.addAnswerAtTime(DNSAddress(info.server, _TYPE_A, |
|
1413 | out.addAnswerAtTime(DNSAddress(info.server, _TYPE_A, | |
|
1414 | _CLASS_IN, ttl, info.address), 0) | |||
1361 | self.send(out) |
|
1415 | self.send(out) | |
1362 | i += 1 |
|
1416 | i += 1 | |
1363 | nextTime += _REGISTER_TIME |
|
1417 | nextTime += _REGISTER_TIME | |
@@ -1381,11 +1435,18 b' class Zeroconf(object):' | |||||
1381 | now = currentTimeMillis() |
|
1435 | now = currentTimeMillis() | |
1382 | continue |
|
1436 | continue | |
1383 | out = DNSOutgoing(_FLAGS_QR_RESPONSE | _FLAGS_AA) |
|
1437 | out = DNSOutgoing(_FLAGS_QR_RESPONSE | _FLAGS_AA) | |
1384 | out.addAnswerAtTime(DNSPointer(info.type, _TYPE_PTR, _CLASS_IN, 0, info.name), 0) |
|
1438 | out.addAnswerAtTime( | |
1385 |
|
|
1439 | DNSPointer(info.type, _TYPE_PTR, _CLASS_IN, 0, info.name), 0) | |
1386 | out.addAnswerAtTime(DNSText(info.name, _TYPE_TXT, _CLASS_IN, 0, info.text), 0) |
|
1440 | out.addAnswerAtTime( | |
|
1441 | DNSService(info.name, _TYPE_SRV, | |||
|
1442 | _CLASS_IN, 0, info.priority, info.weight, info.port, | |||
|
1443 | info.name), | |||
|
1444 | 0) | |||
|
1445 | out.addAnswerAtTime(DNSText(info.name, _TYPE_TXT, | |||
|
1446 | _CLASS_IN, 0, info.text), 0) | |||
1387 | if info.address: |
|
1447 | if info.address: | |
1388 |
out.addAnswerAtTime(DNSAddress(info.server, _TYPE_A, |
|
1448 | out.addAnswerAtTime(DNSAddress(info.server, _TYPE_A, | |
|
1449 | _CLASS_IN, 0, info.address), 0) | |||
1389 | self.send(out) |
|
1450 | self.send(out) | |
1390 | i += 1 |
|
1451 | i += 1 | |
1391 | nextTime += _UNREGISTER_TIME |
|
1452 | nextTime += _UNREGISTER_TIME | |
@@ -1403,11 +1464,18 b' class Zeroconf(object):' | |||||
1403 | continue |
|
1464 | continue | |
1404 | out = DNSOutgoing(_FLAGS_QR_RESPONSE | _FLAGS_AA) |
|
1465 | out = DNSOutgoing(_FLAGS_QR_RESPONSE | _FLAGS_AA) | |
1405 | for info in self.services.values(): |
|
1466 | for info in self.services.values(): | |
1406 |
out.addAnswerAtTime(DNSPointer(info.type, _TYPE_PTR, |
|
1467 | out.addAnswerAtTime(DNSPointer(info.type, _TYPE_PTR, | |
1407 | out.addAnswerAtTime(DNSService(info.name, _TYPE_SRV, _CLASS_IN, 0, info.priority, info.weight, info.port, info.server), 0) |
|
1468 | _CLASS_IN, 0, info.name), 0) | |
1408 | out.addAnswerAtTime(DNSText(info.name, _TYPE_TXT, _CLASS_IN, 0, info.text), 0) |
|
1469 | out.addAnswerAtTime( | |
|
1470 | DNSService(info.name, _TYPE_SRV, | |||
|
1471 | _CLASS_IN, 0, info.priority, info.weight, | |||
|
1472 | info.port, info.server), | |||
|
1473 | 0) | |||
|
1474 | out.addAnswerAtTime(DNSText(info.name, _TYPE_TXT, | |||
|
1475 | _CLASS_IN, 0, info.text), 0) | |||
1409 | if info.address: |
|
1476 | if info.address: | |
1410 |
out.addAnswerAtTime(DNSAddress(info.server, _TYPE_A, |
|
1477 | out.addAnswerAtTime(DNSAddress(info.server, _TYPE_A, | |
|
1478 | _CLASS_IN, 0, info.address), 0) | |||
1411 | self.send(out) |
|
1479 | self.send(out) | |
1412 | i += 1 |
|
1480 | i += 1 | |
1413 | nextTime += _UNREGISTER_TIME |
|
1481 | nextTime += _UNREGISTER_TIME | |
@@ -1420,9 +1488,11 b' class Zeroconf(object):' | |||||
1420 | i = 0 |
|
1488 | i = 0 | |
1421 | while i < 3: |
|
1489 | while i < 3: | |
1422 | for record in self.cache.entriesWithName(info.type): |
|
1490 | for record in self.cache.entriesWithName(info.type): | |
1423 |
if record.type == _TYPE_PTR and not record.isExpired(now) and |
|
1491 | if (record.type == _TYPE_PTR and not record.isExpired(now) and | |
|
1492 | record.alias == info.name): | |||
1424 | if (info.name.find('.') < 0): |
|
1493 | if (info.name.find('.') < 0): | |
1425 | info.name = info.name + ".[" + info.address + ":" + info.port + "]." + info.type |
|
1494 | info.name = ("%w.[%s:%d].%s" % | |
|
1495 | (info.name, info.address, info.port, info.type)) | |||
1426 | self.checkService(info) |
|
1496 | self.checkService(info) | |
1427 | return |
|
1497 | return | |
1428 | raise NonUniqueNameException |
|
1498 | raise NonUniqueNameException | |
@@ -1433,7 +1503,8 b' class Zeroconf(object):' | |||||
1433 | out = DNSOutgoing(_FLAGS_QR_QUERY | _FLAGS_AA) |
|
1503 | out = DNSOutgoing(_FLAGS_QR_QUERY | _FLAGS_AA) | |
1434 | self.debug = out |
|
1504 | self.debug = out | |
1435 | out.addQuestion(DNSQuestion(info.type, _TYPE_PTR, _CLASS_IN)) |
|
1505 | out.addQuestion(DNSQuestion(info.type, _TYPE_PTR, _CLASS_IN)) | |
1436 |
out.addAuthoritativeAnswer(DNSPointer(info.type, _TYPE_PTR, |
|
1506 | out.addAuthoritativeAnswer(DNSPointer(info.type, _TYPE_PTR, | |
|
1507 | _CLASS_IN, _DNS_TTL, info.name)) | |||
1437 | self.send(out) |
|
1508 | self.send(out) | |
1438 | i += 1 |
|
1509 | i += 1 | |
1439 | nextTime += _CHECK_TIME |
|
1510 | nextTime += _CHECK_TIME | |
@@ -1502,12 +1573,17 b' class Zeroconf(object):' | |||||
1502 | for stype in self.servicetypes.keys(): |
|
1573 | for stype in self.servicetypes.keys(): | |
1503 | if out is None: |
|
1574 | if out is None: | |
1504 | out = DNSOutgoing(_FLAGS_QR_RESPONSE | _FLAGS_AA) |
|
1575 | out = DNSOutgoing(_FLAGS_QR_RESPONSE | _FLAGS_AA) | |
1505 | out.addAnswer(msg, DNSPointer("_services._dns-sd._udp.local.", _TYPE_PTR, _CLASS_IN, _DNS_TTL, stype)) |
|
1576 | out.addAnswer(msg, | |
|
1577 | DNSPointer( | |||
|
1578 | "_services._dns-sd._udp.local.", | |||
|
1579 | _TYPE_PTR, _CLASS_IN, | |||
|
1580 | _DNS_TTL, stype)) | |||
1506 | for service in self.services.values(): |
|
1581 | for service in self.services.values(): | |
1507 | if question.name == service.type: |
|
1582 | if question.name == service.type: | |
1508 | if out is None: |
|
1583 | if out is None: | |
1509 | out = DNSOutgoing(_FLAGS_QR_RESPONSE | _FLAGS_AA) |
|
1584 | out = DNSOutgoing(_FLAGS_QR_RESPONSE | _FLAGS_AA) | |
1510 |
out.addAnswer(msg, DNSPointer(service.type, _TYPE_PTR, |
|
1585 | out.addAnswer(msg, DNSPointer(service.type, _TYPE_PTR, | |
|
1586 | _CLASS_IN, _DNS_TTL, service.name)) | |||
1511 | else: |
|
1587 | else: | |
1512 | try: |
|
1588 | try: | |
1513 | if out is None: |
|
1589 | if out is None: | |
@@ -1517,17 +1593,31 b' class Zeroconf(object):' | |||||
1517 | if question.type == _TYPE_A or question.type == _TYPE_ANY: |
|
1593 | if question.type == _TYPE_A or question.type == _TYPE_ANY: | |
1518 | for service in self.services.values(): |
|
1594 | for service in self.services.values(): | |
1519 | if service.server == question.name.lower(): |
|
1595 | if service.server == question.name.lower(): | |
1520 | out.addAnswer(msg, DNSAddress(question.name, _TYPE_A, _CLASS_IN | _CLASS_UNIQUE, _DNS_TTL, service.address)) |
|
1596 | out.addAnswer(msg, | |
|
1597 | DNSAddress(question.name, _TYPE_A, | |||
|
1598 | _CLASS_IN | _CLASS_UNIQUE, | |||
|
1599 | _DNS_TTL, service.address)) | |||
1521 |
|
1600 | |||
1522 | service = self.services.get(question.name.lower(), None) |
|
1601 | service = self.services.get(question.name.lower(), None) | |
1523 | if not service: continue |
|
1602 | if not service: continue | |
1524 |
|
1603 | |||
1525 |
if question.type == _TYPE_SRV or |
|
1604 | if (question.type == _TYPE_SRV or | |
1526 | out.addAnswer(msg, DNSService(question.name, _TYPE_SRV, _CLASS_IN | _CLASS_UNIQUE, _DNS_TTL, service.priority, service.weight, service.port, service.server)) |
|
1605 | question.type == _TYPE_ANY): | |
1527 | if question.type == _TYPE_TXT or question.type == _TYPE_ANY: |
|
1606 | out.addAnswer(msg, | |
1528 | out.addAnswer(msg, DNSText(question.name, _TYPE_TXT, _CLASS_IN | _CLASS_UNIQUE, _DNS_TTL, service.text)) |
|
1607 | DNSService(question.name, _TYPE_SRV, | |
|
1608 | _CLASS_IN | _CLASS_UNIQUE, | |||
|
1609 | _DNS_TTL, service.priority, | |||
|
1610 | service.weight, service.port, | |||
|
1611 | service.server)) | |||
|
1612 | if (question.type == _TYPE_TXT or | |||
|
1613 | question.type == _TYPE_ANY): | |||
|
1614 | out.addAnswer(msg, DNSText(question.name, _TYPE_TXT, | |||
|
1615 | _CLASS_IN | _CLASS_UNIQUE, _DNS_TTL, service.text)) | |||
1529 | if question.type == _TYPE_SRV: |
|
1616 | if question.type == _TYPE_SRV: | |
1530 | out.addAdditionalAnswer(DNSAddress(service.server, _TYPE_A, _CLASS_IN | _CLASS_UNIQUE, _DNS_TTL, service.address)) |
|
1617 | out.addAdditionalAnswer( | |
|
1618 | DNSAddress(service.server, _TYPE_A, | |||
|
1619 | _CLASS_IN | _CLASS_UNIQUE, | |||
|
1620 | _DNS_TTL, service.address)) | |||
1531 | except Exception: |
|
1621 | except Exception: | |
1532 | traceback.print_exc() |
|
1622 | traceback.print_exc() | |
1533 |
|
1623 | |||
@@ -1553,7 +1643,8 b' class Zeroconf(object):' | |||||
1553 | self.notifyAll() |
|
1643 | self.notifyAll() | |
1554 | self.engine.notify() |
|
1644 | self.engine.notify() | |
1555 | self.unregisterAllServices() |
|
1645 | self.unregisterAllServices() | |
1556 |
self.socket.setsockopt(socket.SOL_IP, socket.IP_DROP_MEMBERSHIP, |
|
1646 | self.socket.setsockopt(socket.SOL_IP, socket.IP_DROP_MEMBERSHIP, | |
|
1647 | socket.inet_aton(_MDNS_ADDR) + socket.inet_aton('0.0.0.0')) | |||
1557 | self.socket.close() |
|
1648 | self.socket.close() | |
1558 |
|
1649 | |||
1559 | # Test a few module features, including service registration, service |
|
1650 | # Test a few module features, including service registration, service | |
@@ -1564,15 +1655,20 b" if __name__ == '__main__':" | |||||
1564 | r = Zeroconf() |
|
1655 | r = Zeroconf() | |
1565 | print("1. Testing registration of a service...") |
|
1656 | print("1. Testing registration of a service...") | |
1566 | desc = {'version':'0.10','a':'test value', 'b':'another value'} |
|
1657 | desc = {'version':'0.10','a':'test value', 'b':'another value'} | |
1567 | info = ServiceInfo("_http._tcp.local.", "My Service Name._http._tcp.local.", socket.inet_aton("127.0.0.1"), 1234, 0, 0, desc) |
|
1658 | info = ServiceInfo("_http._tcp.local.", | |
|
1659 | "My Service Name._http._tcp.local.", | |||
|
1660 | socket.inet_aton("127.0.0.1"), 1234, 0, 0, desc) | |||
1568 | print(" Registering service...") |
|
1661 | print(" Registering service...") | |
1569 | r.registerService(info) |
|
1662 | r.registerService(info) | |
1570 | print(" Registration done.") |
|
1663 | print(" Registration done.") | |
1571 | print("2. Testing query of service information...") |
|
1664 | print("2. Testing query of service information...") | |
1572 | print(" Getting ZOE service:", str(r.getServiceInfo("_http._tcp.local.", "ZOE._http._tcp.local."))) |
|
1665 | print(" Getting ZOE service:", | |
|
1666 | str(r.getServiceInfo("_http._tcp.local.", "ZOE._http._tcp.local."))) | |||
1573 | print(" Query done.") |
|
1667 | print(" Query done.") | |
1574 | print("3. Testing query of own service...") |
|
1668 | print("3. Testing query of own service...") | |
1575 | print(" Getting self:", str(r.getServiceInfo("_http._tcp.local.", "My Service Name._http._tcp.local."))) |
|
1669 | print(" Getting self:", | |
|
1670 | str(r.getServiceInfo("_http._tcp.local.", | |||
|
1671 | "My Service Name._http._tcp.local."))) | |||
1576 | print(" Query done.") |
|
1672 | print(" Query done.") | |
1577 | print("4. Testing unregister of service information...") |
|
1673 | print("4. Testing unregister of service information...") | |
1578 | r.unregisterService(info) |
|
1674 | r.unregisterService(info) |
General Comments 0
You need to be logged in to leave comments.
Login now