Browse Source

Merge branch 'trac3286'

Mukund Sivaraman 11 years ago
parent
commit
1f0e3dc6f4
3 changed files with 50 additions and 10 deletions
  1. 9 3
      src/lib/dns/message.cc
  2. 6 1
      src/lib/dns/message.h
  3. 35 6
      src/lib/dns/tests/message_unittest.cc

+ 9 - 3
src/lib/dns/message.cc

@@ -620,6 +620,10 @@ Message::parseHeader(InputBuffer& buffer) {
                   "Message parse attempted in non parse mode");
     }
 
+    if (impl_->header_parsed_) {
+        return;
+    }
+
     if ((buffer.getLength() - buffer.getPosition()) < HEADERLEN) {
         isc_throw(MessageTooShort, "Malformed DNS message (short length): "
                   << buffer.getLength() - buffer.getPosition());
@@ -645,9 +649,11 @@ Message::fromWire(InputBuffer& buffer, ParseOptions options) {
                   "Message parse attempted in non parse mode");
     }
 
-    if (!impl_->header_parsed_) {
-        parseHeader(buffer);
-    }
+    // Clear any old parsed data
+    clear(Message::PARSE);
+
+    buffer.setPosition(0);
+    parseHeader(buffer);
 
     impl_->counts_[SECTION_QUESTION] = impl_->parseQuestion(buffer);
     impl_->counts_[SECTION_ANSWER] =

+ 6 - 1
src/lib/dns/message.h

@@ -607,6 +607,10 @@ public:
     };
 
     /// \brief Parse the header section of the \c Message.
+    ///
+    /// NOTE: If the header has already been parsed by a previous call
+    /// to this method, this method simply returns (i.e., it does not
+    /// read from the \c buffer).
     void parseHeader(isc::util::InputBuffer& buffer);
 
     /// \brief (Re)build a \c Message object from wire-format data.
@@ -642,7 +646,8 @@ public:
     /// \exception std::bad_alloc Memory allocation failure
     /// \exception Others \c Name, \c Rdata, and \c EDNS classes can also throw
     ///
-    /// \param buffer A input buffer object that stores the wire data
+    /// \param buffer A input buffer object that stores the wire
+    /// data. This method reads from position 0 in the passed buffer.
     /// \param options Parse options
     void fromWire(isc::util::InputBuffer& buffer, ParseOptions options
         = PARSE_DEFAULT);

+ 35 - 6
src/lib/dns/tests/message_unittest.cc

@@ -572,12 +572,10 @@ TEST_F(MessageTest, parseHeader) {
                 message_parse.endSection(Message::SECTION_ADDITIONAL));
 }
 
-TEST_F(MessageTest, fromWire) {
-    // fromWire() isn't allowed in the render mode.
-    EXPECT_THROW(factoryFromFile(message_render, "message_fromWire1"),
-                 InvalidMessageOperation);
-
-    factoryFromFile(message_parse, "message_fromWire1");
+void
+checkMessageFromWire(const Message& message_parse,
+                     const Name& test_name)
+{
     EXPECT_EQ(0x1035, message_parse.getQid());
     EXPECT_EQ(Opcode::QUERY(), message_parse.getOpcode());
     EXPECT_EQ(Rcode::NOERROR(), message_parse.getRcode());
@@ -608,6 +606,37 @@ TEST_F(MessageTest, fromWire) {
     EXPECT_TRUE(it->isLast());
 }
 
+
+TEST_F(MessageTest, fromWire) {
+    // fromWire() isn't allowed in the render mode.
+    EXPECT_THROW(factoryFromFile(message_render, "message_fromWire1"),
+                 InvalidMessageOperation);
+
+    factoryFromFile(message_parse, "message_fromWire1");
+    checkMessageFromWire(message_parse, test_name);
+}
+
+TEST_F(MessageTest, fromWireMultiple) {
+    // Parse from wire multiple times.
+    factoryFromFile(message_parse, "message_fromWire1");
+    factoryFromFile(message_parse, "message_fromWire1");
+    factoryFromFile(message_parse, "message_fromWire1");
+    factoryFromFile(message_parse, "message_fromWire1");
+    checkMessageFromWire(message_parse, test_name);
+
+    // Calling parseHeader() directly before fromWire() should not cause
+    // any problems.
+    received_data.clear();
+    UnitTestUtil::readWireData("message_fromWire1", received_data);
+
+    InputBuffer buffer(&received_data[0], received_data.size());
+    message_parse.parseHeader(buffer);
+    message_parse.fromWire(buffer);
+    message_parse.parseHeader(buffer);
+    message_parse.fromWire(buffer);
+    checkMessageFromWire(message_parse, test_name);
+}
+
 TEST_F(MessageTest, fromWireShortBuffer) {
     // We trim a valid message (ending with an SOA RR) for one byte.
     // fromWire() should throw an exception while parsing the trimmed RR.