Browse Source

supported toText() and "from text" constructor for the generic (unknown) type
of RDATA


git-svn-id: svn://bind10.isc.org/svn/bind10/branches/jinmei-dnsrdata2@757 e5f2f494-b856-4b98-b285-d166d9295462

JINMEI Tatuya 15 years ago
parent
commit
450c2681a1
1 changed files with 58 additions and 10 deletions
  1. 58 10
      src/lib/dns/cpp/rdata.cc

+ 58 - 10
src/lib/dns/cpp/rdata.cc

@@ -16,6 +16,9 @@
 
 #include <cctype>
 #include <string>
+#include <sstream>
+#include <iomanip>
+#include <ios>
 
 #include <stdint.h>
 #include <string.h>
@@ -23,8 +26,6 @@
 #include <boost/lexical_cast.hpp>
 #include <boost/shared_ptr.hpp>
 
-#include <arpa/inet.h> // XXX: for inet_pton/ntop(), not exist in C++ standards
-
 #include "buffer.h"
 #include "name.h"
 #include "messagerenderer.h"
@@ -103,14 +104,66 @@ Generic::Generic(InputBuffer& buffer, size_t rdata_len) :
 
 Generic::Generic(const string& rdata_string)
 {
-    // parse the \# n xx xx... format (TBD)
+    istringstream iss(rdata_string);
+    string unknown_mark;
+    int32_t rdlen;
+
+    iss >> unknown_mark;
+    if (unknown_mark != "\\#") {
+        dns_throw(InvalidRdataText,
+                  "Missing the special token (\\#) for generic RDATA encoding");
+    }
+
+    iss >> rdlen;
+    if (iss.bad() || iss.fail() || rdlen < 0 || rdlen > 0xffff) {
+        dns_throw(InvalidRdataLength, "RDATA length is out of range");
+    }
+
+     while (!iss.eof() && data_.size() < rdlen) {
+        string bytes;
+        iss >> bytes;
+        if (iss.bad() || iss.fail() || (bytes.size() % 2) != 0) {
+            dns_throw(InvalidRdataText,
+                      "Invalid hex encoding of generic RDATA");
+        }
+
+        for (int pos = 0; pos < bytes.size(); pos += 2) {
+            unsigned int ch;
+            istringstream(bytes.substr(pos, 2)) >> hex >> ch;
+            data_.push_back(ch);
+        }
+    }
+
+    if (data_.size() != rdlen) {
+        dns_throw(InvalidRdataLength,
+                  "Generic RDATA code doesn't match RDLENGTH");
+    }
+}
+
+namespace {
+class UnknownRdataDumper {
+public:
+    UnknownRdataDumper(ostringstream& oss) : oss_(&oss) {}
+    void operator()(const unsigned char d)
+    {
+        *oss_ << setw(2) << static_cast<unsigned int>(d);
+    }
+private:
+    ostringstream* oss_;
+};
 }
 
 string
 Generic::toText() const
 {
-    // return rdata in the \# n xx xx format (TBD)
-    dns_throw(InvalidRdataText, "Not implemented yet");
+    ostringstream oss;
+
+    oss << "\\# " << data_.size() << " ";
+    oss.fill('0');
+    oss << right << hex;
+    for_each(data_.begin(), data_.end(), UnknownRdataDumper(oss));
+
+    return (oss.str());
 }
 
 void
@@ -145,11 +198,6 @@ Generic::compare(const Rdata& other) const
 
 } // end of namespace generic
 
-namespace in {
-} // end of namespace in
-
-namespace ch {
-} // end of namespace ch
 } // end of namespace rdata
 }
 }