From: Marek VavruĊĦa Date: Thu, 15 Mar 2018 23:13:47 +0000 (-0700) Subject: kres: added interface for RR set wire size and packet remaining bytes X-Git-Tag: v2.4.0~54^2~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=47275ddf2dc72c8c15036084bcf8a4cebe7e1345;p=thirdparty%2Fknot-resolver.git kres: added interface for RR set wire size and packet remaining bytes --- diff --git a/daemon/lua/kres-gen.lua b/daemon/lua/kres-gen.lua index 7a8e59732..911e2e090 100644 --- a/daemon/lua/kres-gen.lua +++ b/daemon/lua/kres-gen.lua @@ -252,6 +252,7 @@ void knot_rrset_init_empty(knot_rrset_t *); uint32_t knot_rrset_ttl(const knot_rrset_t *); int knot_rrset_txt_dump(const knot_rrset_t *, char **, size_t *, const knot_dump_style_t *); int knot_rrset_txt_dump_data(const knot_rrset_t *, const size_t, char *, const size_t, const knot_dump_style_t *); +size_t knot_rrset_size(const knot_rrset_t *); uint16_t knot_rrsig_type_covered(const knot_rdataset_t *, size_t); uint32_t knot_rrsig_sig_expiration(const knot_rdataset_t *, size_t); uint32_t knot_rrsig_sig_inception(const knot_rdataset_t *, size_t); @@ -260,6 +261,7 @@ uint16_t knot_pkt_qtype(const knot_pkt_t *); uint16_t knot_pkt_qclass(const knot_pkt_t *); int knot_pkt_begin(knot_pkt_t *, knot_section_t); int knot_pkt_put_question(knot_pkt_t *, const knot_dname_t *, uint16_t, uint16_t); +int knot_pkt_put(knot_pkt_t *, uint16_t, const knot_rrset_t *, uint16_t); const knot_rrset_t *knot_pkt_rr(const knot_pktsection_t *, uint16_t); const knot_pktsection_t *knot_pkt_section(const knot_pkt_t *, knot_section_t); knot_pkt_t *knot_pkt_new(void *, uint16_t, knot_mm_t *); diff --git a/daemon/lua/kres-gen.sh b/daemon/lua/kres-gen.sh index 9c7b55818..fa2f11461 100755 --- a/daemon/lua/kres-gen.sh +++ b/daemon/lua/kres-gen.sh @@ -111,6 +111,7 @@ printf "\tchar _stub[];\n};\n" knot_rrset_ttl knot_rrset_txt_dump knot_rrset_txt_dump_data + knot_rrset_size knot_rrsig_type_covered knot_rrsig_sig_expiration knot_rrsig_sig_inception @@ -120,6 +121,7 @@ printf "\tchar _stub[];\n};\n" knot_pkt_qclass knot_pkt_begin knot_pkt_put_question + knot_pkt_put knot_pkt_rr knot_pkt_section knot_pkt_new diff --git a/daemon/lua/kres.lua b/daemon/lua/kres.lua index b75f5c79a..61cac2267 100644 --- a/daemon/lua/kres.lua +++ b/daemon/lua/kres.lua @@ -379,6 +379,11 @@ ffi.metatype( knot_rrset_t, { assert(rrsig.type == const_type.RRSIG) return (rr.type == rrsig:type_covered() and rr:owner() == rrsig:owner()) end, + -- Return RR set wire size + wire_size = function(rr) + assert(ffi.istype(knot_rrset_t, rr)) + return tonumber(knot.knot_rrset_size(rr)) + end, }, }) @@ -560,6 +565,15 @@ ffi.metatype( knot_pkt_t, { if ret ~= 0 then return nil, knot_error_t(ret) end return true end, + -- Put an RR set in the packet + -- Note: the packet doesn't take ownership of the RR set + put_rr = function (pkt, rr) + assert(ffi.istype(knot_pkt_t, pkt)) + assert(ffi.istype(knot_rrset_t, rr)) + local ret = C.knot_pkt_put(pkt, 0, rr, 0) + if ret ~= 0 then return nil, knot_error_t(ret) end + return true + end, recycle = function (pkt) assert(ffi.istype(knot_pkt_t, pkt)) local ret = C.kr_pkt_recycle(pkt) @@ -588,6 +602,14 @@ ffi.metatype( knot_pkt_t, { assert(ffi.istype(knot_pkt_t, pkt)) return packet_tostring(pkt) end, + -- Return number of remaining empty bytes in the packet + -- This is generally useful to check if there's enough space + remaining_bytes = function (pkt) + assert(ffi.istype(knot_pkt_t, pkt)) + local occupied = pkt.size + pkt.reserved + assert(pkt.max_size >= occupied) + return tonumber(pkt.max_size - occupied) + end, -- Packet manipulation parse = function (pkt) assert(ffi.istype(knot_pkt_t, pkt)) diff --git a/tests/config/basic.test.lua b/tests/config/basic.test.lua index 55f133393..95c24bc56 100644 --- a/tests/config/basic.test.lua +++ b/tests/config/basic.test.lua @@ -45,7 +45,9 @@ local function test_rrset_functions() same(rr:class(kres.class.IN), kres.class.IN, 'can restore a class') same(rr.type, kres.type.A, 'created RR has correct type') -- test adding rdata + same(rr:wire_size(), 0, 'empty RR wire size is zero') ok(rr:add_rdata('\1\2\3\4', 4, 66), 'adding RDATA works') + same(rr:wire_size(), 5 + 4 + 4 + 2 + 4, 'RR wire size works after adding RDATA') -- test conversion to text local expect = 'com. 66 A 1.2.3.4\n' same(rr:txt_dump(), expect, 'RR to text works') @@ -104,7 +106,9 @@ local function test_packet_functions() boom(pkt.begin, {pkt, 10}, 'switching to invalid section doesnt work') ok(pkt:begin(kres.section.ADDITIONAL), 'switching to different section works') boom(pkt.begin, {pkt, 0}, 'rewinding sections doesnt work') + local before_insert = pkt:remaining_bytes() ok(pkt:put(pkt:qname(), 900, pkt:qclass(), kres.type.A, '\4\3\2\1'), 'adding rrsets to different section works') + same(pkt:remaining_bytes(), before_insert - (2 + 4 + 4 + 2 + 4), 'remaining bytes count goes down with insertions') -- Test conversions to text like(pkt:tostring(), '->>HEADER<<-', 'packet to text works') -- Test deserialization @@ -126,6 +130,15 @@ local function test_packet_functions() same(parsed:arcount(), pkt:arcount(), 'parsed packet has same additional count') same(parsed:tostring(), pkt:tostring(), 'parsed packet is equal to source packet') + -- Test adding RR sets directly + local copy = kres.packet(512) + copy:question(todname('hello'), kres.class.IN, kres.type.A) + copy:begin(kres.section.ANSWER) + local rr = kres.rrset(pkt:qname(), kres.type.A) + rr:add_rdata('\4\3\2\1', 4, 66) + ok(copy:put_rr(rr), 'adding RR sets directly works') + ok(copy:recycle()) + -- Test recycling of packets -- Clear_payload keeps header + question intact local cleared = kres.packet(#wire, wire) -- same as "parsed" above