Process one message in the transfer. The message should have the same relativization as was specified when the `dns.xfr.Inbound` was created. The message should also have been created with `one_rr_per_rrset=True` because order matters. Returns `True` if the transfe
(self, message: dns.message.Message)
| 99 | self.delete_mode = False |
| 100 | |
| 101 | def process_message(self, message: dns.message.Message) -> bool: |
| 102 | """Process one message in the transfer. |
| 103 | |
| 104 | The message should have the same relativization as was specified when |
| 105 | the `dns.xfr.Inbound` was created. The message should also have been |
| 106 | created with `one_rr_per_rrset=True` because order matters. |
| 107 | |
| 108 | Returns `True` if the transfer is complete, and `False` otherwise. |
| 109 | """ |
| 110 | if self.txn is None: |
| 111 | self.txn = self.txn_manager.writer(not self.incremental) |
| 112 | rcode = message.rcode() |
| 113 | if rcode != dns.rcode.NOERROR: |
| 114 | raise TransferError(rcode) |
| 115 | # |
| 116 | # We don't require a question section, but if it is present is |
| 117 | # should be correct. |
| 118 | # |
| 119 | if len(message.question) > 0: |
| 120 | if message.question[0].name != self.origin: |
| 121 | raise dns.exception.FormError("wrong question name") |
| 122 | if message.question[0].rdtype != self.rdtype: |
| 123 | raise dns.exception.FormError("wrong question rdatatype") |
| 124 | answer_index = 0 |
| 125 | if self.soa_rdataset is None: |
| 126 | # |
| 127 | # This is the first message. We're expecting an SOA at |
| 128 | # the origin. |
| 129 | # |
| 130 | if not message.answer or message.answer[0].name != self.origin: |
| 131 | raise dns.exception.FormError("No answer or RRset not for zone origin") |
| 132 | rrset = message.answer[0] |
| 133 | rdataset = rrset |
| 134 | if rdataset.rdtype != dns.rdatatype.SOA: |
| 135 | raise dns.exception.FormError("first RRset is not an SOA") |
| 136 | answer_index = 1 |
| 137 | self.soa_rdataset = rdataset.copy() # pyright: ignore |
| 138 | if self.incremental: |
| 139 | assert self.soa_rdataset is not None |
| 140 | soa = cast(dns.rdtypes.ANY.SOA.SOA, self.soa_rdataset[0]) |
| 141 | if soa.serial == self.serial: |
| 142 | # |
| 143 | # We're already up-to-date. |
| 144 | # |
| 145 | self.done = True |
| 146 | elif dns.serial.Serial(soa.serial) < self.serial: |
| 147 | # It went backwards! |
| 148 | raise SerialWentBackwards |
| 149 | else: |
| 150 | if self.is_udp and len(message.answer[answer_index:]) == 0: |
| 151 | # |
| 152 | # There are no more records, so this is the |
| 153 | # "truncated" response. Say to use TCP |
| 154 | # |
| 155 | raise UseTCP |
| 156 | # |
| 157 | # Note we're expecting another SOA so we can detect |
| 158 | # if this IXFR response is an AXFR-style response. |