Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "net/dns/mdns_cache.h" | |
| 6 | |
| 7 #include "base/stl_util.h" | |
| 8 #include "base/strings/string_number_conversions.h" | |
| 9 #include "net/dns/dns_protocol.h" | |
| 10 #include "net/dns/record_parsed.h" | |
| 11 #include "net/dns/record_rdata.h" | |
| 12 | |
| 13 // TODO(noamsml): Recursive CNAME closure (backwards and forwards). | |
| 14 | |
| 15 namespace net { | |
| 16 | |
| 17 // The effective TTL given to records with a nominal zero TTL. | |
| 18 // Allows time for hosts to send updated records. | |
|
szym
2013/05/17 05:04:34
I suggest referring to RFC 6762 Section 10.1 here.
Noam Samuel
2013/05/17 22:26:05
Done.
| |
| 19 static const unsigned kZeroTTLSeconds = 1; | |
| 20 | |
| 21 MDnsCache::DnsRecordCacheKey::DnsRecordCacheKey(unsigned type, | |
| 22 const std::string& name, | |
| 23 const std::string& optional) | |
| 24 : type_(type), name_(name), optional_(optional) { | |
| 25 } | |
| 26 | |
| 27 MDnsCache::DnsRecordCacheKey::~DnsRecordCacheKey() { | |
| 28 } | |
| 29 | |
| 30 bool MDnsCache::DnsRecordCacheKey::operator<( | |
| 31 const MDnsCache::DnsRecordCacheKey& key) const { | |
| 32 if (type_ != key.type_) | |
| 33 return type_ < key.type_; | |
| 34 | |
| 35 if (name_ != key.name_) | |
| 36 return name_ < key.name_; | |
| 37 | |
| 38 if (optional_ != key.optional_) | |
| 39 return optional_ < key.optional_; | |
| 40 return false; // keys are equal | |
| 41 } | |
| 42 | |
| 43 bool MDnsCache::DnsRecordCacheKey::operator==( | |
| 44 const MDnsCache::DnsRecordCacheKey& key) const { | |
| 45 return type_ == key.type_ && name_ == key.name_ && optional_ == key.optional_; | |
| 46 } | |
| 47 | |
| 48 MDnsCache::MDnsCache( | |
| 49 const MDnsCache::RecordRemovedCallback& record_removed_callback) | |
| 50 : record_removed_callback_(record_removed_callback) { | |
| 51 } | |
| 52 | |
| 53 MDnsCache::~MDnsCache() { | |
| 54 Clear(); | |
| 55 } | |
| 56 | |
| 57 void MDnsCache::Clear() { | |
| 58 next_expiration_ = base::Time(); | |
| 59 STLDeleteValues(&mdns_cache_); | |
| 60 } | |
| 61 | |
| 62 MDnsCache::UpdateType MDnsCache::UpdateDnsRecord( | |
| 63 scoped_ptr<const RecordParsed> record) { | |
| 64 UpdateType type = NoChange; | |
| 65 | |
| 66 MDnsCache::DnsRecordCacheKey cache_key = MDnsCache::DnsRecordCacheKey( | |
| 67 record->type(), | |
| 68 record->name(), | |
| 69 GetOptionalFieldForRecord(record.get())); | |
| 70 | |
| 71 base::Time expiration = GetEffectiveExpiration(record.get()); | |
| 72 if (next_expiration_ == base::Time() || expiration < next_expiration_) { | |
| 73 next_expiration_ = expiration; | |
| 74 } | |
| 75 | |
| 76 MDnsCacheMap::iterator i = mdns_cache_.find(cache_key); | |
|
szym
2013/05/17 05:04:34
I'd suggest:
const RecordParsed*& found = mdns_ca
Noam Samuel
2013/05/17 22:26:05
Done.
| |
| 77 if (i != mdns_cache_.end()) { | |
| 78 if (!record->IsEqual(i->second, true)) { | |
| 79 type = RecordChanged; | |
|
szym
2013/05/17 05:04:34
IMPORTANT: There is no RecordParsed::IsEqual.
Noam Samuel
2013/05/17 22:26:05
Oh whoops. Uploaded the patch wrong. This upload i
| |
| 80 } | |
| 81 delete i->second; | |
| 82 i->second = record.release(); | |
| 83 } else { | |
| 84 mdns_cache_[cache_key] = record.release(); | |
| 85 type = RecordAdded; | |
| 86 } | |
| 87 | |
| 88 return type; | |
| 89 } | |
| 90 | |
| 91 void MDnsCache::CleanupRecords( | |
|
szym
2013/05/17 05:04:34
nit: fits on a single line.
Noam Samuel
2013/05/17 22:26:05
Done.
| |
| 92 base::Time now) { | |
| 93 base::Time next_expiration; | |
| 94 | |
| 95 // We are guaranteed that next_expiration_ will be at or before the next | |
|
szym
2013/05/17 05:04:34
nit: || around variable names.
Noam Samuel
2013/05/17 22:26:05
Done.
| |
| 96 // expiration. This allows clients to eagrely call CleanupRecords with | |
| 97 // impunity. | |
| 98 if (now < next_expiration_) return; | |
| 99 | |
| 100 std::vector<MDnsCacheMap::iterator> to_delete; | |
|
szym
2013/05/17 05:04:34
Instead of keeping a handle on the iterators, remo
Noam Samuel
2013/05/17 22:26:05
Done.
| |
| 101 for (MDnsCacheMap::iterator i = mdns_cache_.begin(); | |
| 102 i != mdns_cache_.end(); i++) { | |
| 103 base::Time expiration = GetEffectiveExpiration(i->second); | |
| 104 if (now >= expiration) { | |
| 105 to_delete.push_back(i); | |
| 106 } else { | |
| 107 if (next_expiration == base::Time() || expiration < next_expiration) { | |
| 108 next_expiration = expiration; | |
| 109 } | |
| 110 } | |
| 111 } | |
| 112 | |
| 113 for (std::vector<MDnsCacheMap::iterator>::iterator i = to_delete.begin(); | |
| 114 i != to_delete.end(); ++i) { | |
| 115 record_removed_callback_.Run((*i)->second); | |
| 116 delete (*i)->second; | |
| 117 mdns_cache_.erase(*i); | |
| 118 } | |
| 119 | |
| 120 next_expiration_ = next_expiration; | |
| 121 } | |
| 122 | |
| 123 void MDnsCache::FindDnsRecords(unsigned type, | |
| 124 const std::string& name, | |
| 125 std::vector<const RecordParsed*>* results, | |
| 126 base::Time now) { | |
| 127 results->clear(); | |
|
szym
2013/05/17 05:04:34
DCHECK(results)
Noam Samuel
2013/05/17 22:26:05
Done.
| |
| 128 | |
| 129 MDnsCacheMap::iterator i = | |
| 130 mdns_cache_.lower_bound(DnsRecordCacheKey(type, name, "")); | |
| 131 for (; i != mdns_cache_.end(); ++i) { | |
| 132 if (i->first.type() != type || | |
| 133 (!name.empty() && i->first.name() != name)) { | |
| 134 break; | |
| 135 } | |
| 136 | |
| 137 const RecordParsed* record = i->second; | |
| 138 | |
| 139 // Records are deleted only upon request to make this op idempotent | |
| 140 if (now >= GetEffectiveExpiration(record)) continue; | |
| 141 | |
| 142 results->push_back(record); | |
| 143 } | |
| 144 } | |
| 145 | |
| 146 std::string MDnsCache::GetOptionalFieldForRecord(const RecordParsed* record) { | |
| 147 switch (record->type()) { | |
| 148 case PtrRecordRdata::kType: { | |
| 149 const PtrRecordRdata* rdata = record->rdata<PtrRecordRdata>(); | |
| 150 return rdata->ptrdomain(); | |
| 151 } | |
| 152 default: // Most records are considered unique for our purposes | |
| 153 return ""; | |
| 154 } | |
| 155 } | |
| 156 | |
| 157 base::Time MDnsCache::GetEffectiveExpiration(const RecordParsed* record) { | |
| 158 base::TimeDelta ttl; | |
| 159 | |
| 160 if (record->ttl()) { | |
| 161 ttl = base::TimeDelta::FromSeconds(record->ttl()); | |
| 162 } else { | |
| 163 ttl = base::TimeDelta::FromSeconds(kZeroTTLSeconds); | |
| 164 } | |
| 165 | |
| 166 return record->time_created() + ttl; | |
| 167 } | |
| 168 | |
| 169 } // namespace net | |
| OLD | NEW |