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 <utility> | |
| 8 | |
| 9 #include "base/stl_util.h" | |
| 10 #include "base/strings/string_number_conversions.h" | |
| 11 #include "net/dns/dns_protocol.h" | |
| 12 #include "net/dns/record_parsed.h" | |
| 13 #include "net/dns/record_rdata.h" | |
| 14 | |
| 15 // TODO(noamsml): Recursive CNAME closure (backwards and forwards). | |
| 16 | |
| 17 namespace net { | |
| 18 | |
| 19 // The effective TTL given to records with a nominal zero TTL. | |
| 20 // Allows time for hosts to send updated records, as detailed in RFC 6762 | |
| 21 // Section 10.1. | |
| 22 static const unsigned kZeroTTLSeconds = 1; | |
| 23 | |
| 24 MDnsCache::DnsRecordCacheKey::DnsRecordCacheKey(unsigned type, | |
| 25 const std::string& name, | |
| 26 const std::string& optional) | |
| 27 : type_(type), name_(name), optional_(optional) { | |
| 28 } | |
| 29 | |
| 30 MDnsCache::DnsRecordCacheKey::DnsRecordCacheKey( | |
| 31 const MDnsCache::DnsRecordCacheKey& other) | |
| 32 : type_(other.type_), name_(other.name_), optional_(other.optional_) { | |
| 33 } | |
| 34 | |
| 35 | |
| 36 MDnsCache::DnsRecordCacheKey& MDnsCache::DnsRecordCacheKey::operator=( | |
| 37 const MDnsCache::DnsRecordCacheKey& other) { | |
| 38 type_ = other.type_; | |
| 39 name_ = other.name_; | |
| 40 optional_ = other.optional_; | |
| 41 return *this; | |
| 42 } | |
| 43 | |
| 44 MDnsCache::DnsRecordCacheKey::~DnsRecordCacheKey() { | |
| 45 } | |
| 46 | |
| 47 bool MDnsCache::DnsRecordCacheKey::operator<( | |
| 48 const MDnsCache::DnsRecordCacheKey& key) const { | |
| 49 if (type_ != key.type_) | |
| 50 return type_ < key.type_; | |
| 51 | |
| 52 if (name_ != key.name_) | |
| 53 return name_ < key.name_; | |
| 54 | |
| 55 if (optional_ != key.optional_) | |
| 56 return optional_ < key.optional_; | |
| 57 return false; // keys are equal | |
| 58 } | |
| 59 | |
| 60 bool MDnsCache::DnsRecordCacheKey::operator==( | |
| 61 const MDnsCache::DnsRecordCacheKey& key) const { | |
| 62 return type_ == key.type_ && name_ == key.name_ && optional_ == key.optional_; | |
| 63 } | |
| 64 | |
| 65 MDnsCache::MDnsCache() { | |
| 66 } | |
| 67 | |
| 68 MDnsCache::~MDnsCache() { | |
| 69 Clear(); | |
| 70 } | |
| 71 | |
| 72 void MDnsCache::Clear() { | |
| 73 next_expiration_ = base::Time(); | |
| 74 STLDeleteValues(&mdns_cache_); | |
| 75 } | |
| 76 | |
| 77 MDnsCache::UpdateType MDnsCache::UpdateDnsRecord( | |
| 78 scoped_ptr<const RecordParsed> record) { | |
| 79 UpdateType type = NoChange; | |
| 80 | |
| 81 MDnsCache::DnsRecordCacheKey cache_key = MDnsCache::DnsRecordCacheKey( | |
| 82 record->type(), | |
| 83 record->name(), | |
| 84 GetOptionalFieldForRecord(record.get())); | |
| 85 | |
| 86 base::Time expiration = GetEffectiveExpiration(record.get()); | |
| 87 if (next_expiration_ == base::Time() || expiration < next_expiration_) { | |
| 88 next_expiration_ = expiration; | |
| 89 } | |
| 90 | |
| 91 std::pair<MDnsCacheMap::iterator, bool> insert_result = | |
| 92 mdns_cache_.insert(std::make_pair(cache_key, (const RecordParsed*)NULL)); | |
| 93 | |
| 94 if (insert_result.second) { | |
| 95 type = RecordAdded; | |
| 96 insert_result.first->second = record.release(); | |
| 97 } else { | |
| 98 const RecordParsed* other_record = insert_result.first->second; | |
| 99 | |
| 100 if (!record->IsEqual(other_record, true)) { | |
| 101 type = RecordChanged; | |
| 102 } | |
| 103 delete other_record; | |
| 104 insert_result.first->second = record.release(); | |
| 105 } | |
| 106 | |
| 107 return type; | |
| 108 } | |
| 109 | |
| 110 void MDnsCache::CleanupRecords( | |
| 111 base::Time now, | |
| 112 const RecordRemovedCallback& record_removed_callback) { | |
| 113 base::Time next_expiration; | |
| 114 | |
| 115 // We are guaranteed that |next_expiration_| will be at or before the next | |
| 116 // expiration. This allows clients to eagrely call CleanupRecords with | |
| 117 // impunity. | |
| 118 if (now < next_expiration_) return; | |
| 119 | |
| 120 for (MDnsCacheMap::iterator i = mdns_cache_.begin(); | |
| 121 i != mdns_cache_.end(); ) { | |
| 122 base::Time expiration = GetEffectiveExpiration(i->second); | |
| 123 if (now >= expiration) { | |
| 124 record_removed_callback.Run(i->second); | |
| 125 delete i->second; | |
| 126 mdns_cache_.erase(i++); | |
| 127 } else { | |
| 128 if (next_expiration == base::Time() || expiration < next_expiration) { | |
| 129 next_expiration = expiration; | |
| 130 } | |
| 131 ++i; | |
| 132 } | |
| 133 } | |
| 134 | |
| 135 next_expiration_ = next_expiration; | |
| 136 } | |
| 137 | |
| 138 void MDnsCache::FindDnsRecords(unsigned type, | |
| 139 const std::string& name, | |
| 140 std::vector<const RecordParsed*>* results, | |
| 141 base::Time now) { | |
| 142 DCHECK(results); | |
| 143 results->clear(); | |
| 144 | |
| 145 MDnsCacheMap::iterator i = | |
| 146 mdns_cache_.lower_bound(DnsRecordCacheKey(type, name, "")); | |
| 147 for (; i != mdns_cache_.end(); ++i) { | |
| 148 if (i->first.type() != type || | |
| 149 (!name.empty() && i->first.name() != name)) { | |
| 150 break; | |
| 151 } | |
| 152 | |
| 153 const RecordParsed* record = i->second; | |
| 154 | |
| 155 // Records are deleted only upon request to make this op idempotent | |
|
szym
2013/05/20 19:35:15
The op would still be idempotent (same result) if
Noam Samuel
2013/05/20 21:07:02
Fixed comment.
On 2013/05/20 19:35:15, szym wrot
| |
| 156 if (now >= GetEffectiveExpiration(record)) continue; | |
| 157 | |
| 158 results->push_back(record); | |
| 159 } | |
| 160 } | |
| 161 | |
| 162 std::string MDnsCache::GetOptionalFieldForRecord(const RecordParsed* record) { | |
|
szym
2013/05/20 19:35:15
Mark const.
Noam Samuel
2013/05/20 21:07:02
Done.
| |
| 163 switch (record->type()) { | |
| 164 case PtrRecordRdata::kType: { | |
| 165 const PtrRecordRdata* rdata = record->rdata<PtrRecordRdata>(); | |
| 166 return rdata->ptrdomain(); | |
| 167 } | |
| 168 default: // Most records are considered unique for our purposes | |
| 169 return ""; | |
| 170 } | |
| 171 } | |
| 172 | |
| 173 base::Time MDnsCache::GetEffectiveExpiration(const RecordParsed* record) { | |
|
szym
2013/05/20 19:35:15
Mark const.
Noam Samuel
2013/05/20 21:07:02
Done.
| |
| 174 base::TimeDelta ttl; | |
| 175 | |
| 176 if (record->ttl()) { | |
| 177 ttl = base::TimeDelta::FromSeconds(record->ttl()); | |
| 178 } else { | |
| 179 ttl = base::TimeDelta::FromSeconds(kZeroTTLSeconds); | |
| 180 } | |
| 181 | |
| 182 return record->time_created() + ttl; | |
| 183 } | |
| 184 | |
| 185 } // namespace net | |
| OLD | NEW |