[svn] commit: r65 - in /experiments/jinmei-messageapi: Makefile.in dnsexceptions.hh dnsmessage-test.cc dnsmessage.cc dnsmessage.hh dnsname.cc dnsname.hh iobuffer.cc iobuffer.hh iscexceptions.hh rrset.cc rrset.hh
BIND 10 source code commits
bind10-changes at lists.isc.org
Wed Oct 7 08:38:07 UTC 2009
Author: jinmei
Date: Wed Oct 7 08:38:07 2009
New Revision: 65
Log:
- added message parser
- added a tiny server as a sample
Added:
experiments/jinmei-messageapi/iobuffer.cc
experiments/jinmei-messageapi/iobuffer.hh
Modified:
experiments/jinmei-messageapi/Makefile.in
experiments/jinmei-messageapi/dnsexceptions.hh
experiments/jinmei-messageapi/dnsmessage-test.cc
experiments/jinmei-messageapi/dnsmessage.cc
experiments/jinmei-messageapi/dnsmessage.hh
experiments/jinmei-messageapi/dnsname.cc
experiments/jinmei-messageapi/dnsname.hh
experiments/jinmei-messageapi/iscexceptions.hh
experiments/jinmei-messageapi/rrset.cc
experiments/jinmei-messageapi/rrset.hh
Modified: experiments/jinmei-messageapi/Makefile.in
==============================================================================
--- experiments/jinmei-messageapi/Makefile.in (original)
+++ experiments/jinmei-messageapi/Makefile.in Wed Oct 7 08:38:07 2009
@@ -22,14 +22,15 @@
all: $(TARGET)
-dnsname-test: dnsname.o dnsname-test.o
- $(CXX) dnsname.o dnsname-test.o -o $@
+dnsname-test: dnsname.o dnsresult.o dnsname-test.o
+ $(CXX) dnsname.o dnsresult.o dnsname-test.o -o $@
-rrset-test: rrset.o dnsname.o rrset-test.o
- $(CXX) rrset.o dnsname.o rrset-test.o -o $@
+rrset-test: rrset.o dnsname.o dnsresult.o rrset-test.o
+ $(CXX) rrset.o dnsname.o dnsresult.o rrset-test.o -o $@
-dnsmessage-test: rrset.o dnsname.o dnsmessage.o dnsmessage-test.o
- $(CXX) dnsmessage.o rrset.o dnsname.o dnsmessage-test.o -o $@
+dnsmessage-test: rrset.o dnsname.o dnsresult.o dnsmessage.o dnsmessage-test.o iobuffer.o
+ $(CXX) dnsmessage.o rrset.o dnsname.o dnsresult.o iobuffer.o \
+ dnsmessage-test.o -o $@
##
clean:
Modified: experiments/jinmei-messageapi/dnsexceptions.hh
==============================================================================
--- experiments/jinmei-messageapi/dnsexceptions.hh (original)
+++ experiments/jinmei-messageapi/dnsexceptions.hh Wed Oct 7 08:38:07 2009
@@ -29,8 +29,9 @@
class DNSInvalidRdataType : public DNSException {};
class DNSRdtypeMismatch : public DNSException {};
class DNSInvalidWireRdata : public DNSException {};
-class DNSNoMessageRenderer : public DNSException {};
+class DNSNoMessageIOBuffer : public DNSException {};
class DNSNoNameCompressor : public DNSException {};
+class DNSNoNameDecompressor : public DNSException {};
class DNSNoMessageParser : public DNSException {};
class DNSInvalidMessageSection : public DNSException {};
class DNSInvalidRendererPosition : public DNSException {};
Modified: experiments/jinmei-messageapi/dnsmessage-test.cc
==============================================================================
--- experiments/jinmei-messageapi/dnsmessage-test.cc (original)
+++ experiments/jinmei-messageapi/dnsmessage-test.cc Wed Oct 7 08:38:07 2009
@@ -18,6 +18,7 @@
#include <sys/socket.h>
#include <netdb.h>
+#include <map>
#include <iostream>
#include "dnsname.hh"
@@ -27,6 +28,81 @@
using namespace std;
using namespace ISC::DNS;
+static void
+start_server(int s, const struct addrinfo *res)
+{
+ if (bind(s, res->ai_addr, res->ai_addrlen) < 0)
+ return;
+
+ // Create Database
+ map<string, string> a_db, aaaa_db;
+ a_db.insert(pair<string,string>("www.jinmei.org", "149.20.54.162"));
+ aaaa_db.insert(pair<string,string>("www.jinmei.org", "2001:4f8:3:36::162"));
+ a_db.insert(pair<string,string>("www.isc.org", "149.20.64.42"));
+ aaaa_db.insert(pair<string,string>("www.isc.org", "2001:4f8:0:2::d"));
+
+ int cc;
+ struct sockaddr_storage ss;
+ struct sockaddr* sa;
+ socklen_t sa_len;
+
+ while (1) {
+ Message msg;
+
+ sa_len = sizeof(ss);
+ sa = static_cast<struct sockaddr*>((void*)&ss);
+ cc = msg.get_iobuffer().recv_from(s, sa, &sa_len);
+ if (cc > 0) {
+ ISC::ConstResult result = msg.from_wire();
+
+ if (result != ISC::Result::Success) {
+ cerr << "parse failed: " << result->to_text() << endl;
+ continue;
+ }
+
+ cout << "received a message:\n" << msg.to_text() << endl;
+ if (msg.get_section(SECTION_QUESTION).size() != 1)
+ continue;
+
+ msg.make_response();
+ msg.set_aa(true);
+
+ RRSetPtr query = msg.get_section(SECTION_QUESTION)[0];
+ map<string, string>::const_iterator it;
+ rdataptr_t rdatap;
+
+ if (query->get_type() == RdataType::A) {
+ it = a_db.find(query->get_name().to_text(true));
+ if (it != a_db.end()) {
+ rdatap = rdataptr_t(new ARdata(it->second));
+ }
+ } else if (query->get_type() == RdataType::AAAA) {
+ it = aaaa_db.find(query->get_name().to_text(true));
+ if (it != a_db.end()) {
+ rdatap = rdataptr_t(new AAAARdata(it->second));
+ }
+ }
+ if (rdatap == NULL) {
+ msg.set_rcode(Message::RCODE_NXDOMAIN);
+ // should add SOA to the authority section, but not implemented.
+ } else {
+ msg.set_rcode(Message::RCODE_NOERROR);
+
+ RRSet* rrset = new RRSet(query->get_name(), query->get_class(),
+ query->get_type(), TTL(3600));
+ rrset->add_rdata(rdatap);
+ msg.add_rrset(SECTION_ANSWER, RRSetPtr(rrset));
+ }
+
+ msg.to_wire();
+ cout << "sending a response (" <<
+ boost::lexical_cast<string>(msg.get_iobuffer().get_size())
+ << " bytes):\n" << msg.to_text() << endl;
+ msg.get_iobuffer().send_to(s, *sa, sa_len);
+ }
+ }
+}
+
int
main(int argc, char* argv[])
{
@@ -34,9 +110,17 @@
int ch;
const char* server_address = "127.0.0.1";
const char* type_name = "A";
+ const char* port = "53";
+ bool receive_mode = false;
- while ((ch = getopt(argc, argv, "s:t:")) != -1) {
+ while ((ch = getopt(argc, argv, "p:rs:t:")) != -1) {
switch (ch) {
+ case 'p':
+ port = optarg;
+ break;
+ case 'r':
+ receive_mode = true;
+ break;
case 's':
server_address = optarg;
break;
@@ -49,7 +133,7 @@
argc -= optind;
argv += optind;
- if (argc < 1) {
+ if (argc < 1 && !receive_mode) {
cerr << "usage: dnsmessage-test [-s server_address] [-t qtype] qname\n"
<< endl;
return (1);
@@ -60,23 +144,33 @@
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
- e = getaddrinfo(server_address, "53", &hints, &res);
+ hints.ai_flags = receive_mode ? AI_PASSIVE : 0;
+ e = getaddrinfo(server_address, port, &hints, &res);
if (e != 0) {
cerr << "getaddrinfo failed: " << gai_strerror(e) << endl;
return (1);
}
-
+
int s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (s < 0) {
cerr << "failed to open socket" << endl;
return (1);
}
- msg.set_qid(42); // can be omitted, then QID will be 0
- msg.set_rd(true);
- msg.add_question(Name(argv[0]), RdataClass::IN, RdataType(type_name));
- msg.to_wire();
- msg.get_renderer().send_to(s, *res->ai_addr, res->ai_addrlen);
+ if (receive_mode) {
+ start_server(s, res);
+ } else {
+ msg.set_qid(42); // can be omitted, then QID will be 0
+ msg.set_rd(true);
+ msg.add_question(Name(argv[0]), RdataClass::IN, RdataType(type_name));
+ msg.to_wire();
+ msg.get_iobuffer().send_to(s, *res->ai_addr, res->ai_addrlen);
+
+ // print sent message
+ cout << msg.to_text() << endl;
+ }
+
+ freeaddrinfo(res);
return (0);
}
Modified: experiments/jinmei-messageapi/dnsmessage.cc
==============================================================================
--- experiments/jinmei-messageapi/dnsmessage.cc (original)
+++ experiments/jinmei-messageapi/dnsmessage.cc Wed Oct 7 08:38:07 2009
@@ -15,9 +15,13 @@
// $Id$
#include <sys/types.h>
+#include <sys/socket.h>
#include <stdexcept>
+#include <boost/lexical_cast.hpp>
+
+#include "dnsresult.hh"
#include "rrset.hh"
#include "dnsmessage.hh"
@@ -28,17 +32,21 @@
{
initialize();
- _default_renderer = new MessageRendererToBuffer;
- _renderer = _default_renderer;
+ _default_iobuffer = new SingleIOBuffer;
+ _iobuffer = _default_iobuffer;
_default_compressor = new NameCompressor;
_compressor = _default_compressor;
+
+ _default_decompressor = new NameDecompressor;
+ _decompressor = _default_decompressor;
}
Message::~Message()
{
- delete _default_renderer;
+ delete _default_iobuffer;
delete _default_compressor;
+ delete _default_decompressor;
}
void
@@ -53,12 +61,12 @@
}
_edns = NULL;
- _parser = NULL;
- _renderer = NULL;
+ _iobuffer = NULL;
_compressor = NULL;
+ _decompressor = NULL;
_sorter = NULL;
- _default_renderer = NULL;
_default_compressor = NULL;
+ _default_decompressor = NULL;
}
void
@@ -83,15 +91,16 @@
{
uint16_t codes_and_flags;
- if (_renderer == NULL)
- throw DNSNoMessageRenderer();
+ if (_iobuffer == NULL)
+ throw DNSNoMessageIOBuffer();
// reserve room for the header
- _renderer->reserve(HEADERLEN);
+ _iobuffer->reserve(HEADERLEN);
for (int section = SECTION_QUESTION; section < SECTION_MAX; ++section) {
if (_sorter != NULL)
_sorter->sort(*this, (section_t)section); //TBD
+ _counts[section] = 0;
for (vector<RRSetPtr>::const_iterator it =
get_section((section_t)section).begin();
it != get_section((section_t)section).end();
@@ -111,26 +120,185 @@
// fill in the header
size_t header_pos = 0;
- _renderer->write_uint16_at(_qid, header_pos);
+ _iobuffer->write_uint16_at(_qid, header_pos);
header_pos += sizeof(uint16_t);
codes_and_flags = (_opcode << OPCODE_SHIFT) & OPCODE_MASK;
- codes_and_flags |= (_rcode << RCODE_MASK);
+ codes_and_flags |= (_rcode & RCODE_MASK);
codes_and_flags |= (_flags & FLAG_MASK);
- _renderer->write_uint16_at(codes_and_flags, header_pos);
+ _iobuffer->write_uint16_at(codes_and_flags, header_pos);
header_pos += sizeof(uint16_t);
for (int section = SECTION_QUESTION; section < SECTION_MAX; ++section) {
- _renderer->write_uint16_at(_counts[section], header_pos);
+ _iobuffer->write_uint16_at(_counts[section], header_pos);
header_pos += sizeof(uint16_t);
}
}
-// TBD: this should be defined somewhere else. Also, the interface should be
-// revisited.
-int
-MessageRendererToBuffer::send_to(int s, struct sockaddr& to, socklen_t to_len)
-{
- int cc;
-
- cc = sendto(s, &_buf[0], _buf.size(), 0, &to, to_len);
- return (cc);
-}
+ISC::ConstResult
+Message::from_wire()
+{
+ if (_iobuffer == NULL)
+ throw DNSNoMessageIOBuffer();
+
+ if (_iobuffer->get_space() < HEADERLEN)
+ return (Result::MessageTooShort);
+
+ _qid = _iobuffer->read_uint16();
+ uint16_t codes_and_flags = _iobuffer->read_uint16();
+ _opcode = ((codes_and_flags & OPCODE_MASK) >> OPCODE_SHIFT);
+ _rcode = (codes_and_flags & RCODE_MASK);
+ _flags = (codes_and_flags & FLAG_MASK);
+ _counts[SECTION_QUESTION] = _iobuffer->read_uint16();
+ _counts[SECTION_ANSWER] = _iobuffer->read_uint16();
+ _counts[SECTION_AUTHORITY] = _iobuffer->read_uint16();
+ _counts[SECTION_ADDITIONAL] = _iobuffer->read_uint16();
+
+ ISC::ConstResult result = parse_question();
+ // parse other sections (TBD)
+
+ return (result);
+}
+
+ISC::ConstResult
+Message::parse_question()
+{
+ Name name;
+ ISC::ConstResult result;
+
+ if (_iobuffer == NULL)
+ throw DNSNoMessageIOBuffer();
+
+ for (int count = 0; count < this->_counts[SECTION_QUESTION]; count++) {
+ result = name.from_wire(get_decompressor(), *_iobuffer);
+ if (result != ISC::Result::Success)
+ goto cleanup;
+
+ // Get type and class
+ if (_iobuffer->get_space() < 2 * sizeof(uint16_t))
+ goto cleanup;
+
+ // XXX: need a duplicate check. We might also want to have an optimized
+ // algorithm that requires the question section contain exactly one
+ // RR.
+
+ RdataType rdtype(_iobuffer->read_uint16());
+ RdataClass rdclass(_iobuffer->read_uint16());
+ add_rrset(SECTION_QUESTION,
+ RRSetPtr(new Question(name, rdclass, rdtype)));
+ }
+
+ return (result);
+
+ cleanup:
+ _sections[SECTION_QUESTION].clear();
+ return (result);
+}
+
+static const char *opcodetext[] = {
+ "QUERY",
+ "IQUERY",
+ "STATUS",
+ "RESERVED3",
+ "NOTIFY",
+ "UPDATE",
+ "RESERVED6",
+ "RESERVED7",
+ "RESERVED8",
+ "RESERVED9",
+ "RESERVED10",
+ "RESERVED11",
+ "RESERVED12",
+ "RESERVED13",
+ "RESERVED14",
+ "RESERVED15"
+};
+
+static const char *rcodetext[] = {
+ "NOERROR",
+ "FORMERR",
+ "SERVFAIL",
+ "NXDOMAIN",
+ "NOTIMP",
+ "REFUSED",
+ "YXDOMAIN",
+ "YXRRSET",
+ "NXRRSET",
+ "NOTAUTH",
+ "NOTZONE",
+ "RESERVED11",
+ "RESERVED12",
+ "RESERVED13",
+ "RESERVED14",
+ "RESERVED15"
+};
+
+static const char *sectiontext[] = {
+ "QUESTION",
+ "ANSWER",
+ "AUTHORITY",
+ "ADDITIONAL"
+};
+
+string
+Message::to_text() const
+{
+ string s;
+
+ s += ";; ->>HEADER<<- opcode: " + string(opcodetext[_opcode]);
+ // for simplicity we don't consider extended rcode (unlike BIND9)
+ s += ", status: " + string(rcodetext[_rcode]);
+ s += ", id: " + boost::lexical_cast<string>(_qid);
+ s += "\n;; flags: ";
+ if (get_qr())
+ s += "qr ";
+ if (get_aa())
+ s += "aa ";
+ if (get_tc())
+ s += "tc ";
+ if (get_rd())
+ s += "rd ";
+ if (get_ra())
+ s += "ra ";
+ if (get_ad())
+ s += "ad ";
+ if (get_cd())
+ s += "cd ";
+
+ // for simply, don't consider the update case
+ s += "; QUESTION: " +
+ boost::lexical_cast<string>(_counts[SECTION_QUESTION]);
+ s += ", ANSWER: " + boost::lexical_cast<string>(_counts[SECTION_ANSWER]);
+ s += ", AUTHORITY: " +
+ boost::lexical_cast<string>(_counts[SECTION_AUTHORITY]);
+ s += ", ADDITIONAL: " +
+ boost::lexical_cast<string>(_counts[SECTION_ADDITIONAL]) + "\n";
+
+ for (int section = SECTION_QUESTION; section < SECTION_MAX; ++section) {
+ if (_sections[section].empty())
+ continue;
+
+ s += "\n;; " + string(sectiontext[section]) + " SECTION:\n";
+
+ vector<RRSetPtr>::const_iterator it;
+ for (it = _sections[section].begin();
+ it != _sections[section].end();
+ ++it)
+ {
+ if (section == SECTION_QUESTION)
+ s += ";";
+ s += (**it).to_text() + "\n";
+ }
+ }
+
+ return (s);
+}
+
+void
+Message::make_response()
+{
+ _flags &= MESSAGE_REPLYPRESERVE;
+ set_qr(true);
+
+ for (int section = SECTION_ANSWER; section < SECTION_MAX; ++section) {
+ _sections[section].clear();
+ }
+}
Modified: experiments/jinmei-messageapi/dnsmessage.hh
==============================================================================
--- experiments/jinmei-messageapi/dnsmessage.hh (original)
+++ experiments/jinmei-messageapi/dnsmessage.hh Wed Oct 7 08:38:07 2009
@@ -25,7 +25,7 @@
#include <boost/shared_ptr.hpp>
#include "dnsexceptions.hh"
-
+#include "iobuffer.hh"
#include "dnsname.hh"
#include "rrset.hh"
@@ -40,8 +40,6 @@
class Message;
class EDNS; // see below
-class MessageParser;
-class MessageRenderer;
typedef boost::shared_ptr<AbstractRRSet> RRSetPtr;
@@ -51,74 +49,38 @@
};
class NameCompressor {}; // empty class for prototyping
-
-class MessageRenderer {
-public:
- virtual void reserve(size_t len) = 0;
- virtual void write_data(const char *cp, size_t len) = 0;
- virtual void write_uint32(uint32_t data) = 0;
- virtual void write_uint16(uint16_t data) = 0;
- virtual void write_uint16_at(uint16_t data, size_t pos) = 0;
- virtual void write_uint8(uint8_t data) = 0;
- virtual int send_to(int s, struct sockaddr& to, socklen_t to_len) = 0;
-};
-
-class MessageRendererToBuffer : public MessageRenderer {
-public:
- void reserve(size_t len) // XXX: API and implementation should be revisited
- {
- _buf.resize(len);
- }
- void write_data(const char *cp, size_t len)
- { _buf.insert(_buf.end(), cp, cp + len); }
- void write_uint32(uint32_t data)
- {
- data = htonl(data);
- uint8_t* cp = static_cast<uint8_t*>((void*)&data);
- _buf.insert(_buf.end(), cp, cp + sizeof(uint32_t));
- }
- void write_uint16(uint16_t data)
- {
- data = htons(data);
- uint8_t* cp = static_cast<uint8_t*>((void*)&data);
- _buf.insert(_buf.end(), cp, cp + sizeof(uint16_t));
- }
- void write_uint16_at(uint16_t data, size_t pos)
- {
- if (pos + sizeof(data) >= _buf.size())
- throw DNSInvalidRendererPosition();
-
- data = htons(data);
- uint8_t* cp = static_cast<uint8_t*>((void*)&data);
- copy(cp, cp + sizeof(uint16_t), _buf.begin() + pos);
- }
- void write_uint8(uint8_t data)
- {
- _buf.push_back(data);
- }
- int send_to(int s, struct sockaddr& to, socklen_t to_len);
-private:
- vector<uint8_t> _buf;
-};
+class NameDecompressor {}; // ditto
+
+#define get_msgflg(flg, capflg) \
+bool get_ ## flg() const { return ((_flags & FLAG_ ## capflg) != 0); }
+#define set_msgflg(flg, capflg) \
+bool set_ ## flg(bool on) { \
+ if (on) \
+ _flags |= FLAG_ ## capflg; \
+ else \
+ _flags &= ~FLAG_ ## capflg; \
+ }
class Message {
public:
Message();
- Message(MessageParser* parser);
- Message(MessageRenderer* renderer, NameCompressor* compressor);
~Message();
qid_t get_qid() const { return (_qid); }
void set_qid(qid_t qid) { _qid = qid; }
- bool get_rd() const { return ((_flags & FLAG_RD) != 0); }
- void set_rd(bool on)
- {
- if (on)
- _flags |= FLAG_RD;
- else
- _flags &= ~FLAG_RD;
- }
- bool get_aa() const; // return true if set; false otherwise
- void set_aa(bool on); // same for QR, TC, RD, RA, AD, CD
+ get_msgflg(rd, RD)
+ set_msgflg(rd, RD)
+ get_msgflg(aa, AA)
+ set_msgflg(aa, AA)
+ get_msgflg(qr, QR)
+ set_msgflg(qr, QR)
+ get_msgflg(tc, TC)
+ set_msgflg(tc, TC)
+ get_msgflg(ra, RA)
+ set_msgflg(ra, RA)
+ get_msgflg(ad, AD)
+ set_msgflg(ad, AD)
+ get_msgflg(cd, CD)
+ set_msgflg(cd, CD)
rcode_t get_rcode() const { return (_rcode); }
void set_rcode(rcode_t rcode) { _rcode = rcode; }
opcode_t get_opcode() const { return (_opcode); }
@@ -152,18 +114,20 @@
void set_edns(EDNS* edns); // TBD
const EDNS* get_edns() const; // TBD
- // prepare for making a response from a request: see
- // dns_message_reply() of BIND9
- void make_response(MessageRenderer* renderer, NameCompressor* compressor);
+ // prepare for making a response from a request. This will clear the
+ // DNS header except those fields that should be kept for the response,
+ // and clear answer and the following sections.
+ // see also dns_message_reply() of BIND9.
+ void make_response();
// Render message
void to_wire(); // should probably return some result code?
- MessageRenderer& get_renderer()
+ IOBuffer& get_iobuffer()
{
- if (_renderer == NULL)
- throw DNSNoMessageRenderer();
- return (*_renderer);
+ if (_iobuffer == NULL)
+ throw DNSNoMessageIOBuffer();
+ return (*_iobuffer);
}
NameCompressor& get_compressor()
@@ -173,11 +137,38 @@
return (*_compressor);
}
- // Parse message: TBD
- void parse();
+ NameDecompressor& get_decompressor()
+ {
+ if (_decompressor == NULL)
+ throw DNSNoNameDecompressor();
+ return (*_decompressor);
+ }
+
+ // Parse message:
+ // In general, we don't trust data from wire, so we return an explicit
+ // error code rather than throw an exception when we encounter a malformed
+ // message. We cannot make it a constructor for the same reason.
+ ISC::ConstResult from_wire();
+
+public:
+ // public protocol constants
+ static const rcode_t RCODE_NOERROR = 0;
+ static const rcode_t RCODE_FORMERR = 1;
+ static const rcode_t RCODE_SERVFAIL = 2;
+ static const rcode_t RCODE_NXDOMAIN = 3;
+ static const rcode_t RCODE_NOTIMP = 4;
+ static const rcode_t RCODE_REFUSED = 5;
+ // ...more to follow
+
+ static const opcode_t OPCODE_QUERY = 0;
+ static const opcode_t OPCODE_IQUERY = 1;
+ static const opcode_t OPCODE_STATUS = 2;
+ static const opcode_t OPCODE_NOTIFY = 4;
+ static const opcode_t OPCODE_UPDATE = 5;
private:
void initialize();
+ ISC::ConstResult parse_question();
private:
// Open issues: should we rather have a header in wire-format
@@ -194,31 +185,18 @@
// tsig/sig0: TODO
EDNS* _edns;
- MessageParser* _parser;
- MessageRenderer* _renderer;
+ IOBuffer* _iobuffer;
NameCompressor* _compressor;
+ NameDecompressor* _decompressor;
RRSetsSorter* _sorter;
// created internally with the default constructor. TBD: revisit this idea.
- MessageRenderer* _default_renderer;
+ IOBuffer* _default_iobuffer;
NameCompressor* _default_compressor;
+ NameDecompressor* _default_decompressor;
// protocol constants
static const size_t HEADERLEN = 12;
-
- static const rcode_t RCODE_NOERROR = 0;
- static const rcode_t RCODE_FORMERR = 1;
- static const rcode_t RCODE_SERVFAIL = 2;
- static const rcode_t RCODE_NXDOMAIN = 3;
- static const rcode_t RCODE_NOTIMP = 4;
- static const rcode_t RCODE_REFUSED = 5;
- // ...more to follow
-
- static const opcode_t OPCODE_QUERY = 0;
- static const opcode_t OPCODE_IQUERY = 1;
- static const opcode_t OPCODE_STATUS = 2;
- static const opcode_t OPCODE_NOTIFY = 4;
- static const opcode_t OPCODE_UPDATE = 5;
static const flags_t FLAG_QR = 0x8000;
static const flags_t FLAG_AA = 0x0400;
@@ -232,6 +210,8 @@
static const unsigned int OPCODE_SHIFT = 11;
static const unsigned int RCODE_MASK = 0x000f;
static const unsigned int FLAG_MASK = 0x8ff0;
+
+ static const unsigned int MESSAGE_REPLYPRESERVE = (FLAG_RD | FLAG_CD);
};
}
}
Modified: experiments/jinmei-messageapi/dnsname.cc
==============================================================================
--- experiments/jinmei-messageapi/dnsname.cc (original)
+++ experiments/jinmei-messageapi/dnsname.cc Wed Oct 7 08:38:07 2009
@@ -16,6 +16,8 @@
#include <stdexcept>
+#include "dnsresult.hh"
+#include "iobuffer.hh"
#include "dnsname.hh"
#include "dnsmessage.hh"
#include "dnsexceptions.hh"
@@ -32,6 +34,13 @@
ft_escdecimal,
ft_at
} ft_state;
+
+typedef enum {
+ fw_start = 0,
+ fw_ordinary,
+ fw_copy,
+ fw_newcurrent
+} fw_state;
static char digitvalue[256] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 16
@@ -400,11 +409,115 @@
}
void
-Name::to_wire(MessageRenderer& r, NameCompressor& c) const
+Name::to_wire(IOBuffer& b, NameCompressor& c) const
{
// TBD: very simple version for prototyping; e.g. it omits compression.
- r.write_data(_ndata.c_str(), _ndata.size());
- r.write_uint8(0); // XXX: explicitly need trailing null char
+ b.write_data(_ndata.c_str(), _ndata.size());
+ if (!_is_absolute) // should be revisited
+ b.write_uint8(0); // XXX: explicitly need trailing null char
+}
+
+const ISC::Result*
+Name::from_wire(NameDecompressor& decompressor, IOBuffer& source)
+{
+ unsigned int nused, labels, n, nmax;
+ unsigned int current;
+ bool done;
+ fw_state state = fw_start;
+ unsigned int c;
+ bool downcase;
+ bool seen_pointer;
+
+ /*
+ * Initialize things to make the compiler happy; they're not required.
+ */
+ n = 0;
+
+ /*
+ * Set up.
+ */
+ labels = 0;
+ done = false;
+ nused = 0;
+
+ /*
+ * Find the maximum number of uncompressed target name
+ * bytes we are willing to generate. This is the smaller
+ * of the available target buffer length and the
+ * maximum legal domain name length (255).
+ */
+ nmax = NAME_MAXWIRE;
+
+ current = source.get_current();
+
+ /*
+ * Note: The following code is not optimized for speed, but
+ * rather for correctness. Speed will be addressed in the future.
+ */
+ while (current < source.get_size() && !done) {
+ c = source.read_uint8();
+ current++;
+
+ switch (state) {
+ case fw_start:
+ if (c < 64) {
+ _offsets.push_back(nused);
+ labels++;
+ if (nused + c + 1 > nmax)
+ goto full;
+ nused += c + 1;
+ _ndata.push_back(c);
+ if (c == 0)
+ done = true;
+ n = c;
+ state = fw_ordinary;
+ } else if (c >= 128 && c < 192) {
+ /*
+ * 14 bit local compression pointer.
+ * Local compression is no longer an
+ * IETF draft.
+ */
+ return (ISC::DNS::Result::BadLabelType);
+ } else if (c >= 192) {
+ /*
+ * Ordinary 14-bit pointer.
+ */
+ return (ISC::DNS::Result::BadLabelType); // XXX not implemented
+ } else
+ return (ISC::DNS::Result::BadLabelType);
+ break;
+ case fw_ordinary:
+ if (downcase)
+ c = maptolower[c];
+ /* FALLTHROUGH */
+ case fw_copy:
+ _ndata.push_back(c);
+ n--;
+ if (n == 0)
+ state = fw_start;
+ break;
+ case fw_newcurrent:
+ // XXX not implemented, fall through
+ default:
+ throw ISCUnexpected();
+ }
+ }
+
+ if (!done)
+ return (ISC::Result::Unexpected);
+
+ _labels = labels;
+ _length = nused;
+ _is_absolute = true;
+
+ return (ISC::Result::Success);
+
+ full:
+ /*
+ * The name did not fit even though we had a buffer
+ * big enough to fit a maximum-length name.
+ */
+ return (ISC::DNS::Result::NameTooLong);
}
bool
Modified: experiments/jinmei-messageapi/dnsname.hh
==============================================================================
--- experiments/jinmei-messageapi/dnsname.hh (original)
+++ experiments/jinmei-messageapi/dnsname.hh Wed Oct 7 08:38:07 2009
@@ -22,13 +22,15 @@
#include "iscexceptions.hh"
#include "dnsexceptions.hh"
+#include "dnsresult.hh"
+#include "iobuffer.hh"
using namespace std;
namespace ISC {
namespace DNS {
-class MessageRenderer;
class NameCompressor;
+class NameDecompressor;
typedef enum {
namereln_none = 0,
@@ -67,7 +69,8 @@
// public methods
string to_text(bool omit_final_dot) const;
- void to_wire(MessageRenderer& r, NameCompressor& c) const;
+ void to_wire(IOBuffer& r, NameCompressor& c) const;
+ const ISC::Result* from_wire(NameDecompressor& c, IOBuffer& iobuf);
unsigned int countlabels() const { return (_labels); }
NameComparisonResult fullcompare(const Name &other) const;
Name split(unsigned int first, unsigned int n) const;
@@ -83,6 +86,8 @@
bool operator>=(const Name &other) const;
bool operator<(const Name &other) const;
bool operator>(const Name &other) const;
+
+ static const unsigned int NAME_MAXWIRE = 255;
private:
string _ndata; // or vector<unsigned char>?
vector<char> _offsets;
Modified: experiments/jinmei-messageapi/iscexceptions.hh
==============================================================================
--- experiments/jinmei-messageapi/iscexceptions.hh (original)
+++ experiments/jinmei-messageapi/iscexceptions.hh Wed Oct 7 08:38:07 2009
@@ -20,7 +20,9 @@
namespace ISC {
// quick hack exception classes
class ISCException {};
+class ISCUnexpected : public ISCException {};
class ISCNoSpace : public ISCException {};
class ISCInvalidAddressString : public ISCException {};
+class ISCIOBufferInvalidPosition : public ISCException {};
}
#endif // __ISCEXCEPTIONS_HH
Modified: experiments/jinmei-messageapi/rrset.cc
==============================================================================
--- experiments/jinmei-messageapi/rrset.cc (original)
+++ experiments/jinmei-messageapi/rrset.cc Wed Oct 7 08:38:07 2009
@@ -52,9 +52,9 @@
}
void
-RdataClass::to_wire(MessageRenderer& r) const
-{
- r.write_uint16(_classval);
+RdataClass::to_wire(IOBuffer& b) const
+{
+ b.write_uint16(_classval);
}
const RdataClass RdataClass::IN("IN");
@@ -83,9 +83,9 @@
}
void
-RdataType::to_wire(MessageRenderer& r) const
-{
- r.write_uint16(_typeval);
+RdataType::to_wire(IOBuffer& b) const
+{
+ b.write_uint16(_typeval);
}
const RdataType RdataType::A("A");
@@ -93,9 +93,9 @@
// ...more to follow
void
-TTL::to_wire(MessageRenderer& r) const
-{
- r.write_uint16(_ttlval);
+TTL::to_wire(IOBuffer& b) const
+{
+ b.write_uint32(_ttlval);
}
ARdata::ARdata(const string& addrstr)
@@ -113,9 +113,10 @@
}
void
-ARdata::to_wire(MessageRenderer& renderer, NameCompressor& compressor) const
-{
- //TBD: copy (const char *)&_addr, sizeof(_addr)
+ARdata::to_wire(IOBuffer& buffer, NameCompressor& compressor) const
+{
+ buffer.write_uint16(sizeof(_addr));
+ buffer.write_data(static_cast<const char *>((void *)&_addr), sizeof(_addr));
}
string
@@ -144,9 +145,10 @@
}
void
-AAAARdata::to_wire(MessageRenderer& renderer, NameCompressor& compressor) const
-{
- //TBD: copy (const char *)&_addr, sizeof(_addr)
+AAAARdata::to_wire(IOBuffer& buffer, NameCompressor& compressor) const
+{
+ buffer.write_uint16(sizeof(_addr));
+ buffer.write_data(static_cast<const char *>((void *)&_addr), sizeof(_addr));
}
string
@@ -221,17 +223,17 @@
// sort Rdata list based on rrset-order and sortlist, and possible
// other options. Details to be considered.
- MessageRenderer& r = message.get_renderer();
+ IOBuffer& b = message.get_iobuffer();
NameCompressor& c = message.get_compressor();
for (vector<rdataptr_t>::iterator it = _rdatalist.begin();
it != _rdatalist.end();
++it, ++num_rrs)
{
- _name.to_wire(r, c);
- _rdtype.to_wire(r);
- _rdclass.to_wire(r);
- _ttl.to_wire(r);
- (**it).to_wire(r, c);
+ _name.to_wire(b, c);
+ _rdtype.to_wire(b);
+ _rdclass.to_wire(b);
+ _ttl.to_wire(b);
+ (**it).to_wire(b, c);
// TBD: handle truncation case
}
@@ -251,12 +253,12 @@
int
Question::to_wire(Message& message, section_t section)
{
- MessageRenderer& r = message.get_renderer();
+ IOBuffer& b = message.get_iobuffer();
NameCompressor& c = message.get_compressor();
- _name.to_wire(r, c);
- _rdtype.to_wire(r);
- _rdclass.to_wire(r);
+ _name.to_wire(b, c);
+ _rdtype.to_wire(b);
+ _rdclass.to_wire(b);
return (1);
}
@@ -268,7 +270,7 @@
// sort Rdata list based on rrset-order and sortlist, and possible
// other options with no or fewer copies. Details to be considered.
- MessageRenderer& r = message.get_renderer();
+ IOBuffer& b = message.get_iobuffer();
// directly copy or link to wire-formatted data in the renderer for
// faster rendering. details to be considered.
Modified: experiments/jinmei-messageapi/rrset.hh
==============================================================================
--- experiments/jinmei-messageapi/rrset.hh (original)
+++ experiments/jinmei-messageapi/rrset.hh Wed Oct 7 08:38:07 2009
@@ -42,7 +42,6 @@
// to care much more about resource leak.
//typedef Rdata * rdataptr_t;
class Message;
-class MessageRenderer;
class NameCompressor;
// XXX: this should be defined somewhere else.
@@ -59,7 +58,7 @@
_classval(classval) {}
explicit RdataClass(const string& classstr);
const string to_text() const;
- void to_wire(MessageRenderer& r) const;
+ void to_wire(IOBuffer& b) const;
uint16_t get_value() const { return (_classval); }
bool operator==(const RdataClass& other) const
{ return (_classval == other._classval); }
@@ -80,7 +79,7 @@
_typeval(typeval) {}
explicit RdataType(const string& typestr);
const string to_text() const;
- void to_wire(MessageRenderer& r) const;
+ void to_wire(IOBuffer& b) const;
uint16_t get_value() const { return (_typeval); }
bool operator==(const RdataType& other) const
{ return (_typeval == other._typeval); }
@@ -105,7 +104,7 @@
TTL(uint32_t ttlval) : _ttlval(ttlval) {}
string to_text() const
{ return (boost::lexical_cast<string>(_ttlval)); }
- void to_wire(MessageRenderer& r) const;
+ void to_wire(IOBuffer& b) const;
uint32_t get_value() { return (_ttlval); }
bool operator==(const TTL& other) const
{ return (_ttlval == other._ttlval); }
@@ -128,8 +127,7 @@
virtual const RdataType& get_type() const = 0;
virtual string to_text() const = 0;
virtual void from_wire(const string& wireData) = 0;
- virtual void to_wire(MessageRenderer& r,
- NameCompressor& c) const = 0;
+ virtual void to_wire(IOBuffer& b, NameCompressor& c) const = 0;
// need generic method for getting n-th field? c.f. ldns
// e.g. string getField(int n);
};
@@ -165,7 +163,7 @@
static const RdataType& get_type_static() { return (RdataType::A); }
string to_text() const;
void from_wire(const string& wireData);
- void to_wire(MessageRenderer& r, NameCompressor& c) const;
+ void to_wire(IOBuffer& b, NameCompressor& c) const;
const struct in_addr& getAddress() const
{ return (_addr); }
bool operator==(const ARdata &other) const
@@ -189,7 +187,7 @@
static const RdataType& get_type_static()
{ return (RdataType::AAAA); }
void from_wire(const string& wireData);
- void to_wire(MessageRenderer& r, NameCompressor& c) const;
+ void to_wire(IOBuffer& b, NameCompressor& c) const;
const struct in6_addr& getAddress() const
{ return (_addr); }
bool operator==(const AAAARdata &other) const
@@ -322,7 +320,7 @@
explicit RR(const string& rrstr);
explicit RR(const Name &name, const RdataClass &rdclass,
const RdataType &rdtype, const TTL &ttl,
- const Rdata &rdata) {}
+ const Rdata &rdata);
string to_text() const
{ return (_rrset.to_text()); }
const Name& get_name() const
More information about the bind10-changes
mailing list