Commit 42fcfa9ede for bind
commit 42fcfa9ede8ac532a8800b1bbd95beae9da9635d
Author: Štěpán Balážik <stepan@isc.org>
Date: Tue Sep 8 19:36:00 2026 +0200
Match on the transfer state in xfer/ans11 with a matcher
The SOA handlers read the initial-AXFR flag through a matcher of
their own, and the AXFR handler sets it while serving, which was
previously done in match() methods.
Assisted-by: Claude:claude-fable-5
diff --git a/bin/tests/system/xfer/ans11/ans.py b/bin/tests/system/xfer/ans11/ans.py
index c2282af8ed..8d558217a8 100644
--- a/bin/tests/system/xfer/ans11/ans.py
+++ b/bin/tests/system/xfer/ans11/ans.py
@@ -25,7 +25,7 @@ from isctest.asyncserver import (
)
from isctest.asyncserver.actions import DnsResponseSend
from isctest.asyncserver.handlers import AxfrHandler, StaticResponseHandler
-from isctest.asyncserver.matchers import Protocol, Qtype
+from isctest.asyncserver.matchers import Matcher, Protocol, Qtype
ZONE = "ixfr-race."
NS_NAME = f"ns.{ZONE}"
@@ -95,6 +95,21 @@ class TransferState:
self.initial_axfr_served = False
+class InitialAxfrServed(Matcher):
+ """
+ Match once the initial AXFR has been served.
+ """
+
+ def __init__(self, progress: TransferState) -> None:
+ self._progress = progress
+
+ def match(self, qctx: QueryContext) -> bool:
+ return self._progress.initial_axfr_served
+
+ def __str__(self) -> str:
+ return "after the initial AXFR"
+
+
class TransferHandler(ResponseHandler):
"""
Base for the handlers that share a single TransferState.
@@ -108,17 +123,17 @@ class TransferHandler(ResponseHandler):
class InitialSoaHandler(TransferHandler, StaticResponseHandler):
answer = [soa(1)]
- def match(self, qctx: QueryContext) -> bool:
- return (
- qctx.qtype == dns.rdatatype.SOA and not self._progress.initial_axfr_served
- )
+ def __init__(self, progress: TransferState) -> None:
+ super().__init__(progress)
+ self.matcher = Qtype(dns.rdatatype.SOA) & ~InitialAxfrServed(progress)
class RefreshSoaHandler(TransferHandler, StaticResponseHandler):
answer = [soa(4)]
- def match(self, qctx: QueryContext) -> bool:
- return qctx.qtype == dns.rdatatype.SOA and self._progress.initial_axfr_served
+ def __init__(self, progress: TransferState) -> None:
+ super().__init__(progress)
+ self.matcher = Qtype(dns.rdatatype.SOA) & InitialAxfrServed(progress)
class InitialAxfrHandler(TransferHandler, AxfrHandler):
@@ -133,11 +148,12 @@ class InitialAxfrHandler(TransferHandler, AxfrHandler):
]
final_soa = soa(1)
- def match(self, qctx: QueryContext) -> bool:
- matched = super().match(qctx)
- if matched:
- self._progress.initial_axfr_served = True
- return matched
+ async def get_responses(
+ self, qctx: QueryContext
+ ) -> AsyncGenerator[DnsResponseSend, None]:
+ self._progress.initial_axfr_served = True
+ async for action in super().get_responses(qctx):
+ yield action
class TruncatedIxfrHandler(ResponseHandler):