summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBob Halley <halley@play-bow.org>2020-07-02 09:07:47 -0700
committerBob Halley <halley@play-bow.org>2020-07-02 09:07:47 -0700
commit2f3beeaa0158e3c0b0060dbe08216c374e2902f1 (patch)
tree69063a99d290155e6760ef2b433040c3c3ffec5a
parent4acc470f4ae5ba8df2c45808dd2383584b93609b (diff)
downloaddnspython-2f3beeaa0158e3c0b0060dbe08216c374e2902f1.tar.gz
Add basic from_parser() support to rdata including scaffolding for not-yet-refactored classes.
-rw-r--r--dns/rdata.py48
-rw-r--r--tests/test_rdata.py6
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()