Part of the uglification is that we now special case unescaped names, which are the vast majority of cases.
Simultaneously, this moves us back to DNSName boost::container::string on non-Apple platforms, which delivered another 15% speedup on general operations
Finally, an additional unit test is added.
#include <stdio.h>
#include <unistd.h>
#include <string>
+#include "dnsname.hh"
#include "namespaces.hh"
namespace {
return ret;
};
-deque<string> segmentDNSName(const string& input )
+
+DNSName::string_t segmentDNSNameRaw(const char* realinput)
{
- // cerr<<"segmentDNSName("<<input<<")"<<endl;
%%{
- machine dnsname;
+ machine dnsnameraw;
write data;
alphtype unsigned char;
}%%
- (void)dnsname_error; // silence warnings
- (void)dnsname_en_main;
+ (void)dnsnameraw_error; // silence warnings
+ (void)dnsnameraw_en_main;
- deque<string> ret;
+ DNSName::string_t ret;
- string realinput;
- if(input.empty() || input == ".") return ret;
+ if(!*realinput || *realinput == '.') {
+ ret.append(1, (char)0);
+ return ret;
+ }
- if(input[input.size()-1]!='.') realinput=input+"."; // FIXME400 YOLO
- else realinput=input;
+ unsigned int inputlen=strlen(realinput);
+ ret.reserve(inputlen+1);
- const char *p = realinput.c_str(), *pe = realinput.c_str() + realinput.length();
+ const char *p = realinput, *pe = realinput + inputlen;
const char* eof = pe;
int cs;
char val = 0;
-
- string label;
- label.reserve(10);
+ char labellen=0;
+ unsigned int lenpos=0;
%%{
action labelEnd {
- ret.push_back(label);
- label.clear();
+ ret[lenpos]=labellen;
+ labellen=0;
}
action labelBegin {
- label.clear();
+ lenpos=ret.size();
+ ret.append(1, (char)0);
+ labellen=0;
}
action reportEscaped {
char c = *fpc;
- label.append(1, c);
+ ret.append(1, c);
+ labellen++;
}
action reportEscapedNumber {
char c = *fpc;
val *= 10;
val += c-'0';
-
}
action doneEscapedNumber {
- label.append(1, val);
+ ret.append(1, val);
+ labellen++;
val=0;
}
action reportPlain {
- label.append(1, *(fpc));
+ ret.append(1, *(fpc));
+ labellen++;
}
escaped = '\\' (([^0-9]@reportEscaped) | ([0-9]{3}$reportEscapedNumber%doneEscapedNumber));
plain = (extend-'\\'-'.') $ reportPlain;
labelElement = escaped | plain;
- main := ((labelElement+ '.') >labelBegin %labelEnd)+;
+ label = labelElement+ >labelBegin %labelEnd;
+
+ main:= label ('.' label )* '.'?;
+
+ #main := labelElement((labelElement+ '.') >labelBegin %labelEnd)+;
+
+ # label = (plain | escaped | escdecb)+ >label_init %label_fin;
+ # dnsname := '.'? label ('.' label >label_sep)* '.'?;
# Initialize and execute.
write init;
write exec;
}%%
- if ( cs < dnsname_first_final ) {
- throw runtime_error("Unable to parse DNS name '"+input+"' ('"+realinput+"'): cs="+std::to_string(cs));
+ if ( cs < dnsnameraw_first_final ) {
+ throw runtime_error("Unable to parse DNS name '"+string(realinput)+"': cs="+std::to_string(cs));
}
-
+ ret.append(1, (char)0);
return ret;
};
+
#if 0
int main()
{
return os <<d.toString();
}
-
DNSName::DNSName(const char* p)
{
if(p[0]==0 || (p[0]=='.' && p[1]==0)) {
d_storage.assign(1, (char)0);
} else {
- d_storage.reserve(strlen(p)+1);
- auto labels = segmentDNSName(p);
- for(const auto& e : labels)
- appendRawLabel(e);
+ if(!strchr(p, '\\')) {
+ unsigned char lenpos=0;
+ unsigned char labellen=0;
+ unsigned int plen=strlen(p);
+ const char* const pbegin=p, *pend=p+plen;
+ d_storage.reserve(plen+1);
+ for(auto iter = pbegin; iter != pend; ) {
+ lenpos = d_storage.size();
+ if(*iter=='.')
+ throw std::runtime_error("Found . in wrong position in DNSName "+string(p));
+ d_storage.append(1, (char)0);
+ labellen=0;
+ auto begiter=iter;
+ for(; iter != pend && *iter!='.'; ++iter) {
+ labellen++;
+ }
+ d_storage.append(begiter,iter);
+ if(iter != pend)
+ ++iter;
+ if(labellen > 63)
+ throw std::range_error("label too long to append");
+
+ if(iter-pbegin > 254) // reserve two bytes, one for length and one for the root label
+ throw std::range_error("name too long to append");
+
+ d_storage[lenpos]=labellen;
+ }
+ d_storage.append(1, (char)0);
+ }
+ else
+ d_storage=segmentDNSNameRaw(p);
}
}
+
DNSName::DNSName(const char* pos, int len, int offset, bool uncompress, uint16_t* qtype, uint16_t* qclass, unsigned int* consumed)
{
if (offset >= len)
#include <deque>
#include <strings.h>
#include <stdexcept>
+
+// it crashes on OSX..
+#ifndef __APPLE__
#include <boost/container/string.hpp>
+#endif
uint32_t burtleCI(const unsigned char* k, uint32_t lengh, uint32_t init);
public:
DNSName() {} //!< Constructs an *empty* DNSName, NOT the root!
explicit DNSName(const char* p); //!< Constructs from a human formatted, escaped presentation
- explicit DNSName(const std::string& str) : DNSName(str.c_str()) {} //!< Constructs from a human formatted, escaped presentation
+ explicit DNSName(const std::string& str) : DNSName(str.c_str()) {}; //!< Constructs from a human formatted, escaped presentation
DNSName(const char* p, int len, int offset, bool uncompress, uint16_t* qtype=0, uint16_t* qclass=0, unsigned int* consumed=0); //!< Construct from a DNS Packet, taking the first question if offset=12
bool isPartOf(const DNSName& rhs) const; //!< Are we part of the rhs name?
inline bool canonCompare(const DNSName& rhs) const;
bool slowCanonCompare(const DNSName& rhs) const;
-private:
+
+#ifdef __APPLE__
+ typedef std::string string_t;
+#else
typedef boost::container::string string_t;
- // typedef std::string string_t;
+#endif
+private:
string_t d_storage;
void packetParser(const char* p, int len, int offset, bool uncompress, uint16_t* qtype=0, uint16_t* qclass=0, unsigned int* consumed=0, int depth=0);
size_t operator () (const DNSName& dn) const { return dn.hash(0); }
};
}
+
+DNSName::string_t segmentDNSNameRaw(const char* input); // from ragel
}
BOOST_AUTO_TEST_CASE(test_toolong) {
+
BOOST_CHECK_THROW(DNSName w("1234567890123456789012345678901234567890123456789012345678901234567890.com."), std::range_error);
+
+ BOOST_CHECK_THROW(DNSName w("12345678901234567890.12345678901234567890123456.789012345678901.234567890.12345678901234567890.12345678901234567890123456.789012345678901.234567890.12345678901234567890.12345678901234567890123456.789012345678901.234567890.234567890.789012345678901.234567890.234567890.789012345678901.234567890.234567890.com."), std::range_error);
}
BOOST_AUTO_TEST_CASE(test_dnsstrings) {