Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit ea64265

Browse filesBrowse files
inwotepjstasiak
authored andcommitted
Add additional recommended records to PTR responses (python-zeroconf#184)
RFC6763 indicates a server should include the SRV/TXT/A/AAAA records when responding to a PTR record request. This optimization ensures the client doesn't have to then query for these additional records. It has been observed that when multiple Windows 10 machines are monitoring for the same service, this unoptimized response to the PTR record request can cause extremely high CPU usage in both the DHCP Client & Device Association service (I suspect due to all clients having to then sending/receiving the additional queries/responses).
1 parent ceb602c commit ea64265
Copy full SHA for ea64265

File tree

2 files changed

+91
-2
lines changed
Filter options

2 files changed

+91
-2
lines changed

‎test_zeroconf.py

Copy file name to clipboardExpand all lines: test_zeroconf.py
+57-2Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -621,7 +621,7 @@ def send(out, addr=r._MDNS_ADDR, port=r._MDNS_PORT):
621621
query.add_question(r.DNSQuestion(info.name, r._TYPE_TXT, r._CLASS_IN))
622622
query.add_question(r.DNSQuestion(info.server, r._TYPE_A, r._CLASS_IN))
623623
zc.handle_query(r.DNSIncoming(query.packet()), r._MDNS_ADDR, r._MDNS_PORT)
624-
assert nbr_answers == 4 and nbr_additionals == 1 and nbr_authorities == 0
624+
assert nbr_answers == 4 and nbr_additionals == 4 and nbr_authorities == 0
625625
nbr_answers = nbr_additionals = nbr_authorities = 0
626626

627627
# unregister
@@ -644,7 +644,7 @@ def send(out, addr=r._MDNS_ADDR, port=r._MDNS_PORT):
644644
query.add_question(r.DNSQuestion(info.name, r._TYPE_TXT, r._CLASS_IN))
645645
query.add_question(r.DNSQuestion(info.server, r._TYPE_A, r._CLASS_IN))
646646
zc.handle_query(r.DNSIncoming(query.packet()), r._MDNS_ADDR, r._MDNS_PORT)
647-
assert nbr_answers == 4 and nbr_additionals == 1 and nbr_authorities == 0
647+
assert nbr_answers == 4 and nbr_additionals == 4 and nbr_authorities == 0
648648
nbr_answers = nbr_additionals = nbr_authorities = 0
649649

650650
# unregister
@@ -1036,3 +1036,58 @@ def test_multiple_addresses():
10361036
)
10371037

10381038
assert info.addresses == [address, address]
1039+
1040+
1041+
def test_ptr_optimization():
1042+
1043+
# instantiate a zeroconf instance
1044+
zc = Zeroconf(interfaces=['127.0.0.1'])
1045+
1046+
# service definition
1047+
type_ = "_test-srvc-type._tcp.local."
1048+
name = "xxxyyy"
1049+
registration_name = "%s.%s" % (name, type_)
1050+
1051+
desc = {'path': '/~paulsm/'}
1052+
info = ServiceInfo(type_, registration_name, socket.inet_aton("10.0.1.2"), 80, 0, 0, desc, "ash-2.local.")
1053+
1054+
# we are going to monkey patch the zeroconf send to check packet sizes
1055+
old_send = zc.send
1056+
1057+
nbr_answers = nbr_additionals = nbr_authorities = 0
1058+
has_srv = has_txt = has_a = False
1059+
1060+
def send(out, addr=r._MDNS_ADDR, port=r._MDNS_PORT):
1061+
"""Sends an outgoing packet."""
1062+
nonlocal nbr_answers, nbr_additionals, nbr_authorities
1063+
nonlocal has_srv, has_txt, has_a
1064+
1065+
nbr_answers += len(out.answers)
1066+
nbr_authorities += len(out.authorities)
1067+
for answer in out.additionals:
1068+
nbr_additionals += 1
1069+
if answer.type == r._TYPE_SRV:
1070+
has_srv = True
1071+
elif answer.type == r._TYPE_TXT:
1072+
has_txt = True
1073+
elif answer.type == r._TYPE_A:
1074+
has_a = True
1075+
1076+
old_send(out, addr=addr, port=port)
1077+
1078+
# monkey patch the zeroconf send
1079+
setattr(zc, "send", send)
1080+
1081+
# register
1082+
zc.register_service(info)
1083+
nbr_answers = nbr_additionals = nbr_authorities = 0
1084+
1085+
# query
1086+
query = r.DNSOutgoing(r._FLAGS_QR_QUERY | r._FLAGS_AA)
1087+
query.add_question(r.DNSQuestion(info.type, r._TYPE_PTR, r._CLASS_IN))
1088+
zc.handle_query(r.DNSIncoming(query.packet()), r._MDNS_ADDR, r._MDNS_PORT)
1089+
assert nbr_answers == 1 and nbr_additionals == 3 and nbr_authorities == 0
1090+
assert has_srv and has_txt and has_a
1091+
1092+
# unregister
1093+
zc.unregister_service(info)

‎zeroconf.py

Copy file name to clipboardExpand all lines: zeroconf.py
+34Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2338,6 +2338,40 @@ def handle_query(self, msg: DNSIncoming, addr: Optional[str], port: int) -> None
23382338
msg,
23392339
DNSPointer(service.type, _TYPE_PTR, _CLASS_IN, service.other_ttl, service.name),
23402340
)
2341+
2342+
# Add recommended additional answers according to
2343+
# https://tools.ietf.org/html/rfc6763#section-12.1.
2344+
out.add_additional_answer(
2345+
DNSService(
2346+
service.name,
2347+
_TYPE_SRV,
2348+
_CLASS_IN | _CLASS_UNIQUE,
2349+
service.host_ttl,
2350+
service.priority,
2351+
service.weight,
2352+
service.port,
2353+
service.server,
2354+
)
2355+
)
2356+
out.add_additional_answer(
2357+
DNSText(
2358+
service.name,
2359+
_TYPE_TXT,
2360+
_CLASS_IN | _CLASS_UNIQUE,
2361+
service.other_ttl,
2362+
service.text,
2363+
)
2364+
)
2365+
for address in service.addresses:
2366+
out.add_additional_answer(
2367+
DNSAddress(
2368+
service.server,
2369+
_TYPE_A,
2370+
_CLASS_IN | _CLASS_UNIQUE,
2371+
service.host_ttl,
2372+
address,
2373+
)
2374+
)
23412375
else:
23422376
try:
23432377
if out is None:

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.