| 260 | return [thing] |
| 261 | |
| 262 | def handle_wire(self, wire, peer, local, connection_type): |
| 263 | # |
| 264 | # This is the common code to parse wire format, call handle() on |
| 265 | # the message, and then generate response wire format (if handle() |
| 266 | # didn't do it). |
| 267 | # |
| 268 | # It also handles any exceptions from handle() |
| 269 | # |
| 270 | # Returns a (possibly empty) list of wire format message to send. |
| 271 | items = [] |
| 272 | r = None |
| 273 | try: |
| 274 | q = dns.message.from_wire(wire, keyring=self.keyring) |
| 275 | except dns.message.ShortHeader: |
| 276 | # There is no hope of answering this one! |
| 277 | return |
| 278 | except Exception: |
| 279 | # Try to make a FORMERR using just the question section. |
| 280 | try: |
| 281 | q = dns.message.from_wire(wire, question_only=True) |
| 282 | r = dns.message.make_response(q) |
| 283 | r.set_rcode(dns.rcode.FORMERR) |
| 284 | items.append(r) |
| 285 | except Exception: |
| 286 | # We could try to make a response from only the header |
| 287 | # if dnspython had a header_only option to |
| 288 | # from_wire(), or if we truncated wire ourselves, but |
| 289 | # for now we just drop. |
| 290 | return |
| 291 | try: |
| 292 | # items might have been appended to above, so skip |
| 293 | # handle() if we already have a response. |
| 294 | if not items: |
| 295 | request = Request(q, wire, peer, local, connection_type) |
| 296 | items = self.maybe_listify(self.handle(request)) |
| 297 | except Exception as e: |
| 298 | # Exceptions from handle get a SERVFAIL response, and a print because |
| 299 | # they are usually bugs in the the test! |
| 300 | self.caught("handle", e) |
| 301 | r = dns.message.make_response(q) |
| 302 | r.set_rcode(dns.rcode.SERVFAIL) |
| 303 | items = [r] |
| 304 | |
| 305 | tsig_ctx = None |
| 306 | multi = len(items) > 1 |
| 307 | for thing in items: |
| 308 | if isinstance(thing, dns.message.Message): |
| 309 | out = thing.to_wire(self.origin, multi=multi, tsig_ctx=tsig_ctx) |
| 310 | tsig_ctx = thing.tsig_ctx |
| 311 | yield out |
| 312 | elif thing is not None: |
| 313 | yield thing |
| 314 | |
| 315 | async def serve_udp(self, connection_type): |
| 316 | with trio.socket.from_stdlib_socket(self.sockets[connection_type]) as sock: |