diff options
author | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-01-13 20:27:50 +0000 |
---|---|---|
committer | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-01-13 20:27:50 +0000 |
commit | b1d8c25b97a98dbde3d4e8c8c298b8f46a3ddb29 (patch) | |
tree | 841a45d29cb2a0b87d322f520560422b135a9051 /net/base | |
parent | b16df4c69cedc3862c05c85cba62e2673a1ce345 (diff) | |
download | chromium_src-b1d8c25b97a98dbde3d4e8c8c298b8f46a3ddb29.zip chromium_src-b1d8c25b97a98dbde3d4e8c8c298b8f46a3ddb29.tar.gz chromium_src-b1d8c25b97a98dbde3d4e8c8c298b8f46a3ddb29.tar.bz2 |
net: enable DnsRRResolver on Windows
(Note that this code was developed by try-server so if something appears
to be terribly wrong, it probably is.)
BUG=none
TEST=net_unittests
http://codereview.chromium.org/6180001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@71349 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/base')
-rw-r--r-- | net/base/dns_util.h | 2 | ||||
-rw-r--r-- | net/base/dnsrr_resolver.cc | 90 | ||||
-rw-r--r-- | net/base/dnsrr_resolver_unittest.cc | 43 |
3 files changed, 124 insertions, 11 deletions
diff --git a/net/base/dns_util.h b/net/base/dns_util.h index 1120140..d86fcb9 100644 --- a/net/base/dns_util.h +++ b/net/base/dns_util.h @@ -28,6 +28,8 @@ std::string TrimEndingDot(const std::string& host); // DNS resource record types. See // http://www.iana.org/assignments/dns-parameters +// WARNING: if you're adding any new values here you may need to add them to +// dnsrr_resolver.cc:DnsRRIsParsedByWindows. static const uint16 kDNS_CNAME = 5; static const uint16 kDNS_TXT = 16; diff --git a/net/base/dnsrr_resolver.cc b/net/base/dnsrr_resolver.cc index 14b7b93..203ae52 100644 --- a/net/base/dnsrr_resolver.cc +++ b/net/base/dnsrr_resolver.cc @@ -8,6 +8,10 @@ #include <resolv.h> #endif +#if defined(OS_WIN) +#include <windns.h> +#endif + #include "base/lock.h" #include "base/message_loop.h" #include "base/scoped_ptr.h" @@ -70,10 +74,30 @@ // // Post - - namespace net { +#if defined(OS_WIN) +// DnsRRIsParsedByWindows returns true if Windows knows how to parse the given +// RR type. RR data is returned in a DNS_RECORD structure which may be raw (if +// Windows doesn't parse it) or may be a parse result. It's unclear how this +// API is intended to evolve in the future. If Windows adds support for new RR +// types in a future version a client which expected raw data will break. +// See http://msdn.microsoft.com/en-us/library/ms682082(v=vs.85).aspx +static bool DnsRRIsParsedByWindows(uint16 rrtype) { + // We only cover the types which are defined in dns_util.h + switch (rrtype) { + case kDNS_CNAME: + case kDNS_TXT: + case kDNS_DS: + case kDNS_RRSIG: + case kDNS_DNSKEY: + return true; + default: + return false; + } +} +#endif + static const uint16 kClassIN = 1; // kMaxCacheEntries is the number of RRResponse objects that we'll cache. static const unsigned kMaxCacheEntries = 32; @@ -233,9 +257,67 @@ class RRResolverWorker { return; } + // See http://msdn.microsoft.com/en-us/library/ms682016(v=vs.85).aspx + PDNS_RECORD record = NULL; + DNS_STATUS status = + DnsQuery_A(name_.c_str(), rrtype_, DNS_QUERY_STANDARD, + NULL /* pExtra (reserved) */, &record, NULL /* pReserved */); response_.fetch_time = base::Time::Now(); - response_.negative = true; - result_ = ERR_NAME_NOT_RESOLVED; + response_.name = name_; + response_.dnssec = false; + response_.ttl = 0; + + if (status != 0) { + response_.negative = true; + result_ = ERR_NAME_NOT_RESOLVED; + } else { + response_.negative = false; + result_ = OK; + for (DNS_RECORD* cur = record; cur; cur = cur->pNext) { + if (cur->wType == rrtype_) { + response_.ttl = record->dwTtl; + // Windows will parse some types of resource records. If we want one + // of these types then we have to reserialise the record. + switch (rrtype_) { + case kDNS_TXT: { + // http://msdn.microsoft.com/en-us/library/ms682109(v=vs.85).aspx + const DNS_TXT_DATA* txt = &cur->Data.TXT; + std::string rrdata; + + for (DWORD i = 0; i < txt->dwStringCount; i++) { + // Although the string is typed as a PWSTR, it's actually just + // an ASCII byte-string. Also, the string must be < 256 + // elements because the length in the DNS packet is a single + // byte. + const char* s = reinterpret_cast<char*>(txt->pStringArray[i]); + size_t len = strlen(s); + DCHECK_LT(len, 256u); + char len8 = static_cast<char>(len); + rrdata.push_back(len8); + rrdata += s; + } + response_.rrdatas.push_back(rrdata); + break; + } + default: + if (DnsRRIsParsedByWindows(rrtype_)) { + // Windows parses this type, but we don't have code to unparse + // it. + NOTREACHED() << "you need to add code for the RR type here"; + response_.negative = true; + result_ = ERR_INVALID_ARGUMENT; + } else { + // This type is given to us raw. + response_.rrdatas.push_back( + std::string(reinterpret_cast<char*>(&cur->Data), + cur->wDataLength)); + } + } + } + } + } + + DnsRecordListFree(record, DnsFreeRecordList); Finish(); } diff --git a/net/base/dnsrr_resolver_unittest.cc b/net/base/dnsrr_resolver_unittest.cc index dfa904a..560052a 100644 --- a/net/base/dnsrr_resolver_unittest.cc +++ b/net/base/dnsrr_resolver_unittest.cc @@ -17,8 +17,6 @@ namespace net { class DnsRRResolverTest : public testing::Test { }; -#if defined(OS_LINUX) - class ExplodingCallback : public CallbackRunner<Tuple1<int> > { public: virtual void RunWithParams(const Tuple1<int>& params) { @@ -26,8 +24,39 @@ class ExplodingCallback : public CallbackRunner<Tuple1<int> > { } }; -// This test is disabled because it depends on the external network to pass. -// However, it may be useful when chaging the code. +// These tests are disabled because they depend on the external network to +// pass. However, they may be useful when chaging the code. +TEST_F(DnsRRResolverTest, DISABLED_ResolveReal) { + RRResponse response; + TestCompletionCallback callback; + DnsRRResolver resolver; + DnsRRResolver::Handle handle; + + handle = resolver.Resolve("test.imperialviolet.org", 13172, 0, + &callback, &response, 0, BoundNetLog()); + ASSERT_TRUE(handle != DnsRRResolver::kInvalidHandle); + ASSERT_EQ(OK, callback.WaitForResult()); + ASSERT_EQ(1u, response.rrdatas.size()); + LOG(ERROR) << "result length " << response.rrdatas[0].size(); + LOG(ERROR) << "result is " << response.rrdatas[0]; +} + +TEST_F(DnsRRResolverTest, DISABLED_ResolveReal2) { + RRResponse response; + TestCompletionCallback callback; + DnsRRResolver resolver; + DnsRRResolver::Handle handle; + + handle = resolver.Resolve("google.com", kDNS_TXT, 0, + &callback, &response, 0, BoundNetLog()); + ASSERT_TRUE(handle != DnsRRResolver::kInvalidHandle); + ASSERT_EQ(OK, callback.WaitForResult()); + ASSERT_EQ(1u, response.rrdatas.size()); + LOG(ERROR) << "result length " << response.rrdatas[0].size(); + LOG(ERROR) << "result is " << response.rrdatas[0]; +} + + TEST_F(DnsRRResolverTest, Resolve) { RRResponse response; TestCompletionCallback callback; @@ -55,7 +84,7 @@ TEST_F(DnsRRResolverTest, Resolve) { ASSERT_EQ(1u, resolver.cache_hits()); ASSERT_EQ(0u, resolver.inflight_joins()); - // Test that a callback is never made. This depends on there before another + // Test that a callback is never made. This depends on there being another // test after this one which will pump the MessageLoop. ExplodingCallback callback3; handle = resolver.Resolve("www.testing.notatld", kDNS_TESTING, 0, @@ -94,6 +123,7 @@ TEST_F(DnsRRResolverTest, Resolve) { ASSERT_EQ(1u, resolver.inflight_joins()); } +#if defined(OS_POSIX) // This is a DNS packet resulting from querying a recursive resolver for a TXT // record for agl._pka.imperialviolet.org. You should be able to get a // replacement from a packet capture should it ever be needed. @@ -178,7 +208,6 @@ TEST_F(DnsRRResolverTest, FuzzCorruption) { response.ParseFromResponse(copy, sizeof(copy), kDNS_TXT); } } - -#endif // OS_LINUX +#endif } // namespace net |