diff options
| author | Bob Halley <halley@play-bow.org> | 2020-07-02 09:07:47 -0700 |
|---|---|---|
| committer | Bob Halley <halley@play-bow.org> | 2020-07-02 09:07:47 -0700 |
| commit | 2f3beeaa0158e3c0b0060dbe08216c374e2902f1 (patch) | |
| tree | 69063a99d290155e6760ef2b433040c3c3ffec5a | |
| parent | 4acc470f4ae5ba8df2c45808dd2383584b93609b (diff) | |
| download | dnspython-2f3beeaa0158e3c0b0060dbe08216c374e2902f1.tar.gz | |
Add basic from_parser() support to rdata including scaffolding for not-yet-refactored classes.
| -rw-r--r-- | dns/rdata.py | 48 | ||||
| -rw-r--r-- | tests/test_rdata.py | 6 |
2 files changed, 48 insertions, 6 deletions
diff --git a/dns/rdata.py b/dns/rdata.py index 2de1763..b681d34 100644 --- a/dns/rdata.py +++ b/dns/rdata.py @@ -474,6 +474,46 @@ def from_text(rdclass, rdtype, tok, origin=None, relativize=True, relativize_to) +def from_parser(rdclass, rdtype, parser, rdlen, origin=None): + """Build an rdata object from wire format + + This function attempts to dynamically load a class which + implements the specified rdata class and type. If there is no + class-and-type-specific implementation, the GenericRdata class + is used. + + Once a class is chosen, its from_wire() class method is called + with the parameters to this function. + + *rdclass*, an ``int``, the rdataclass. + + *rdtype*, an ``int``, the rdatatype. + + *parser*, a ``dns.binary.Parser``, the parser. + + *rdlen*, an ``int``, the length of the wire-format rdata + + *origin*, a ``dns.name.Name`` (or ``None``). If not ``None``, + then names will be relativized to this origin. + + Returns an instance of the chosen Rdata subclass. + """ + + rdclass = dns.rdataclass.RdataClass.make(rdclass) + rdtype = dns.rdatatype.RdataType.make(rdtype) + cls = get_rdata_class(rdclass, rdtype) + try: + with parser.restrict_to(rdlen): + return cls.from_parser(rdclass, rdtype, parser, origin) + except AttributeError: + # XXXRTH This is a temporary porting hack + wire = dns.wiredata.maybe_wrap(parser.wire) + rdata = cls.from_wire(rdclass, rdtype, wire, parser.current, + rdlen, origin) + parser.get_bytes(rdlen) + return rdata + + def from_wire(rdclass, rdtype, wire, current, rdlen, origin=None): """Build an rdata object from wire format @@ -501,12 +541,8 @@ def from_wire(rdclass, rdtype, wire, current, rdlen, origin=None): Returns an instance of the chosen Rdata subclass. """ - - wire = dns.wiredata.maybe_wrap(wire) - rdclass = dns.rdataclass.RdataClass.make(rdclass) - rdtype = dns.rdatatype.RdataType.make(rdtype) - cls = get_rdata_class(rdclass, rdtype) - return cls.from_wire(rdclass, rdtype, wire, current, rdlen, origin) + parser = dns._binary.Parser(wire, current) + return from_parser(rdclass, rdtype, parser, rdlen, origin) class RdatatypeExists(dns.exception.DNSException): diff --git a/tests/test_rdata.py b/tests/test_rdata.py index 0ed38b7..9b1fdf8 100644 --- a/tests/test_rdata.py +++ b/tests/test_rdata.py @@ -409,5 +409,11 @@ class RdataTestCase(unittest.TestCase): binascii.unhexlify('f00100030000'), 0, 6) self.assertRaises(dns.exception.FormError, bad2) + def test_from_parser(self): + wire = bytes.fromhex('01020304') + rdata = dns.rdata.from_wire('in', 'a', wire, 0, 4) + print(rdata) + self.assertEqual(rdata, dns.rdata.from_text('in', 'a', '1.2.3.4')) + if __name__ == '__main__': unittest.main() |
