BIND 10 #2165: update Message::addRRset() to be unaware of signedness

BIND 10 Development do-not-reply at isc.org
Mon Aug 27 01:42:29 UTC 2012


#2165: update Message::addRRset() to be unaware of signedness
-------------------------------------+-------------------------------------
                   Reporter:         |                 Owner:  vorner
  jinmei                             |                Status:  reviewing
                       Type:  task   |             Milestone:
                   Priority:         |  Sprint-20120904
  medium                             |            Resolution:
                  Component:         |             Sensitive:  0
  libdns++                           |           Sub-Project:  DNS
                   Keywords:         |  Estimated Difficulty:  5
            Defect Severity:  N/A    |           Total Hours:  0
Feature Depending on Ticket:         |
  scalable inmemory                  |
        Add Hours to Ticket:  0      |
                  Internal?:  0      |
-------------------------------------+-------------------------------------
Changes (by muks):

 * owner:  muks => vorner


Comment:

 Hi vorner

 Replying to [comment:10 vorner]:
 > Hello
 >
 > I'll answer both tickets here, I reviewed it as one diff.
 >
 > Regarding style, you use `rr` as the name for an RRset in many places.
 Isn't that misleading little bit? RR usually means single Resource Record.
 Or is it really so the RRset contains only one?

 This was unintentional. It was used simply as a tiny temporary name, such
 as `i` for example. I'll change them to `r` or `rp`. :)

 > It is not related to this ticket much, but it reminded me of the
 problem. There are many calls like this:
 > {{{#!c++
 > boost::const_pointer_cast<AbstractRRset>(rrset));
 > }}}
 >
 > This is bad, but there was some problem with some method of rrset not
 being const even if it was a getter method and there was some technical
 reason for it inside the implementation. I think it was related to the
 signatures. Would you know by any chance if it is still a problem?

 I hope I follow what you are asking for correctly. I see two cases of it:

 * In this one, I think `setTTL()` is called eventually on the `RRset`
 passed to `Message::addRRset()`.
 {{{
 bin/auth/query.cc-        message.addRRset(section,
 bin/auth/query.cc:
 boost::const_pointer_cast<AbstractRRset>(rrset));
 bin/auth/query.cc-        added_.push_back(rrset.get());
 }}}

 * In this one, `RRset::addRRsig()` is not const and would modify the
 `covered_rrset`.
 {{{
 lib/datasrc/memory_datasrc.cc-        // cases.
 lib/datasrc/memory_datasrc.cc:
 boost::const_pointer_cast<AbstractRRset>(covered_rrset)->addRRsig(sig_rrset);
 lib/datasrc/memory_datasrc.cc-
 }}}

 >
 > In this code, it seems to me if the RRset has no RRSIG, it is still
 „stripped“. That is probably a needless work (query unittests, somewhere
 below line 711):
 > {{{#!c++
 > if (found_rrset != found_domain->second.end()) {
 >     ConstRRsetPtr rrset;
 >     // Strip whatever signature there is in case DNSSEC is not required
 >     // Just to make sure the Query asks for it when it is needed
 >     if ((options & ZoneFinder::FIND_DNSSEC) != 0 &&
 >       found_rrset->second->getRRsig()) {
 >       rrset = found_rrset->second;
 >     } else {
 >       RRsetPtr noconst(new RRset(found_rrset->second->getName(),
 >                                  found_rrset->second->getClass(),
 >                                  found_rrset->second->getType(),
 >                                  found_rrset->second->getTTL()));
 >       for (RdataIteratorPtr
 >            i(found_rrset->second->getRdataIterator());
 >            !i->isLast(); i->next()) {
 >           noconst->addRdata(i->getCurrent());
 >       }
 >       rrset = noconst;
 >     }
 >     return (createContext(options, SUCCESS, rrset));
 > }}}

 This was existing code from before #2165. This code has been replaced now
 with stripRRsigs(). :) I avoided making changes unless they affected
 something (caused tests to fail or resulted in incorrect behavior) so that
 side effects were not introduced by mistake.

 > You disabled the tests for the old API. If I leave aside the fact we
 still have the API in our tree, even if it is not used (I think it is not
 used), why are the files listed in EXTRA_DIST? If the test files are not
 compiled, is there a reason to include them in the tarball?

 This is so that the files are present in the tarball for any downloader to
 view/use. In projects I have worked in, such extra stuff in the tree
 became a part of the tarball. As you see, it was added to `EXTRA_DIST` on
 purpose. The real question here is if the test files should be in the tree
 anymore. When it goes from the tree, it can go from the tarball too.

 > The `stripRRsigs` function, should the whole (nontrivial) implementation
 be in header file? And, is the ZoneFinder the best place for it? Doesn't
 the function work on any RRset?

 `ZoneFinder` is probably not the best place for all of that code, but it
 checks the `options` argument against `FIND_DNSSEC` which is why it's
 there. Otherwise we'll have to check these inline in code and
 conditionally call `stripRRsigs()` as it doesn't make sense for
 `RRset::stripRRsigs()` to take a bool argument (whether to strip or not).
 A part of it can be moved to `RRset`, but if we want to use it optimally
 by not creating `RRsetPtr` unless required, it'll result in ugly API as
 `AbstractRRset::stripRRsigs()` could either return `(this)` or a new
 `RRset` depending on whether RRSIGs are present.

 The code has been moved to `zone_finder.cc`. It's used by users of
 datasrc, so unless it becomes a problem I think we can keep it as it is.

 > Looking at the code of `toWire(AbstractMessageRenderer, …)`, can it
 happen that the real RR is not rendered, because it does not fit (64k long
 TXT record, for example), but then the signatures fit, so they are
 included? If so, is it OK?

 Nice one. :) I added a test for it first, and then updated the code to not
 render the signatures if truncation would happen with the records firstly.

 > Both toWire methods would probably deserve a description about what is
 being returned. If I didn't read the code, I'd ask if it was number of
 bytes, number of records or some status code.

 API functions are properly documented in the header files.
 `RRset::toWire()` inherits from `AbstractRRset::toWire()` and says so in
 its API documentation. `AbstractRRset::toWire()` has detailed
 documentation. It returns the number of records rendered.

 > This comment isn't true any more (or, it is probably true in some sense,
 but still very misleading) ‒ the removed one lowers the count by 2, not 1:
 > {{{#!c++
 > // Locate the AAAA RRset and remove it; this has one RR in it.
 > }}}

 This comment has been updated. :)

 > Regarding this:
 > {{{#!c++
 > #if (0)
 >         // Disabled by #2165. The RRSIG RRsets are no longer directly
 >         // stored in the Message's rrsets, so the iterator will not find
 >         // them. The expected text used in many tests are flattened,
 >         // where the RRSIGs are inline. In other words, RRSIGs may occur
 >         // between (expected_begin, expected_end) but not between
 >         // (actual_begin, actual_end).
 >
 >         // make sure rrsets only contains expected RRsets
 >         EXPECT_EQ(std::distance(expected_begin, expected_end),
 >                   std::distance(actual_begin, actual_end));
 > #endif
 > }}}
 >
 > First, I don't like to see any code commented out without any FIXME or
 TODO mark besides it (these allow for easy grepping for problems).
 >
 > However, the more serious concern is, when do we fix the test to test
 what it did before? Is there a ticket for it? Will it be deprecated? If
 not, maybe rendering it to text, sorting both texts by lines and comparing
 as strings? Would that work? Or, we need to see they are the same size, so
 actually comparing only the lengths of the strings?

 This test doesn't make sense anymore as the RRSIGs are no longer "inline"
 in `Message`'s rrsets vector, and the test measures vector index
 distances. I couldn't quickly think of a way to modify it in place to get
 the same effect. It could mean writing fresh tests for such calls. I've
 created #2223 and added a TODO pointing to that bug in the comment. :)


 Replying to [comment:11 jinmei]:
 > I happen to notice one other thing.
 >
 > In `DatabaseClient::Finder::getRRsets` I believe you can simply
 > ignore any RRSIGs if sigs is false.  Also, if we have a simple test
 > method to tell if `RRsigStore` is empty, this part:
 >
 > {{{#!cpp
 >     if (sigs) {
 >         // Add signatures to all found RRsets
 >         for (std::map<RRType, RRsetPtr>::iterator i(result.begin());
 >              i != result.end(); ++ i) {
 >             sig_store.appendSignatures(i->second);
 >         }
 >     }
 > }}}
 >
 > can be like this:
 >
 > {{{#!cpp
 >     if (!sig_store.empty()) {
 >         // Add signatures to all found RRsets
 >         for (std::map<RRType, RRsetPtr>::iterator i(result.begin());
 >              i != result.end(); ++ i) {
 >             sig_store.appendSignatures(i->second);
 >         }
 >     }
 > }}}
 >
 > This works whether or not `sigs` is true, and in case the zone isn't
 > signed we can avoid iterating over the other types of RRsets for
 > nothing.

 This has been fixed too. :)

-- 
Ticket URL: <http://bind10.isc.org/ticket/2165#comment:12>
BIND 10 Development <http://bind10.isc.org>
BIND 10 Development


More information about the bind10-tickets mailing list